Merge "Import translations. DO NOT MERGE" into rvc-dev
diff --git a/api/test-current.txt b/api/test-current.txt
index d080d3d..6cdcc32 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -580,6 +580,7 @@
     method public java.util.List<java.lang.String> getOwnerInstalledCaCerts(@NonNull android.os.UserHandle);
     method public boolean isCurrentInputMethodSetByOwner();
     method public boolean isDeviceManaged();
+    method public boolean isFactoryResetProtectionPolicySupported();
     field public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_ALLOWED";
     field public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_DISALLOWED";
     field public static final String ACTION_DATA_SHARING_RESTRICTION_APPLIED = "android.app.action.DATA_SHARING_RESTRICTION_APPLIED";
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 41e2dc0..4b05045 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -10953,6 +10953,22 @@
     }
 
     /**
+     * Returns whether factory reset protection policy is supported on the device.
+     *
+     * @return {@code true} if the device support factory reset protection policy.
+     *
+     * @hide
+     */
+    @TestApi
+    public boolean isFactoryResetProtectionPolicySupported() {
+        try {
+            return mService.isFactoryResetProtectionPolicySupported();
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Called by the device owner or profile owner to clear application user data of a given
      * package. The behaviour of this is equivalent to the target application calling
      * {@link android.app.ActivityManager#clearApplicationUserData()}.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index d10153c..9c6a274 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -108,6 +108,7 @@
 
     void setFactoryResetProtectionPolicy(in ComponentName who, in FactoryResetProtectionPolicy policy);
     FactoryResetProtectionPolicy getFactoryResetProtectionPolicy(in ComponentName who);
+    boolean isFactoryResetProtectionPolicySupported();
 
     ComponentName setGlobalProxy(in ComponentName admin, String proxySpec, String exclusionList);
     ComponentName getGlobalProxyAdmin(int userHandle);
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index 65a8e15..6bc962b 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -650,6 +650,68 @@
     }
 
     /**
+     * Controls whether volume control commands via HDMI CEC are enabled.
+     *
+     * <p>When disabled:
+     * <ul>
+     *     <li>the device will not send any HDMI CEC audio messages
+     *     <li>received HDMI CEC audio messages are responded to with {@code <Feature Abort>}
+     * </ul>
+     *
+     * <p>Effects on different device types:
+     * <table>
+     *     <tr><th>HDMI CEC device type</th><th>enabled</th><th>disabled</th></tr>
+     *     <tr>
+     *         <td>TV (type: 0)</td>
+     *         <td>Per CEC specification.</td>
+     *         <td>TV changes system volume. TV no longer reacts to incoming volume changes via
+     *         {@code <User Control Pressed>}. TV no longer handles {@code <Report Audio Status>}
+     *         .</td>
+     *     </tr>
+     *     <tr>
+     *         <td>Playback device (type: 4)</td>
+     *         <td>Device sends volume commands to TV/Audio system via {@code <User Control
+     *         Pressed>}</td><td>Device does not send volume commands via {@code <User Control
+     *         Pressed>}.</td>
+     *     </tr>
+     *     <tr>
+     *         <td>Audio device (type: 5)</td>
+     *         <td>Full "System Audio Control" capabilities.</td>
+     *         <td>Audio device no longer reacts to incoming {@code <User Control Pressed>}
+     *         volume commands. Audio device no longer reports volume changes via {@code <Report
+     *         Audio Status>}.</td>
+     *     </tr>
+     * </table>
+     *
+     * <p> Due to the resulting behavior, usage on TV and Audio devices is discouraged.
+     *
+     * @param isHdmiCecVolumeControlEnabled target state of HDMI CEC volume control.
+     * @see Settings.Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.HDMI_CEC)
+    public void setHdmiCecVolumeControlEnabled(boolean isHdmiCecVolumeControlEnabled) {
+        try {
+            mService.setHdmiCecVolumeControlEnabled(isHdmiCecVolumeControlEnabled);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns whether volume changes via HDMI CEC are enabled.
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.HDMI_CEC)
+    public boolean isHdmiCecVolumeControlEnabled() {
+        try {
+            return mService.isHdmiCecVolumeControlEnabled();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Gets whether the system is in system audio mode.
      *
      * @hide
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
index a8fed2b..3582a92 100644
--- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -80,6 +80,8 @@
     void sendMhlVendorCommand(int portId, int offset, int length, in byte[] data);
     void addHdmiMhlVendorCommandListener(IHdmiMhlVendorCommandListener listener);
     void setStandbyMode(boolean isStandbyModeOn);
+    void setHdmiCecVolumeControlEnabled(boolean isHdmiCecVolumeControlEnabled);
+    boolean isHdmiCecVolumeControlEnabled();
     void reportAudioStatus(int deviceType, int volume, int maxVolume, boolean isMute);
     void setSystemAudioModeOnForAudioOnlySource();
 }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ac1998a..fbd6cba 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -9614,6 +9614,43 @@
         */
        public static final String HDMI_CONTROL_ENABLED = "hdmi_control_enabled";
 
+        /**
+         * Controls whether volume control commands via HDMI CEC are enabled. (0 = false, 1 =
+         * true).
+         *
+         * <p>Effects on different device types:
+         * <table>
+         *     <tr><th>HDMI CEC device type</th><th>0: disabled</th><th>1: enabled</th></tr>
+         *     <tr>
+         *         <td>TV (type: 0)</td>
+         *         <td>Per CEC specification.</td>
+         *         <td>TV changes system volume. TV no longer reacts to incoming volume changes
+         *         via {@code <User Control Pressed>}. TV no longer handles {@code <Report Audio
+         *         Status>}.</td>
+         *     </tr>
+         *     <tr>
+         *         <td>Playback device (type: 4)</td>
+         *         <td>Device sends volume commands to TV/Audio system via {@code <User Control
+         *         Pressed>}</td>
+         *         <td>Device does not send volume commands via {@code <User Control Pressed>}.</td>
+         *     </tr>
+         *     <tr>
+         *         <td>Audio device (type: 5)</td>
+         *         <td>Full "System Audio Control" capabilities.</td>
+         *         <td>Audio device no longer reacts to incoming {@code <User Control Pressed>}
+         *         volume commands. Audio device no longer reports volume changes via {@code
+         *         <Report Audio Status>}.</td>
+         *     </tr>
+         * </table>
+         *
+         * <p> Due to the resulting behavior, usage on TV and Audio devices is discouraged.
+         *
+         * @hide
+         * @see android.hardware.hdmi.HdmiControlManager#setHdmiCecVolumeControlEnabled(boolean)
+         */
+        public static final String HDMI_CONTROL_VOLUME_CONTROL_ENABLED =
+                "hdmi_control_volume_control_enabled";
+
        /**
         * Whether HDMI System Audio Control feature is enabled. If enabled, TV will try to turn on
         * system audio mode if there's a connected CEC-enabled AV Receiver. Then audio stream will
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 2975d5e..28a18da 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -36,6 +36,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.IResultReceiver;
 
 import java.util.List;
@@ -69,7 +70,8 @@
 public final class WindowManagerImpl implements WindowManager {
     @UnsupportedAppUsage
     private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
-    private final Context mContext;
+    @VisibleForTesting
+    public final Context mContext;
     private final Window mParentWindow;
 
     private IBinder mDefaultToken;
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 71dd665..3cf6109 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -645,11 +645,6 @@
         @Override
         public void setCurrentRootView(ViewRootImpl rootView) {
             synchronized (mH) {
-                if (mCurRootView != null) {
-                    // Reset the last served view and restart window focus state of the root view.
-                    mCurRootView.getImeFocusController().setServedView(null);
-                    mRestartOnNextWindowFocus = true;
-                }
                 mCurRootView = rootView;
             }
         }
diff --git a/core/java/com/android/internal/policy/DecorContext.java b/core/java/com/android/internal/policy/DecorContext.java
index 99b4b5f..51b4119 100644
--- a/core/java/com/android/internal/policy/DecorContext.java
+++ b/core/java/com/android/internal/policy/DecorContext.java
@@ -22,8 +22,6 @@
 import android.content.res.AssetManager;
 import android.content.res.Resources;
 import android.view.ContextThemeWrapper;
-import android.view.WindowManager;
-import android.view.WindowManagerImpl;
 import android.view.contentcapture.ContentCaptureManager;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -31,8 +29,8 @@
 import java.lang.ref.WeakReference;
 
 /**
- * Context for decor views which can be seeded with pure application context and not depend on the
- * activity, but still provide some of the facilities that Activity has,
+ * Context for decor views which can be seeded with display context and not depend on the activity,
+ * but still provide some of the facilities that Activity has,
  * e.g. themes, activity-based resources, etc.
  *
  * @hide
@@ -40,80 +38,93 @@
 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
 public class DecorContext extends ContextThemeWrapper {
     private PhoneWindow mPhoneWindow;
-    private WindowManager mWindowManager;
-    private Resources mActivityResources;
+    private Resources mResources;
     private ContentCaptureManager mContentCaptureManager;
 
-    private WeakReference<Context> mActivityContext;
+    private WeakReference<Context> mContext;
 
-    // TODO(b/149928768): Non-activity context can be passed.
     @VisibleForTesting
-    public DecorContext(Context context, Context activityContext) {
-        super(context.createDisplayContext(activityContext.getDisplayNoVerify()), null);
-        mActivityContext = new WeakReference<>(activityContext);
-        mActivityResources = activityContext.getResources();
+    public DecorContext(Context baseContext, PhoneWindow phoneWindow) {
+        super(null /* base */, null);
+        setPhoneWindow(phoneWindow);
+        final Context displayContext = baseContext.createDisplayContext(
+                // TODO(b/149790106): Non-activity context can be passed.
+                phoneWindow.getContext().getDisplayNoVerify());
+        attachBaseContext(displayContext);
     }
 
     void setPhoneWindow(PhoneWindow phoneWindow) {
         mPhoneWindow = phoneWindow;
-        mWindowManager = null;
+        final Context context = phoneWindow.getContext();
+        mContext = new WeakReference<>(context);
+        mResources = context.getResources();
     }
 
     @Override
     public Object getSystemService(String name) {
         if (Context.WINDOW_SERVICE.equals(name)) {
-            if (mWindowManager == null) {
-                WindowManagerImpl wm =
-                        (WindowManagerImpl) super.getSystemService(Context.WINDOW_SERVICE);
-                mWindowManager = wm.createLocalWindowManager(mPhoneWindow);
-            }
-            return mWindowManager;
+            return mPhoneWindow.getWindowManager();
         }
+        final Context context = mContext.get();
         if (Context.CONTENT_CAPTURE_MANAGER_SERVICE.equals(name)) {
-            if (mContentCaptureManager == null) {
-                Context activityContext = mActivityContext.get();
-                if (activityContext != null) {
-                    mContentCaptureManager = (ContentCaptureManager) activityContext
-                            .getSystemService(name);
-                }
+            if (context != null && mContentCaptureManager == null) {
+                mContentCaptureManager = (ContentCaptureManager) context.getSystemService(name);
             }
             return mContentCaptureManager;
         }
-        return super.getSystemService(name);
+        // TODO(b/154191411): Try to revisit this issue in S.
+        // We use application to get DisplayManager here because ViewRootImpl holds reference of
+        // DisplayManager and implicitly holds reference of mContext, which makes activity cannot
+        // be GC'd even after destroyed if mContext is an activity object.
+        if (Context.DISPLAY_SERVICE.equals(name)) {
+            return super.getSystemService(name);
+        }
+        // LayoutInflater and WallpaperManagerService should also be obtained from visual context
+        // instead of base context.
+        return (context != null) ? context.getSystemService(name) : super.getSystemService(name);
     }
 
     @Override
     public Resources getResources() {
-        Context activityContext = mActivityContext.get();
+        Context context = mContext.get();
         // Attempt to update the local cached Resources from the activity context. If the activity
         // is no longer around, return the old cached values.
-        if (activityContext != null) {
-            mActivityResources = activityContext.getResources();
+        if (context != null) {
+            mResources = context.getResources();
         }
 
-        return mActivityResources;
+        return mResources;
     }
 
     @Override
     public AssetManager getAssets() {
-        return mActivityResources.getAssets();
+        return mResources.getAssets();
     }
 
     @Override
     public AutofillOptions getAutofillOptions() {
-        Context activityContext = mActivityContext.get();
-        if (activityContext != null) {
-            return activityContext.getAutofillOptions();
+        Context context = mContext.get();
+        if (context != null) {
+            return context.getAutofillOptions();
         }
         return null;
     }
 
     @Override
     public ContentCaptureOptions getContentCaptureOptions() {
-        Context activityContext = mActivityContext.get();
-        if (activityContext != null) {
-            return activityContext.getContentCaptureOptions();
+        Context context = mContext.get();
+        if (context != null) {
+            return context.getContentCaptureOptions();
         }
         return null;
     }
+
+    @Override
+    public boolean isUiContext() {
+        Context context = mContext.get();
+        if (context != null) {
+            return context.isUiContext();
+        }
+        return false;
+    }
 }
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 23ba653..aa75d40 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -2358,7 +2358,7 @@
             if (applicationContext == null) {
                 context = getContext();
             } else {
-                context = new DecorContext(applicationContext, getContext());
+                context = new DecorContext(applicationContext, this);
                 if (mTheme != -1) {
                     context.setTheme(mTheme);
                 }
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index d06bc3b..dfd729e 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -724,7 +724,7 @@
   </string-array>
   <string-array name="emailAddressTypes">
     <item msgid="7786349763648997741">"المنزل"</item>
-    <item msgid="435564470865989199">"عمل"</item>
+    <item msgid="435564470865989199">"العمل"</item>
     <item msgid="4199433197875490373">"آخر"</item>
     <item msgid="3233938986670468328">"مخصص"</item>
   </string-array>
@@ -778,7 +778,7 @@
     <string name="phoneTypeMms" msgid="1799747455131365989">"رسالة وسائط متعددة"</string>
     <string name="eventTypeCustom" msgid="3257367158986466481">"مخصص"</string>
     <string name="eventTypeBirthday" msgid="7770026752793912283">"عيد ميلاد"</string>
-    <string name="eventTypeAnniversary" msgid="4684702412407916888">"الذكرى السنوية"</string>
+    <string name="eventTypeAnniversary" msgid="4684702412407916888">"ذكرى سنوية"</string>
     <string name="eventTypeOther" msgid="530671238533887997">"غير ذلك"</string>
     <string name="emailTypeCustom" msgid="1809435350482181786">"مخصص"</string>
     <string name="emailTypeHome" msgid="1597116303154775999">"المنزل"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 5c38284..569b284 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1806,7 +1806,7 @@
       <item quantity="other">%1$d मिनट के लिए (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> तक)</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="7725354244196466758">
-      <item quantity="one">%1$d घंटों के लिए (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> तक)</item>
+      <item quantity="one">%1$d घंटे के लिए (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> तक)</item>
       <item quantity="other">%1$d घंटों के लिए (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> तक)</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_summary_short" formatted="false" msgid="588719069121765642">
@@ -1822,7 +1822,7 @@
       <item quantity="other">%d मिनट के लिए</item>
     </plurals>
     <plurals name="zen_mode_duration_hours" formatted="false" msgid="525401855645490022">
-      <item quantity="one">%d घंटों के लिए</item>
+      <item quantity="one">%d घंटे के लिए</item>
       <item quantity="other">%d घंटों के लिए</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_short" formatted="false" msgid="7644653189680911640">
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 1ba41b3..73c0c0c 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1403,8 +1403,8 @@
     <string name="ime_action_default" msgid="8265027027659800121">"Կատարել"</string>
     <string name="dial_number_using" msgid="6060769078933953531">"Հավաքել հեռախոսահամարը`\nօգտագործելով <xliff:g id="NUMBER">%s</xliff:g>-ը"</string>
     <string name="create_contact_using" msgid="6200708808003692594">"Ստեղծել կոնտակտ`\nօգտագործելով <xliff:g id="NUMBER">%s</xliff:g>-ը"</string>
-    <string name="grant_credentials_permission_message_header" msgid="5365733888842570481">"Հետևյալ մեկ կամ ավել հավելվածներ մուտքի թույլտվության հարցում են անում` այժմ և հետագայում ձեր հաշվին մուտք ունենալու համար:"</string>
-    <string name="grant_credentials_permission_message_footer" msgid="1886710210516246461">"Ցանկանու՞մ եք թույլատրել այս հարցումը:"</string>
+    <string name="grant_credentials_permission_message_header" msgid="5365733888842570481">"Հետևյալ մեկ կամ մի քանի հավելվածներին թույլտվություն է անհրաժեշտ՝ այժմ և հետագայում ձեր հաշվի տվյալներն օգտագործելու համար։"</string>
+    <string name="grant_credentials_permission_message_footer" msgid="1886710210516246461">"Թույլատրե՞լ"</string>
     <string name="grant_permissions_header_text" msgid="3420736827804657201">"Մուտքի հարցում"</string>
     <string name="allow" msgid="6195617008611933762">"Թույլատրել"</string>
     <string name="deny" msgid="6632259981847676572">"Մերժել"</string>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 0e40c98..9c93c3e 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4410,6 +4410,12 @@
     shortcut enabled. [CHAR LIMIT=none] -->
     <string name="accessibility_shortcut_off">Don’t turn on</string>
 
+    <!-- Text for a feature status that is enabled. [CHAR LIMIT=10] -->
+    <string name="accessibility_shortcut_menu_item_status_on">ON</string>
+
+    <!-- Text for a feature status that is disabled. [CHAR LIMIT=10] -->
+    <string name="accessibility_shortcut_menu_item_status_off">OFF</string>
+
     <!-- Title for a warning about security implications of enabling an accessibility
     service. [CHAR LIMIT=NONE] -->
     <string name="accessibility_enable_service_title">Allow
diff --git a/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java b/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java
index 3e40466..02870a5 100644
--- a/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java
+++ b/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java
@@ -19,20 +19,26 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
+import android.app.Activity;
+import android.app.EmptyActivity;
 import android.content.Context;
 import android.hardware.display.DisplayManagerGlobal;
 import android.platform.test.annotations.Presubmit;
 import android.view.Display;
 import android.view.DisplayAdjustments;
 import android.view.DisplayInfo;
+import android.view.WindowManager;
+import android.view.WindowManagerImpl;
 
-import androidx.test.InstrumentationRegistry;
+import androidx.test.core.app.ApplicationProvider;
 import androidx.test.filters.SmallTest;
+import androidx.test.rule.ActivityTestRule;
 import androidx.test.runner.AndroidJUnit4;
 
-
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -46,17 +52,22 @@
     private Context mContext;
     private static final int EXTERNAL_DISPLAY = DEFAULT_DISPLAY + 1;
 
+    @Rule
+    public ActivityTestRule<EmptyActivity> mActivityRule =
+            new ActivityTestRule<>(EmptyActivity.class);
+
     @Before
-    public void setUp() throws Exception {
-        mContext = InstrumentationRegistry.getContext();
+    public void setUp() {
+        mContext = ApplicationProvider.getApplicationContext();
     }
 
     @Test
     public void testDecorContextWithDefaultDisplay() {
         Display defaultDisplay = new Display(DisplayManagerGlobal.getInstance(), DEFAULT_DISPLAY,
                 new DisplayInfo(), DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
-        DecorContext context = new DecorContext(mContext.getApplicationContext(),
-                mContext.createDisplayContext(defaultDisplay));
+        final Context defaultDisplayContext = mContext.createDisplayContext(defaultDisplay);
+        final PhoneWindow window = new PhoneWindow(defaultDisplayContext);
+        DecorContext context = new DecorContext(mContext.getApplicationContext(), window);
 
         assertDecorContextDisplay(DEFAULT_DISPLAY, context);
     }
@@ -65,8 +76,9 @@
     public void testDecorContextWithExternalDisplay() {
         Display display = new Display(DisplayManagerGlobal.getInstance(), EXTERNAL_DISPLAY,
                 new DisplayInfo(), DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
-        DecorContext context = new DecorContext(mContext.getApplicationContext(),
-                mContext.createDisplayContext(display));
+        final Context defaultDisplayContext = mContext.createDisplayContext(display);
+        final PhoneWindow window = new PhoneWindow(defaultDisplayContext);
+        DecorContext context = new DecorContext(mContext.getApplicationContext(), window);
 
         assertDecorContextDisplay(EXTERNAL_DISPLAY, context);
     }
@@ -76,4 +88,29 @@
         Display associatedDisplay = decorContext.getDisplay();
         assertEquals(expectedDisplayId, associatedDisplay.getDisplayId());
     }
+
+    @Test
+    public void testGetWindowManagerFromVisualDecorContext() throws Throwable {
+        mActivityRule.runOnUiThread(() -> {
+            Activity activity = mActivityRule.getActivity();
+            final DecorContext decorContext = new DecorContext(mContext.getApplicationContext(),
+                    (PhoneWindow) activity.getWindow());
+            WindowManagerImpl actualWm = (WindowManagerImpl)
+                    decorContext.getSystemService(WindowManager.class);
+            WindowManagerImpl expectedWm = (WindowManagerImpl)
+                    activity.getSystemService(WindowManager.class);
+            // Verify that window manager is from activity not application context.
+            assertEquals(expectedWm.mContext, actualWm.mContext);
+        });
+    }
+
+    @Test
+    public void testIsUiContextFromVisualDecorContext() throws Throwable {
+        mActivityRule.runOnUiThread(() -> {
+            Activity activity = mActivityRule.getActivity();
+            final DecorContext decorContext = new DecorContext(mContext.getApplicationContext(),
+                    (PhoneWindow) activity.getWindow());
+            assertTrue(decorContext.isUiContext());
+        });
+    }
 }
diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
index 2141b81..7cd2f3b 100644
--- a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
+++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
@@ -354,6 +354,15 @@
         @Override
         public void askRemoteDeviceToBecomeActiveSource(int physicalAddress) {
         }
+
+        @Override
+        public void setHdmiCecVolumeControlEnabled(boolean isHdmiCecVolumeControlEnabled) {
+        }
+
+        @Override
+        public boolean isHdmiCecVolumeControlEnabled() {
+            return true;
+        }
     }
 
 }
diff --git a/packages/DynamicSystemInstallationService/res/values/strings.xml b/packages/DynamicSystemInstallationService/res/values/strings.xml
index e124be6..719fc73 100644
--- a/packages/DynamicSystemInstallationService/res/values/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values/strings.xml
@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-    <!-- application name [CHAR LIMIT=32] -->
+    <!-- application name [DO NOT TRANSLATE] -->
     <string name="app_name">Dynamic System Updates</string>
 
-    <!-- notification channel name [CHAR LIMIT=32] -->
+    <!-- notification channel name [DO NOT TRANSLATE] -->
     <string name="notification_channel_name">Dynamic System Updates</string>
 
-    <!-- password page title [CHAR LIMIT=32] -->
+    <!-- password page title [DO NOT TRANSLATE] -->
     <string name="keyguard_title">Dynamic System Updates</string>
 
     <!-- password page description [CHAR LIMIT=128] -->
@@ -23,19 +23,19 @@
     <!-- Displayed on notification: We are running in Dynamic System [CHAR LIMIT=128] -->
     <string name="notification_dynsystem_in_use">Currently running a dynamic system. Restart to use the original Android version.</string>
 
-    <!-- Action on notification: Cancel installation [CHAR LIMIT=16] -->
+    <!-- Action on notification: Cancel installation [CHAR LIMIT=24] -->
     <string name="notification_action_cancel">Cancel</string>
-    <!-- Action on notification: Discard installation [CHAR LIMIT=16] -->
+    <!-- Action on notification: Discard installation [CHAR LIMIT=24] -->
     <string name="notification_action_discard">Discard</string>
-    <!-- Action on notification: Restart to Dynamic System [CHAR LIMIT=16] -->
+    <!-- Action on notification: Restart to Dynamic System [CHAR LIMIT=24] -->
     <string name="notification_action_reboot_to_dynsystem">Restart</string>
-    <!-- Action on notification: Restart to original Android version [CHAR LIMIT=16] -->
+    <!-- Action on notification: Restart to original Android version [CHAR LIMIT=24] -->
     <string name="notification_action_reboot_to_origin">Restart</string>
 
 
-    <!-- Toast when installed Dynamic System is discarded [CHAR LIMIT=64] -->
+    <!-- Toast when installed Dynamic System is discarded [CHAR LIMIT=128] -->
     <string name="toast_dynsystem_discarded">Discarded dynamic system</string>
-    <!-- Toast when we fail to launch into Dynamic System [CHAR LIMIT=64] -->
+    <!-- Toast when we fail to launch into Dynamic System [CHAR LIMIT=128] -->
     <string name="toast_failed_to_reboot_to_dynsystem">Can\u2019t restart or load dynamic system</string>
 
     <!-- URL of Dynamic System Key Revocation List [DO NOT TRANSLATE] -->
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 03f6df0..0dd7fb8 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -296,6 +296,7 @@
                     Settings.Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED,
                     Settings.Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED,
                     Settings.Global.HDMI_CONTROL_ENABLED,
+                    Settings.Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED,
                     Settings.Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED,
                     Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED,
                     Settings.Global.HIDDEN_API_POLICY,
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 0c7aef9..03af224 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -416,7 +416,7 @@
     <string name="quick_settings_night_display_label" msgid="8180030659141778180">"Ноќно светло"</string>
     <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Вклуч. на зајдисонце"</string>
     <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"До изгрејсонце"</string>
-    <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Ќе се вклучи во <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Вклучување: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"До <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Темна тема"</string>
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Штедач на батерија"</string>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-ne/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ne/strings.xml
index 2a73300..12d6c2c 100644
--- a/packages/Tethering/res/values-mcc310-mnc004-ne/strings.xml
+++ b/packages/Tethering/res/values-mcc310-mnc004-ne/strings.xml
@@ -16,13 +16,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for no_upstream_notification_title (5030042590486713460) -->
-    <skip />
-    <!-- no translation found for no_upstream_notification_message (3843613362272973447) -->
-    <skip />
-    <!-- no translation found for no_upstream_notification_disable_button (6385491461813507624) -->
-    <skip />
-    <!-- no translation found for upstream_roaming_notification_title (3015912166812283303) -->
-    <skip />
+    <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering has no internet"</string>
+    <string name="no_upstream_notification_message" msgid="3843613362272973447">"यन्त्रहरू कनेक्ट गर्न सकिएन"</string>
+    <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"टेदरिङ निष्क्रिय पार्नुहोस्"</string>
+    <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"हटस्पट वा टेदरिङ सक्रिय छ"</string>
     <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"रोमिङ सेवा प्रयोग गर्दा अतिरिक्त शुल्क लाग्न सक्छ"</string>
 </resources>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-ta/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ta/strings.xml
index ea04821..f4b15aa 100644
--- a/packages/Tethering/res/values-mcc310-mnc004-ta/strings.xml
+++ b/packages/Tethering/res/values-mcc310-mnc004-ta/strings.xml
@@ -16,13 +16,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for no_upstream_notification_title (5030042590486713460) -->
-    <skip />
-    <!-- no translation found for no_upstream_notification_message (3843613362272973447) -->
-    <skip />
-    <!-- no translation found for no_upstream_notification_disable_button (6385491461813507624) -->
-    <skip />
-    <!-- no translation found for upstream_roaming_notification_title (3015912166812283303) -->
-    <skip />
+    <string name="no_upstream_notification_title" msgid="5030042590486713460">"இணைப்பு முறைக்கு இணைய இணைப்பு இல்லை"</string>
+    <string name="no_upstream_notification_message" msgid="3843613362272973447">"சாதனங்களால் இணைய முடியவில்லை"</string>
+    <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"இணைப்பு முறையை ஆஃப் செய்"</string>
+    <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"ஹாட்ஸ்பாட் அல்லது இணைப்பு முறை ஆன் செய்யப்பட்டுள்ளது"</string>
     <string name="upstream_roaming_notification_message" msgid="6724434706748439902">"ரோமிங்கின்போது கூடுதல் கட்டணங்கள் விதிக்கப்படக்கூடும்"</string>
 </resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-ne/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ne/strings.xml
index 617c50d..0a0aa21 100644
--- a/packages/Tethering/res/values-mcc311-mnc480-ne/strings.xml
+++ b/packages/Tethering/res/values-mcc311-mnc480-ne/strings.xml
@@ -16,13 +16,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for no_upstream_notification_title (611650570559011140) -->
-    <skip />
-    <!-- no translation found for no_upstream_notification_message (6508394877641864863) -->
-    <skip />
-    <!-- no translation found for no_upstream_notification_disable_button (7609346639290990508) -->
-    <skip />
-    <!-- no translation found for upstream_roaming_notification_title (6032901176124830787) -->
-    <skip />
+    <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering has no internet"</string>
+    <string name="no_upstream_notification_message" msgid="6508394877641864863">"यन्त्रहरू कनेक्ट गर्न सकिएन"</string>
+    <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"टेदरिङ निष्क्रिय पार्नुहोस्"</string>
+    <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"हटस्पट वा टेदरिङ सक्रिय छ"</string>
     <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"रोमिङ सेवा प्रयोग गर्दा अतिरिक्त शुल्क लाग्न सक्छ"</string>
 </resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-ta/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ta/strings.xml
index 0e43759..2ea2467 100644
--- a/packages/Tethering/res/values-mcc311-mnc480-ta/strings.xml
+++ b/packages/Tethering/res/values-mcc311-mnc480-ta/strings.xml
@@ -16,13 +16,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for no_upstream_notification_title (611650570559011140) -->
-    <skip />
-    <!-- no translation found for no_upstream_notification_message (6508394877641864863) -->
-    <skip />
-    <!-- no translation found for no_upstream_notification_disable_button (7609346639290990508) -->
-    <skip />
-    <!-- no translation found for upstream_roaming_notification_title (6032901176124830787) -->
-    <skip />
+    <string name="no_upstream_notification_title" msgid="611650570559011140">"இணைப்பு முறைக்கு இணைய இணைப்பு இல்லை"</string>
+    <string name="no_upstream_notification_message" msgid="6508394877641864863">"சாதனங்களால் இணைய முடியவில்லை"</string>
+    <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"இணைப்பு முறையை ஆஃப் செய்"</string>
+    <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"ஹாட்ஸ்பாட் அல்லது இணைப்பு முறை ஆன் செய்யப்பட்டுள்ளது"</string>
     <string name="upstream_roaming_notification_message" msgid="7599056263326217523">"ரோமிங்கின்போது கூடுதல் கட்டணங்கள் விதிக்கப்படக்கூடும்"</string>
 </resources>
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java b/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
index 55344fc..c4a1078 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
@@ -41,6 +41,7 @@
 import java.net.SocketAddress;
 import java.net.SocketException;
 import java.util.ArrayList;
+import java.util.NoSuchElementException;
 
 
 /**
@@ -143,7 +144,7 @@
         IOffloadConfig offloadConfig;
         try {
             offloadConfig = IOffloadConfig.getService(true /*retry*/);
-        } catch (RemoteException e) {
+        } catch (RemoteException | NoSuchElementException e) {
             mLog.e("getIOffloadConfig error " + e);
             return false;
         }
@@ -239,8 +240,8 @@
 
         if (mOffloadControl == null) {
             try {
-                mOffloadControl = IOffloadControl.getService();
-            } catch (RemoteException e) {
+                mOffloadControl = IOffloadControl.getService(true /*retry*/);
+            } catch (RemoteException | NoSuchElementException e) {
                 mLog.e("tethering offload control not supported: " + e);
                 return false;
             }
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 992e984..dc35c77 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -318,6 +318,9 @@
 
     private static final String SERIAL_ID_FILE = "serial_id";
 
+    private static final String SKIP_USER_FACING_DATA = "backup_skip_user_facing_data";
+    private static final String WALLPAPER_PACKAGE = "com.android.wallpaperbackup";
+
     private final @UserIdInt int mUserId;
     private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
     private final TransportManager mTransportManager;
@@ -3553,6 +3556,40 @@
         }
     }
 
