Merge "cec: Reset system audio mode status carefully [2/2]"
diff --git a/ProtoLibraries.bp b/ProtoLibraries.bp
index a0944d4..18c562b 100644
--- a/ProtoLibraries.bp
+++ b/ProtoLibraries.bp
@@ -21,10 +21,6 @@
         "soong_zip",
     ],
 
-    tool_files: [
-        ":libprotobuf-internal-protos",
-    ],
-
     cmd: "mkdir -p $(genDir)/$(in) " +
         "&& $(location aprotoc) " +
         "  --plugin=$(location protoc-gen-javastream) " +
@@ -43,6 +39,11 @@
         "libs/incident/**/*.proto",
         ":service-permission-streaming-proto-sources",
     ],
+
+    data: [
+        ":libprotobuf-internal-protos",
+    ],
+
     output_extension: "srcjar",
 }
 
@@ -54,10 +55,6 @@
         "protoc-gen-cppstream",
     ],
 
-    tool_files: [
-        ":libprotobuf-internal-protos",
-    ],
-
     cmd: "mkdir -p $(genDir) " +
         "&& $(location aprotoc) " +
         "  --plugin=$(location protoc-gen-cppstream) " +
@@ -75,6 +72,10 @@
         ":service-permission-streaming-proto-sources",
     ],
 
+    data: [
+        ":libprotobuf-internal-protos",
+    ],
+
     output_extension: "proto.h",
 }
 
diff --git a/core/java/android/database/sqlite/package.html b/core/java/android/database/sqlite/package.html
index 6ececa2..71b8f3f 100644
--- a/core/java/android/database/sqlite/package.html
+++ b/core/java/android/database/sqlite/package.html
@@ -20,6 +20,9 @@
 <p>The version of SQLite depends on the version of Android. See the following table:
 <table style="width:auto;">
   <tr><th>Android API</th><th>SQLite Version</th></tr>
+  <tr><td>API 34</td><td>3.39</td></tr>
+  <tr><td>API 33</td><td>3.32</td></tr>
+  <tr><td>API 32</td><td>3.32</td></tr>
   <tr><td>API 31</td><td>3.32</td></tr>
   <tr><td>API 30</td><td>3.28</td></tr>
   <tr><td>API 28</td><td>3.22</td></tr>
diff --git a/core/java/android/net/ITetheringStatsProvider.aidl b/core/java/android/net/ITetheringStatsProvider.aidl
deleted file mode 100644
index da0bf4c..0000000
--- a/core/java/android/net/ITetheringStatsProvider.aidl
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this 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.NetworkStats;
-
-/**
- * Interface for NetworkManagementService to query tethering statistics and set data limits.
- *
- * TODO: this does not really need to be an interface since Tethering runs in the same process
- * as NetworkManagementService. Consider refactoring Tethering to use direct access to
- * NetworkManagementService instead of using INetworkManagementService, and then deleting this
- * interface.
- *
- * @hide
- */
-interface ITetheringStatsProvider {
-    // Returns cumulative statistics for all tethering sessions since boot, on all upstreams.
-    // @code {how} is one of the NetworkStats.STATS_PER_* constants. If {@code how} is
-    // {@code STATS_PER_IFACE}, the provider should not include any traffic that is already
-    // counted by kernel interface counters.
-    NetworkStats getTetherStats(int how);
-
-    // Sets the interface quota for the specified upstream interface. This is defined as the number
-    // of bytes, starting from zero and counting from now, after which data should stop being
-    // forwarded to/from the specified upstream. A value of QUOTA_UNLIMITED means there is no limit.
-    void setInterfaceQuota(String iface, long quotaBytes);
-
-    // Indicates that no data usage limit is set.
-    const int QUOTA_UNLIMITED = -1;
-}
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 91d6a9b..ec69e2a 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -19,7 +19,6 @@
 
 import android.net.InterfaceConfiguration;
 import android.net.INetworkManagementEventObserver;
-import android.net.ITetheringStatsProvider;
 import android.net.Network;
 import android.net.NetworkStats;
 import android.net.RouteInfo;
@@ -143,14 +142,6 @@
     void startTethering(in String[] dhcpRanges);
 
     /**
-     * Start tethering services with the specified dhcp server range and
-     * DNS proxy config.
-     * {@code boolean} is used to control legacy DNS proxy server.
-     * {@code String[]} is a set of start end pairs defining the ranges.
-     */
-    void startTetheringWithConfiguration(boolean usingLegacyDnsProxy, in String[] dhcpRanges);
-
-    /**
      * Stop currently running tethering services
      */
     @UnsupportedAppUsage
@@ -181,23 +172,6 @@
     String[] listTetheredInterfaces();
 
     /**
-     * Returns the list of DNS forwarders (in order of priority)
-     */
-    String[] getDnsForwarders();
-
-    /**
-     * Enables unidirectional packet forwarding from {@code fromIface} to
-     * {@code toIface}.
-     */
-    void startInterfaceForwarding(String fromIface, String toIface);
-
-    /**
-     * Disables unidirectional packet forwarding from {@code fromIface} to
-     * {@code toIface}.
-     */
-    void stopInterfaceForwarding(String fromIface, String toIface);
-
-    /**
      *  Enables Network Address Translation between two interfaces.
      *  The address and netmask of the external interface is used for
      *  the NAT'ed network.
@@ -212,42 +186,10 @@
     void disableNat(String internalInterface, String externalInterface);
 
     /**
-     * Registers a {@code ITetheringStatsProvider} to provide tethering statistics.
-     * All registered providers will be called in order, and their results will be added together.
-     * Netd is always registered as a tethering stats provider.
-     */
-    void registerTetheringStatsProvider(ITetheringStatsProvider provider, String name);
-
-    /**
-     * Unregisters a previously-registered {@code ITetheringStatsProvider}.
-     */
-    void unregisterTetheringStatsProvider(ITetheringStatsProvider provider);
-
-    /**
-     * Reports that a tethering provider has reached a data limit.
-     *
-     * Currently triggers a global alert, which causes NetworkStatsService to poll counters and
-     * re-evaluate data usage.
-     *
-     * This does not take an interface name because:
-     * 1. The tethering offload stats provider cannot reliably determine the interface on which the
-     *    limit was reached, because the HAL does not provide it.
-     * 2. Firing an interface-specific alert instead of a global alert isn't really useful since in
-     *    all cases of interest, the system responds to both in the same way - it polls stats, and
-     *    then notifies NetworkPolicyManagerService of the fact.
-     */
-    void tetherLimitReached(ITetheringStatsProvider provider);
-
-    /**
      ** DATA USAGE RELATED
      **/
 
     /**
-     * Return summary of network statistics all tethering interfaces.
-     */
-    NetworkStats getNetworkStatsTethering(int how);
-
-    /**
      * Set quota for an interface.
      */
     void setInterfaceQuota(String iface, long quotaBytes);
@@ -268,11 +210,6 @@
     void removeInterfaceAlert(String iface);
 
     /**
-     * Set alert across all interfaces.
-     */
-    void setGlobalAlert(long alertBytes);
-
-    /**
      * Control network activity of a UID over interfaces with a quota limit.
      */
     void setUidOnMeteredNetworkDenylist(int uid, boolean enable);
@@ -289,7 +226,6 @@
 
     void setFirewallEnabled(boolean enabled);
     boolean isFirewallEnabled();