+    /**
+     * We want to skip backup/restore of certain packages if 'backup_skip_user_facing_data' is
+     * set to true in secure settings. See b/153940088 for details.
+     *
+     * TODO(b/154822946): Remove this logic in the next release.
+     */
+    public List<PackageInfo> filterUserFacingPackages(List<PackageInfo> packages) {
+        if (!shouldSkipUserFacingData()) {
+            return packages;
+        }
+
+        List<PackageInfo> filteredPackages = new ArrayList<>(packages.size());
+        for (PackageInfo packageInfo : packages)  {
+            if (!shouldSkipPackage(packageInfo.packageName)) {
+                filteredPackages.add(packageInfo);
+            } else {
+                Slog.i(TAG, "Will skip backup/restore for " + packageInfo.packageName);
+            }
+        }
+
+        return filteredPackages;
+    }
+
+    @VisibleForTesting
+    public boolean shouldSkipUserFacingData() {
+        return Settings.Secure.getInt(mContext.getContentResolver(), SKIP_USER_FACING_DATA,
+                /* def */ 0) != 0;
+    }
+
+    @VisibleForTesting
+    public boolean shouldSkipPackage(String packageName) {
+        return WALLPAPER_PACKAGE.equals(packageName);
+    }
+
     private void updateStateForTransport(String newTransportName) {
         // Publish the name change
         Settings.Secure.putStringForUser(mContext.getContentResolver(),
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
index f7f0138..738dd9bf 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
@@ -61,6 +61,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.List;
 import java.util.Objects;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -131,7 +132,7 @@
     private UserBackupManagerService mUserBackupManagerService;
     private final Object mCancelLock = new Object();
 
-    ArrayList<PackageInfo> mPackages;
+    List<PackageInfo> mPackages;
     PackageInfo mCurrentPackage;
     boolean mUpdateSchedule;
     CountDownLatch mLatch;
@@ -249,6 +250,8 @@
                         null);
             }
         }