-    void setFirewallInterfaceRule(String iface, boolean allow);
     void setFirewallUidRule(int chain, int uid, int rule);
     void setFirewallUidRules(int chain, in int[] uids, in int[] rules);
     void setFirewallChainEnabled(int chain, boolean enable);
@@ -304,9 +240,5 @@
      */
     void denyProtect(int uid);
 
-    void addInterfaceToLocalNetwork(String iface, in List<RouteInfo> routes);
-    void removeInterfaceFromLocalNetwork(String iface);
-    int removeRoutesFromLocalNetwork(in List<RouteInfo> routes);
-
     boolean isNetworkRestricted(int uid);
 }
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 3d5abb3..f9307b4b 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -597,12 +597,9 @@
 
     @Override
     public boolean equals(@Nullable Object obj) {
-        try {
-            if (obj != null) {
-                UserHandle other = (UserHandle)obj;
-                return mHandle == other.mHandle;
-            }
-        } catch (ClassCastException ignore) {
+        if (obj instanceof UserHandle) {
+            UserHandle other = (UserHandle) obj;
+            return mHandle == other.mHandle;
         }
         return false;
     }
diff --git a/core/java/android/os/storage/OWNERS b/core/java/android/os/storage/OWNERS
index c80c57c..bf22dcc 100644
--- a/core/java/android/os/storage/OWNERS
+++ b/core/java/android/os/storage/OWNERS
@@ -1,15 +1,19 @@
 # Bug component: 95221
 
+# Please assign new bugs to android-storage-triage@, not to individual people
+
 # Android Storage Team
-abkaur@google.com
-corinac@google.com
+alukin@google.com
+ankitavyas@google.com
 dipankarb@google.com
+gargshivam@google.com
 krishang@google.com
+riyaghai@google.com
 sahanas@google.com
 sergeynv@google.com
+shikhamalhotra@google.com
 shubhisaxena@google.com
 tylersaunders@google.com
 
 maco@google.com
 nandana@google.com
-narayan@google.com
diff --git a/core/java/android/text/style/URLSpan.java b/core/java/android/text/style/URLSpan.java
index eab1ef4..5bd52dd 100644
--- a/core/java/android/text/style/URLSpan.java
+++ b/core/java/android/text/style/URLSpan.java
@@ -106,7 +106,7 @@
         try {
             context.startActivity(intent);
         } catch (ActivityNotFoundException e) {
-            Log.w("URLSpan", "Actvity was not found for intent, " + intent.toString());
+            Log.w("URLSpan", "Activity was not found for intent, " + intent.toString());
         }
     }
 }
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index cd0dd1d..662550b 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -440,12 +440,16 @@
     /**
      * Represents the event of clicking on a {@link android.view.View} like
      * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.
+     * <p>See {@link AccessibilityNodeInfo.AccessibilityAction#ACTION_CLICK} for more
+     * details.
      */
     public static final int TYPE_VIEW_CLICKED = 0x00000001;
 
     /**
      * Represents the event of long clicking on a {@link android.view.View} like
      * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.
+     * <p>See {@link AccessibilityNodeInfo.AccessibilityAction#ACTION_LONG_CLICK} for more
+     * details.
      */
     public static final int TYPE_VIEW_LONG_CLICKED = 0x00000002;
 
@@ -563,6 +567,8 @@
 
     /**
      * Represents the event of a context click on a {@link android.view.View}.
+     * <p>See {@link AccessibilityNodeInfo.AccessibilityAction#ACTION_CONTEXT_CLICK} for more
+     * details.
      */
     public static final int TYPE_VIEW_CONTEXT_CLICKED = 0x00800000;
 
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index a20b2b2..0d49772 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -251,7 +251,7 @@
     /**
      * Action that clicks on the node info.
      *
-     * See {@link AccessibilityAction#ACTION_CLICK}
+     * @see AccessibilityAction#ACTION_CLICK
      */
     public static final int ACTION_CLICK = 0x00000010;
 
@@ -259,6 +259,7 @@
      * Action that long clicks on the node.
      *
      * <p>It does not support coordinate information for anchoring.</p>
+     * @see AccessibilityAction#ACTION_LONG_CLICK
      */
     public static final int ACTION_LONG_CLICK = 0x00000020;
 
@@ -4679,7 +4680,7 @@
      * and handled by custom widgets. i.e. ones that are not part of the UI toolkit. For
      * example, an application may define a custom action for clearing the user history.
      * </li>
-     * <li><strong>Overriden standard actions</strong> - These are actions that override
+     * <li><strong>Overridden standard actions</strong> - These are actions that override
      * standard actions to customize them. For example, an app may add a label to the
      * standard {@link #ACTION_CLICK} action to indicate to the user that this action clears
      * browsing history.
@@ -4729,12 +4730,29 @@
 
         /**
          * Action that clicks on the node info.
+         *
+         * <p>The UI element that implements this should send a
+         * {@link AccessibilityEvent#TYPE_VIEW_CLICKED} event. In the View system,
+         * the default handling of this action when performed by a service is to call
+         * {@link View#performClick()}, and setting a
+         * {@link View#setOnClickListener(View.OnClickListener)} automatically adds this action.
+         *
+         * <p>{@link #isClickable()} should return true if this action is available.
          */
         public static final AccessibilityAction ACTION_CLICK =
                 new AccessibilityAction(AccessibilityNodeInfo.ACTION_CLICK);
 
         /**
          * Action that long clicks on the node.
+         *
+         * <p>The UI element that implements this should send a
+         * {@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED} event. In the View system,
+         * the default handling of this action when performed by a service is to call
+         * {@link View#performLongClick()}, and setting a
+         * {@link View#setOnLongClickListener(View.OnLongClickListener)} automatically adds this
+         * action.
+         *
+         * <p>{@link #isLongClickable()} should return true if this action is available.
          */
         public static final AccessibilityAction ACTION_LONG_CLICK =
                 new AccessibilityAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
@@ -5047,6 +5065,18 @@
 
         /**
          * Action that context clicks the node.
+         *
+         * <p>The UI element that implements this should send a
+         * {@link AccessibilityEvent#TYPE_VIEW_CONTEXT_CLICKED} event. In the View system,
+         * the default handling of this action when performed by a service is to call
+         * {@link View#performContextClick()}, and setting a
+         * {@link View#setOnContextClickListener(View.OnContextClickListener)} automatically adds
+         * this action.
+         *
+         * <p>A context click usually occurs from a mouse pointer right-click or a stylus button
+         * press.
+         *
+         * <p>{@link #isContextClickable()} should return true if this action is available.
          */
         public static final AccessibilityAction ACTION_CONTEXT_CLICK =
                 new AccessibilityAction(R.id.accessibilityActionContextClick);
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 5c3aa96..2a35312 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -359,6 +359,51 @@
  codec to use a previously created {@linkplain #createPersistentInputSurface persistent input
  surface} by calling {@link #setInputSurface}.
 
+ <h4 id=EncoderProfiles><a name="EncoderProfiles"></a>Encoder Profiles</h4>
+ <p>
+ When using an encoder, it is recommended to set the desired codec {@link MediaFormat#KEY_PROFILE
+ profile} during {@link #configure configure()}. (This is only meaningful for
+ {@link MediaFormat#KEY_MIME media formats} for which profiles are defined.)
+ <p>
+ If a profile is not specified during {@code configure}, the encoder will choose a profile for the
+ session based on the available information. We will call this value the <i>default profile</i>.
+ The selection of the default profile is device specific and may not be deterministic
+ (could be ad hoc or even experimental). The encoder may choose a default profile that is not
+ suitable for the intended encoding session, which may result in the encoder ultimately rejecting
+ the session.
+ <p>
+ The encoder may reject the encoding session if the configured (or default if unspecified) profile
+ does not support the codec input (mainly the {@link MediaFormat#KEY_COLOR_FORMAT color format} for
+ video/image codecs, or the {@link MediaFormat#KEY_PCM_ENCODING sample encoding} and the {@link
+ MediaFormat#KEY_CHANNEL_COUNT number of channels} for audio codecs, but also possibly
+ {@link MediaFormat#KEY_WIDTH width}, {@link MediaFormat#KEY_HEIGHT height},
+ {@link MediaFormat#KEY_FRAME_RATE frame rate}, {@link MediaFormat#KEY_BIT_RATE bitrate} or
+ {@link MediaFormat#KEY_SAMPLE_RATE sample rate}.)
+ Alternatively, the encoder may choose to (but is not required to) convert the input to support the
+ selected (or default) profile - or adjust the chosen profile based on the presumed or detected
+ input format - to ensure a successful encoding session. <b>Note</b>: Converting the input to match
+ an incompatible profile will in most cases result in decreased codec performance.
+ <p>
+ To ensure backward compatibility, the following guarantees are provided by Android:
+ <ul>
+ <li>The default video encoder profile always supports 8-bit YUV 4:2:0 color format ({@link
+ CodecCapabilities#COLOR_FormatYUV420Flexible COLOR_FormatYUV420Flexible} and equivalent
+ {@link CodecCapabilities#colorFormats supported formats}) for both Surface and ByteBuffer modes.
+ <li>The default video encoder profile always supports the default 8-bit RGBA color format in
+ Surface mode even if no such formats are enumerated in the {@link CodecCapabilities#colorFormats
+ supported formats}.
+ </ul>
+ <p class=note>
+ <b>Note</b>: the accepted profile can be queried through the {@link #getOutputFormat output
+ format} of the encoder after {@code configure} to allow applications to set up their
+ codec input to a format supported by the encoder profile.
+ <p>
+ <b>Implication:</b>
+ <ul>
+ <li>Applications that want to encode 4:2:2, 4:4:4, 10+ bit or HDR video input <b>MUST</b> configure
+ a suitable profile for encoders.
+ </ul>
+
  <h4 id=CSD><a name="CSD"></a>Codec-specific Data</h4>
  <p>
  Some formats, notably AAC audio and MPEG4, H.264 and H.265 video formats require the actual data
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 193544e..88b9643 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -934,13 +934,25 @@
                     }
                 }
                 levelCaps = createFromProfileLevel(mMime, profile, maxLevel);
-                // remove profile from this format otherwise levelCaps.isFormatSupported will
-                // get into this same conditon and loop forever.
-                Map<String, Object> mapWithoutProfile = new HashMap<>(map);
-                mapWithoutProfile.remove(MediaFormat.KEY_PROFILE);
-                MediaFormat formatWithoutProfile = new MediaFormat(mapWithoutProfile);
-                if (levelCaps != null && !levelCaps.isFormatSupported(formatWithoutProfile)) {
-                    return false;
+                // We must remove the profile from this format otherwise levelCaps.isFormatSupported
+                // will get into this same condition and loop forever. Furthermore, since levelCaps
+                // does not contain features and bitrate specific keys, keep only keys relevant for
+                // a level check.
+                Map<String, Object> levelCriticalFormatMap = new HashMap<>(map);
+                final Set<String> criticalKeys =
+                    isVideo() ? VideoCapabilities.VIDEO_LEVEL_CRITICAL_FORMAT_KEYS :
+                    isAudio() ? AudioCapabilities.AUDIO_LEVEL_CRITICAL_FORMAT_KEYS :
+                    null;
+
+                // critical keys will always contain KEY_MIME, but should also contain others to be
+                // meaningful
+                if (criticalKeys != null && criticalKeys.size() > 1 && levelCaps != null) {
+                    levelCriticalFormatMap.keySet().retainAll(criticalKeys);
+
+                    MediaFormat levelCriticalFormat = new MediaFormat(levelCriticalFormatMap);
+                    if (!levelCaps.isFormatSupported(levelCriticalFormat)) {
+                        return false;
+                    }
                 }
             }
             if (mAudioCaps != null && !mAudioCaps.supportsFormat(format)) {
@@ -1633,6 +1645,16 @@
             }
         }
 
+        /* package private */
+        // must not contain KEY_PROFILE
+        static final Set<String> AUDIO_LEVEL_CRITICAL_FORMAT_KEYS = Set.of(
+                // We don't set level-specific limits for audio codecs today. Key candidates would
+                // be sample rate, bit rate or channel count.
+                // MediaFormat.KEY_SAMPLE_RATE,
+                // MediaFormat.KEY_CHANNEL_COUNT,
+                // MediaFormat.KEY_BIT_RATE,
+                MediaFormat.KEY_MIME);
+
         /** @hide */
         public boolean supportsFormat(MediaFormat format) {
             Map<String, Object> map = format.getMap();
@@ -2357,6 +2379,15 @@
             return ok;
         }
 
+        /* package private */
+        // must not contain KEY_PROFILE
+        static final Set<String> VIDEO_LEVEL_CRITICAL_FORMAT_KEYS = Set.of(
+                MediaFormat.KEY_WIDTH,
+                MediaFormat.KEY_HEIGHT,
+                MediaFormat.KEY_FRAME_RATE,
+                MediaFormat.KEY_BIT_RATE,
+                MediaFormat.KEY_MIME);
+
         /**
          * @hide
          * @throws java.lang.ClassCastException */
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index c33d206..6149ec4 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -1097,11 +1097,14 @@
      * may fail if other parameters are not compatible with the desired
      * profile or if the desired profile is not supported, but it may also
      * fail silently (where the encoder ends up using a different, compatible profile.)
+     * <p>
+     * It is recommended that the profile is set for all encoders. For more information, see
+     * the <i>Encoder Profiles</i> section of the {@link MediaCodec} API reference.
      * <p class="note">
      * <strong>Note:</strong> Codecs are free to use all the available
      * coding tools at the specified profile, but may ultimately choose to not do so.
      * <p class="note">
-     * <strong>Note:</strong> When configuring video encoders, profile must be
+     * <strong>Note:</strong> When configuring video encoders, profile (if set) must be
      * set together with {@link #KEY_LEVEL level}.
      *
      * @see MediaCodecInfo.CodecCapabilities#profileLevels
diff --git a/packages/SettingsLib/src/com/android/settingslib/connectivity/OWNERS b/packages/SettingsLib/src/com/android/settingslib/connectivity/OWNERS
index c88ed8e..9f15c1b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/connectivity/OWNERS
+++ b/packages/SettingsLib/src/com/android/settingslib/connectivity/OWNERS
@@ -2,7 +2,6 @@
 andychou@google.com
 arcwang@google.com
 changbetty@google.com
-goldmanj@google.com
 qal@google.com
 wengsu@google.com
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/qrcode/OWNERS b/packages/SettingsLib/src/com/android/settingslib/qrcode/OWNERS
index 61c73fb..372eb81 100644
--- a/packages/SettingsLib/src/com/android/settingslib/qrcode/OWNERS
+++ b/packages/SettingsLib/src/com/android/settingslib/qrcode/OWNERS
@@ -1,7 +1,6 @@
 # Default reviewers for this and subdirectories.
 bonianchen@google.com
 changbetty@google.com
-goldmanj@google.com
 wengsu@google.com
 zoeychen@google.com
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
index fd986e5..21eb35a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
@@ -87,7 +87,13 @@
             // Fallback for platforms that do not need friction icon resources.
             frictionSld = null;
         }
-        return frictionSld != null ? (StateListDrawable) frictionSld.getDrawable(0) : null;
+        if (frictionSld != null) {
+            StateListDrawable val = (StateListDrawable) frictionSld.getDrawable(0);
+            frictionSld.recycle();
+            return val;
+        } else {
+            return null;
+        }
     }
 
     // Used for fake pref.
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/OWNERS b/packages/SettingsLib/src/com/android/settingslib/wifi/OWNERS
index f3b600c..b9449ac 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/OWNERS
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/OWNERS
@@ -3,7 +3,6 @@
 arcwang@google.com
 asapperstein@google.com
 changbetty@google.com
-goldmanj@google.com
 qal@google.com
 wengsu@google.com
 
diff --git a/packages/SystemUI/plugin_core/Android.bp b/packages/SystemUI/plugin_core/Android.bp
index 34d31d9..4e39f1a 100644
--- a/packages/SystemUI/plugin_core/Android.bp
+++ b/packages/SystemUI/plugin_core/Android.bp
@@ -25,6 +25,9 @@
     sdk_version: "current",
     name: "PluginCoreLib",
     srcs: ["src/**/*.java"],
+    optimize: {
+        proguard_flags_files: ["proguard.flags"],
+    },
 
     // Enforce that the library is built against java 8 so that there are
     // no compatibility issues with launcher
diff --git a/packages/SystemUI/plugin_core/proguard.flags b/packages/SystemUI/plugin_core/proguard.flags
new file mode 100644
index 0000000..6240898
--- /dev/null
+++ b/packages/SystemUI/plugin_core/proguard.flags
@@ -0,0 +1,11 @@
+# R8's full mode is a bit more aggressive in stripping annotations, but the
+# SystemUI plugin architecture requires these annotations at runtime. The
+# following rules are the minimal set necessary to ensure compatibility.
+# For more details, see:
+# https://r8.googlesource.com/r8/+/refs/heads/master/compatibility-faq.md#r8-full-mode
+-keepattributes RuntimeVisible*Annotation*,AnnotationDefault
+
+-keep interface com.android.systemui.plugins.annotations.** {
+    *;
+}
+-keep,allowshrinking,allowoptimization,allowobfuscation,allowaccessmodification @com.android.systemui.plugins.annotations.** class *
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/biometrics/OWNERS
index adb10f0..5420c37 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/OWNERS
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/OWNERS
@@ -1,4 +1,5 @@
 set noparent
 
+# Bug component: 879035
 include /services/core/java/com/android/server/biometrics/OWNERS
 beverlyt@google.com
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 17cdfdb2..a027e04 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -37,8 +37,6 @@
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
 
-import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT;
-
 import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.content.Context;
@@ -46,15 +44,12 @@
 import android.net.INetd;
 import android.net.INetdUnsolicitedEventListener;
 import android.net.INetworkManagementEventObserver;
-import android.net.ITetheringStatsProvider;
 import android.net.InetAddresses;
 import android.net.InterfaceConfiguration;
 import android.net.InterfaceConfigurationParcel;
 import android.net.IpPrefix;
 import android.net.LinkAddress;
 import android.net.NetworkPolicyManager;
-import android.net.NetworkStack;
-import android.net.NetworkStats;
 import android.net.RouteInfo;
 import android.net.util.NetdService;
 import android.os.BatteryStats;
@@ -80,26 +75,18 @@
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.HexDump;
-import com.android.internal.util.Preconditions;
 import com.android.net.module.util.NetdUtils;
 import com.android.net.module.util.NetdUtils.ModifyOperation;
+import com.android.net.module.util.PermissionUtils;
 
 import com.google.android.collect.Maps;
 
-import java.io.BufferedReader;
-import java.io.DataInputStream;
 import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
 import java.io.PrintWriter;
 import java.net.InetAddress;
-import java.net.InterfaceAddress;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 
 /**
  * @hide
@@ -129,13 +116,6 @@
     private static final String TAG = "NetworkManagement";
     private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
 
-    private static final int MAX_UID_RANGES_PER_COMMAND = 10;
-
-    static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1;
-
-    static final boolean MODIFY_OPERATION_ADD = true;
-    static final boolean MODIFY_OPERATION_REMOVE = false;
-
     /**
      * Binder context for this service
      */
@@ -154,10 +134,6 @@
     private final RemoteCallbackList<INetworkManagementEventObserver> mObservers =
             new RemoteCallbackList<>();
 
-    @GuardedBy("mTetheringStatsProviders")
-    private final HashMap<ITetheringStatsProvider, String>
-            mTetheringStatsProviders = Maps.newHashMap();
-
     /**
      * If both locks need to be held, then they should be obtained in the order:
      * first {@link #mQuotaLock} and then {@link #mRulesLock}.
@@ -182,35 +158,35 @@
     private SparseIntArray mUidCleartextPolicy = new SparseIntArray();
     /** Set of UIDs that are to be blocked/allowed by firewall controller. */
     @GuardedBy("mRulesLock")
-    private SparseIntArray mUidFirewallRules = new SparseIntArray();
+    private final SparseIntArray mUidFirewallRules = new SparseIntArray();
     /**
      * Set of UIDs that are to be blocked/allowed by firewall controller.  This set of Ids matches
      * to application idles.
      */
     @GuardedBy("mRulesLock")
-    private SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
+    private final SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
     /**
      * Set of UIDs that are to be blocked/allowed by firewall controller.  This set of Ids matches
      * to device idles.
      */
     @GuardedBy("mRulesLock")
-    private SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
+    private final SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
     /**
      * Set of UIDs that are to be blocked/allowed by firewall controller.  This set of Ids matches
      * to device on power-save mode.
      */
     @GuardedBy("mRulesLock")
-    private SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
+    private final SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
     /**
      * Contains the per-UID firewall rules that are used when Restricted Networking Mode is enabled.
      */
     @GuardedBy("mRulesLock")
-    private SparseIntArray mUidFirewallRestrictedRules = new SparseIntArray();
+    private final SparseIntArray mUidFirewallRestrictedRules = new SparseIntArray();
     /**
      * Contains the per-UID firewall rules that are used when Low Power Standby is enabled.
      */
     @GuardedBy("mRulesLock")
-    private SparseIntArray mUidFirewallLowPowerStandbyRules = new SparseIntArray();
+    private final SparseIntArray mUidFirewallLowPowerStandbyRules = new SparseIntArray();
     /** Set of states for the child firewall chains. True if the chain is active. */
     @GuardedBy("mRulesLock")
     final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
@@ -236,17 +212,6 @@
         mNetdUnsolicitedEventListener = new NetdUnsolicitedEventListener();
 
         mDeps.registerLocalService(new LocalService());
-
-        synchronized (mTetheringStatsProviders) {
-            mTetheringStatsProviders.put(new NetdTetheringStatsProvider(), "netd");
-        }
-    }
-
-    private NetworkManagementService() {
-        mContext = null;
-        mDaemonHandler = null;
-        mDeps = null;
-        mNetdUnsolicitedEventListener = null;
     }
 
     static NetworkManagementService create(Context context, Dependencies deps)
@@ -289,19 +254,19 @@
 
     @Override
     public void registerObserver(INetworkManagementEventObserver observer) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         mObservers.register(observer);
     }
 
     @Override
     public void unregisterObserver(INetworkManagementEventObserver observer) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         mObservers.unregister(observer);
     }
 
     @FunctionalInterface
     private interface NetworkManagementEventCallback {
-        public void sendCallback(INetworkManagementEventObserver o) throws RemoteException;
+        void sendCallback(INetworkManagementEventObserver o) throws RemoteException;
     }
 
     private void invokeForAllObservers(NetworkManagementEventCallback eventCallback) {
@@ -367,35 +332,6 @@
                 type, isActive, tsNanos, uid));
     }
 
-    @Override
-    public void registerTetheringStatsProvider(ITetheringStatsProvider provider, String name) {
-        NetworkStack.checkNetworkStackPermission(mContext);
-        Objects.requireNonNull(provider);
-        synchronized(mTetheringStatsProviders) {
-            mTetheringStatsProviders.put(provider, name);
-        }
-    }
-
-    @Override
-    public void unregisterTetheringStatsProvider(ITetheringStatsProvider provider) {
-        NetworkStack.checkNetworkStackPermission(mContext);
-        synchronized(mTetheringStatsProviders) {
-            mTetheringStatsProviders.remove(provider);
-        }
-    }
-
-    @Override
-    public void tetherLimitReached(ITetheringStatsProvider provider) {
-        NetworkStack.checkNetworkStackPermission(mContext);
-        synchronized(mTetheringStatsProviders) {
-            if (!mTetheringStatsProviders.containsKey(provider)) {
-                return;
-            }
-            // No current code examines the interface parameter in a global alert. Just pass null.
-            mDaemonHandler.post(() -> notifyLimitReached(LIMIT_GLOBAL_ALERT, null));
-        }
-    }
-
     // Sync the state of the given chain with the native daemon.
     private void syncFirewallChainLocked(int chain, String name) {
         SparseIntArray rules;
@@ -665,7 +601,7 @@
     public String[] listInterfaces() {
         // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
         //  APIs.
-        NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
+        PermissionUtils.enforceNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
         try {
             return mNetdService.interfaceGetList();
         } catch (RemoteException | ServiceSpecificException e) {
@@ -717,7 +653,7 @@
     public InterfaceConfiguration getInterfaceConfig(String iface) {
         // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
         //  APIs.
-        NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
+        PermissionUtils.enforceNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
         final InterfaceConfigurationParcel result;
         try {
             result = mNetdService.interfaceGetCfg(iface);
@@ -737,7 +673,7 @@
     public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) {
         // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
         //  APIs.
-        NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
+        PermissionUtils.enforceNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
         LinkAddress linkAddr = cfg.getLinkAddress();
         if (linkAddr == null || linkAddr.getAddress() == null) {
             throw new IllegalStateException("Null LinkAddress given");
@@ -754,7 +690,7 @@
 
     @Override
     public void setInterfaceDown(String iface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
         ifcg.setInterfaceDown();
         setInterfaceConfig(iface, ifcg);
@@ -762,7 +698,7 @@
 
     @Override
     public void setInterfaceUp(String iface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
         ifcg.setInterfaceUp();
         setInterfaceConfig(iface, ifcg);
@@ -770,7 +706,7 @@
 
     @Override
     public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             mNetdService.interfaceSetIPv6PrivacyExtensions(iface, enable);
         } catch (RemoteException | ServiceSpecificException e) {
@@ -782,7 +718,7 @@
        IPv6 addresses on interface down, but we need to do full clean up here */
     @Override
     public void clearInterfaceAddresses(String iface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             mNetdService.interfaceClearAddrs(iface);
         } catch (RemoteException | ServiceSpecificException e) {
@@ -792,7 +728,7 @@
 
     @Override
     public void enableIpv6(String iface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             mNetdService.interfaceSetEnableIPv6(iface, true);
         } catch (RemoteException | ServiceSpecificException e) {
@@ -802,7 +738,7 @@
 
     @Override
     public void setIPv6AddrGenMode(String iface, int mode) throws ServiceSpecificException {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             mNetdService.setIPv6AddrGenMode(iface, mode);
         } catch (RemoteException e) {
@@ -812,7 +748,7 @@
 
     @Override
     public void disableIpv6(String iface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             mNetdService.interfaceSetEnableIPv6(iface, false);
         } catch (RemoteException | ServiceSpecificException e) {
@@ -822,44 +758,16 @@
 
     @Override
     public void addRoute(int netId, RouteInfo route) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         NetdUtils.modifyRoute(mNetdService, ModifyOperation.ADD, netId, route);
     }
 
     @Override
     public void removeRoute(int netId, RouteInfo route) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         NetdUtils.modifyRoute(mNetdService, ModifyOperation.REMOVE, netId, route);
     }
 
-    private ArrayList<String> readRouteList(String filename) {
-        FileInputStream fstream = null;
-        ArrayList<String> list = new ArrayList<>();
-
-        try {
-            fstream = new FileInputStream(filename);
-            DataInputStream in = new DataInputStream(fstream);
-            BufferedReader br = new BufferedReader(new InputStreamReader(in));
-            String s;
-
-            // throw away the title line
-
-            while (((s = br.readLine()) != null) && (s.length() != 0)) {
-                list.add(s);
-            }
-        } catch (IOException ex) {
-            // return current list, possibly empty
-        } finally {
-            if (fstream != null) {
-                try {
-                    fstream.close();
-                } catch (IOException ex) {}
-            }
-        }
-
-        return list;
-    }
-
     @Override
     public void shutdown() {
         // TODO: remove from aidl if nobody calls externally
@@ -870,11 +778,10 @@
 
     @Override
     public boolean getIpForwardingEnabled() throws IllegalStateException{
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
 
         try {
-            final boolean isEnabled = mNetdService.ipfwdEnabled();
-            return isEnabled;
+            return mNetdService.ipfwdEnabled();
         } catch (RemoteException | ServiceSpecificException e) {
             throw new IllegalStateException(e);
         }
@@ -882,7 +789,7 @@
 
     @Override
     public void setIpForwardingEnabled(boolean enable) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             if (enable) {
                 mNetdService.ipfwdEnableForwarding("tethering");
@@ -896,14 +803,9 @@
 
     @Override
     public void startTethering(String[] dhcpRange) {
-        startTetheringWithConfiguration(true, dhcpRange);
-    }
-
-    @Override
-    public void startTetheringWithConfiguration(boolean usingLegacyDnsProxy, String[] dhcpRange) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
-            NetdUtils.tetherStart(mNetdService, usingLegacyDnsProxy, dhcpRange);
+            NetdUtils.tetherStart(mNetdService, true /* usingLegacyDnsProxy */, dhcpRange);
         } catch (RemoteException | ServiceSpecificException e) {
             throw new IllegalStateException(e);
         }
@@ -911,7 +813,7 @@
 
     @Override
     public void stopTethering() {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             mNetdService.tetherStop();
         } catch (RemoteException | ServiceSpecificException e) {
@@ -921,11 +823,9 @@
 
     @Override
     public boolean isTetheringStarted() {
-        NetworkStack.checkNetworkStackPermission(mContext);
-
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
-            final boolean isEnabled = mNetdService.tetherIsEnabled();
-            return isEnabled;
+            return mNetdService.tetherIsEnabled();
         } catch (RemoteException | ServiceSpecificException e) {
             throw new IllegalStateException(e);
         }
@@ -933,7 +833,7 @@
 
     @Override
     public void tetherInterface(String iface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             final LinkAddress addr = getInterfaceConfig(iface).getLinkAddress();
             final IpPrefix dest = new IpPrefix(addr.getAddress(), addr.getPrefixLength());
@@ -945,7 +845,7 @@
 
     @Override
     public void untetherInterface(String iface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             NetdUtils.untetherInterface(mNetdService, iface);
         } catch (RemoteException | ServiceSpecificException e) {
@@ -955,7 +855,7 @@
 
     @Override
     public String[] listTetheredInterfaces() {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             return mNetdService.tetherInterfaceList();
         } catch (RemoteException | ServiceSpecificException e) {
@@ -964,51 +864,8 @@
     }
 
     @Override
-    public String[] getDnsForwarders() {
-        NetworkStack.checkNetworkStackPermission(mContext);
-        try {
-            return mNetdService.tetherDnsList();
-        } catch (RemoteException | ServiceSpecificException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
-    private List<InterfaceAddress> excludeLinkLocal(List<InterfaceAddress> addresses) {
-        ArrayList<InterfaceAddress> filtered = new ArrayList<>(addresses.size());
-        for (InterfaceAddress ia : addresses) {
-            if (!ia.getAddress().isLinkLocalAddress())
-                filtered.add(ia);
-        }
-        return filtered;
-    }
-
-    private void modifyInterfaceForward(boolean add, String fromIface, String toIface) {
-        try {
-            if (add) {
-                mNetdService.ipfwdAddInterfaceForward(fromIface, toIface);
-            } else {
-                mNetdService.ipfwdRemoveInterfaceForward(fromIface, toIface);
-            }
-        } catch (RemoteException | ServiceSpecificException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
-    @Override
-    public void startInterfaceForwarding(String fromIface, String toIface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
-        modifyInterfaceForward(true, fromIface, toIface);
-    }
-
-    @Override
-    public void stopInterfaceForwarding(String fromIface, String toIface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
-        modifyInterfaceForward(false, fromIface, toIface);
-    }
-
-    @Override
     public void enableNat(String internalInterface, String externalInterface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             mNetdService.tetherAddForward(internalInterface, externalInterface);
         } catch (RemoteException | ServiceSpecificException e) {
@@ -1018,7 +875,7 @@
 
     @Override
     public void disableNat(String internalInterface, String externalInterface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         try {
             mNetdService.tetherRemoveForward(internalInterface, externalInterface);
         } catch (RemoteException | ServiceSpecificException e) {
@@ -1028,7 +885,7 @@
 
     @Override
     public void setInterfaceQuota(String iface, long quotaBytes) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
 
         synchronized (mQuotaLock) {
             if (mActiveQuotas.containsKey(iface)) {
@@ -1043,23 +900,12 @@
             } catch (RemoteException | ServiceSpecificException e) {
                 throw new IllegalStateException(e);
             }
-
-            synchronized (mTetheringStatsProviders) {
-                for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
-                    try {
-                        provider.setInterfaceQuota(iface, quotaBytes);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Problem setting tethering data limit on provider " +
-                                mTetheringStatsProviders.get(provider) + ": " + e);
-                    }
-                }
-            }
         }
     }
 
     @Override
     public void removeInterfaceQuota(String iface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
 
         synchronized (mQuotaLock) {
             if (!mActiveQuotas.containsKey(iface)) {
@@ -1076,23 +922,12 @@
             } catch (RemoteException | ServiceSpecificException e) {
                 throw new IllegalStateException(e);
             }
-
-            synchronized (mTetheringStatsProviders) {
-                for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
-                    try {
-                        provider.setInterfaceQuota(iface, ITetheringStatsProvider.QUOTA_UNLIMITED);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Problem removing tethering data limit on provider " +
-                                mTetheringStatsProviders.get(provider) + ": " + e);
-                    }
-                }
-            }
         }
     }
 
     @Override
     public void setInterfaceAlert(String iface, long alertBytes) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
 
         // quick validity check
         if (!mActiveQuotas.containsKey(iface)) {
@@ -1116,7 +951,7 @@
 
     @Override
     public void removeInterfaceAlert(String iface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
 
         synchronized (mQuotaLock) {
             if (!mActiveAlerts.containsKey(iface)) {
@@ -1134,19 +969,8 @@
         }
     }
 
-    @Override
-    public void setGlobalAlert(long alertBytes) {
-        NetworkStack.checkNetworkStackPermission(mContext);
-
-        try {
-            mNetdService.bandwidthSetGlobalAlert(alertBytes);
-        } catch (RemoteException | ServiceSpecificException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
     private void setUidOnMeteredNetworkList(int uid, boolean allowlist, boolean enable) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
 
         synchronized (mQuotaLock) {
             boolean oldEnable;
@@ -1256,7 +1080,7 @@
     @Override
     public void setUidCleartextNetworkPolicy(int uid, int policy) {
         if (mDeps.getCallingUid() != uid) {
-            NetworkStack.checkNetworkStackPermission(mContext);
+            PermissionUtils.enforceNetworkStackPermission(mContext);
         }
 
         synchronized (mQuotaLock) {
@@ -1293,27 +1117,6 @@
         return true;
     }
 
-    private class NetdTetheringStatsProvider extends ITetheringStatsProvider.Stub {
-        @Override
-        public NetworkStats getTetherStats(int how) {
-            // Remove the implementation of NetdTetheringStatsProvider#getTetherStats
-            // since all callers are migrated to use INetd#tetherGetStats directly.
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public void setInterfaceQuota(String iface, long quotaBytes) {
-            // Do nothing. netd is already informed of quota changes in setInterfaceQuota.
-        }
-    }
-
-    @Override
-    public NetworkStats getNetworkStatsTethering(int how) {
-        // Remove the implementation of getNetworkStatsTethering since all callers are migrated
-        // to use INetd#tetherGetStats directly.
-        throw new UnsupportedOperationException();
-    }
-
     @Override
     public void setFirewallEnabled(boolean enabled) {
         enforceSystemUid();
@@ -1333,18 +1136,6 @@
     }
 
     @Override
-    public void setFirewallInterfaceRule(String iface, boolean allow) {
-        enforceSystemUid();
-        Preconditions.checkState(mFirewallEnabled);
-        try {
-            mNetdService.firewallSetInterfaceRule(iface,
-                    allow ? INetd.FIREWALL_RULE_ALLOW : INetd.FIREWALL_RULE_DENY);
-        } catch (RemoteException | ServiceSpecificException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
-    @Override
     public void setFirewallChainEnabled(int chain, boolean enable) {
         enforceSystemUid();
         synchronized (mQuotaLock) {
@@ -1620,22 +1411,9 @@
         pw.println("]");
     }
 
-    private void modifyInterfaceInNetwork(boolean add, int netId, String iface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
-        try {
-            if (add) {
-                mNetdService.networkAddInterface(netId, iface);
-            } else {
-                mNetdService.networkRemoveInterface(netId, iface);
-            }
-        } catch (RemoteException | ServiceSpecificException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
     @Override
     public void allowProtect(int uid) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
 
         try {
             mNetdService.networkSetProtectAllow(uid);
@@ -1646,7 +1424,7 @@
 
     @Override
     public void denyProtect(int uid) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
 
         try {
             mNetdService.networkSetProtectDeny(uid);
@@ -1656,24 +1434,6 @@
     }
 
     @Override
-    public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) {
-        modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, iface);
-        // modifyInterfaceInNetwork already check calling permission.
-        NetdUtils.addRoutesToLocalNetwork(mNetdService, iface, routes);
-    }
-
-    @Override
-    public void removeInterfaceFromLocalNetwork(String iface) {
-        modifyInterfaceInNetwork(MODIFY_OPERATION_REMOVE, INetd.LOCAL_NET_ID, iface);
-    }
-
-    @Override
-    public int removeRoutesFromLocalNetwork(List<RouteInfo> routes) {
-        NetworkStack.checkNetworkStackPermission(mContext);
-        return NetdUtils.removeRoutesFromLocalNetwork(mNetdService, routes);
-    }
-
-    @Override
     public boolean isNetworkRestricted(int uid) {
         mContext.enforceCallingOrSelfPermission(OBSERVE_NETWORK_POLICY, TAG);
         return isNetworkRestrictedInternal(uid);
diff --git a/services/core/java/com/android/server/TEST_MAPPING b/services/core/java/com/android/server/TEST_MAPPING
index a317d23..4b00aca 100644
--- a/services/core/java/com/android/server/TEST_MAPPING
+++ b/services/core/java/com/android/server/TEST_MAPPING
@@ -53,6 +53,14 @@
             // GWP-ASan's CTS test ensures that recoverable tombstones work,
             // which is emitted by the NativeTombstoneManager.
             "name": "CtsGwpAsanTestCases"
+        },
+        {
+            "name": "FrameworksVcnTests",
+            "file_patterns": ["VcnManagementService\\.java"]
+        },
+        {
+            "name": "CtsVcnTestCases",
+            "file_patterns": ["VcnManagementService\\.java"]
         }
     ],
     "presubmit-large": [
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index e8c85ce..c6e9a7d 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -162,6 +162,8 @@
 // TODO(b/180451994): ensure all incoming + outgoing calls have a cleared calling identity
 public class VcnManagementService extends IVcnManagementService.Stub {
     @NonNull private static final String TAG = VcnManagementService.class.getSimpleName();
+    @NonNull private static final String CONTEXT_ATTRIBUTION_TAG = "VCN";
+
     private static final long DUMP_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(5);
     private static final int LOCAL_LOG_LINE_COUNT = 512;
 
@@ -223,7 +225,9 @@
 
     @VisibleForTesting(visibility = Visibility.PRIVATE)
     VcnManagementService(@NonNull Context context, @NonNull Dependencies deps) {
-        mContext = requireNonNull(context, "Missing context");
+        mContext =
+                requireNonNull(context, "Missing context")
+                        .createAttributionContext(CONTEXT_ATTRIBUTION_TAG);
         mDeps = requireNonNull(deps, "Missing dependencies");
 
         mLooper = mDeps.getLooper();
@@ -1065,13 +1069,20 @@
             boolean isRestricted = false;
             synchronized (mLock) {
                 final Vcn vcn = mVcns.get(subGrp);
+                final VcnConfig vcnConfig = mConfigs.get(subGrp);
                 if (vcn != null) {
+                    if (vcnConfig == null) {
+                        // TODO: b/284381334 Investigate for the root cause of this issue
+                        // and handle it properly
+                        logWtf("Vcn instance exists but VcnConfig does not for " + subGrp);
+                    }
+
                     if (vcn.getStatus() == VCN_STATUS_CODE_ACTIVE) {
                         isVcnManagedNetwork = true;
                     }
 
                     final Set<Integer> restrictedTransports = mDeps.getRestrictedTransports(
-                            subGrp, mLastSnapshot, mConfigs.get(subGrp));
+                            subGrp, mLastSnapshot, vcnConfig);
                     for (int restrictedTransport : restrictedTransports) {
                         if (ncCopy.hasTransport(restrictedTransport)) {
                             if (restrictedTransport == TRANSPORT_CELLULAR
diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java
index 9b4f968..0d423d8 100644
--- a/services/core/java/com/android/server/VpnManagerService.java
+++ b/services/core/java/com/android/server/VpnManagerService.java
@@ -80,6 +80,7 @@
  */
 public class VpnManagerService extends IVpnManager.Stub {
     private static final String TAG = VpnManagerService.class.getSimpleName();
+    private static final String CONTEXT_ATTRIBUTION_TAG = "VPN_MANAGER";
 
     @VisibleForTesting
     protected final HandlerThread mHandlerThread;
@@ -157,7 +158,7 @@
     }
 
     public VpnManagerService(Context context, Dependencies deps) {
-        mContext = context;
+        mContext = context.createAttributionContext(CONTEXT_ATTRIBUTION_TAG);
         mDeps = deps;
         mHandlerThread = mDeps.makeHandlerThread();
         mHandlerThread.start();
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 139217b..a614b65 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -3105,12 +3105,17 @@
     }
 
     /**
-     * Ports are highly platform-specific, so only allow these to be specified in the vendor
+     * Ports are highly platform-specific, so allow these to be specified in the odm/vendor
      * directory.
      */
     private static Map<String, Integer> loadStaticInputPortAssociations() {
-        final File baseDir = Environment.getVendorDirectory();
-        final File confFile = new File(baseDir, PORT_ASSOCIATIONS_PATH);
+        File baseDir = Environment.getOdmDirectory();
+        File confFile = new File(baseDir, PORT_ASSOCIATIONS_PATH);
+
+        if (!confFile.exists()) {
+            baseDir = Environment.getVendorDirectory();
+            confFile = new File(baseDir, PORT_ASSOCIATIONS_PATH);
+        }
 
         try (final InputStream stream = new FileInputStream(confFile)) {
             return ConfigurationProcessor.processInputPortAssociations(stream);
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index b92e73c..554e269 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -2868,7 +2868,9 @@
                             } else if (!permissionPolicyInitialized
                                     || (!hardRestricted || restrictionExempt)) {
                                 if ((origPermState != null && origPermState.isGranted())) {
-                                    uidState.grantPermission(bp);
+                                    if (!uidState.grantPermission(bp)) {
+                                        wasChanged = true;
+                                    }
                                 }
                             }
                             if (mIsLeanback && NOTIFICATION_PERMISSIONS.contains(permName)) {
diff --git a/services/core/java/com/android/server/policy/OWNERS b/services/core/java/com/android/server/policy/OWNERS
index 8887e40..f20ea4b 100644
--- a/services/core/java/com/android/server/policy/OWNERS
+++ b/services/core/java/com/android/server/policy/OWNERS
@@ -1,3 +1,6 @@
 include /services/core/java/com/android/server/wm/OWNERS
 include /services/core/java/com/android/server/input/OWNERS
-include /services/core/java/com/android/server/pm/permission/OWNERS
+per-file *AppOp* = file:/services/core/java/com/android/server/pm/permission/OWNERS
+per-file *Permission* = file:/services/core/java/com/android/server/pm/permission/OWNERS
+per-file OWNERS = file:/services/core/java/com/android/server/pm/permission/OWNERS
+per-file TEST_MAPPING = file:/services/core/java/com/android/server/pm/permission/OWNERS
diff --git a/services/core/java/com/android/server/policy/role/OWNERS b/services/core/java/com/android/server/policy/role/OWNERS
new file mode 100644
index 0000000..a462da8
--- /dev/null
+++ b/services/core/java/com/android/server/policy/role/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/permission/OWNERS
diff --git a/services/core/java/com/android/server/power/ThermalManagerService.java b/services/core/java/com/android/server/power/ThermalManagerService.java
index 96823c8a..0dbb280 100644
--- a/services/core/java/com/android/server/power/ThermalManagerService.java
+++ b/services/core/java/com/android/server/power/ThermalManagerService.java
@@ -547,6 +547,8 @@
         @Override
         public int onCommand(String cmd) {
             switch(cmd != null ? cmd : "") {
+                case "inject-temperature":
+                    return runInjectTemperature();
                 case "override-status":
                     return runOverrideStatus();
                 case "reset":
@@ -569,6 +571,95 @@
             }
         }
 
+
+        private int runInjectTemperature() {
+            final long token = Binder.clearCallingIdentity();
+            try {
+                final PrintWriter pw = getOutPrintWriter();
+                int type;
+                String typeName = getNextArgRequired();
+                switch (typeName.toUpperCase()) {
+                    case "UNKNOWN":
+                        type = Temperature.TYPE_UNKNOWN;
+                        break;
+                    case "CPU":
+                        type = Temperature.TYPE_CPU;
+                        break;
+                    case "GPU":
+                        type = Temperature.TYPE_GPU;
+                        break;
+                    case "BATTERY":
+                        type = Temperature.TYPE_BATTERY;
+                        break;
+                    case "SKIN":
+                        type = Temperature.TYPE_SKIN;
+                        break;
+                    case "USB_PORT":
+                        type = Temperature.TYPE_USB_PORT;
+                        break;
+                    case "POWER_AMPLIFIER":
+                        type = Temperature.TYPE_POWER_AMPLIFIER;
+                        break;
+                    case "BCL_VOLTAGE":
+                        type = Temperature.TYPE_BCL_VOLTAGE;
+                        break;
+                    case "BCL_CURRENT":
+                        type = Temperature.TYPE_BCL_CURRENT;
+                        break;
+                    case "BCL_PERCENTAGE":
+                        type = Temperature.TYPE_BCL_PERCENTAGE;
+                        break;
+                    case "NPU":
+                        type = Temperature.TYPE_NPU;
+                        break;
+                    default:
+                        pw.println("Invalid temperature type: " + typeName);
+                        return -1;
+                }
+                int throttle;
+                String throttleName = getNextArgRequired();
+                switch (throttleName.toUpperCase()) {
+                    case "NONE":
+                        throttle = Temperature.THROTTLING_NONE;
+                        break;
+                    case "LIGHT":
+                        throttle = Temperature.THROTTLING_LIGHT;
+                        break;
+                    case "MODERATE":
+                        throttle = Temperature.THROTTLING_MODERATE;
+                        break;
+                    case "SEVERE":
+                        throttle = Temperature.THROTTLING_SEVERE;
+                        break;
+                    case "CRITICAL":
+                        throttle = Temperature.THROTTLING_CRITICAL;
+                        break;
+                    case "EMERGENCY":
+                        throttle = Temperature.THROTTLING_EMERGENCY;
+                        break;
+                    case "SHUTDOWN":
+                        throttle = Temperature.THROTTLING_SHUTDOWN;
+                        break;
+                    default:
+                        pw.println("Invalid throttle status: " + throttleName);
+                        return -1;
+                }
+                String name = getNextArgRequired();
+                float value = 28.0f;
+                try {
+                    String valueStr = getNextArg();
+                    if (valueStr != null) value = Float.parseFloat(valueStr);
+                } catch (RuntimeException ex) {
+                    pw.println("Error: " + ex.toString());
+                    return -1;
+                }
+                onTemperatureChanged(new Temperature(value, type, name, throttle), true);
+                return 0;
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
         private int runOverrideStatus() {
             final long token = Binder.clearCallingIdentity();
             try {
@@ -601,6 +692,9 @@
             pw.println("  help");
             pw.println("    Print this help text.");
             pw.println("");
+            pw.println("  inject-temperature TYPE STATUS NAME [VALUE]");
+            pw.println("    injects a new temperature sample for the specified device.");
+            pw.println("    type and status strings follow the names in android.os.Temperature.");
             pw.println("  override-status STATUS");
             pw.println("    sets and locks the thermal status of the device to STATUS.");
             pw.println("    status code is defined in android.os.Temperature.");
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 6084ead..e0008b0 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -2313,8 +2313,8 @@
                 && Arrays.equals(mLastLetterboxDetails, letterboxDetails)) {
             return;
         }
-        if (mDisplayContent.isDefaultDisplay && mLastFocusIsFullscreen != isFullscreen
-                && ((mLastAppearance ^ appearance) & APPEARANCE_LOW_PROFILE_BARS) != 0) {
+        if (mDisplayContent.isDefaultDisplay && (mLastFocusIsFullscreen != isFullscreen
+                || ((mLastAppearance ^ appearance) & APPEARANCE_LOW_PROFILE_BARS) != 0)) {
             mService.mInputManager.setSystemUiLightsOut(
                     isFullscreen || (appearance & APPEARANCE_LOW_PROFILE_BARS) != 0);
         }
diff --git a/services/core/java/com/android/server/wm/OWNERS b/services/core/java/com/android/server/wm/OWNERS
index 07f3bc6..0af9fe9 100644
--- a/services/core/java/com/android/server/wm/OWNERS
+++ b/services/core/java/com/android/server/wm/OWNERS
@@ -15,6 +15,7 @@
 lihongyu@google.com
 mariiasand@google.com
 rgl@google.com
+yunfanc@google.com
 
 per-file BackgroundActivityStartController.java = set noparent
 per-file BackgroundActivityStartController.java = brufino@google.com, ogunwale@google.com, louischang@google.com, lus@google.com, rickywai@google.com
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index 4123f80..960b57c 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -118,6 +118,7 @@
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class VcnManagementServiceTest {
+    private static final String CONTEXT_ATTRIBUTION_TAG = "VCN";
     private static final String TEST_PACKAGE_NAME =
             VcnManagementServiceTest.class.getPackage().getName();
     private static final String TEST_PACKAGE_NAME_2 = "TEST_PKG_2";
@@ -177,6 +178,7 @@
                     0 /* carrierId */,
                     0 /* profileClass */);
 
+    private final Context mMockContextWithoutAttributionTag = mock(Context.class);
     private final Context mMockContext = mock(Context.class);
     private final VcnManagementService.Dependencies mMockDeps =
             mock(VcnManagementService.Dependencies.class);
@@ -202,6 +204,10 @@
     private final IBinder mMockIBinder = mock(IBinder.class);
 
     public VcnManagementServiceTest() throws Exception {
+        doReturn(mMockContext)
+                .when(mMockContextWithoutAttributionTag)
+                .createAttributionContext(CONTEXT_ATTRIBUTION_TAG);
+
         setupSystemService(
                 mMockContext, mConnMgr, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class);
         setupSystemService(
@@ -249,7 +255,7 @@
         doReturn(bundle).when(mConfigReadWriteHelper).readFromDisk();
 
         setupMockedCarrierPrivilege(true);
-        mVcnMgmtSvc = new VcnManagementService(mMockContext, mMockDeps);
+        mVcnMgmtSvc = new VcnManagementService(mMockContextWithoutAttributionTag, mMockDeps);
         setupActiveSubscription(TEST_UUID_1);
 
         doReturn(mMockIBinder).when(mMockPolicyListener).asBinder();