+
+        mPackages = backupManagerService.filterUserFacingPackages(mPackages);
     }
 
     private void registerTask() {
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index e434be6..12113fe 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -270,6 +270,8 @@
             }
         }
 
+        mAcceptSet = backupManagerService.filterUserFacingPackages(mAcceptSet);
+
         if (MORE_DEBUG) {
             Slog.v(TAG, "Restore; accept set size is " + mAcceptSet.size());
             for (PackageInfo info : mAcceptSet) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index a358707..3ff6ec1 100755
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -32,6 +32,7 @@
 import android.view.KeyEvent;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.hdmi.Constants.LocalActivePort;
 import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
@@ -144,7 +145,8 @@
 
     // A collection of FeatureAction.
     // Note that access to this collection should happen in service thread.
-    private final ArrayList<HdmiCecFeatureAction> mActions = new ArrayList<>();
+    @VisibleForTesting
+    final ArrayList<HdmiCecFeatureAction> mActions = new ArrayList<>();
 
     private final Handler mHandler =
             new Handler() {
@@ -544,6 +546,8 @@
         } else if (mService.isPowerStandbyOrTransient() && isPowerOnOrToggleCommand(message)) {
             mService.wakeUp();
             return true;
+        } else if (!mService.isHdmiCecVolumeControlEnabled() && isVolumeOrMuteCommand(message)) {
+            return false;
         }
 
         final long downTime = SystemClock.uptimeMillis();
@@ -618,6 +622,16 @@
                         || params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER_TOGGLE_FUNCTION);
     }
 
+    static boolean isVolumeOrMuteCommand(HdmiCecMessage message) {
+        byte[] params = message.getParams();
+        return message.getOpcode() == Constants.MESSAGE_USER_CONTROL_PRESSED
+                && (params[0] == HdmiCecKeycode.CEC_KEYCODE_VOLUME_DOWN
+                    || params[0] == HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP
+                    || params[0] == HdmiCecKeycode.CEC_KEYCODE_MUTE
+                    || params[0] == HdmiCecKeycode.CEC_KEYCODE_MUTE_FUNCTION
+                    || params[0] == HdmiCecKeycode.CEC_KEYCODE_RESTORE_VOLUME_FUNCTION);
+    }
+
     protected boolean handleTextViewOn(HdmiCecMessage message) {
         return false;
     }
@@ -1038,6 +1052,9 @@
     @ServiceThreadOnly
     protected void sendVolumeKeyEvent(int keyCode, boolean isPressed) {
         assertRunOnServiceThread();
+        if (!mService.isHdmiCecVolumeControlEnabled()) {
+            return;
+        }
         if (!HdmiCecKeycode.isVolumeKeycode(keyCode)) {
             Slog.w(TAG, "Not a volume key: " + keyCode);
             return;
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
index e5a08d3..611b8c6 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
@@ -575,7 +575,7 @@
     @ServiceThreadOnly
     protected boolean handleGiveAudioStatus(HdmiCecMessage message) {
         assertRunOnServiceThread();
-        if (isSystemAudioControlFeatureEnabled()) {
+        if (isSystemAudioControlFeatureEnabled() && mService.isHdmiCecVolumeControlEnabled()) {
             reportAudioStatus(message.getSource());
         } else {
             mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED);
@@ -930,6 +930,9 @@
 
     void reportAudioStatus(int source) {
         assertRunOnServiceThread();
+        if (!mService.isHdmiCecVolumeControlEnabled()) {
+            return;
+        }
 
         int volume = mService.getAudioManager().getStreamVolume(AudioManager.STREAM_MUSIC);
         boolean mute = mService.getAudioManager().isStreamMute(AudioManager.STREAM_MUSIC);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index a702ce5..0ac4f9e 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -678,6 +678,9 @@
     @ServiceThreadOnly
     protected boolean handleReportAudioStatus(HdmiCecMessage message) {
         assertRunOnServiceThread();
+        if (!mService.isHdmiCecVolumeControlEnabled()) {
+            return false;
+        }
 
         boolean mute = HdmiUtils.isAudioStatusMute(message);
         int volume = HdmiUtils.getAudioStatusVolume(message);
@@ -987,7 +990,7 @@
     }
 
     void setAudioStatus(boolean mute, int volume) {
-        if (!isSystemAudioActivated()) {
+        if (!isSystemAudioActivated() || !mService.isHdmiCecVolumeControlEnabled()) {
             return;
         }
         synchronized (mLock) {
@@ -1009,7 +1012,7 @@
             // On initialization process, getAvrDeviceInfo() may return null and cause exception
             return;
         }
-        if (delta == 0 || !isSystemAudioActivated()) {
+        if (delta == 0 || !isSystemAudioActivated() || !mService.isHdmiCecVolumeControlEnabled()) {
             return;
         }
 
@@ -1038,7 +1041,7 @@
     @ServiceThreadOnly
     void changeMute(boolean mute) {
         assertRunOnServiceThread();
-        if (getAvrDeviceInfo() == null) {
+        if (getAvrDeviceInfo() == null || !mService.isHdmiCecVolumeControlEnabled()) {
             // On initialization process, getAvrDeviceInfo() may return null and cause exception
             return;
         }
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index d9e3025..53f9ebc 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -177,6 +177,10 @@
     @GuardedBy("mLock")
     protected final ActiveSource mActiveSource = new ActiveSource();
 
+    // Whether HDMI CEC volume control is enabled or not.
+    @GuardedBy("mLock")
+    private boolean mHdmiCecVolumeControlEnabled;
+
     // Whether System Audio Mode is activated or not.
     @GuardedBy("mLock")
     private boolean mSystemAudioActivated = false;
@@ -497,6 +501,8 @@
         mPowerStatus = getInitialPowerStatus();
         mProhibitMode = false;
         mHdmiControlEnabled = readBooleanSetting(Global.HDMI_CONTROL_ENABLED, true);
+        mHdmiCecVolumeControlEnabled = readBooleanSetting(
+                Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED, true);
         mMhlInputChangeEnabled = readBooleanSetting(Global.MHL_INPUT_SWITCHING_ENABLED, true);
 
         if (mCecController == null) {
@@ -646,6 +652,7 @@
         ContentResolver resolver = getContext().getContentResolver();
         String[] settings = new String[] {
                 Global.HDMI_CONTROL_ENABLED,
+                Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED,
                 Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED,
                 Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED,
                 Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED,
@@ -674,6 +681,9 @@
                 case Global.HDMI_CONTROL_ENABLED:
                     setControlEnabled(enabled);
                     break;
+                case Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED:
+                    setHdmiCecVolumeControlEnabled(enabled);
+                    break;
                 case Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED:
                     if (isTvDeviceEnabled()) {
                         tv().setAutoWakeup(enabled);
@@ -1273,7 +1283,9 @@
     }
 
     void setAudioStatus(boolean mute, int volume) {
-        if (!isTvDeviceEnabled() || !tv().isSystemAudioActivated()) {
+        if (!isTvDeviceEnabled()
+                || !tv().isSystemAudioActivated()
+                || !isHdmiCecVolumeControlEnabled()) {
             return;
         }
         AudioManager audioManager = getAudioManager();
@@ -2187,6 +2199,24 @@
         }
 
         @Override
+        public boolean isHdmiCecVolumeControlEnabled() {
+            enforceAccessPermission();
+            return HdmiControlService.this.isHdmiCecVolumeControlEnabled();
+        }
+
+        @Override
+        public void setHdmiCecVolumeControlEnabled(final boolean isHdmiCecVolumeControlEnabled) {
+            enforceAccessPermission();
+            runOnServiceThread(new Runnable() {
+                @Override
+                public void run() {
+                    HdmiControlService.this.setHdmiCecVolumeControlEnabled(
+                            isHdmiCecVolumeControlEnabled);
+                }
+            });
+        }
+
+        @Override
         public void reportAudioStatus(final int deviceType, final int volume, final int maxVolume,
                 final boolean isMute) {
             enforceAccessPermission();
@@ -2250,6 +2280,7 @@
             pw.println("mHdmiControlEnabled: " + mHdmiControlEnabled);
             pw.println("mMhlInputChangeEnabled: " + mMhlInputChangeEnabled);
             pw.println("mSystemAudioActivated: " + isSystemAudioActivated());
+            pw.println("mHdmiCecVolumeControlEnabled " + mHdmiCecVolumeControlEnabled);
             pw.decreaseIndent();
 
             pw.println("mMhlController: ");
@@ -2982,6 +3013,29 @@
         }
     }
 
+    void setHdmiCecVolumeControlEnabled(boolean isHdmiCecVolumeControlEnabled) {
+        assertRunOnServiceThread();
+        synchronized (mLock) {
+            mHdmiCecVolumeControlEnabled = isHdmiCecVolumeControlEnabled;
+
+            boolean storedValue = readBooleanSetting(Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED,
+                    true);
+            if (storedValue != isHdmiCecVolumeControlEnabled) {
+                HdmiLogger.debug("Changing HDMI CEC volume control feature state: %s",
+                        isHdmiCecVolumeControlEnabled);
+                writeBooleanSetting(Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED,
+                        isHdmiCecVolumeControlEnabled);
+            }
+        }
+    }
+
+    boolean isHdmiCecVolumeControlEnabled() {
+        assertRunOnServiceThread();
+        synchronized (mLock) {
+            return mHdmiCecVolumeControlEnabled;
+        }
+    }
+
     boolean isProhibitMode() {
         synchronized (mLock) {
             return mProhibitMode;
@@ -3022,8 +3076,12 @@
 
         if (enabled) {
             enableHdmiControlService();
+            setHdmiCecVolumeControlEnabled(
+                    readBooleanSetting(Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED, true));
             return;
         }
+
+        setHdmiCecVolumeControlEnabled(false);
         // Call the vendor handler before the service is disabled.
         invokeVendorCommandListenersOnControlStateChanged(false,
                 HdmiControlManager.CONTROL_STATE_CHANGED_REASON_SETTING);
diff --git a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
index 393e8db..2cae1d6 100644
--- a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
+++ b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
@@ -360,7 +360,7 @@
      * Verify the UID and return the installer package name.
      *
      * @return the package name of the installer, or null if it cannot be determined or it is
-     *     installed via adb.
+     * installed via adb.
      */
     @Nullable
     private String getInstallerPackageName(Intent intent) {
@@ -568,7 +568,10 @@
         try (PackageParser2 parser = mParserSupplier.get()) {
             ParsedPackage pkg = parser.parsePackage(installationPath, 0, false);
             int flags = PackageManager.GET_SIGNING_CERTIFICATES | PackageManager.GET_META_DATA;
-            pkg.setSigningDetails(ParsingPackageUtils.collectCertificates(pkg, false));
+            // APK signatures is already verified elsewhere in PackageManager. We do not need to
+            // verify it again since it could cause a timeout for large APKs.
+            pkg.setSigningDetails(
+                    ParsingPackageUtils.collectCertificates(pkg, /* skipVerify= */ true));
             return PackageInfoUtils.generate(
                     pkg,
                     null,
@@ -709,7 +712,7 @@
 
         // Filter out the rule provider packages that are not system apps.
         List<String> systemAppRuleProviders = new ArrayList<>();
-        for (String ruleProvider: integrityRuleProviders) {
+        for (String ruleProvider : integrityRuleProviders) {
             if (isSystemApp(ruleProvider)) {
                 systemAppRuleProviders.add(ruleProvider);
             }
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index 537ca08..5efc924 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -382,8 +382,8 @@
 
         @Override
         public void apply(SurfaceControl.Transaction t, SurfaceControl sc, long currentPlayTime) {
-            float alpha = ((float) currentPlayTime / getDuration()) * (mToAlpha - mFromAlpha)
-                    + mFromAlpha;
+            final float fraction = getFraction(currentPlayTime);
+            final float alpha = fraction * (mToAlpha - mFromAlpha) + mFromAlpha;
             t.setAlpha(sc, alpha);
         }
 
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 656dca5..1b1898b 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -27,7 +27,6 @@
 
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
 import android.graphics.Rect;
@@ -38,7 +37,6 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.util.ArrayMap;
-import android.util.Log;
 import android.util.Slog;
 import android.view.InputApplicationHandle;
 import android.view.InputChannel;
@@ -138,18 +136,6 @@
 
                 // If there's a drag in flight, provide a pseudo-window to catch drag input
                 final boolean inDrag = mService.mDragDropController.dragDropActiveLocked();
-                final boolean inPositioning =
-                        mService.mTaskPositioningController.isPositioningLocked();
-                if (inPositioning) {
-                    if (DEBUG_TASK_POSITIONING) {
-                        Log.d(TAG_WM, "Inserting window handle for repositioning");
-                    }
-                    mService.mTaskPositioningController.showInputSurface(mInputTransaction,
-                            mDisplayId);
-                } else {
-                    mService.mTaskPositioningController.hideInputSurface(mInputTransaction,
-                            mDisplayId);
-                }
 
                 // Add all windows on the default display.
                 mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag);
diff --git a/services/core/java/com/android/server/wm/LocalAnimationAdapter.java b/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
index 7c1a616..f0629fa 100644
--- a/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
+++ b/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
@@ -130,6 +130,16 @@
          */
         default boolean needsEarlyWakeup() { return false; }
 
+        /**
+         * @return The fraction of the animation, returns 1 if duration is 0.
+         *
+         * @param currentPlayTime The current play time.
+         */
+        default float getFraction(float currentPlayTime) {
+            final float duration = getDuration();
+            return duration > 0 ? currentPlayTime / duration : 1.0f;
+        }
+
         void dump(PrintWriter pw, String prefix);
 
         default void dumpDebug(ProtoOutputStream proto, long fieldId) {
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index 86e0818..90936ef 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -646,8 +646,8 @@
                     @Override
                     public void apply(SurfaceControl.Transaction t, SurfaceControl leash,
                         long currentPlayTime) {
-                        float fraction = (float)currentPlayTime / (float)getDuration();
-                        int color = (Integer) va.evaluate(fraction, startColor, endColor);
+                        final float fraction = getFraction(currentPlayTime);
+                        final int color = (Integer) va.evaluate(fraction, startColor, endColor);
                         Color middleColor = Color.valueOf(color);
                         rgbTmpFloat[0] = middleColor.red();
                         rgbTmpFloat[1] = middleColor.green();
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index be0d6f8..c68b660 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -53,7 +53,6 @@
 import android.view.InputEvent;
 import android.view.InputWindowHandle;
 import android.view.MotionEvent;
-import android.view.SurfaceControl;
 import android.view.WindowManager;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -268,9 +267,7 @@
         mDisplayContent.getDisplayRotation().pause();
 
         // Notify InputMonitor to take mDragWindowHandle.
-        final SurfaceControl.Transaction t = mService.mTransactionFactory.get();
-        mDisplayContent.getInputMonitor().updateInputWindowsImmediately(t);
-        t.syncInputWindows().apply();
+        mService.mTaskPositioningController.showInputSurface(win.getDisplayId());
 
         final DisplayMetrics displayMetrics = displayContent.getDisplayMetrics();
         mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, displayMetrics);
@@ -301,6 +298,7 @@
             return;
         }
 
+        mService.mTaskPositioningController.hideInputSurface(mDisplayContent.getDisplayId());
         mService.mInputManager.unregisterInputChannel(mServerChannel);
 
         mInputEventReceiver.dispose();
diff --git a/services/core/java/com/android/server/wm/TaskPositioningController.java b/services/core/java/com/android/server/wm/TaskPositioningController.java
index 2d303fa..d343daf 100644
--- a/services/core/java/com/android/server/wm/TaskPositioningController.java
+++ b/services/core/java/com/android/server/wm/TaskPositioningController.java
@@ -55,6 +55,8 @@
         return mTaskPositioner != null;
     }
 
+    final SurfaceControl.Transaction mTransaction;
+
     InputWindowHandle getDragWindowHandleLocked() {
         return mTaskPositioner != null ? mTaskPositioner.mDragWindowHandle : null;
     }
@@ -65,16 +67,18 @@
         mInputManager = inputManager;
         mActivityManager = activityManager;
         mHandler = new Handler(looper);
+        mTransaction = service.mTransactionFactory.get();
     }
 
-    void hideInputSurface(SurfaceControl.Transaction t, int displayId) {
+    void hideInputSurface(int displayId) {
         if (mPositioningDisplay != null && mPositioningDisplay.getDisplayId() == displayId
                 && mInputSurface != null) {
-            t.hide(mInputSurface);
+            mTransaction.hide(mInputSurface);
+            mTransaction.syncInputWindows().apply();
         }
     }
 
-    void showInputSurface(SurfaceControl.Transaction t, int displayId) {
+    void showInputSurface(int displayId) {
         if (mPositioningDisplay == null || mPositioningDisplay.getDisplayId() != displayId) {
             return;
         }
@@ -92,16 +96,17 @@
             return;
         }
 
-        t.show(mInputSurface);
-        t.setInputWindowInfo(mInputSurface, h);
-        t.setLayer(mInputSurface, Integer.MAX_VALUE);
+        mTransaction.show(mInputSurface);
+        mTransaction.setInputWindowInfo(mInputSurface, h);
+        mTransaction.setLayer(mInputSurface, Integer.MAX_VALUE);
 
         final Display display = dc.getDisplay();
         final Point p = new Point();
         display.getRealSize(p);
 
         mTmpClipRect.set(0, 0, p.x, p.y);
-        t.setWindowCrop(mInputSurface, mTmpClipRect);
+        mTransaction.setWindowCrop(mInputSurface, mTmpClipRect);
+        mTransaction.syncInputWindows().apply();
     }
 
     boolean startMovingTask(IWindow window, float startX, float startY) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 706dcba..a3387ab 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2491,6 +2491,23 @@
     }
 
     /**
+     * Expands the given rectangle by the region of window resize handle for freeform window.
+     * @param inOutRect The rectangle to update.
+     */
+    private void adjustRegionInFreefromWindowMode(Rect inOutRect) {
+        if (!inFreeformWindowingMode()) {
+            return;
+        }
+
+        // For freeform windows, we need the touch region to include the whole
+        // surface for the shadows.
+        final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics();
+        final int delta = WindowManagerService.dipToPixel(
+                RESIZE_HANDLE_WIDTH_IN_DP, displayMetrics);
+        inOutRect.inset(-delta, -delta);
+    }
+
+    /**
      * Updates the region for a window in an Activity that was a touch modal. This will limit
      * the outer touch to the activity stack region.
      * @param outRegion The region to update.
@@ -2513,14 +2530,7 @@
                 getRootTask().getDimBounds(mTmpRect);
             }
         }
-        if (inFreeformWindowingMode()) {
-            // For freeform windows, we need the touch region to include the whole
-            // surface for the shadows.
-            final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics();
-            final int delta = WindowManagerService.dipToPixel(
-                    RESIZE_HANDLE_WIDTH_IN_DP, displayMetrics);
-            mTmpRect.inset(-delta, -delta);
-        }
+        adjustRegionInFreefromWindowMode(mTmpRect);
         outRegion.set(mTmpRect);
         cropRegionToStackBoundsIfNeeded(outRegion);
     }
@@ -3335,7 +3345,7 @@
         }
 
         final ActivityStack stack = task.getStack();
-        if (stack == null) {
+        if (stack == null || inFreeformWindowingMode()) {
             return;
         }
 
@@ -3354,6 +3364,7 @@
         }
 
         stack.getDimBounds(mTmpRect);
+        adjustRegionInFreefromWindowMode(mTmpRect);
         region.op(mTmpRect, Region.Op.INTERSECT);
     }
 
@@ -5595,7 +5606,7 @@
 
         @Override
         public void apply(Transaction t, SurfaceControl leash, long currentPlayTime) {
-            final float fraction = (float) currentPlayTime / getDuration();
+            final float fraction = getFraction(currentPlayTime);
             final float v = mInterpolator.getInterpolation(fraction);
             t.setPosition(leash, mFrom.x + (mTo.x - mFrom.x) * v,
                     mFrom.y + (mTo.y - mFrom.y) * v);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 5d5e424..7e4c8f3 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -7326,13 +7326,23 @@
         return admin != null ? admin.mFactoryResetProtectionPolicy : null;
     }
 
-    private int getFrpManagementAgentUidOrThrow() {
+    private int getFrpManagementAgentUid() {
         PersistentDataBlockManagerInternal pdb = mInjector.getPersistentDataBlockManagerInternal();
-        if ((pdb == null) || (pdb.getAllowedUid() == -1)) {
+        return pdb != null ? pdb.getAllowedUid() : -1;
+    }
+
+    private int getFrpManagementAgentUidOrThrow() {
+        int uid = getFrpManagementAgentUid();
+        if (uid == -1) {
             throw new UnsupportedOperationException(
                     "The persistent data block service is not supported on this device");
         }
-        return pdb.getAllowedUid();
+        return uid;
+    }
+
+    @Override
+    public boolean isFactoryResetProtectionPolicySupported() {
+        return getFrpManagementAgentUid() != -1;
     }
 
     @Override
diff --git a/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java b/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java
index fea61aa..dfe75ed 100644
--- a/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java
@@ -30,10 +30,13 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import static org.robolectric.Shadows.shadowOf;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.expectThrows;
 
 import android.app.backup.BackupManager;
@@ -86,6 +89,7 @@
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -104,6 +108,7 @@
     private static final String TAG = "BMSTest";
     private static final String PACKAGE_1 = "some.package.1";
     private static final String PACKAGE_2 = "some.package.2";
+    private static final String USER_FACING_PACKAGE = "user.facing.package";
     private static final int USER_ID = 10;
 
     @Mock private TransportManager mTransportManager;
@@ -1186,6 +1191,47 @@
                 eq(packageTrackingReceiver), eq(UserHandle.of(USER_ID)), any(), any(), any());
     }
 
+    @Test
+    public void testFilterUserFacingPackages_shouldSkipUserFacing_filtersUserFacing() {
+        List<PackageInfo> packages = Arrays.asList(getPackageInfo(USER_FACING_PACKAGE),
+                getPackageInfo(PACKAGE_1));
+        UserBackupManagerService backupManagerService = spy(
+                createUserBackupManagerServiceAndRunTasks());
+        when(backupManagerService.shouldSkipUserFacingData()).thenReturn(true);
+        when(backupManagerService.shouldSkipPackage(eq(USER_FACING_PACKAGE))).thenReturn(true);
+
+        List<PackageInfo> filteredPackages = backupManagerService.filterUserFacingPackages(
+                packages);
+
+        assertFalse(containsPackage(filteredPackages, USER_FACING_PACKAGE));
+        assertTrue(containsPackage(filteredPackages, PACKAGE_1));
+    }
+
+    @Test
+    public void testFilterUserFacingPackages_shouldNotSkipUserFacing_doesNotFilterUserFacing() {
+        List<PackageInfo> packages = Arrays.asList(getPackageInfo(USER_FACING_PACKAGE),
+                getPackageInfo(PACKAGE_1));
+        UserBackupManagerService backupManagerService = spy(
+                createUserBackupManagerServiceAndRunTasks());
+        when(backupManagerService.shouldSkipUserFacingData()).thenReturn(false);
+        when(backupManagerService.shouldSkipPackage(eq(USER_FACING_PACKAGE))).thenReturn(true);
+
+        List<PackageInfo> filteredPackages = backupManagerService.filterUserFacingPackages(
+                packages);
+
+        assertTrue(containsPackage(filteredPackages, USER_FACING_PACKAGE));
+        assertTrue(containsPackage(filteredPackages, PACKAGE_1));
+    }
+
+    private static boolean containsPackage(List<PackageInfo> packages, String targetPackage) {
+        for (PackageInfo packageInfo : packages) {
+            if (targetPackage.equals(packageInfo.packageName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private UserBackupManagerService createUserBackupManagerServiceAndRunTasks() {
         return BackupManagerServiceTestUtils.createUserBackupManagerServiceAndRunTasks(
                 USER_ID, mContext, mBackupThread, mBaseStateDir, mDataDir, mTransportManager);
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
index a587029..28887fd 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
@@ -24,6 +24,7 @@
 import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_2;
 import static com.android.server.hdmi.Constants.ADDR_TUNER_1;
 import static com.android.server.hdmi.Constants.ADDR_TV;
+import static com.android.server.hdmi.Constants.MESSAGE_GIVE_AUDIO_STATUS;
 import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
 import static com.android.server.hdmi.HdmiControlService.STANDBY_SCREEN_OFF;
 
@@ -47,6 +48,7 @@
 import org.junit.runners.JUnit4;
 
 import java.util.ArrayList;
+
 @SmallTest
 @RunWith(JUnit4.class)
 /** Tests for {@link HdmiCecLocalDeviceAudioSystem} class. */
@@ -167,6 +169,8 @@
                 }
             };
 
+        mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+
         mMyLooper = mTestLooper.getLooper();
         mHdmiCecLocalDeviceAudioSystem = new HdmiCecLocalDeviceAudioSystem(mHdmiControlService);
         mHdmiCecLocalDevicePlayback = new HdmiCecLocalDevicePlayback(mHdmiControlService) {
@@ -717,4 +721,112 @@
         mHdmiCecLocalDeviceAudioSystem.onHotplug(0, false);
         assertThat(mWokenUp).isFalse();
     }
+
+    @Test
+    public void giveAudioStatus_volumeEnabled() {
+        mMusicVolume = 50;
+        mMusicMaxVolume = 100;
+        mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+        mHdmiCecLocalDeviceAudioSystem.setSystemAudioControlFeatureEnabled(true);
+
+        int volume = mHdmiControlService.getAudioManager()
+                .getStreamVolume(AudioManager.STREAM_MUSIC);
+        boolean mute = mHdmiControlService.getAudioManager()
+                .isStreamMute(AudioManager.STREAM_MUSIC);
+        int maxVolume = mHdmiControlService.getAudioManager()
+                .getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+        int scaledVolume = VolumeControlAction.scaleToCecVolume(volume, maxVolume);
+        HdmiCecMessage expected = HdmiCecMessageBuilder.buildReportAudioStatus(ADDR_AUDIO_SYSTEM,
+                ADDR_TV, scaledVolume, mute);
+        HdmiCecMessage featureAbort = HdmiCecMessageBuilder.buildFeatureAbortCommand(
+                ADDR_AUDIO_SYSTEM, ADDR_TV, MESSAGE_GIVE_AUDIO_STATUS, Constants.ABORT_REFUSED);
+
+        HdmiCecMessage giveAudioStatus = HdmiCecMessageBuilder.buildGiveAudioStatus(ADDR_TV,
+                ADDR_AUDIO_SYSTEM);
+        mNativeWrapper.clearResultMessages();
+        boolean handled = mHdmiCecLocalDeviceAudioSystem.handleGiveAudioStatus(giveAudioStatus);
+        mTestLooper.dispatchAll();
+
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected);
+        assertThat(mNativeWrapper.getResultMessages()).doesNotContain(featureAbort);
+        assertThat(handled).isTrue();
+    }
+
+    @Test
+    public void giveAudioStatus_volumeDisabled() {
+        mMusicVolume = 50;
+        mMusicMaxVolume = 100;
+        mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
+        mHdmiCecLocalDeviceAudioSystem.setSystemAudioControlFeatureEnabled(true);
+
+        int volume = mHdmiControlService.getAudioManager()
+                .getStreamVolume(AudioManager.STREAM_MUSIC);
+        boolean mute = mHdmiControlService.getAudioManager()
+                .isStreamMute(AudioManager.STREAM_MUSIC);
+        int maxVolume = mHdmiControlService.getAudioManager()
+                .getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+        int scaledVolume = VolumeControlAction.scaleToCecVolume(volume, maxVolume);
+        HdmiCecMessage unexpected = HdmiCecMessageBuilder.buildReportAudioStatus(ADDR_AUDIO_SYSTEM,
+                ADDR_TV, scaledVolume, mute);
+        HdmiCecMessage featureAbort = HdmiCecMessageBuilder.buildFeatureAbortCommand(
+                ADDR_AUDIO_SYSTEM, ADDR_TV, MESSAGE_GIVE_AUDIO_STATUS, Constants.ABORT_REFUSED);
+
+        HdmiCecMessage giveAudioStatus = HdmiCecMessageBuilder.buildGiveAudioStatus(ADDR_TV,
+                ADDR_AUDIO_SYSTEM);
+        mNativeWrapper.clearResultMessages();
+        boolean handled = mHdmiCecLocalDeviceAudioSystem.handleGiveAudioStatus(giveAudioStatus);
+        mTestLooper.dispatchAll();
+
+        assertThat(mNativeWrapper.getResultMessages()).contains(featureAbort);
+        assertThat(mNativeWrapper.getResultMessages()).doesNotContain(unexpected);
+        assertThat(handled).isTrue();
+    }
+
+    @Test
+    public void reportAudioStatus_volumeEnabled() {
+        mMusicVolume = 50;
+        mMusicMaxVolume = 100;
+        mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+        mHdmiCecLocalDeviceAudioSystem.setSystemAudioControlFeatureEnabled(true);
+
+        int volume = mHdmiControlService.getAudioManager()
+                .getStreamVolume(AudioManager.STREAM_MUSIC);
+        boolean mute = mHdmiControlService.getAudioManager()
+                .isStreamMute(AudioManager.STREAM_MUSIC);
+        int maxVolume = mHdmiControlService.getAudioManager()
+                .getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+        int scaledVolume = VolumeControlAction.scaleToCecVolume(volume, maxVolume);
+        HdmiCecMessage expected = HdmiCecMessageBuilder.buildReportAudioStatus(ADDR_AUDIO_SYSTEM,
+                ADDR_TV, scaledVolume, mute);
+
+        mNativeWrapper.clearResultMessages();
+        mHdmiCecLocalDeviceAudioSystem.reportAudioStatus(ADDR_TV);
+        mTestLooper.dispatchAll();
+
+        assertThat(mNativeWrapper.getResultMessages()).contains(expected);
+    }
+
+    @Test
+    public void reportAudioStatus_volumeDisabled() {
+        mMusicVolume = 50;
+        mMusicMaxVolume = 100;
+        mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
+        mHdmiCecLocalDeviceAudioSystem.setSystemAudioControlFeatureEnabled(true);
+
+        int volume = mHdmiControlService.getAudioManager()
+                .getStreamVolume(AudioManager.STREAM_MUSIC);
+        boolean mute = mHdmiControlService.getAudioManager()
+                .isStreamMute(AudioManager.STREAM_MUSIC);
+        int maxVolume = mHdmiControlService.getAudioManager()
+                .getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+        int scaledVolume = VolumeControlAction.scaleToCecVolume(volume, maxVolume);
+        HdmiCecMessage unexpected = HdmiCecMessageBuilder.buildReportAudioStatus(ADDR_AUDIO_SYSTEM,
+                ADDR_TV, scaledVolume, mute);
+
+        mNativeWrapper.clearResultMessages();
+        mHdmiCecLocalDeviceAudioSystem.reportAudioStatus(ADDR_TV);
+        mTestLooper.dispatchAll();
+
+        assertThat(mNativeWrapper.getResultMessages()).doesNotContain(unexpected);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
index f72d622..b8394e3 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
@@ -22,6 +22,7 @@
 
 import android.os.Looper;
 import android.os.test.TestLooper;
+import android.view.KeyEvent;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -153,4 +154,75 @@
         mHdmiCecLocalDevicePlayback.onHotplug(0, false);
         assertThat(mWokenUp).isFalse();
     }
+
+    @Test
+    @Ignore("b/151147315")
+    public void sendVolumeKeyEvent_up_volumeEnabled() {
+        mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+        mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, true);
+        mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, false);
+
+        assertThat(hasSendKeyAction()).isTrue();
+    }
+
+    @Test
+    @Ignore("b/151147315")
+    public void sendVolumeKeyEvent_down_volumeEnabled() {
+        mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+        mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_DOWN, true);
+        mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_DOWN, false);
+
+        assertThat(hasSendKeyAction()).isTrue();
+    }
+
+    @Test
+    @Ignore("b/151147315")
+    public void sendVolumeKeyEvent_mute_volumeEnabled() {
+        mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+        mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_MUTE, true);
+        mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_MUTE, false);
+
+        assertThat(hasSendKeyAction()).isTrue();
+    }
+
+    @Test
+    @Ignore("b/151147315")
+    public void sendVolumeKeyEvent_up_volumeDisabled() {
+        mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
+        mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, true);
+        mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, false);
+
+        assertThat(hasSendKeyAction()).isFalse();
+    }
+
+    @Test
+    @Ignore("b/151147315")
+    public void sendVolumeKeyEvent_down_volumeDisabled() {
+        mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
+        mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_DOWN, true);
+        mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_DOWN, false);
+
+        assertThat(hasSendKeyAction()).isFalse();
+    }
+
+    @Test
+    @Ignore("b/151147315")
+    public void sendVolumeKeyEvent_mute_volumeDisabled() {
+        mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
+        mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_MUTE, true);
+        mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_MUTE, false);
+
+        assertThat(hasSendKeyAction()).isFalse();
+    }
+
+    private boolean hasSendKeyAction() {
+        boolean match = false;
+        for (HdmiCecFeatureAction action : mHdmiCecLocalDevicePlayback.mActions) {
+            if (action instanceof SendKeyAction) {
+                match = true;
+                break;
+            }
+        }
+        return match;
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
index 039b904..e0bada31 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
@@ -19,6 +19,7 @@
 
 import static com.android.server.hdmi.Constants.ADDR_AUDIO_SYSTEM;
 import static com.android.server.hdmi.Constants.ADDR_BROADCAST;
+import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_1;
 import static com.android.server.hdmi.Constants.ADDR_TV;
 import static com.android.server.hdmi.Constants.ADDR_UNREGISTERED;
 import static com.android.server.hdmi.Constants.MESSAGE_DEVICE_VENDOR_ID;
@@ -185,4 +186,64 @@
                 HdmiCecMessageBuilder.buildStandby(ADDR_TV, ADDR_AUDIO_SYSTEM));
         assertTrue(mStandbyMessageReceived);
     }
+
+    @Test
+    public void handleUserControlPressed_volumeUp() {
+        mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+        boolean result = mHdmiLocalDevice.handleUserControlPressed(
+                HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
+                        HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP));
+
+        assertTrue(result);
+    }
+
+    @Test
+    public void handleUserControlPressed_volumeDown() {
+        mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+        boolean result = mHdmiLocalDevice.handleUserControlPressed(
+                HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
+                        HdmiCecKeycode.CEC_KEYCODE_VOLUME_DOWN));
+
+        assertTrue(result);
+    }
+
+    @Test
+    public void handleUserControlPressed_volumeMute() {
+        mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+        boolean result = mHdmiLocalDevice.handleUserControlPressed(
+                HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
+                        HdmiCecKeycode.CEC_KEYCODE_MUTE));
+
+        assertTrue(result);
+    }
+
+    @Test
+    public void handleUserControlPressed_volumeUp_disabled() {
+        mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
+        boolean result = mHdmiLocalDevice.handleUserControlPressed(
+                HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
+                        HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP));
+
+        assertFalse(result);
+    }
+
+    @Test
+    public void handleUserControlPressed_volumeDown_disabled() {
+        mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
+        boolean result = mHdmiLocalDevice.handleUserControlPressed(
+                HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
+                        HdmiCecKeycode.CEC_KEYCODE_VOLUME_DOWN));
+
+        assertFalse(result);
+    }
+
+    @Test
+    public void handleUserControlPressed_volumeMute_disabled() {
+        mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
+        boolean result = mHdmiLocalDevice.handleUserControlPressed(
+                HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
+                        HdmiCecKeycode.CEC_KEYCODE_MUTE));
+
+        assertFalse(result);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
index fa19814..7af7a23 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
@@ -252,4 +252,13 @@
         assertThat(mHdmiControlService.getPowerStatus()).isEqualTo(
                 HdmiControlManager.POWER_STATUS_STANDBY);
     }
+
+    @Test
+    public void setAndGetCecVolumeControlEnabled_isApi() {
+        mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
+        assertThat(mHdmiControlService.isHdmiCecVolumeControlEnabled()).isFalse();
+
+        mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+        assertThat(mHdmiControlService.isHdmiCecVolumeControlEnabled()).isTrue();
+    }
 }