Merge "Move IInputMethodSession to com.android.internal.inputmethod"
diff --git a/apct-tests/perftests/rubidium/Android.bp b/apct-tests/perftests/rubidium/Android.bp
new file mode 100644
index 0000000..fe90bc9
--- /dev/null
+++ b/apct-tests/perftests/rubidium/Android.bp
@@ -0,0 +1,40 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this 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 {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+    name: "RubidiumPerfTests",
+    srcs: ["src/**/*.java"],
+    static_libs: [
+        "androidx.test.rules",
+        "androidx.annotation_annotation",
+        "apct-perftests-utils",
+        "collector-device-lib",
+        "compatibility-device-util-axt",
+        "platform-test-annotations",
+        "adservices-service-core",
+    ],
+    test_suites: ["device-tests"],
+    data: [":perfetto_artifacts"],
+    platform_apis: true,
+    certificate: "platform",
+}
diff --git a/apct-tests/perftests/rubidium/AndroidManifest.xml b/apct-tests/perftests/rubidium/AndroidManifest.xml
new file mode 100644
index 0000000..1c6b73c
--- /dev/null
+++ b/apct-tests/perftests/rubidium/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.perftests.rubidium">
+
+    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.perftests.rubidium"/>
+</manifest>
diff --git a/apct-tests/perftests/rubidium/AndroidTest.xml b/apct-tests/perftests/rubidium/AndroidTest.xml
new file mode 100644
index 0000000..f538cf5
--- /dev/null
+++ b/apct-tests/perftests/rubidium/AndroidTest.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this 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 undtradefed.testtype.AndroidJUniter 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.
+-->
+<configuration description="Runs RubidiumPerfTests metric instrumentation.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-metric-instrumentation" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="RubidiumPerfTests.apk" />
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+        <option name="force-skip-system-props" value="true" />
+        <option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
+        <option name="run-command" value="cmd window dismiss-keyguard" />
+        <option name="run-command" value="cmd package compile -m speed com.android.perftests.rubidium" />
+    </target_preparer>
+
+    <!-- Needed for pushing the trace config file -->
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="push-file" key="trace_config_detailed.textproto" value="/data/misc/perfetto-traces/trace_config.textproto" />
+        <!--Install the content provider automatically when we push some file in sdcard folder.-->
+        <!--Needed to avoid the installation during the test suite.-->
+        <option name="push-file" key="trace_config_detailed.textproto" value="/sdcard/sample.textproto" />
+    </target_preparer>
+
+    <!-- Needed for storing the perfetto trace files in the sdcard/test_results-->
+    <option name="isolated-storage" value="false" />
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="com.android.perftests.rubidium" />
+        <option name="hidden-api-checks" value="false"/>
+
+        <!-- Listener related args for collecting the traces and waiting for the device to stabilize. -->
+        <option name="device-listeners" value="android.device.collectors.ProcLoadListener,android.device.collectors.PerfettoListener" />
+
+        <!-- Guarantee that user defined RunListeners will be running before any of the default listeners defined in this runner. -->
+        <option name="instrumentation-arg" key="newRunListenerMode" value="true" />
+
+        <!-- Kill background operations -->
+        <option name="instrumentation-arg" key="kill-bg" value="true" />
+
+        <!-- ProcLoadListener related arguments -->
+        <!-- Wait for device last minute threshold to reach 3 with 2 minute timeout before starting the test run -->
+        <option name="instrumentation-arg" key="procload-collector:per_run" value="true" />
+        <option name="instrumentation-arg" key="proc-loadavg-threshold" value="3" />
+        <option name="instrumentation-arg" key="proc-loadavg-timeout" value="120000" />
+        <option name="instrumentation-arg" key="proc-loadavg-interval" value="10000" />
+
+        <!-- PerfettoListener related arguments -->
+        <option name="instrumentation-arg" key="perfetto_config_text_proto" value="true" />
+        <option name="instrumentation-arg" key="perfetto_config_file" value="trace_config.textproto" />
+    </test>
+
+    <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+        <option name="directory-keys" value="/data/local/tmp/RubidiumPerfTests" />
+        <!-- Needed for pulling the collected trace config on to the host -->
+        <option name="pull-pattern-keys" value="perfetto_file_path" />
+    </metrics_collector>
+</configuration>
diff --git a/apct-tests/perftests/rubidium/assets/empty_generate_bid.js b/apct-tests/perftests/rubidium/assets/empty_generate_bid.js
new file mode 100644
index 0000000..38efc9e
--- /dev/null
+++ b/apct-tests/perftests/rubidium/assets/empty_generate_bid.js
@@ -0,0 +1,11 @@
+"use strict";
+
+function generateBid(ad) {
+  let input = ad.metadata.input;
+
+  return {
+    ad: 'example',
+    bid: input,
+    render: ad.renderUrl
+  }
+}
\ No newline at end of file
diff --git a/apct-tests/perftests/rubidium/assets/turtledove_generate_bid.js b/apct-tests/perftests/rubidium/assets/turtledove_generate_bid.js
new file mode 100644
index 0000000..38d30ac
--- /dev/null
+++ b/apct-tests/perftests/rubidium/assets/turtledove_generate_bid.js
@@ -0,0 +1,117 @@
+/*
+ Copyright The Closure Library Authors.
+ SPDX-License-Identifier: Apache-2.0
+
+ See cl/451090252 for how to generate this file.
+*/
+var n,aa=function(a){var b=0;return function(){return b<a.length?{done:!1,value:a[b++]}:{done:!0}}},ba="function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){if(a==Array.prototype||a==Object.prototype)return a;a[b]=c.value;return a},ca=function(a){a=["object"==typeof globalThis&&globalThis,a,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var b=0;b<a.length;++b){var c=a[b];if(c&&c.Math==Math)return c}throw Error("Cannot find global object");
+},da=ca(this),p=function(a,b){if(b)a:{var c=da;a=a.split(".");for(var d=0;d<a.length-1;d++){var e=a[d];if(!(e in c))break a;c=c[e]}a=a[a.length-1];d=c[a];b=b(d);b!=d&&null!=b&&ba(c,a,{configurable:!0,writable:!0,value:b})}};
+p("Symbol",function(a){if(a)return a;var b=function(g,f){this.ra=g;ba(this,"description",{configurable:!0,writable:!0,value:f})};b.prototype.toString=function(){return this.ra};var c="jscomp_symbol_"+(1E9*Math.random()>>>0)+"_",d=0,e=function(g){if(this instanceof e)throw new TypeError("Symbol is not a constructor");return new b(c+(g||"")+"_"+d++,g)};return e});
+p("Symbol.iterator",function(a){if(a)return a;a=Symbol("Symbol.iterator");for(var b="Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array".split(" "),c=0;c<b.length;c++){var d=da[b[c]];"function"===typeof d&&"function"!=typeof d.prototype[a]&&ba(d.prototype,a,{configurable:!0,writable:!0,value:function(){return ea(aa(this))}})}return a});
+var ea=function(a){a={next:a};a[Symbol.iterator]=function(){return this};return a},r=function(a){var b="undefined"!=typeof Symbol&&Symbol.iterator&&a[Symbol.iterator];return b?b.call(a):{next:aa(a)}},ha="function"==typeof Object.create?Object.create:function(a){var b=function(){};b.prototype=a;return new b},ia;
+if("function"==typeof Object.setPrototypeOf)ia=Object.setPrototypeOf;else{var ja;a:{var ka={a:!0},la={};try{la.__proto__=ka;ja=la.a;break a}catch(a){}ja=!1}ia=ja?function(a,b){a.__proto__=b;if(a.__proto__!==b)throw new TypeError(a+" is not extensible");return a}:null}
+var ma=ia,t=function(a,b){a.prototype=ha(b.prototype);a.prototype.constructor=a;if(ma)ma(a,b);else for(var c in b)if("prototype"!=c)if(Object.defineProperties){var d=Object.getOwnPropertyDescriptor(b,c);d&&Object.defineProperty(a,c,d)}else a[c]=b[c];a.za=b.prototype},u=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)};
+p("WeakMap",function(a){function b(){}function c(l){var k=typeof l;return"object"===k&&null!==l||"function"===k}function d(l){if(!u(l,g)){var k=new b;ba(l,g,{value:k})}}function e(l){var k=Object[l];k&&(Object[l]=function(m){if(m instanceof b)return m;Object.isExtensible(m)&&d(m);return k(m)})}if(function(){if(!a||!Object.seal)return!1;try{var l=Object.seal({}),k=Object.seal({}),m=new a([[l,2],[k,3]]);if(2!=m.get(l)||3!=m.get(k))return!1;m.delete(l);m.set(k,4);return!m.has(l)&&4==m.get(k)}catch(q){return!1}}())return a;
+var g="$jscomp_hidden_"+Math.random();e("freeze");e("preventExtensions");e("seal");var f=0,h=function(l){this.M=(f+=Math.random()+1).toString();if(l){l=r(l);for(var k;!(k=l.next()).done;)k=k.value,this.set(k[0],k[1])}};h.prototype.set=function(l,k){if(!c(l))throw Error("Invalid WeakMap key");d(l);if(!u(l,g))throw Error("WeakMap key fail: "+l);l[g][this.M]=k;return this};h.prototype.get=function(l){return c(l)&&u(l,g)?l[g][this.M]:void 0};h.prototype.has=function(l){return c(l)&&u(l,g)&&u(l[g],this.M)};
+h.prototype.delete=function(l){return c(l)&&u(l,g)&&u(l[g],this.M)?delete l[g][this.M]:!1};return h});
+p("Map",function(a){if(function(){if(!a||"function"!=typeof a||!a.prototype.entries||"function"!=typeof Object.seal)return!1;try{var h=Object.seal({x:4}),l=new a(r([[h,"s"]]));if("s"!=l.get(h)||1!=l.size||l.get({x:4})||l.set({x:4},"t")!=l||2!=l.size)return!1;var k=l.entries(),m=k.next();if(m.done||m.value[0]!=h||"s"!=m.value[1])return!1;m=k.next();return m.done||4!=m.value[0].x||"t"!=m.value[1]||!k.next().done?!1:!0}catch(q){return!1}}())return a;var b=new WeakMap,c=function(h){this.L={};this.A=g();
+this.size=0;if(h){h=r(h);for(var l;!(l=h.next()).done;)l=l.value,this.set(l[0],l[1])}};c.prototype.set=function(h,l){h=0===h?0:h;var k=d(this,h);k.list||(k.list=this.L[k.id]=[]);k.j?k.j.value=l:(k.j={next:this.A,B:this.A.B,head:this.A,key:h,value:l},k.list.push(k.j),this.A.B.next=k.j,this.A.B=k.j,this.size++);return this};c.prototype.delete=function(h){h=d(this,h);return h.j&&h.list?(h.list.splice(h.index,1),h.list.length||delete this.L[h.id],h.j.B.next=h.j.next,h.j.next.B=h.j.B,h.j.head=null,this.size--,
+!0):!1};c.prototype.clear=function(){this.L={};this.A=this.A.B=g();this.size=0};c.prototype.has=function(h){return!!d(this,h).j};c.prototype.get=function(h){return(h=d(this,h).j)&&h.value};c.prototype.entries=function(){return e(this,function(h){return[h.key,h.value]})};c.prototype.keys=function(){return e(this,function(h){return h.key})};c.prototype.values=function(){return e(this,function(h){return h.value})};c.prototype.forEach=function(h,l){for(var k=this.entries(),m;!(m=k.next()).done;)m=m.value,
+h.call(l,m[1],m[0],this)};c.prototype[Symbol.iterator]=c.prototype.entries;var d=function(h,l){var k=l&&typeof l;"object"==k||"function"==k?b.has(l)?k=b.get(l):(k=""+ ++f,b.set(l,k)):k="p_"+l;var m=h.L[k];if(m&&u(h.L,k))for(h=0;h<m.length;h++){var q=m[h];if(l!==l&&q.key!==q.key||l===q.key)return{id:k,list:m,index:h,j:q}}return{id:k,list:m,index:-1,j:void 0}},e=function(h,l){var k=h.A;return ea(function(){if(k){for(;k.head!=h.A;)k=k.B;for(;k.next!=k.head;)return k=k.next,{done:!1,value:l(k)};k=null}return{done:!0,
+value:void 0}})},g=function(){var h={};return h.B=h.next=h.head=h},f=0;return c});p("Number.isFinite",function(a){return a?a:function(b){return"number"!==typeof b?!1:!isNaN(b)&&Infinity!==b&&-Infinity!==b}});var na=function(a,b){a instanceof String&&(a+="");var c=0,d=!1,e={next:function(){if(!d&&c<a.length){var g=c++;return{value:b(g,a[g]),done:!1}}d=!0;return{done:!0,value:void 0}}};e[Symbol.iterator]=function(){return e};return e};
+p("Array.prototype.entries",function(a){return a?a:function(){return na(this,function(b,c){return[b,c]})}});p("Number.isNaN",function(a){return a?a:function(b){return"number"===typeof b&&isNaN(b)}});
+p("Set",function(a){if(function(){if(!a||"function"!=typeof a||!a.prototype.entries||"function"!=typeof Object.seal)return!1;try{var c=Object.seal({x:4}),d=new a(r([c]));if(!d.has(c)||1!=d.size||d.add(c)!=d||1!=d.size||d.add({x:4})!=d||2!=d.size)return!1;var e=d.entries(),g=e.next();if(g.done||g.value[0]!=c||g.value[1]!=c)return!1;g=e.next();return g.done||g.value[0]==c||4!=g.value[0].x||g.value[1]!=g.value[0]?!1:e.next().done}catch(f){return!1}}())return a;var b=function(c){this.m=new Map;if(c){c=
+r(c);for(var d;!(d=c.next()).done;)this.add(d.value)}this.size=this.m.size};b.prototype.add=function(c){c=0===c?0:c;this.m.set(c,c);this.size=this.m.size;return this};b.prototype.delete=function(c){c=this.m.delete(c);this.size=this.m.size;return c};b.prototype.clear=function(){this.m.clear();this.size=0};b.prototype.has=function(c){return this.m.has(c)};b.prototype.entries=function(){return this.m.entries()};b.prototype.values=function(){return this.m.values()};b.prototype.keys=b.prototype.values;
+b.prototype[Symbol.iterator]=b.prototype.values;b.prototype.forEach=function(c,d){var e=this;this.m.forEach(function(g){return c.call(d,g,g,e)})};return b});p("Array.from",function(a){return a?a:function(b,c,d){c=null!=c?c:function(h){return h};var e=[],g="undefined"!=typeof Symbol&&Symbol.iterator&&b[Symbol.iterator];if("function"==typeof g){b=g.call(b);for(var f=0;!(g=b.next()).done;)e.push(c.call(d,g.value,f++))}else for(g=b.length,f=0;f<g;f++)e.push(c.call(d,b[f],f));return e}});
+p("Object.entries",function(a){return a?a:function(b){var c=[],d;for(d in b)u(b,d)&&c.push([d,b[d]]);return c}});p("Object.is",function(a){return a?a:function(b,c){return b===c?0!==b||1/b===1/c:b!==b&&c!==c}});p("Array.prototype.includes",function(a){return a?a:function(b,c){var d=this;d instanceof String&&(d=String(d));var e=d.length;c=c||0;for(0>c&&(c=Math.max(c+e,0));c<e;c++){var g=d[c];if(g===b||Object.is(g,b))return!0}return!1}});
+p("String.prototype.includes",function(a){return a?a:function(b,c){if(null==this)throw new TypeError("The 'this' value for String.prototype.includes must not be null or undefined");if(b instanceof RegExp)throw new TypeError("First argument to String.prototype.includes must not be a regular expression");return-1!==(this+"").indexOf(b,c||0)}});p("Array.prototype.values",function(a){return a?a:function(){return na(this,function(b,c){return c})}});
+var oa=this||self,pa=function(a){var b=typeof a;return"object"!=b?b:a?Array.isArray(a)?"array":b:"null"},ra=function(a,b){function c(){}c.prototype=b.prototype;a.za=b.prototype;a.prototype=new c;a.prototype.constructor=a;a.Ca=function(d,e,g){for(var f=Array(arguments.length-2),h=2;h<arguments.length;h++)f[h-2]=arguments[h];return b.prototype[e].apply(d,f)}};function sa(a){if(Error.captureStackTrace)Error.captureStackTrace(this,sa);else{var b=Error().stack;b&&(this.stack=b)}a&&(this.message=String(a))}ra(sa,Error);sa.prototype.name="CustomError";function ta(a,b){a=a.split("%s");for(var c="",d=a.length-1,e=0;e<d;e++)c+=a[e]+(e<b.length?b[e]:"%s");sa.call(this,c+a[d])}ra(ta,sa);ta.prototype.name="AssertionError";function ua(a,b,c,d){var e="Assertion failed";if(c){e+=": "+c;var g=d}else a&&(e+=": "+a,g=b);throw new ta(""+e,g||[]);}
+var v=function(a,b,c){a||ua("",null,b,Array.prototype.slice.call(arguments,2));return a},va=function(a,b,c){null==a&&ua("Expected to exist: %s.",[a],b,Array.prototype.slice.call(arguments,2));return a},wa=function(a,b){throw new ta("Failure"+(a?": "+a:""),Array.prototype.slice.call(arguments,1));},w=function(a,b,c){Array.isArray(a)||ua("Expected array but got %s: %s.",[pa(a),a],b,Array.prototype.slice.call(arguments,2))},x=function(a,b,c,d){a instanceof b||ua("Expected instanceof %s but got %s.",
+[xa(b),xa(a)],c,Array.prototype.slice.call(arguments,3));return a};function xa(a){return a instanceof Function?a.displayName||a.name||"unknown type name":a instanceof Object?a.constructor.displayName||a.constructor.name||Object.prototype.toString.call(a):null===a?"null":typeof a};var ya={},za=null,Aa=function(a){var b,c=pa(a);v("array"==c||"object"==c&&"number"==typeof a.length,"encodeByteArray takes an array as a parameter");void 0===b&&(b=0);if(!za){za={};c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split("");for(var d=["+/=","+/","-_=","-_.","-_"],e=0;5>e;e++){var g=c.concat(d[e].split(""));ya[e]=g;for(var f=0;f<g.length;f++){var h=g[f],l=za[h];void 0===l?za[h]=f:v(l===f)}}}b=ya[b];c=Array(Math.floor(a.length/3));d=b[64]||"";for(e=g=0;g<a.length-2;g+=
+3){l=a[g];var k=a[g+1];h=a[g+2];f=b[l>>2];l=b[(l&3)<<4|k>>4];k=b[(k&15)<<2|h>>6];h=b[h&63];c[e++]=""+f+l+k+h}f=0;h=d;switch(a.length-g){case 2:f=a[g+1],h=b[(f&15)<<2]||d;case 1:a=a[g],c[e]=""+b[a>>2]+b[(a&3)<<4|f>>4]+h+d}return c.join("")};var Ba="undefined"!==typeof Uint8Array,Ca={};var Da,Ea=function(a){if(Ca!==Ca)throw Error("illegal external caller");this.qa=a;if(null!==a&&0===a.length)throw Error("ByteString should be constructed with non-empty values");};v(!0);var Fa={};var z="function"===typeof Symbol&&"symbol"===typeof Symbol()?Symbol("INTERNAL_ARRAY_STATE"):void 0;function Ga(a,b){Object.isFrozen(a)||(z?a[z]|=b:void 0!==a.F?a.F|=b:Object.defineProperties(a,{F:{value:b,configurable:!0,writable:!0,enumerable:!1}}))}var Ha=Object.getOwnPropertyDescriptor(Array.prototype,"wa");
+Object.defineProperties(Array.prototype,{wa:{get:function(){var a=A(this),b=[];1&a&&b.push("IS_REPEATED_FIELD");2&a&&b.push("IS_IMMUTABLE_ARRAY");4&a&&b.push("IS_API_FORMATTED");8&a&&b.push("ONLY_MUTABLE_VALUES");a=b.join(",");return Ha?Ha.get.call(this)+"|"+a:a},configurable:!0,enumerable:!1}});function A(a){w(a,"state is only maintained on arrays.");a=z?a[z]:a.F;return null==a?0:a}function B(a){w(a,"state is only maintained on arrays.");Ga(a,1);return a}
+function C(a){return Array.isArray(a)?!!(A(a)&2):!1}function Ia(a){if(!Array.isArray(a))throw Error("cannot mark non-array as immutable");Ga(a,2)}function Ja(a,b){if(!Array.isArray(a))throw Error("cannot mark non-array as mutable");b?Ga(a,8):Object.isFrozen(a)||(z?a[z]&=-9:void 0!==a.F&&(a.F&=-9))};function Ka(a){return null!==a&&"object"===typeof a&&!Array.isArray(a)&&a.constructor===Object}var La=Symbol("exempted jspb subclass"),Ma=Symbol("generated by jspb"),Na=Object.freeze(B([])),Oa=function(a){if(C(a.g))throw Error("Cannot mutate an immutable Message");},Pa="undefined"!=typeof Symbol&&"undefined"!=typeof Symbol.hasInstance;function Qa(a){return{value:a,configurable:!1,writable:!1,enumerable:!1}};function Ra(a){return a.displayName||a.name||"unknown type name"}function Sa(a,b){if(!(a instanceof b))throw Error("Expected instanceof "+Ra(b)+" but got "+(a&&Ra(a.constructor)));return a}function Ta(a,b,c){c=void 0===c?!1:c;if(Array.isArray(a))return new b(a);if(c)return new b};var Ua=function(){throw Error("please construct maps as mutable then call toImmutable");};if(Pa){var Va=function(){throw Error("Cannot perform instanceof checks on ImmutableMap");},Wa={};Object.defineProperties(Ua,(Wa[Symbol.hasInstance]=Qa(Va),Wa));v(Ua[Symbol.hasInstance]===Va,"defineProperties did not work: was it monkey-patched?")};function Xa(a){switch(typeof a){case "number":return isFinite(a)?a:String(a);case "object":if(a&&!Array.isArray(a)){if(Ba&&null!=a&&a instanceof Uint8Array)return Aa(a);if(a instanceof Ea){var b=a.qa;null!=b&&"string"!==typeof b&&(Ba&&b instanceof Uint8Array?b=Aa(b):(wa("Cannot coerce to b64 string: "+pa(b)),b=null));return(a.qa=b)||""}}}return a};function Ya(a,b){b=void 0===b?Za:b;w(a);return $a(a,b)}function ab(a,b){if(null!=a){if(Array.isArray(a))a=$a(a,b);else if(Ka(a)){var c={},d;for(d in a)c[d]=ab(a[d],b);a=c}else a=b(a);return a}}function $a(a,b){w(a);for(var c=a.slice(),d=0;d<c.length;d++)c[d]=ab(c[d],b);Array.isArray(a)&&A(a)&1&&B(c);return c}function bb(a){if(a&&"object"==typeof a&&a.toJSON)return a.toJSON();a=Xa(a);return Array.isArray(a)?Ya(a,bb):a}function Za(a){return Ba&&null!=a&&a instanceof Uint8Array?new Uint8Array(a):a};var cb=function(a){return a.C||(a.C=a.g[a.G+a.D]={})},db=function(a,b,c){return-1===b?null:b>=a.G?a.C?a.C[b]:void 0:(void 0===c?0:c)&&a.C&&(c=a.C[b],null!=c)?c:a.g[b+a.D]},D=function(a,b,c,d,e){d=void 0===d?!1:d;(void 0===e?0:e)||Oa(a);b<a.G&&!d?a.g[b+a.D]=c:cb(a)[b]=c},E=function(a,b,c,d){c=void 0===c?!0:c;var e=db(a,b,d);Array.isArray(e)||(e=Na);if(C(a.g))c&&(Ia(e),Object.freeze(e));else if(e===Na||C(e))e=B(e.slice()),D(a,b,e,d);return e},F=function(a,b){var c=Number,d=E(a,b,!1),e;if(e=d.length)e=
+d,w(e,"state is only maintained on arrays."),e=!(A(e)&4);if(e){Object.isFrozen(d)&&(d=B(d.slice()),D(a,b,d,void 0,!0));for(b=0;b<d.length;b++)d[b]=c(d[b]);c=d;w(c,"state is only maintained on arrays.");Ga(c,5)}C(a.g)&&Object.freeze(d);return d},G=function(a,b,c){a=db(a,b);return null==a?c:a},I=function(a,b){a=db(a,b);a=null==a?a:!!a;return null==a?!1:a},J=function(a,b){a=db(a,b);a=null==a?a:+a;return null==a?0:a};function L(a,b,c){Oa(a);0!==c?D(a,b,c):D(a,b,void 0,!1);return a}
+var M=function(a,b,c,d,e){e=void 0===e?!1:e;var g=e;if(-1===c)d=null;else{a.h||(a.h={});var f=a.h[c];if(f)d=f;else{var h=db(a,c,g);b=Ta(h,b,d);void 0==b?d=f:(d&&b.g!==h&&D(a,c,b.g,g,!0),a.h[c]=b,C(a.g)&&Ia(b.g),d=b)}}if(null==d)return d;C(d.g)&&!C(a.g)&&(d=d.fa(Fa),D(a,c,d.g,e),a.h[c]=d);return d},N=function(a,b,c,d){var e=d=void 0===d?!1:d;a.h||(a.h={});var g=C(a.g),f=a.h[c];if(!f){e=E(a,c,!0,e);f=[];var h=g||C(e);g=g||h;for(var l=0;l<e.length;l++){var k=e[l];g=g||C(k);k=Ta(k,b);void 0!==k&&(f.push(k),
+h&&Ia(k.g))}h&&(Ia(f),Object.freeze(f));a.h[c]=f;Ja(e,!g)}b=f;f=C(a.g);if(c=a=E(a,c,d)){if(!Array.isArray(a))throw Error("cannot check mutability state of non-array");c=!(A(a)&8)}if(c){for(c=0;c<b.length;c++)(d=b[c])&&C(d.g)&&!f&&(b[c]=b[c].fa(Fa),a[c]=b[c].g);Ja(a,!0)}return b},eb=function(a,b,c,d){Oa(a);a.h||(a.h={});b=null!=d?Sa(d,va(b)).g:d;a.h[c]=d;D(a,c,b)},O=function(a,b){return G(a,b,"0")};var P=function(a,b,c){x(this,P,"The message constructor should only be used by subclasses");v(this.constructor!==P,"Message is an abstract class and cannot be directly constructed");if(!0!==this[La]){v(!0===this[Ma],"Message can only be subclassed by proto gencode.");var d=Object.getPrototypeOf(v(Object.getPrototypeOf(this)));v(d.hasOwnProperty(Ma),"Generated jspb classes should not be extended")}a||(a=fb);fb=null;d=this.constructor.Ia;a||(a=d?[d]:[]);this.D=(d?0:-1)-(this.constructor.Ga||0);this.h=
+void 0;this.g=a;a:{d=this.g.length;a=d-1;if(d&&(d=this.g[a],Ka(d))){this.G=a-this.D;this.C=d;break a}void 0!==b&&-1<b?(this.G=Math.max(b,a+1-this.D),this.C=void 0):this.G=Number.MAX_VALUE}if(c)for(b=0;b<c.length;b++)if(a=c[b],a<this.G)a+=this.D,(d=this.g[a])?Array.isArray(d)&&B(d):this.g[a]=Na;else{d=cb(this);var e=d[a];e?Array.isArray(e)&&B(e):d[a]=Na}};n=P.prototype;n.toJSON=function(){return Ya(this.g,bb)};n.getExtension=function(a){x(this,a.va);return a.Ea(x(this,P))};
+n.hasExtension=function(a){x(this,a.va);v(!a.Ha,"repeated extensions don't support hasExtension");var b=x(this,P);return null!=db(b,a.Da)};n.clone=function(){var a=x(this,P),b=Ya(a.g);x(a,P);w(b);fb=b;b=new a.constructor(b);x(b,P);fb=null;gb(b,a);return b};n.toString=function(){return this.g.toString()};
+function gb(a,b){v(a,"expected `to` to be non-null");v(b,"expected `from` to be non-null");b.N&&(a.N=b.N.slice());var c=b.h;if(c){b=b.C;for(var d in c){var e=c[d];if(e){var g=!(!b||!b[d]),f=+d;if(Array.isArray(e)){if(e.length)for(g=N(a,e[0].constructor,f,g),f=0;f<Math.min(g.length,e.length);f++)gb(g[f],x(e[f],P))}else x(e,P),(g=M(a,e.constructor,f,void 0,g))&&gb(g,e)}}}}var fb;var hb=function(){P.call(this,void 0);throw Error("ImmutableMessage is not instantiable");};t(hb,P);hb.prototype.clone=function(){return P.prototype.clone.call(this)};if(Pa){var ib=function(){throw Error("Cannot perform instanceof checks for MutableMessage");},jb={};Object.defineProperties(hb,(jb[Symbol.hasInstance]=Qa(ib),jb));v(hb[Symbol.hasInstance]===ib,"broken defineProperties implementation")};var kb=function(){P.apply(this,arguments)};t(kb,P);kb.prototype.fa=function(){return this};if(Pa){var lb=function(){throw Error("Cannot perform instanceof checks for MutableMessage");},mb={};Object.defineProperties(kb,(mb[Symbol.hasInstance]=Qa(lb),mb));v(kb[Symbol.hasInstance]===lb,"defineProperties did not work: was it monkey-patched?")};function nb(a,b,c,d,e,g){if(a=a.h&&a.h[c])if(Array.isArray(a)){e=g.ba?B(a.slice()):a;g=0<e.length?e[0].constructor:void 0;Oa(b);if(null!=e){w(e);d=B([]);a=!1;for(var f=0;f<e.length;f++)d[f]=Sa(e[f],va(g)).g,a=a||C(d[f]);b.h||(b.h={});b.h[c]=e;Ja(d,!a)}else b.h&&(b.h[c]=void 0),d=Na;D(b,c,d)}else eb(b,a.constructor,c,x(a,P));else Ba&&d instanceof Uint8Array?(e=d,x(e,Uint8Array),e=e.length?new Ea(new Uint8Array(e)):Da||(Da=new Ea(null))):(Array.isArray(d)&&(e?Ia(d):Array.isArray(d)&&A(d)&1&&g.ba&&(d=
+d.slice())),e=d),D(b,c,e)};var Q=function(){kb.apply(this,arguments)};t(Q,kb);
+Q.prototype.fa=function(a){if(a!==Fa)throw Error("requires a valid immutable API token");if(C(this.g)){x(this,P);a={ba:!0};var b=C(this.g);if(b&&!a.ba)throw Error("copyRepeatedFields must be true for frozen messages");var c=new this.constructor;this.N&&(c.N=this.N.slice());for(var d=this.g,e=0;e<d.length;e++){var g=d[e];if(e===d.length-1&&Ka(g))for(h in g){var f=+h;Number.isNaN(f)?cb(c)[h]=g[h]:nb(this,c,f,g[h],b,a)}else nb(this,c,e-this.D,g,b,a)}var h=c}else h=this;return h};Q.prototype[Ma]=!0;
+if(Pa){var ob={};Object.defineProperties(Q,(ob[Symbol.hasInstance]=Qa(Object[Symbol.hasInstance]),ob));v(Q[Symbol.hasInstance]===Object[Symbol.hasInstance],"broken defineProperties implementation")};var pb=void 0;function qb(a){var b=pb;pb=void 0;var c=[],d=rb(a,c);if(!d&&c){var e="Expected Array<unknown>, got "+sb(a);c.push(e)}if(!d)throw a="",b&&(a=b()+"\n"),Error(a+"Guard Array<unknown> failed:\n"+c.reverse().join("\n"));return a}
+function sb(a,b){b=void 0===b?new Set:b;if(b.has(a))return"(Recursive reference)";switch(typeof a){case "object":if(a){var c=Object.getPrototypeOf(a);switch(c){case Map.prototype:case Set.prototype:case Array.prototype:b.add(a);var d="["+Array.from(a,function(e){return sb(e,b)}).join(", ")+"]";b.delete(a);c!==Array.prototype&&(d=tb(c.constructor)+"("+d+")");return d;case Object.prototype:return b.add(a),c="{"+Object.entries(a).map(function(e){var g=r(e);e=g.next().value;g=g.next().value;return e+
+": "+sb(g,b)}).join(", ")+"}",b.delete(a),c;default:return d="Object",c&&c.constructor&&(d=tb(c.constructor)),"function"===typeof a.toString&&a.toString!==Object.prototype.toString?d+"("+String(a)+")":"(object "+d+")"}}break;case "function":return"function "+tb(a);case "number":if(!Number.isFinite(a))return String(a);break;case "bigint":return a.toString(10)+"n"}return JSON.stringify(a)}function tb(a){var b=a.name;b||(b=(a=/function\s+([^\(]+)/m.exec(String(a)))?a[1]:"(Anonymous)");return b};var rb=function(a){a.Fa=function(){return"Array<unknown>"};return a}(function(a){return Array.isArray(a)});var ub=[[[["1646440773",[-.21289063,-.014526367,-.0046081543,-.013671875,-.012451172,.056152344,-.05029297,-.15234375,-.044677734,-.29101563,-.099121094,.0014190674,.08496094,.078125,-.009765625,-.09765625,-.045166016,.09765625,-.022583008,.23242188,-.04321289,.0126953125,.032226563,.064941406,.36132813,-.09716797,.28515625,.0074768066,-.11279297,-.0625,.012329102,-.076171875]]],[["1646451678",[-.18652344,.15917969,-.005340576,.055664063,.041015625,-.010253906,.06591797,-.071777344,.024536133,1.828125,
+-.19140625,-.35351563,.13671875,.45117188,.12792969,-.03466797,.18261719,.19628906,.14160156,.17480469,-.04638672,-.06689453,-.30273438,.35351563,-.33789063,-.7578125,-.17675781,.05810547,-.002029419,.005279541,-.025756836,.15234375]]]],null,[1],"CMb9tKfcrvYCFawfBgAdboELOQ",null,[null,null,null,1,[]],[null,null,null,null,[]]];var vb={owner:"https://googleads.g.doubleclick.net/",name:"1j115753478",biddingLogicUrl:"https://googleads.g.doubleclick.net/td/bjs",dailyUpdateUrl:"https://googleads.g.doubleclick.net/td/update",trustedBiddingSignalsUrl:"https://googleads.g.doubleclick.net/td/sjs",trustedBiddingSignalsKeys:["1j115753478"],userBiddingSignals:[],ads:[{renderUrl:"https://googleads.g.doubleclick.net/ads/simple-ad.html?adg_id=28447972118&cr_id=310927197288&cv_id=6",metadata:["28447972118","310927197288","6","377212838"]},
+{renderUrl:"https://googleads.g.doubleclick.net/ads/simple-ad.html?adg_id=28447972118&cr_id=310927197291&cv_id=6",metadata:["28447972118","310927197291","6","377212838"]},{renderUrl:"https://googleads.g.doubleclick.net/ads/simple-ad.html?adg_id=28447972118&cr_id=310966379641&cv_id=5",metadata:["28447972118","310966379641","5","377212838"]},{renderUrl:"https://googleads.g.doubleclick.net/ads/simple-ad.html?adg_id=57015819359&cr_id=331239455455&cv_id=5",metadata:["57015819359","331239455455","5","1499135732"]},
+{renderUrl:"https://googleads.g.doubleclick.net/ads/simple-ad.html?adg_id=57015819359&cr_id=331239455458&cv_id=4",metadata:["57015819359","331239455458","4","1499135732"]},{renderUrl:"https://googleads.g.doubleclick.net/ads/simple-ad.html?adg_id=57015819359&cr_id=331239455461&cv_id=5",metadata:["57015819359","331239455461","5","1499135732"]},{renderUrl:"https://googleads.g.doubleclick.net/ads/simple-ad.html?adg_id=52836427830&cr_id=310927197294&cv_id=4",metadata:["52836427830","310927197294","4",
+"608936333"]},{renderUrl:"https://googleads.g.doubleclick.net/ads/simple-ad.html?adg_id=52836427830&cr_id=310927197297&cv_id=4",metadata:["52836427830","310927197297","4","608936333"]},{renderUrl:"https://googleads.g.doubleclick.net/ads/simple-ad.html?adg_id=52836427830&cr_id=310927197300&cv_id=4",metadata:["52836427830","310927197300","4","608936333"]}]};var wb={"1j115753478":[[["52836427830","310927197294","4",[[["1643849995",[3.09375,.8203125,1.4765625,-.55078125,1.9140625,-.78125,-1.1640625,-3.15625,1.25,3.421875,1.6484375,1.0625,4.96875,-.66796875,-1.4375,.87109375,1.6171875,-4.125,-2.375,3.421875,-2.359375,1.6015625,.625,-4.65625,-5.03125,.416015625,-4.03125,-.24609375,3.296875,-.052001953125,-3.75,3.765625]],["1643804092",[3.09375,.796875,1.46875,-.56640625,1.890625,-.76953125,-1.1484375,-3.140625,1.2109375,3.421875,1.625,1.046875,4.9375,-.65234375,
+-1.421875,.84765625,1.6015625,-4.125,-2.359375,3.453125,-2.34375,1.5859375,.63671875,-4.65625,-5,.396484375,-4.03125,-.26171875,3.296875,-.068359375,-3.734375,3.75]]],null,[["1643822293",[-.039794921875,.035400390625,.357421875,.041748046875,.0054931640625,-.060791015625,.138671875,-.318359375,.2255859375,.10546875,.2099609375,-.240234375,-.07373046875,-.279296875,-.44140625,.015380859375,-.298828125,.119140625,-.09716796875,.1796875,.04248046875,.09033203125,.38671875,.412109375,-.357421875,.259765625,
+-.24609375,-.3828125,.33984375,.07861328125,-.1259765625,.3046875]],["1643799063",[.0079345703125,.0546875,.353515625,.00958251953125,-.01318359375,-.10888671875,.13671875,-.373046875,.208984375,.09228515625,.1962890625,-.248046875,-.031494140625,-.2734375,-.42578125,.0035400390625,-.345703125,.1083984375,-.068359375,.173828125,.0810546875,.1162109375,.361328125,.451171875,-.3671875,.162109375,-.212890625,-.46484375,.337890625,.1083984375,-.177734375,.318359375]]],null,null,null,null,[[null,[318.3513488769531,
+1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["52836427830","310927197297","4",[[["1643849995",[3.125,.953125,1.484375,-.46875,2.109375,-.89453125,-1.265625,-3.15625,1.265625,3.421875,1.7578125,1.1796875,4.9375,-.6796875,-1.5234375,.953125,1.7734375,-4.125,-2.453125,3.4375,-2.375,1.6328125,.3984375,-4.375,-4.96875,.59375,-4.03125,-.08935546875,3.34375,.1806640625,-3.8125,3.796875]],["1643804092",[3.125,.90625,1.4609375,-.5,2.046875,-.8671875,
+-1.234375,-3.140625,1.2265625,3.421875,1.71875,1.1328125,4.90625,-.65625,-1.4921875,.921875,1.734375,-4.125,-2.421875,3.46875,-2.34375,1.6015625,.4296875,-4.375,-4.9375,.55078125,-4.03125,-.123046875,3.328125,.1416015625,-3.78125,3.765625]]],null,[["1643822293",[-.060546875,.0185546875,.353515625,.02587890625,.00311279296875,-.07421875,.1533203125,-.3203125,.2470703125,.06689453125,.193359375,-.234375,.029296875,-.255859375,-.44921875,.0146484375,-.306640625,.11962890625,-.10498046875,.1865234375,
+.049072265625,.1162109375,.365234375,.42578125,-.359375,.26953125,-.2490234375,-.392578125,.306640625,.1103515625,-.1376953125,.310546875]],["1643799063",[-.015869140625,.02978515625,.337890625,-.00628662109375,-.0169677734375,-.12353515625,.1494140625,-.373046875,.232421875,.056640625,.1806640625,-.2353515625,.0966796875,-.2451171875,-.43359375,.004180908203125,-.353515625,.107421875,-.087890625,.1865234375,.087890625,.138671875,.345703125,.455078125,-.36328125,.181640625,-.224609375,-.486328125,
+.294921875,.13671875,-.19921875,.3203125]]],null,null,null,null,[[null,[318.3513488769531,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["52836427830","310927197300","4",[[["1643849995",[3.109375,.99609375,1.59375,-.4609375,2.171875,-.91015625,-1.296875,-3.3125,1.3984375,3.4375,1.8046875,1.2578125,5.09375,-.7421875,-1.59375,1.0078125,1.8125,-4.1875,-2.578125,3.390625,-2.53125,1.765625,.54296875,-4.71875,-5.09375,.55859375,-4.09375,-.1318359375,
+3.328125,.0654296875,-3.890625,3.859375]],["1643804092",[3.109375,.953125,1.5703125,-.48828125,2.109375,-.88671875,-1.2734375,-3.296875,1.359375,3.4375,1.7734375,1.21875,5.0625,-.71875,-1.5625,.9765625,1.7734375,-4.1875,-2.53125,3.4375,-2.5,1.734375,.5703125,-4.71875,-5.0625,.5234375,-4.0625,-.1591796875,3.328125,.03515625,-3.84375,3.828125]]],null,[["1643822293",[-.048095703125,.0179443359375,.36328125,.033203125,.030029296875,-.07568359375,.15625,-.326171875,.224609375,.07568359375,.1787109375,
+-.234375,-.0277099609375,-.265625,-.412109375,.00909423828125,-.3046875,.11865234375,-.103515625,.1767578125,.048095703125,.12158203125,.36328125,.421875,-.359375,.255859375,-.25,-.396484375,.29296875,.10205078125,-.1279296875,.318359375]],["1643799063",[-.0045166015625,.03173828125,.353515625,.003631591796875,.00927734375,-.126953125,.154296875,-.37890625,.208984375,.06689453125,.1708984375,-.234375,.03173828125,-.255859375,-.396484375,-.00384521484375,-.353515625,.10693359375,-.0830078125,.1708984375,
+.08935546875,.1474609375,.341796875,.44921875,-.3671875,.1669921875,-.224609375,-.482421875,.28125,.130859375,-.1796875,.326171875]]],null,null,null,null,[[null,[318.3513488769531,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]]]],"1j380357233":[[["52836427830","310927197294","4",[[["1643849995",[4.53125,1.8671875,.13671875,3.3125,-7.5625,.546875,2.953125,-7.90625,4.71875,7.375,.0047607421875,-3.25,.74609375,.298828125,-1.34375,-2.4375,-6.34375,
+-9.1875,-1.3359375,9.875,1.1796875,-3.15625,3.796875,-6.90625,-3.203125,-.09375,-7.65625,-.71875,4.65625,-.75390625,-6.28125,3.6875]],["1643804092",[4.53125,1.9453125,.19140625,3.40625,-7.53125,.52734375,2.9375,-7.9375,4.625,7.375,.01416015625,-3.25,.74609375,.28125,-1.34375,-2.484375,-6.34375,-9.25,-1.328125,9.9375,1.2421875,-3.171875,3.71875,-6.71875,-3.21875,-.0311279296875,-7.71875,-.69140625,4.65625,-.70703125,-6.40625,3.71875]]],null,[["1643822293",[-.09033203125,.037109375,.423828125,.0439453125,
+.0390625,-.04345703125,.162109375,-.3125,.2197265625,.06884765625,.25,-.240234375,-.07763671875,-.267578125,-.416015625,.0150146484375,-.2890625,.126953125,-.08740234375,.158203125,.035888671875,.130859375,.3515625,.412109375,-.38671875,.27734375,-.234375,-.408203125,.337890625,.0458984375,-.1328125,.36328125]],["1643799063",[-.044921875,.056640625,.3984375,.0162353515625,.01373291015625,-.08544921875,.1611328125,-.359375,.1982421875,.06298828125,.2421875,-.2421875,-.05078125,-.263671875,-.39453125,
+.001953125,-.33203125,.11767578125,-.060546875,.1513671875,.07080078125,.14453125,.3359375,.4453125,-.388671875,.1865234375,-.1904296875,-.48046875,.3359375,.0693359375,-.177734375,.37109375]]],null,null,null,null,[[null,[318.3513488769531,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["52836427830","310927197297","4",[[["1643849995",[4.4375,1.90625,.20703125,3.125,-7.03125,.44140625,2.703125,-7.46875,4.5,7.1875,.080078125,-3.03125,.94140625,
+.25390625,-1.3203125,-2.25,-5.875,-8.875,-1.375,9.4375,1.0234375,-2.984375,3.453125,-6.46875,-3.171875,.007781982421875,-7.4375,-.62890625,4.5625,-.58984375,-6.125,3.609375]],["1643804092",[4.46875,1.9765625,.26171875,3.1875,-6.9375,.41015625,2.671875,-7.53125,4.375,7.21875,.09716796875,-3.015625,1.0078125,.232421875,-1.3203125,-2.28125,-5.84375,-8.875,-1.3828125,9.5625,1.0859375,-2.96875,3.359375,-6.3125,-3.234375,.06494140625,-7.5,-.6171875,4.5625,-.53125,-6.28125,3.703125]]],null,[["1643822293",
+[-.107421875,.017822265625,.427734375,.0274658203125,.0289306640625,-.05908203125,.17578125,-.31640625,.2373046875,.033447265625,.2470703125,-.23046875,.00579833984375,-.25,-.421875,.01385498046875,-.298828125,.1240234375,-.09912109375,.16796875,.036865234375,.1435546875,.33984375,.4296875,-.380859375,.28515625,-.232421875,-.427734375,.3125,.0654296875,-.1513671875,.373046875]],["1643799063",[-.07177734375,.024658203125,.396484375,-.0016937255859375,.01434326171875,-.11328125,.1748046875,-.3671875,
+.2255859375,.026611328125,.224609375,-.2197265625,.07470703125,-.232421875,-.396484375,.01507568359375,-.341796875,.11376953125,-.087890625,.16015625,.072265625,.173828125,.3203125,.44921875,-.3828125,.19921875,-.2080078125,-.5078125,.28125,.1044921875,-.21484375,.380859375]]],null,null,null,null,[[null,[318.3513488769531,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["52836427830","310927197300","4",[[["1643849995",[4.5,1.96875,.2099609375,
+3.328125,-7.28125,.458984375,2.8125,-7.84375,4.84375,7.3125,.09814453125,-3.078125,.859375,.224609375,-1.4296875,-2.3125,-6.09375,-9.125,-1.4453125,9.75,1.0078125,-3,3.71875,-6.90625,-3.203125,-.04931640625,-7.5625,-.6328125,4.625,-.69140625,-6.25,3.671875]],["1643804092",[4.5,2.09375,.298828125,3.453125,-7.1875,.416015625,2.765625,-7.90625,4.75,7.3125,.1318359375,-3.046875,.9140625,.17578125,-1.4453125,-2.328125,-6.0625,-9.125,-1.46875,9.75,1.046875,-2.984375,3.59375,-6.6875,-3.25,.041015625,-7.625,
+-.5859375,4.625,-.6171875,-6.40625,3.75]]],null,[["1643822293",[-.09765625,.0216064453125,.421875,.03955078125,.056396484375,-.0546875,.1767578125,-.31640625,.208984375,.04248046875,.2265625,-.2314453125,-.0419921875,-.2578125,-.3828125,.0084228515625,-.29296875,.123046875,-.09423828125,.1533203125,.0380859375,.1474609375,.333984375,.4140625,-.384765625,.275390625,-.232421875,-.4140625,.291015625,.06591796875,-.1337890625,.376953125]],["1643799063",[-.0673828125,.03271484375,.41796875,.01336669921875,
+.041748046875,-.10595703125,.1767578125,-.37109375,.1982421875,.0294189453125,.212890625,-.2275390625,.02880859375,-.248046875,-.361328125,.00909423828125,-.337890625,.115234375,-.0732421875,.14453125,.07080078125,.1875,.310546875,.4453125,-.39453125,.1875,-.203125,-.5078125,.26953125,.095703125,-.1962890625,.40625]]],null,null,null,null,[[null,[318.3513488769531,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["31279674038","113383149038",
+null,[[["1643849995",[7.875,2.375,-3.078125,9.8125,-20.875,2.46875,9.1875,-18.25,10,13.0625,-1.1171875,-8.875,-6.9375,2.078125,-2.1875,-7.34375,-17.375,-19.375,.640625,21.375,7.0625,-9.875,7.875,-9.5625,-2.09375,.034423828125,-13.4375,-.3359375,8.5625,-.75390625,-11.375,6.15625]],["1643804092",[7.875,2.4375,-3.015625,10,-20.75,2.453125,9.1875,-18.25,9.6875,13,-1.1484375,-8.9375,-6.875,2.078125,-2.125,-7.4375,-17.5,-19.25,.71875,21.25,7.3125,-9.9375,7.65625,-9.125,-2.171875,.1513671875,-13.5625,-.34765625,
+8.5625,-.69921875,-11.6875,6.28125]]],null,[["1643822293",[-.337890625,-.1884765625,.1923828125,-.0213623046875,-.1953125,.5234375,.326171875,.0908203125,-.09033203125,.019775390625,.40234375,.462890625,-.19921875,-.08642578125,-.29296875,-.1943359375,.248046875,-.2470703125,-.2099609375,.2353515625,.0400390625,.1767578125,.828125,-.059326171875,-.0218505859375,.5703125,-.431640625,-.30859375,.19921875,.1455078125,-.486328125,-.2578125]],["1643799063",[-.37109375,-.1455078125,.361328125,-.0595703125,
+-.1611328125,.5234375,.3203125,.07568359375,-.0791015625,.03173828125,.423828125,.4609375,-.2412109375,-.09130859375,-.310546875,-.193359375,.232421875,-.2353515625,-.19140625,.2177734375,.0205078125,.232421875,.8359375,-.04150390625,-.045166015625,.55078125,-.451171875,-.412109375,.298828125,.1220703125,-.56640625,-.11767578125]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["31279674038",
+"113383149158",null,[[["1643849995",[8.1875,2.0625,-3.328125,9.5,-21.125,2.609375,9.3125,-17.875,9.5,13.375,-1.2578125,-9.1875,-7,2.265625,-1.9140625,-7.5,-17.625,-19.5,.953125,21.375,7.46875,-10.3125,7.65625,-9.125,-2.265625,.02490234375,-13.75,-.4375,8.8125,-.59765625,-11.4375,6.40625]],["1643804092",[8.125,2.140625,-3.25,9.6875,-21.125,2.59375,9.3125,-17.875,9.25,13.25,-1.25,-9.1875,-6.90625,2.234375,-1.8671875,-7.5625,-17.625,-19.5,1.0078125,21.25,7.625,-10.375,7.5,-8.8125,-2.359375,.1494140625,
+-13.75,-.458984375,8.75,-.5625,-11.6875,6.5]]],null,[["1643822293",[-.349609375,-.19140625,.1767578125,-.0213623046875,-.197265625,.5234375,.330078125,.0927734375,-.0908203125,.027587890625,.3984375,.462890625,-.2001953125,-.0810546875,-.296875,-.19140625,.2490234375,-.244140625,-.2119140625,.2392578125,.0400390625,.181640625,.828125,-.05859375,-.0181884765625,.5703125,-.4296875,-.302734375,.1982421875,.1494140625,-.490234375,-.263671875]],["1643799063",[-.369140625,-.1435546875,.353515625,-.05908203125,
+-.1552734375,.515625,.322265625,.0703125,-.07177734375,.04345703125,.421875,.45703125,-.248046875,-.08935546875,-.30859375,-.1953125,.2255859375,-.2333984375,-.1943359375,.220703125,.021484375,.2431640625,.83984375,-.0419921875,-.04052734375,.54296875,-.443359375,-.41015625,.30078125,.11767578125,-.5703125,-.12158203125]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["31279674038","113383149518",
+null,[[["1643849995",[7.71875,2.21875,-2.984375,9.3125,-20.25,2.40625,8.875,-17.375,9.5,12.75,-1.1015625,-8.6875,-6.53125,2.03125,-2.03125,-7.09375,-16.875,-18.625,.61328125,20.625,6.84375,-9.625,7.625,-9.3125,-2.140625,-.0341796875,-13.125,-.435546875,8.375,-.8046875,-11.0625,6]],["1643804092",[7.65625,2.328125,-2.875,9.5,-20.125,2.375,8.8125,-17.375,9.3125,12.625,-1.09375,-8.625,-6.46875,1.9921875,-2.015625,-7.125,-16.875,-18.625,.671875,20.5,7,-9.625,7.4375,-8.9375,-2.15625,.1357421875,-13.125,
+-.4140625,8.25,-.73046875,-11.25,6.0625]]],null,[["1643822293",[-.34765625,-.193359375,.208984375,-.025390625,-.201171875,.5234375,.330078125,.09326171875,-.09423828125,.0084228515625,.41015625,.46484375,-.1767578125,-.08251953125,-.310546875,-.19140625,.25,-.24609375,-.212890625,.2392578125,.0380859375,.17578125,.828125,-.0576171875,-.01904296875,.578125,-.43359375,-.31640625,.2060546875,.14453125,-.4921875,-.255859375]],["1643799063",[-.369140625,-.150390625,.37890625,-.0546875,-.1630859375,.53125,
+.3203125,.08251953125,-.08447265625,.01318359375,.43359375,.462890625,-.2392578125,-.09619140625,-.310546875,-.189453125,.2421875,-.2333984375,-.1953125,.2119140625,.0142822265625,.23046875,.83203125,-.0284423828125,-.047119140625,.55078125,-.447265625,-.427734375,.306640625,.115234375,-.57421875,-.107421875]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]]]],"1j395640136":[[["31279674038","113383149038",
+null,[[["1643849995",[3.34375,.197265625,.66015625,-.796875,1.1015625,-.5546875,-.78515625,-2.21875,.84765625,3.390625,1.28125,.482421875,3.9375,-.1865234375,-1.09375,.609375,1.1484375,-4.0625,-1.7890625,4.5625,-1.859375,.83203125,.64453125,-4,-4.09375,.02587890625,-3.734375,-.31640625,3.65625,-.025146484375,-2.5625,3.03125]],["1643804092",[3.34375,.177734375,.6484375,-.8125,1.078125,-.54296875,-.76953125,-2.203125,.81640625,3.40625,1.265625,.462890625,3.9375,-.171875,-1.078125,.59375,1.125,-4.09375,
+-1.7734375,4.59375,-1.8359375,.8203125,.65625,-3.984375,-4.09375,.0101318359375,-3.75,-.33203125,3.671875,-.039794921875,-2.546875,3.015625]]],null,[["1643822293",[-.345703125,-.1962890625,.2109375,-.034912109375,-.2158203125,.5234375,.3359375,.09619140625,-.09326171875,.01385498046875,.427734375,.474609375,-.1806640625,-.0771484375,-.3203125,-.2060546875,.2451171875,-.2578125,-.2177734375,.2490234375,.035888671875,.1513671875,.84375,-.04638671875,-.01220703125,.5703125,-.439453125,-.32421875,.2138671875,
+.1513671875,-.50390625,-.263671875]],["1643799063",[-.3828125,-.1494140625,.384765625,-.058837890625,-.1826171875,.53125,.322265625,.0859375,-.08837890625,.0159912109375,.458984375,.462890625,-.2275390625,-.08984375,-.328125,-.1962890625,.23828125,-.23828125,-.189453125,.22265625,.01556396484375,.2109375,.83203125,-.0238037109375,-.044677734375,.55859375,-.453125,-.43359375,.31640625,.12158203125,-.57421875,-.11328125]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,
+[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["31279674038","113383149158",null,[[["1643849995",[3.34375,.130859375,.62109375,-.84765625,.98046875,-.453125,-.68359375,-2.03125,.51953125,3.453125,1.140625,.291015625,3.96875,-.15625,-.8828125,.435546875,1.0078125,-4,-1.515625,4.15625,-1.5234375,.62890625,.37890625,-3.421875,-4.21875,.1220703125,-3.84375,-.345703125,3.5625,.10791015625,-2.828125,3.25]],["1643804092",[3.34375,.130859375,.62109375,-.8515625,.98046875,-.451171875,
+-.68359375,-2.03125,.50390625,3.453125,1.1328125,.287109375,3.96875,-.1533203125,-.875,.427734375,1.0078125,-4,-1.5078125,4.15625,-1.515625,.625,.369140625,-3.390625,-4.21875,.1259765625,-3.84375,-.34765625,3.5625,.11181640625,-2.828125,3.25]]],null,[["1643822293",[-.3515625,-.1982421875,.185546875,-.027099609375,-.21875,.5234375,.333984375,.099609375,-.09423828125,.0244140625,.42578125,.47265625,-.1845703125,-.0751953125,-.314453125,-.2001953125,.2470703125,-.25390625,-.216796875,.248046875,.036865234375,
+.1533203125,.83984375,-.044189453125,-.00933837890625,.5703125,-.43359375,-.31640625,.212890625,.15625,-.5,-.275390625]],["1643799063",[-.38671875,-.138671875,.375,-.061767578125,-.177734375,.5234375,.3203125,.07666015625,-.080078125,.033447265625,.4453125,.447265625,-.2333984375,-.09130859375,-.333984375,-.19921875,.2265625,-.2275390625,-.18359375,.2255859375,.02197265625,.2197265625,.828125,-.0189208984375,-.047119140625,.55078125,-.44140625,-.4296875,.328125,.11962890625,-.5703125,-.11572265625]]],
+null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["31279674038","113383149518",null,[[["1643849995",[3.21875,.1484375,.6796875,-.8203125,1,-.486328125,-.73046875,-2.21875,.77734375,3.3125,1.1875,.419921875,3.875,-.1904296875,-1.015625,.52734375,1.046875,-3.984375,-1.7265625,4.46875,-1.8046875,.828125,.7421875,-4.03125,-4.0625,-.07080078125,-3.671875,-.3984375,3.53125,-.1494140625,-2.515625,2.953125]],
+["1643804092",[3.21875,.1416015625,.671875,-.828125,1,-.486328125,-.73046875,-2.21875,.75390625,3.3125,1.1796875,.416015625,3.890625,-.1796875,-1.015625,.51953125,1.046875,-3.984375,-1.71875,4.5,-1.7890625,.8203125,.73046875,-4,-4.0625,-.06640625,-3.6875,-.3984375,3.53125,-.142578125,-2.53125,2.96875]]],null,[["1643822293",[-.349609375,-.19921875,.2109375,-.03173828125,-.2158203125,.53515625,.333984375,.10400390625,-.11181640625,.00836181640625,.431640625,.4765625,-.16796875,-.07568359375,-.32421875,
+-.201171875,.25390625,-.26171875,-.21875,.251953125,.032958984375,.142578125,.83984375,-.05126953125,-.00836181640625,.58203125,-.439453125,-.31640625,.21875,.1513671875,-.498046875,-.267578125]],["1643799063",[-.376953125,-.1513671875,.38671875,-.061279296875,-.1875,.53125,.322265625,.08642578125,-.08935546875,.01324462890625,.45703125,.462890625,-.224609375,-.08984375,-.333984375,-.19921875,.23828125,-.240234375,-.1962890625,.2197265625,.01519775390625,.2041015625,.8359375,-.0179443359375,-.041748046875,
+.5546875,-.451171875,-.43359375,.3203125,.123046875,-.578125,-.11962890625]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]]]],"1j396781473":[[["31279674038","113383149038",null,[[["1643849995",[3.28125,.37890625,.828125,-.734375,1.3359375,-.625,-.89453125,-2.390625,.7578125,3.40625,1.3515625,.58984375,4.125,-.2734375,-1.125,.6171875,1.2734375,-4.0625,-1.859375,4.3125,-1.84375,.953125,.427734375,
+-3.71875,-4.28125,.2119140625,-3.828125,-.244140625,3.5625,.134765625,-2.9375,3.25]],["1643804092",[3.28125,.345703125,.80859375,-.75390625,1.2890625,-.6015625,-.87109375,-2.375,.72265625,3.40625,1.3203125,.5546875,4.09375,-.255859375,-1.09375,.5859375,1.234375,-4.0625,-1.828125,4.34375,-1.8125,.92578125,.4453125,-3.71875,-4.28125,.185546875,-3.84375,-.267578125,3.5625,.111328125,-2.921875,3.234375]]],null,[["1643822293",[-.32421875,-.203125,.212890625,-.006622314453125,-.224609375,.5234375,.330078125,
+.099609375,-.08203125,-.01239013671875,.41015625,.484375,-.140625,-.0751953125,-.3046875,-.17578125,.251953125,-.25,-.2119140625,.2119140625,.030029296875,.1689453125,.8359375,-.041748046875,-.022216796875,.5546875,-.412109375,-.34375,.1748046875,.1806640625,-.5,-.2470703125]],["1643799063",[-.3359375,-.1572265625,.376953125,-.039306640625,-.1982421875,.515625,.314453125,.076171875,-.0595703125,-.0079345703125,.43359375,.4765625,-.208984375,-.091796875,-.3125,-.1708984375,.23046875,-.23828125,-.1962890625,
+.1787109375,.01556396484375,.220703125,.84375,-.0184326171875,-.052001953125,.51953125,-.4296875,-.458984375,.263671875,.1494140625,-.58203125,-.10498046875]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["31279674038","113383149158",null,[[["1643849995",[3.328125,.369140625,.8125,-.7578125,1.3125,-.56640625,-.84375,-2.25,.478515625,3.484375,1.2734375,.462890625,4.21875,-.265625,-.96875,.4921875,
+1.2109375,-4.03125,-1.640625,3.875,-1.5546875,.7890625,.10302734375,-3.125,-4.4375,.375,-3.96875,-.2236328125,3.5,.3359375,-3.265625,3.515625]],["1643804092",[3.3125,.349609375,.80078125,-.76953125,1.28125,-.5546875,-.828125,-2.234375,.4453125,3.46875,1.25,.44140625,4.1875,-.251953125,-.94921875,.47265625,1.1875,-4.03125,-1.6171875,3.890625,-1.53125,.76953125,.10888671875,-3.109375,-4.4375,.359375,-3.953125,-.236328125,3.5,.32421875,-3.234375,3.5]]],null,[["1643822293",[-.326171875,-.201171875,.1884765625,
+-.0014190673828125,-.2216796875,.53125,.330078125,.10107421875,-.0849609375,-.00994873046875,.404296875,.4765625,-.1513671875,-.07470703125,-.298828125,-.17578125,.25390625,-.2421875,-.2099609375,.2109375,.0322265625,.1728515625,.83203125,-.0380859375,-.0242919921875,.55859375,-.408203125,-.33984375,.177734375,.18359375,-.494140625,-.25390625]],["1643799063",[-.33984375,-.1474609375,.3515625,-.03466796875,-.1923828125,.5078125,.3125,.0712890625,-.057861328125,.01446533203125,.431640625,.46484375,
+-.2109375,-.0927734375,-.310546875,-.17578125,.220703125,-.2294921875,-.1923828125,.1796875,.023681640625,.2314453125,.83984375,-.0205078125,-.049072265625,.51953125,-.41796875,-.4453125,.2734375,.1513671875,-.57421875,-.115234375]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]],["31279674038","113383149518",null,[[["1643849995",[3.15625,.34765625,.8515625,-.74609375,1.2578125,-.56640625,-.85546875,
+-2.40625,.6953125,3.328125,1.265625,.546875,4.09375,-.283203125,-1.0625,.54296875,1.1953125,-3.984375,-1.8046875,4.1875,-1.796875,.95703125,.5,-3.75,-4.25,.1376953125,-3.78125,-.310546875,3.4375,.03173828125,-2.921875,3.1875]],["1643804092",[3.171875,.322265625,.8359375,-.765625,1.2265625,-.546875,-.8359375,-2.390625,.65625,3.328125,1.2421875,.515625,4.0625,-.265625,-1.0390625,.51953125,1.171875,-3.984375,-1.7734375,4.21875,-1.765625,.93359375,.5,-3.71875,-4.25,.12353515625,-3.78125,-.32421875,3.4375,
+.0242919921875,-2.921875,3.1875]]],null,[["1643822293",[-.32421875,-.21484375,.212890625,-.00543212890625,-.2333984375,.52734375,.333984375,.10498046875,-.08740234375,-.0296630859375,.416015625,.49609375,-.1357421875,-.072265625,-.302734375,-.1728515625,.2578125,-.259765625,-.2177734375,.208984375,.028564453125,.1640625,.83984375,-.042724609375,-.0184326171875,.55859375,-.41796875,-.345703125,.162109375,.185546875,-.5078125,-.25390625]],["1643799063",[-.345703125,-.1650390625,.375,-.041748046875,
+-.1962890625,.51953125,.318359375,.08056640625,-.06396484375,-.004486083984375,.447265625,.486328125,-.197265625,-.0888671875,-.3203125,-.166015625,.234375,-.2431640625,-.2041015625,.1826171875,.01495361328125,.2216796875,.84765625,-.029052734375,-.044921875,.53125,-.431640625,-.4609375,.2578125,.1494140625,-.5859375,-.115234375]]],null,null,null,null,[[null,[176.8618621826172,1],[1,2],[1,1],null,3]]],[null,[[2,0,null,["PubPolicy1"]]]],"608936333",null,null,null,[[2,1,7]],[[2,1,5]]]]],"1j475122041":[[["60795725037",
+"306664789872",null,[[["1643849995",[3.421875,1.78125,1.6796875,.048095703125,2.796875,-1.3984375,-1.703125,-3.5625,1.328125,3.796875,2.265625,1.5,5.125,-.80078125,-1.8515625,1.1796875,2.203125,-4.53125,-2.78125,3.5625,-2.265625,1.6796875,-.76171875,-2.8125,-5.09375,1.5078125,-4.5,.59375,3.609375,1.359375,-4.78125,4.375]],["1643804092",[3.40625,1.75,1.6640625,.0306396484375,2.75,-1.3828125,-1.6875,-3.53125,1.3125,3.78125,2.25,1.4765625,5.09375,-.79296875,-1.828125,1.171875,2.171875,-4.53125,-2.765625,
+3.5625,-2.25,1.6640625,-.73046875,-2.84375,-5.0625,1.4765625,-4.5,.56640625,3.609375,1.3203125,-4.75,4.34375]]],null,[["1643822293",[1.2734375,1.0859375,.298828125,.09619140625,.10107421875,-.09375,-.52734375,-.953125,-.1259765625,-.5078125,-.1611328125,-.498046875,-1.3515625,-.412109375,.94140625,-.33984375,-.578125,.2578125,.47265625,-.478515625,.255859375,-.1005859375,-.06396484375,.166015625,-.9765625,.029541015625,.314453125,.0106201171875,.74609375,-.38671875,.83984375,.75390625]],["1643799063",
+[1.3046875,1.0625,.3828125,.06201171875,.1142578125,-.046875,-.52734375,-.94921875,-.134765625,-.56640625,-.08740234375,-.439453125,-1.3671875,-.4296875,1.046875,-.33203125,-.5625,.2734375,.50390625,-.54296875,.1728515625,-.123046875,-.0233154296875,.1962890625,-1.0546875,.05859375,.318359375,-.0537109375,.8125,-.423828125,.79296875,.953125]]],null,null,null,null,[[null,[61170.82421875,1],[1,2],[1,1],null,3]]],[null,[[3,0,null,["AdvControlbrand-unsafe"]]]],"1614272341"]]]};function xb(a,b){return!b||0>=b?a:Math.min(a,b)}function R(a,b,c){return b?b:c?c:a?1:0}function yb(a){a=null==a?void 0:G(a,9,0);return void 0===a?!1:[61,51,52].includes(a)};var S=function(a){Q.call(this,a,-1,zb)};t(S,Q);var zb=[2];var Ab=function(a){Q.call(this,a)};t(Ab,Q);var Cb=function(a){Q.call(this,a,-1,Bb)};t(Cb,Q);Cb.prototype.ca=function(){return N(this,Ab,3)};var Bb=[2,3];var Eb=function(a){Q.call(this,a,-1,Db)};t(Eb,Q);var Gb=function(a){Q.call(this,a,-1,Fb)};t(Gb,Q);var Ib=function(a){Q.call(this,a,-1,Hb)};t(Ib,Q);Ib.prototype.ca=function(){return N(this,Ab,5)};var Db=[1,2],Fb=[3,4],Hb=[3,4,5];var Kb=function(a){Q.call(this,a,-1,Jb)};t(Kb,Q);var T=function(a){return M(a,Lb,3)},Nb=function(a){Q.call(this,a,-1,Mb)};t(Nb,Q);Nb.prototype.Y=function(){return N(this,S,2)};Nb.prototype.ma=function(){return N(this,S,3)};var Ob=function(a){Q.call(this,a)};t(Ob,Q);Ob.prototype.u=function(){return O(this,1)};Ob.prototype.v=function(){return O(this,2)};Ob.prototype.da=function(){return J(this,3)};var Lb=function(a){Q.call(this,a)};t(Lb,Q);var U=function(a){Q.call(this,a)};t(U,Q);
+var V=function(a){Q.call(this,a)};t(V,Q);var Rb=function(a){var b=new V;return L(b,1,a)},X=function(a){Q.call(this,a)};t(X,Q);X.prototype.u=function(){return O(this,2)};X.prototype.v=function(){return O(this,3)};X.prototype.W=function(){return O(this,4)};X.prototype.da=function(){return J(this,5)};var Jb=[2],Mb=[1,2,3];function Sb(a,b,c){if(!b||0>=b)return{l:0,P:1};var d=R(!0,null==a?void 0:J(a,1),null==c?void 0:J(c,1)),e=R(!1,null==a?void 0:J(a,2),null==c?void 0:J(c,2)),g=R(!1,null==a?void 0:J(a,3),null==c?void 0:J(c,3)),f,h;a=R(!1,null==a?void 0:null==(f=M(a,V,5))?void 0:J(f,1),null==c?void 0:null==(h=M(c,V,5))?void 0:J(h,1));c=new U;f=L(c,1,d);f=L(f,2,e);f=L(f,3,g);h=Rb(a);eb(f,V,5,h);return{l:b*d*(1-1/(1+Math.exp(-e*(Math.log(b/1E6)-a-g)))),P:4,sa:c}};function Tb(a,b){var c=null==a?void 0:M(a,U,6),d,e=null==a?void 0:null==(d=T(a))?void 0:M(d,U,3);if(!b||0>=b)return{l:0,P:1};var g;if(!(null==a?0:null==(g=T(a))?0:I(g,2)))return{l:.85*b,P:2};d=R(!0,null==c?void 0:J(c,4),null==e?void 0:J(e,4));g=R(!0,null==c?void 0:J(c,1),null==e?void 0:J(e,1));var f=R(!1,null==c?void 0:J(c,2),null==e?void 0:J(e,2)),h=R(!1,null==c?void 0:J(c,3),null==e?void 0:J(e,3)),l,k;c=R(!1,null==c?void 0:null==(l=M(c,V,5))?void 0:J(l,1),null==e?void 0:null==(k=M(e,V,5))?void 0:
+J(k,1));l=new U;k=L(l,1,g);k=L(k,2,f);k=L(k,3,h);k=L(k,4,d);var m=Rb(c);eb(k,V,5,m);d=d*b*g*(1-1/(1+Math.exp(-f*(Math.log(d*b/1E6)-c-h))));g=1E6*(null==a?NaN:J(a,8));var q;if((null==a?0:null==(q=T(a))?0:I(q,6))&&d<g&&g<b){var y;d=g+1E6*(null!=(y=null==e?void 0:J(e,7))?y:0)*Math.log(b/g)}return{l:d,P:3,sa:l}};function Ub(a,b){if(!(0<F(a,2).length&&F(a,2).length===E(a,3).length&&F(a,2).length===F(a,4).length))return 0;for(var c=0,d=0,e=1,g=r(E(a,3)),f=g.next();!f.done;f=g.next()){var h=0;switch(f.value){case 1:h=F(a,2)[d]*(b.ea?Math.pow(b.ea,F(a,4)[d]):0);break;case 2:c=h=F(a,2)[d]*(b.oa?Math.pow(b.oa,F(a,4)[d]):0);break;case 3:h=F(a,2)[d]}if(0===h)return 0;e*=h;d+=1}0<J(a,7)&&(e=Math.min(e,J(a,7)*c*1E3));return 1E6*e}
+function Vb(a,b){var c=0;b&&(0<N(b,Wb,7).length?c=Ub(N(b,Wb,7)[0],a):0<N(b,Wb,8).length&&(c=Ub(N(b,Wb,8)[0],a)));return c};function Xb(a,b,c){if(G(a,2,0)!==G(b,2,0))return c;var d=!1;switch(G(a,2,0)){case 1:a:{var e,g=new Set(null!=(e=E(a,3))?e:[]);b=r(E(b,3));for(e=b.next();!e.done;e=b.next())if(g.has(e.value)){d=!0;break a}d=!1}break;case 0:a:{e=new Set(null!=(g=E(a,4))?g:[]);b=r(E(b,4));for(g=b.next();!g.done;g=b.next())if(e.has(g.value)){d=!0;break a}d=!1}break;case 2:b=new Yb(b),d=(e=M(a,Cb,5))?Zb(b,e):!1}return I(a,6)?d?null:c:d?c:null}
+function Zb(a,b){var c=G(b,1,0),d=b.ca(),e=N(b,Cb,2);switch(c){case 2:c=d.every(function(g){return $b(a,g)})&&e.every(function(g){return Zb(a,g)});break;case 1:c=d.some(function(g){return $b(a,g)})||e.some(function(g){return Zb(a,g)});break;default:throw Error("unexpected value "+c+"!");}return I(b,4)?!c:c}
+var Yb=function(a){this.ga=new Map;a=r(a.ca());for(var b=a.next();!b.done;b=a.next()){var c=b.value;b=G(c,1,0);c=G(c,2,0);var d=this.ga.get(b);d||(d=new Set,this.ga.set(b,d));d.add(c)}},$b=function(a,b){var c=G(b,2,0);return(a=a.ga.get(G(b,1,0)))?a.has(c):!1};function ac(a,b){a=r((null==b?void 0:b.get(a))||[]);for(b=a.next();!b.done;b=a.next())if(b=b.value,b.count+1>b.xa)return!1;return!0};function bc(a,b){return null==a.na?!0:!a.na.some(function(c){var d;return null==(d=b.Ba)?void 0:d.includes(c,0)})};var cc=function(a){Q.call(this,a)};t(cc,Q);n=cc.prototype;n.u=function(){return O(this,1)};n.v=function(){return O(this,2)};n.W=function(){return O(this,3)};n.V=function(){return O(this,4)};n.U=function(){return O(this,5)};n.X=function(){return O(this,6)};var ec=function(a){Q.call(this,a,-1,dc)};t(ec,Q);var dc=[1];function fc(a,b){var c=!0;c=void 0===c?!1:c;return gc(0,(null==a?void 0:N(a,S,1))||[],(null==b?void 0:N(b,S,1))||[],c)}function hc(a,b){var c=!0;c=void 0===c?!1:c;return gc(1,(null==a?void 0:a.Y())||[],(null==b?void 0:b.Y())||[],c)}function ic(a,b){var c=!0;c=void 0===c?!1:c;return gc(1,(null==a?void 0:a.ma())||[],(null==b?void 0:b.Y())||[],c)}
+function gc(a,b,c,d){var e=0,g=new Map;b=r(b);for(var f=b.next();!f.done;f=b.next())e=f.value,g.set(G(e,1,""),e),e=J(e,3);b=null;c=r(c);for(f=c.next();!f.done;f=c.next()){var h=f.value;e=J(h,3);if(f=d?g.values().next().value:g.get(G(h,1,""))){a:{b=a;f=F(f,2);h=F(h,2);if(f.length===h.length){for(var l=0,k=0;k<f.length;k++)l+=f[k]*h[k];f=l}else f=void 0;if(void 0!==f)switch(b){case 0:b=1/(1+Math.exp(-1*f));break a;case 1:b=Math.exp(f);break a}b=void 0}if(void 0!==b)return b;b=e}}var m;return null!=
+(m=b)?m:e};var jc=function(a){Q.call(this,a)};t(jc,Q);function kc(a,b,c){"0"===a||c.has(a)||c.set(a,b.filter(function(d){return 0<G(d,3,0)}).map(function(d){var e=G(d,3,0);switch(G(d,1,0)){case 6:d=60*G(d,2,0);break;case 1:d=3600*G(d,2,0);break;case 2:d=86400*G(d,2,0);break;case 3:d=604800*G(d,2,0);break;case 4:d=2592E3*G(d,2,0);break;case 5:d=null;break;default:e=d=0}return{pa:d,xa:e,count:0}}))}function lc(a,b,c){if(b=c.get(b))for(b=r(b),c=b.next();!c.done;c=b.next())c=c.value,(null===c.pa||a.Aa<=c.pa)&&c.count++};var Wb=function(a){Q.call(this,a,-1,mc)};t(Wb,Q);var mc=[2,3,4];var oc=function(a){Q.call(this,a,-1,nc)};t(oc,Q);oc.prototype.Y=function(){return N(this,S,3)};oc.prototype.ma=function(){return N(this,S,10)};var nc=[1,3,10,7,8];var qc=function(a){Q.call(this,a,-1,pc)};t(qc,Q);n=qc.prototype;n.u=function(){return O(this,1)};n.v=function(){return O(this,2)};n.W=function(){return O(this,3)};n.V=function(){return O(this,6)};n.U=function(){return O(this,7)};n.X=function(){return O(this,8)};var pc=[9,10,11,12,13,14];var sc=function(a){Q.call(this,a,-1,rc)};t(sc,Q);var rc=[1];var uc=function(a){Q.call(this,a,-1,tc)};t(uc,Q);var tc=[1];var vc={ad:{},bid:0,render:""};function wc(){new uc;return function(a,b,c,d,e){return xc(a,c,d,e)}}
+function xc(a,b,c,d){b=b?new Kb(qb(b)):void 0;var e,g;if(!b||!(N(b,Ob,2).length||(null==(e=T(b))?0:I(e,1))||(null==(g=T(b))?0:I(g,5))))return vc;e=new ec(qb(a.userBiddingSignals));g=a.ads.map(function(f){return{renderUrl:f.renderUrl,metadata:new cc(qb(f.metadata))}});c=c[a.name]?new sc(qb(c[a.name])):void 0;d=d.prevWins.map(function(f){return{Aa:f[0],I:new cc(qb(f[1].metadata))}});return yc(a.name,e,g,d,c,b)}
+function yc(a,b,c,d,e,g){var f,h={Ja:null!=(f=null==g?void 0:T(g))?f:void 0,T:new Map,O:new Map,R:new Map,S:new Map,Z:new Map,interestGroupName:null!=a?a:void 0};a=new Map;if(e){e=r(N(e,qc,1));for(f=e.next();!f.done;f=e.next())f=f.value,a.set(f.u().concat("+",f.v(),"+",f.W()),f),kc(f.v(),N(f,jc,9),h.T),kc(f.u(),N(f,jc,10),h.O),kc(f.V(),N(f,jc,11),h.R),kc(f.U(),N(f,jc,12),h.S),kc(f.X(),N(f,jc,13),h.Z);d=r(d);for(e=d.next();!e.done;e=d.next())e=e.value,h.T&&lc(e,e.I.v(),h.T),h.O&&lc(e,e.I.u(),h.O),
+h.R&&lc(e,e.I.V(),h.R),h.S&&lc(e,e.I.U(),h.S),h.Z&&lc(e,e.I.X(),h.Z)}e=new Map;if(g)for(d=r(N(g,Ob,2)),f=d.next();!f.done;f=d.next())f=f.value,e.set(f.u().concat("+",f.v(),"+",""),f.da());d=[];c=r(c);for(f=c.next();!f.done;f=c.next()){f=f.value;f={renderUrl:f.renderUrl,H:f.metadata.u(),K:f.metadata.v(),ka:f.metadata.W(),ja:f.metadata.V(),ia:f.metadata.U(),la:f.metadata.X(),i:0,J:0};var l=f.H.concat("+",f.K,"+",f.ka);f.aa=e.get(f.H.concat("+",f.K,"+",""));if(!f.aa){var k=void 0,m=void 0,q=void 0,y=
+void 0;if(!(null==(k=g)?0:null==(m=T(k))?0:I(m,1))&&!(null==(q=g)?0:null==(y=T(q))?0:I(y,5)))continue;else if(!a.get(l))continue;m=k=void 0;f.o=null!=(m=null==(k=a.get(l))?void 0:M(k,oc,4))?m:void 0}m=k=void 0;f.ha=null!=(m=null==(k=a.get(l))?void 0:M(k,Eb,5))?m:void 0;m=k=void 0;f.na=null!=(m=null==(k=a.get(l))?void 0:E(k,14))?m:void 0;d.push(f)}if(c=null==g?void 0:M(g,Eb,5)){a=new Map;e=new Map;f=r(N(c,Gb,1));for(l=f.next();!l.done;l=f.next())l=l.value,a.set(G(l,1,0),l);c=r(N(c,Ib,2));for(f=c.next();!f.done;f=
+c.next())f=f.value,e.set(G(f,1,0),f);h.ta=a;h.ua=e}var H;h.Ba=null!=(H=E(b,1))?H:void 0;b=[];H=new Map;a=r(d);for(d=a.next();!d.done;d=a.next())if(d=d.value,e=h,!(!ac(d.K,e.T)||!ac(d.H,e.O)||d.ja&&!ac(d.ja,e.R)||d.ia&&!ac(d.ia,e.S)||d.la&&!ac(d.la,e.Z))){if(d.ha){c=h;e=c.ta;c=c.ua;f=d.ha;if(e&&c&&f)a:{l=r(N(f,Gb,1));for(k=l.next();!k.done;k=l.next()){q=k.value;y=G(q,1,0);var fa=c.get(y);if(fa){if(I(q,7)){k=H.get(y);m=G(q,8,0);if(void 0===k)k=new Map,H.set(y,k);else{var qa=k.get(m);if(void 0!==qa){e=
+qa;break a}}q=Xb(q,fa,y);k.set(m,q)}else q=Xb(q,fa,y);if(q){e=q;break a}}}c=r(N(f,Ib,2));for(f=c.next();!f.done;f=c.next())if(f=f.value,l=G(f,1,0),k=e.get(l))if(f=Xb(k,f,l)){e=f;break a}e=null}else e=null;if(e)continue}bc(d,h)&&b.push(d)}return zc({ads:b,ya:h},g).bidResponse}
+function zc(a,b){for(var c=[],d=[],e=r(a.ads),g=e.next();!g.done;g=e.next()){g=g.value;var f=void 0,h=void 0;if(null==(f=b)?0:null==(h=T(f))?0:I(h,7)){var l=h=f=void 0,k=void 0,m=void 0,q=void 0;g.H===(null==(f=b)?void 0:null==(h=M(f,X,16))?void 0:h.u())&&g.K===(null==(l=b)?void 0:null==(k=M(l,X,16))?void 0:k.v())&&a.ya.interestGroupName===(null==(m=b)?void 0:null==(q=M(m,X,16))?void 0:G(q,1,""))?(l=h=f=void 0,k=null!=(l=null==(f=b)?void 0:null==(h=M(f,X,16))?void 0:h.da())?l:0,g.i=0===k?1E9:k):g.i=
+0}else if(null!=g.aa){g.i=g.aa;c.push(g);continue}else if(h=f=void 0,null==(f=b)?0:null==(h=T(f))?0:I(h,1))yb(g.o)?(f=void 0,g.ea=ic(null==(f=b)?void 0:M(f,Nb,1),g.o)):(f=void 0,g.oa=fc(null==(f=b)?void 0:M(f,Nb,1),g.o),f=void 0,g.ea=hc(null==(f=b)?void 0:M(f,Nb,1),g.o)),g.i=Vb(g,g.o),g.i||(h=f=void 0,g.i=null!=(h=null==(f=g.o)?void 0:J(f,6))?h:0);else if(h=f=void 0,null==(f=b)?0:null==(h=T(f))?0:I(h,5))h=f=void 0,g.i=null!=(h=null==(f=g.o)?void 0:J(f,6))?h:0;d.push(g)}c={renderUrl:"",H:"",K:"",ka:"",
+i:0,J:0};var y;if(null==b?0:null==(y=T(b))?0:I(y,7))b=a.ads.reduce(function(W,K){return W.i<K.i?K:W},c),b.J=b.i;else{y=a.ads.reduce(function(W,K){return!yb(K.o)&&W.i<K.i?K:W},c);c=a.ads.reduce(function(W,K){return yb(K.o)&&W.i<K.i?K:W},c);a=Tb(b,null==y?void 0:y.i);var H,fa;a.l=xb(a.l,null==b?void 0:null==(H=T(b))?void 0:null==(fa=M(H,U,3))?void 0:J(fa,6));var qa;H=Sb(null==b?void 0:M(b,U,7),null==c?void 0:c.i,null==b?void 0:null==(qa=T(b))?void 0:M(qa,U,4));var Pb,Qb;H.l=xb(H.l,null==b?void 0:null==
+(Pb=T(b))?void 0:null==(Qb=M(Pb,U,4))?void 0:J(Qb,6));a.l>H.l?(b=y,b.J=a.l):(b=c,b.J=H.l)}return{bidResponse:{ad:{},bid:b.J,render:b.renderUrl},debugInfo:void 0}};var Ac={generateBidTime:0,success:!1},Bc=["metrics"],Y=oa;Bc[0]in Y||"undefined"==typeof Y.execScript||Y.execScript("var "+Bc[0]);for(var Z;Bc.length&&(Z=Bc.shift());)Bc.length||void 0===Ac?Y=Y[Z]&&Y[Z]!==Object.prototype[Z]?Y[Z]:Y[Z]={}:Y[Z]=Ac;var Cc=function(){var a={maxFloorCpmUsdMicros:"6250"},b={topWindowHostname:"www.cnn.com",seller:"https://pubads.g.doubleclick.net",joinCount:7,bidCount:0,prevWins:[]},c=wc();return function(){return c(vb,a,ub,wb,b)}};
+
+function generateBid(){var a=Cc(),b=Date.now()
+;a=a();Ac.generateBidTime=Date.now()-b;Ac.success=JSON.stringify(a)===JSON.stringify({ad:{},bid:2937687.988333709,render:"https://googleads.g.doubleclick.net/ads/simple-ad.html?adg_id=52836427830&cr_id=310927197294&cv_id=4"});Ac.bidResponse=a;return Ac}
\ No newline at end of file
diff --git a/apct-tests/perftests/rubidium/src/android/rubidium/js/JSScriptEnginePerfTests.java b/apct-tests/perftests/rubidium/src/android/rubidium/js/JSScriptEnginePerfTests.java
new file mode 100644
index 0000000..ac36ac2
--- /dev/null
+++ b/apct-tests/perftests/rubidium/src/android/rubidium/js/JSScriptEnginePerfTests.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this 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.rubidium.js;
+
+import static com.android.adservices.service.js.JSScriptArgument.numericArg;
+import static com.android.adservices.service.js.JSScriptArgument.recordArg;
+import static com.android.adservices.service.js.JSScriptArgument.stringArg;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+
+import androidx.annotation.NonNull;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.adservices.service.js.JSScriptArgument;
+import com.android.adservices.service.js.JSScriptEngine;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class JSScriptEnginePerfTests {
+    private static final String TAG = JSScriptEnginePerfTests.class.getSimpleName();
+    protected static final Context sContext = ApplicationProvider.getApplicationContext();
+    private final ExecutorService mExecutorService = Executors.newFixedThreadPool(10);
+    private final JSScriptEngine mJSScriptEngine = new JSScriptEngine(sContext);
+
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void evaluate_helloWorld() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            String res =
+                    callJSEngine(
+                            "function test() { return \"hello world\";" + " }",
+                            ImmutableList.of(),
+                            "test");
+            assertThat(res).isEqualTo("\"hello world\"");
+        }
+    }
+
+    @Test
+    public void evaluate_emptyGenerateBid() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        state.pauseTiming();
+
+        InputStream testJsInputStream = sContext.getAssets().open("empty_generate_bid.js");
+        String jsTestFile = new String(testJsInputStream.readAllBytes(), StandardCharsets.UTF_8);
+        JSScriptArgument adDataArgument =
+                recordArg(
+                        "ad",
+                        stringArg("render_url", "http://google.com"),
+                        recordArg("metadata", numericArg("input", 10)));
+        callJSEngine(jsTestFile, ImmutableList.of(adDataArgument), "generateBid");
+
+        state.resumeTiming();
+        while (state.keepRunning()) {
+            callJSEngine(
+                    jsTestFile, ImmutableList.of(adDataArgument), "generateBid");
+        }
+    }
+
+    @Test
+    public void evaluate_turtledoveSampleGenerateBid() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        state.pauseTiming();
+
+        InputStream testJsInputStream = sContext.getAssets().open("turtledove_generate_bid.js");
+        String jsTestFile =
+                new String(testJsInputStream.readAllBytes(), StandardCharsets.UTF_8);
+        // Initialize the environment with one call.
+        callJSEngine(jsTestFile, ImmutableList.of(), "generateBid");
+
+        state.resumeTiming();
+        while (state.keepRunning()) {
+            callJSEngine(jsTestFile, ImmutableList.of(), "generateBid");
+        }
+    }
+
+    private String callJSEngine(
+            @NonNull String jsScript,
+            @NonNull List<JSScriptArgument> args,
+            @NonNull String functionName)
+            throws Exception {
+        return callJSEngine(mJSScriptEngine, jsScript, args, functionName);
+    }
+
+    private String callJSEngine(
+            @NonNull JSScriptEngine jsScriptEngine,
+            @NonNull String jsScript,
+            @NonNull List<JSScriptArgument> args,
+            @NonNull String functionName)
+            throws Exception {
+        CountDownLatch resultLatch = new CountDownLatch(1);
+        ListenableFuture<String> futureResult =
+                callJSEngineAsync(jsScriptEngine, jsScript, args, functionName, resultLatch);
+        resultLatch.await();
+        return futureResult.get();
+    }
+
+    private ListenableFuture<String> callJSEngineAsync(
+            @NonNull String jsScript,
+            @NonNull List<JSScriptArgument> args,
+            @NonNull String functionName,
+            @NonNull CountDownLatch resultLatch) {
+        return callJSEngineAsync(mJSScriptEngine, jsScript, args, functionName, resultLatch);
+    }
+
+    private ListenableFuture<String> callJSEngineAsync(
+            @NonNull JSScriptEngine engine,
+            @NonNull String jsScript,
+            @NonNull List<JSScriptArgument> args,
+            @NonNull String functionName,
+            @NonNull CountDownLatch resultLatch) {
+        Objects.requireNonNull(engine);
+        Objects.requireNonNull(resultLatch);
+        ListenableFuture<String> result = engine.evaluate(jsScript, args, functionName);
+        result.addListener(resultLatch::countDown, mExecutorService);
+        return result;
+    }
+}
diff --git a/config/OWNERS b/config/OWNERS
index c0778f8..74813bc 100644
--- a/config/OWNERS
+++ b/config/OWNERS
@@ -1,8 +1,8 @@
 include /ZYGOTE_OWNERS
 
 # art-team@ manages the boot image profiles
-per-file boot-* = calin@google.com, ngeoffray@google.com, vmarko@google.com
-per-file dirty-image-objects = calin@google.com, ngeoffray@google.com, vmarko@google.com
-per-file generate-preloaded-classes.sh = calin@google.com, ngeoffray@google.com, vmarko@google.com
-per-file preloaded-classes* = calin@google.com, ngeoffray@google.com, vmarko@google.com
+per-file boot-* = ngeoffray@google.com, vmarko@google.com
+per-file dirty-image-objects = ngeoffray@google.com, vmarko@google.com
+per-file generate-preloaded-classes.sh = ngeoffray@google.com, vmarko@google.com
+per-file preloaded-classes* = ngeoffray@google.com, vmarko@google.com
 
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 2664f05..22af712 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -347,7 +347,15 @@
     private static final int EX_SERVICE_SPECIFIC = -8;
     private static final int EX_PARCELABLE = -9;
     /** @hide */
+    // WARNING: DO NOT add more 'reply' headers. These also need to add work to native
+    // code and this encodes extra information in object statuses. If we need to expand
+    // this design, we should add a generic way to attach parcelables/structured parcelables
+    // to transactions which can work across languages.
     public static final int EX_HAS_NOTED_APPOPS_REPLY_HEADER = -127; // special; see below
+    // WARNING: DO NOT add more 'reply' headers. These also need to add work to native
+    // code and this encodes extra information in object statuses. If we need to expand
+    // this design, we should add a generic way to attach parcelables/structured parcelables
+    // to transactions which can work across languages.
     private static final int EX_HAS_STRICTMODE_REPLY_HEADER = -128;  // special; see below
     // EX_TRANSACTION_FAILED is used exclusively in native code.
     // see libbinder's binder/Status.h
diff --git a/core/java/android/window/PictureInPictureSurfaceTransaction.java b/core/java/android/window/PictureInPictureSurfaceTransaction.java
index 0a751c3..3b1fdf5 100644
--- a/core/java/android/window/PictureInPictureSurfaceTransaction.java
+++ b/core/java/android/window/PictureInPictureSurfaceTransaction.java
@@ -51,6 +51,8 @@
 
     private final Rect mWindowCrop;
 
+    private boolean mShouldDisableCanAffectSystemUiFlags;
+
     private PictureInPictureSurfaceTransaction(Parcel in) {
         mAlpha = in.readFloat();
         mPosition = in.readTypedObject(PointF.CREATOR);
@@ -60,6 +62,7 @@
         mCornerRadius = in.readFloat();
         mShadowRadius = in.readFloat();
         mWindowCrop = in.readTypedObject(Rect.CREATOR);
+        mShouldDisableCanAffectSystemUiFlags = in.readBoolean();
     }
 
     private PictureInPictureSurfaceTransaction(float alpha, @Nullable PointF position,
@@ -84,6 +87,7 @@
         this(other.mAlpha, other.mPosition,
                 other.mFloat9, other.mRotation, other.mCornerRadius, other.mShadowRadius,
                 other.mWindowCrop);
+        mShouldDisableCanAffectSystemUiFlags = other.mShouldDisableCanAffectSystemUiFlags;
     }
 
     /** @return {@link Matrix} from {@link #mFloat9} */
@@ -103,6 +107,16 @@
         return mShadowRadius > 0;
     }
 
+    /** Sets the internal {@link #mShouldDisableCanAffectSystemUiFlags}. */
+    public void setShouldDisableCanAffectSystemUiFlags(boolean shouldDisable) {
+        mShouldDisableCanAffectSystemUiFlags = shouldDisable;
+    }
+
+    /** @return {@code true} if we should disable Task#setCanAffectSystemUiFlags. */
+    public boolean getShouldDisableCanAffectSystemUiFlags() {
+        return mShouldDisableCanAffectSystemUiFlags;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
@@ -114,13 +128,16 @@
                 && Objects.equals(mRotation, that.mRotation)
                 && Objects.equals(mCornerRadius, that.mCornerRadius)
                 && Objects.equals(mShadowRadius, that.mShadowRadius)
-                && Objects.equals(mWindowCrop, that.mWindowCrop);
+                && Objects.equals(mWindowCrop, that.mWindowCrop)
+                && mShouldDisableCanAffectSystemUiFlags
+                == that.mShouldDisableCanAffectSystemUiFlags;
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(mAlpha, mPosition, Arrays.hashCode(mFloat9),
-                mRotation, mCornerRadius, mShadowRadius, mWindowCrop);
+                mRotation, mCornerRadius, mShadowRadius, mWindowCrop,
+                mShouldDisableCanAffectSystemUiFlags);
     }
 
     @Override
@@ -137,6 +154,7 @@
         out.writeFloat(mCornerRadius);
         out.writeFloat(mShadowRadius);
         out.writeTypedObject(mWindowCrop, 0 /* flags */);
+        out.writeBoolean(mShouldDisableCanAffectSystemUiFlags);
     }
 
     @Override
@@ -150,6 +168,7 @@
                 + " cornerRadius=" + mCornerRadius
                 + " shadowRadius=" + mShadowRadius
                 + " crop=" + mWindowCrop
+                + " shouldDisableCanAffectSystemUiFlags" + mShouldDisableCanAffectSystemUiFlags
                 + ")";
     }
 
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 6771cdf..17a47d3 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -764,7 +764,7 @@
      * @return true if device is file encrypted
      */
     public static boolean isFileEncryptionEnabled() {
-        return StorageManager.isFileEncryptedNativeOrEmulated();
+        return StorageManager.isFileEncrypted();
     }
 
     /**
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 3436b9e..6a31a62 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -1456,7 +1456,7 @@
 
         // Some devices can be field-converted to FBE, so offer to splice in
         // those features if not already defined by the static config
-        if (StorageManager.isFileEncryptedNativeOnly()) {
+        if (StorageManager.isFileEncrypted()) {
             addFeature(PackageManager.FEATURE_FILE_BASED_ENCRYPTION, 0);
             addFeature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, 0);
         }
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index ac507f9..766a12e 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -5699,6 +5699,9 @@
     <!-- Determines whether SafetyCenter feature is enabled. -->
     <bool name="config_enableSafetyCenter">true</bool>
 
+    <!-- Config for whether Safety Protection is enabled. -->
+    <bool name="config_safetyProtectionEnabled">false</bool>
+
     <!-- Flag indicating if help links for Settings app should be enabled. -->
     <bool name="config_settingsHelpLinksEnabled">false</bool>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 2ae4484..7a86f7e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4755,6 +4755,8 @@
 
   <java-symbol type="bool" name="config_enableSafetyCenter" />
 
+  <java-symbol type="bool" name="config_safetyProtectionEnabled" />
+
   <java-symbol type="string" name="config_devicePolicyManagementUpdater" />
 
   <java-symbol type="string" name="config_deviceSpecificDeviceStatePolicyProvider" />
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
index fb26cb6..692e6acb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
@@ -106,8 +106,6 @@
                 taskInfo.taskId);
         state.mTaskInfo = taskInfo;
         mWindowDecorationViewModel.onTaskInfoChanged(state.mTaskInfo, state.mWindowDecoration);
-        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Info Changed: #%d",
-                taskInfo.taskId);
     }
 
     @Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsAlgorithm.java
index a2eadcd..815f3dd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsAlgorithm.java
@@ -29,7 +29,6 @@
 import android.content.res.Resources;
 import android.graphics.Insets;
 import android.graphics.Rect;
-import android.util.ArraySet;
 import android.util.Size;
 import android.view.Gravity;
 
@@ -139,25 +138,9 @@
         final Rect insetBounds = new Rect();
         getInsetBounds(insetBounds);
 
-        Set<Rect> restrictedKeepClearAreas = mTvPipBoundsState.getRestrictedKeepClearAreas();
-        Set<Rect> unrestrictedKeepClearAreas = mTvPipBoundsState.getUnrestrictedKeepClearAreas();
-
-        if (mTvPipBoundsState.isImeShowing()) {
-            if (DEBUG) {
-                ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
-                        "%s: IME showing, height: %d",
-                        TAG, mTvPipBoundsState.getImeHeight());
-            }
-
-            final Rect imeBounds = new Rect(
-                    0,
-                    insetBounds.bottom - mTvPipBoundsState.getImeHeight(),
-                    insetBounds.right,
-                    insetBounds.bottom);
-
-            unrestrictedKeepClearAreas = new ArraySet<>(unrestrictedKeepClearAreas);
-            unrestrictedKeepClearAreas.add(imeBounds);
-        }
+        final Set<Rect> restrictedKeepClearAreas = mTvPipBoundsState.getRestrictedKeepClearAreas();
+        final Set<Rect> unrestrictedKeepClearAreas =
+                mTvPipBoundsState.getUnrestrictedKeepClearAreas();
 
         mKeepClearAlgorithm.setGravity(mTvPipBoundsState.getTvPipGravity());
         mKeepClearAlgorithm.setScreenSize(screenSize);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 00ecdf4..0c502283 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -30,6 +30,7 @@
 import android.view.SurfaceControl;
 import android.view.SurfaceControlViewHost;
 import android.view.View;
+import android.view.ViewRootImpl;
 import android.view.WindowManager;
 import android.view.WindowlessWindowManager;
 import android.window.WindowContainerTransaction;
@@ -201,12 +202,16 @@
             mViewHost.relayout(lp);
         }
 
-        outResult.mRootView.setTaskFocusState(mTaskInfo.isFocused);
+        if (ViewRootImpl.CAPTION_ON_SHELL) {
+            outResult.mRootView.setTaskFocusState(mTaskInfo.isFocused);
 
-        // Caption insets
-        mCaptionInsetsRect.set(taskBounds);
-        mCaptionInsetsRect.bottom = mCaptionInsetsRect.top + captionHeight;
-        wct.addRectInsetsProvider(mTaskInfo.token, mCaptionInsetsRect, CAPTION_INSETS_TYPES);
+            // Caption insets
+            mCaptionInsetsRect.set(taskBounds);
+            mCaptionInsetsRect.bottom = mCaptionInsetsRect.top + captionHeight;
+            wct.addRectInsetsProvider(mTaskInfo.token, mCaptionInsetsRect, CAPTION_INSETS_TYPES);
+        } else {
+            outResult.mRootView.setVisibility(View.GONE);
+        }
 
         // Task surface itself
         Point taskPosition = mTaskInfo.positionInParent;
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt
index 5a364dd..f73d191 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt
@@ -107,33 +107,6 @@
         uiDevice.wait(Until.gone(By.res(SYSTEMUI_PACKAGE, "dismiss")), FIND_TIMEOUT)
     }
 
-    @JvmOverloads
-    fun enterPipViaHomeButton(wmHelper: WindowManagerStateHelper) {
-        uiDevice.pressHome()
-
-        // Wait on WMHelper or simply wait for 3 seconds
-        wmHelper.waitPipShown() ?: SystemClock.sleep(3_000)
-        // when entering pip, the dismiss button is visible at the start. to ensure the pip
-        // animation is complete, wait until the pip dismiss button is no longer visible.
-        // b/176822698: dismiss-only state will be removed in the future
-        uiDevice.wait(Until.gone(By.res(SYSTEMUI_PACKAGE, "dismiss")), FIND_TIMEOUT)
-    }
-
-    @JvmOverloads
-    fun enterPipViaSwipeToHome(wmHelper: WindowManagerStateHelper) {
-        uiDevice.swipe(
-            uiDevice.displayWidth / 2, uiDevice.displayHeight - 10,
-            uiDevice.displayWidth / 2, uiDevice.displayHeight - 300, 3
-        )
-
-        // Wait on WMHelper or simply wait for 3 seconds
-        wmHelper.waitPipShown() ?: SystemClock.sleep(3_000)
-        // when entering pip, the dismiss button is visible at the start. to ensure the pip
-        // animation is complete, wait until the pip dismiss button is no longer visible.
-        // b/176822698: dismiss-only state will be removed in the future
-        uiDevice.wait(Until.gone(By.res(SYSTEMUI_PACKAGE, "dismiss")), FIND_TIMEOUT)
-    }
-
     fun enableEnterPipOnUserLeaveHint() {
         clickObject(ENTER_PIP_ON_USER_LEAVE_HINT)
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
index 24d82a2..2514e3b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
@@ -18,6 +18,7 @@
 
 import android.platform.test.annotations.FlakyTest
 import androidx.test.filters.RequiresDevice
+import com.android.launcher3.tapl.LauncherInstrumentation
 import com.android.server.wm.flicker.FlickerParametersRunnerFactory
 import com.android.server.wm.flicker.FlickerTestParameter
 import com.android.server.wm.flicker.annotation.Group3
@@ -52,7 +53,7 @@
 @Group3
 @FlakyTest(bugId = 234848637)
 class EnterPipOnUserLeaveHintTest(testSpec: FlickerTestParameter) : EnterPipTest(testSpec) {
-
+    protected val taplInstrumentation = LauncherInstrumentation()
     /**
      * Defines the transition used to run the test
      */
@@ -71,10 +72,7 @@
                 }
             }
             transitions {
-                when (testSpec.isGesturalNavigation) {
-                    true -> pipApp.enterPipViaSwipeToHome(wmHelper)
-                    false -> pipApp.enterPipViaHomeButton(wmHelper)
-                }
+                taplInstrumentation.goHome()
             }
         }
 
diff --git a/packages/SystemUI/compose/core/src/com/android/systemui/compose/SystemUiController.kt b/packages/SystemUI/compose/core/src/com/android/systemui/compose/SystemUiController.kt
index 6bbac69..c9470c8 100644
--- a/packages/SystemUI/compose/core/src/com/android/systemui/compose/SystemUiController.kt
+++ b/packages/SystemUI/compose/core/src/com/android/systemui/compose/SystemUiController.kt
@@ -35,15 +35,16 @@
 import androidx.core.view.WindowCompat
 import androidx.core.view.WindowInsetsCompat
 
-/***************************************************************************************************
+/**
+ * *************************************************************************************************
  * This file was forked from
  * https://github.com/google/accompanist/blob/main/systemuicontroller/src/main/java/com/google/accompanist/systemuicontroller/SystemUiController.kt
  * and will be removed once it lands in AndroidX.
- **************************************************************************************************/
+ */
 
 /**
- * A class which provides easy-to-use utilities for updating the System UI bar
- * colors within Jetpack Compose.
+ * A class which provides easy-to-use utilities for updating the System UI bar colors within Jetpack
+ * Compose.
  *
  * @sample com.google.accompanist.sample.systemuicontroller.SystemUiControllerSample
  */
@@ -98,9 +99,9 @@
      * and [Color.Transparent] will be used on API 29+ where gesture navigation is preferred or the
      * system UI automatically applies background protection in other navigation modes.
      * @param darkIcons Whether dark navigation bar icons would be preferable.
-     * @param navigationBarContrastEnforced Whether the system should ensure that the navigation
-     * bar has enough contrast when a fully transparent background is requested. Only supported on
-     * API 29+.
+     * @param navigationBarContrastEnforced Whether the system should ensure that the navigation bar
+     * has enough contrast when a fully transparent background is requested. Only supported on API
+     * 29+.
      * @param transformColorForLightContent A lambda which will be invoked to transform [color] if
      * dark icons were requested but are not available. Defaults to applying a black scrim.
      *
@@ -135,14 +136,10 @@
         )
     }
 
-    /**
-     * Property which holds whether the status bar icons + content are 'dark' or not.
-     */
+    /** Property which holds whether the status bar icons + content are 'dark' or not. */
     var statusBarDarkContentEnabled: Boolean
 
-    /**
-     * Property which holds whether the navigation bar icons + content are 'dark' or not.
-     */
+    /** Property which holds whether the navigation bar icons + content are 'dark' or not. */
     var navigationBarDarkContentEnabled: Boolean
 
     /**
@@ -157,8 +154,8 @@
 
     /**
      * Property which holds whether the system is ensuring that the navigation bar has enough
-     * contrast when a fully transparent background is requested. Only has an affect when running
-     * on Android API 29+ devices.
+     * contrast when a fully transparent background is requested. Only has an affect when running on
+     * Android API 29+ devices.
      */
     var isNavigationBarContrastEnforced: Boolean
 }
@@ -202,13 +199,9 @@
  *
  * Typically you would use [rememberSystemUiController] to remember an instance of this.
  */
-internal class AndroidSystemUiController(
-    private val view: View,
-    private val window: Window?
-) : SystemUiController {
-    private val windowInsetsController = window?.let {
-        WindowCompat.getInsetsController(it, view)
-    }
+internal class AndroidSystemUiController(private val view: View, private val window: Window?) :
+    SystemUiController {
+    private val windowInsetsController = window?.let { WindowCompat.getInsetsController(it, view) }
 
     override fun setStatusBarColor(
         color: Color,
@@ -217,15 +210,16 @@
     ) {
         statusBarDarkContentEnabled = darkIcons
 
-        window?.statusBarColor = when {
-            darkIcons && windowInsetsController?.isAppearanceLightStatusBars != true -> {
-                // If we're set to use dark icons, but our windowInsetsController call didn't
-                // succeed (usually due to API level), we instead transform the color to maintain
-                // contrast
-                transformColorForLightContent(color)
-            }
-            else -> color
-        }.toArgb()
+        window?.statusBarColor =
+            when {
+                darkIcons && windowInsetsController?.isAppearanceLightStatusBars != true -> {
+                    // If we're set to use dark icons, but our windowInsetsController call didn't
+                    // succeed (usually due to API level), we instead transform the color to
+                    // maintain contrast
+                    transformColorForLightContent(color)
+                }
+                else -> color
+            }.toArgb()
     }
 
     override fun setNavigationBarColor(
@@ -237,15 +231,16 @@
         navigationBarDarkContentEnabled = darkIcons
         isNavigationBarContrastEnforced = navigationBarContrastEnforced
 
-        window?.navigationBarColor = when {
-            darkIcons && windowInsetsController?.isAppearanceLightNavigationBars != true -> {
-                // If we're set to use dark icons, but our windowInsetsController call didn't
-                // succeed (usually due to API level), we instead transform the color to maintain
-                // contrast
-                transformColorForLightContent(color)
-            }
-            else -> color
-        }.toArgb()
+        window?.navigationBarColor =
+            when {
+                darkIcons && windowInsetsController?.isAppearanceLightNavigationBars != true -> {
+                    // If we're set to use dark icons, but our windowInsetsController call didn't
+                    // succeed (usually due to API level), we instead transform the color to
+                    // maintain contrast
+                    transformColorForLightContent(color)
+                }
+                else -> color
+            }.toArgb()
     }
 
     override var isStatusBarVisible: Boolean
@@ -296,6 +291,4 @@
 }
 
 private val BlackScrim = Color(0f, 0f, 0f, 0.3f) // 30% opaque black
-private val BlackScrimmed: (Color) -> Color = { original ->
-    BlackScrim.compositeOver(original)
-}
\ No newline at end of file
+private val BlackScrimmed: (Color) -> Color = { original -> BlackScrim.compositeOver(original) }
diff --git a/packages/SystemUI/compose/core/src/com/android/systemui/compose/theme/SystemUITheme.kt b/packages/SystemUI/compose/core/src/com/android/systemui/compose/theme/SystemUITheme.kt
index e4d1bcf..60e1657 100644
--- a/packages/SystemUI/compose/core/src/com/android/systemui/compose/theme/SystemUITheme.kt
+++ b/packages/SystemUI/compose/core/src/com/android/systemui/compose/theme/SystemUITheme.kt
@@ -24,9 +24,7 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.platform.LocalContext
 
-/**
- * The Material 3 theme that should wrap all SystemUI Composables.
- */
+/** The Material 3 theme that should wrap all SystemUI Composables. */
 @Composable
 fun SystemUITheme(
     isDarkTheme: Boolean = isSystemInDarkTheme(),
@@ -35,14 +33,13 @@
     val context = LocalContext.current
 
     // TODO(b/230605885): Define our typography and color scheme.
-    val colorScheme = if (isDarkTheme) {
-        dynamicDarkColorScheme(context)
-    } else {
-        dynamicLightColorScheme(context)
-    }
+    val colorScheme =
+        if (isDarkTheme) {
+            dynamicDarkColorScheme(context)
+        } else {
+            dynamicLightColorScheme(context)
+        }
     val typography = Typography()
 
-    MaterialTheme(colorScheme, typography) {
-        content()
-    }
-}
\ No newline at end of file
+    MaterialTheme(colorScheme, typography) { content() }
+}
diff --git a/packages/SystemUI/compose/core/tests/src/com/android/systemui/compose/theme/SystemUIThemeTest.kt b/packages/SystemUI/compose/core/tests/src/com/android/systemui/compose/theme/SystemUIThemeTest.kt
index f1b9e9f..155b66c 100644
--- a/packages/SystemUI/compose/core/tests/src/com/android/systemui/compose/theme/SystemUIThemeTest.kt
+++ b/packages/SystemUI/compose/core/tests/src/com/android/systemui/compose/theme/SystemUIThemeTest.kt
@@ -27,17 +27,12 @@
 
 @RunWith(AndroidJUnit4::class)
 class SystemUIThemeTest {
-    @get:Rule
-    val composeRule = createComposeRule()
+    @get:Rule val composeRule = createComposeRule()
 
     @Test
     fun testThemeShowsContent() {
-        composeRule.setContent {
-            SystemUITheme {
-                Text("foo")
-            }
-        }
+        composeRule.setContent { SystemUITheme { Text("foo") } }
 
         composeRule.onNodeWithText("foo").assertIsDisplayed()
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/ExampleFeature.kt b/packages/SystemUI/compose/features/src/com/android/systemui/ExampleFeature.kt
index 73d5e35..1ad5484 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/ExampleFeature.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/ExampleFeature.kt
@@ -44,12 +44,10 @@
     ) {
         var count by remember { mutableStateOf(0) }
         Column(
-            Modifier
-                .clickable { count++ }
-                .padding(16.dp),
+            Modifier.clickable { count++ }.padding(16.dp),
         ) {
             Text(text)
             Text("I was clicked $count times.")
         }
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/compose/features/tests/src/com/android/systemui/ExampleFeatureTest.kt b/packages/SystemUI/compose/features/tests/src/com/android/systemui/ExampleFeatureTest.kt
index b120b96..1c2e8fa 100644
--- a/packages/SystemUI/compose/features/tests/src/com/android/systemui/ExampleFeatureTest.kt
+++ b/packages/SystemUI/compose/features/tests/src/com/android/systemui/ExampleFeatureTest.kt
@@ -27,27 +27,20 @@
 
 @RunWith(AndroidJUnit4::class)
 class ExampleFeatureTest {
-    @get:Rule
-    val composeRule = createComposeRule()
+    @get:Rule val composeRule = createComposeRule()
 
     @Test
     fun testProvidedTextIsDisplayed() {
-        composeRule.setContent {
-            ExampleFeature("foo")
-        }
+        composeRule.setContent { ExampleFeature("foo") }
 
         composeRule.onNodeWithText("foo").assertIsDisplayed()
     }
 
     @Test
     fun testCountIsIncreasedWhenClicking() {
-        composeRule.setContent {
-            ExampleFeature("foo")
-        }
+        composeRule.setContent { ExampleFeature("foo") }
 
-        composeRule.onNodeWithText("I was clicked 0 times.")
-            .assertIsDisplayed()
-            .performClick()
+        composeRule.onNodeWithText("I was clicked 0 times.").assertIsDisplayed().performClick()
         composeRule.onNodeWithText("I was clicked 1 times.").assertIsDisplayed()
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ColorsScreen.kt b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ColorsScreen.kt
index ac9fdbf..b616753 100644
--- a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ColorsScreen.kt
+++ b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ColorsScreen.kt
@@ -78,12 +78,11 @@
     ) {
         val shape = RoundedCornerShape(16.dp)
         Spacer(
-            Modifier
-                .border(1.dp, MaterialTheme.colorScheme.onBackground, shape)
+            Modifier.border(1.dp, MaterialTheme.colorScheme.onBackground, shape)
                 .background(color, shape)
                 .size(64.dp)
         )
         Spacer(Modifier.width(16.dp))
         Text(name)
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ConfigurationControls.kt b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ConfigurationControls.kt
index e8e6080..65ea88a 100644
--- a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ConfigurationControls.kt
+++ b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ConfigurationControls.kt
@@ -83,4 +83,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ExampleFeatureScreen.kt b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ExampleFeatureScreen.kt
index 1c6b9b0..652c403 100644
--- a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ExampleFeatureScreen.kt
+++ b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ExampleFeatureScreen.kt
@@ -23,7 +23,5 @@
 /** The screen that shows ExampleFeature. */
 @Composable
 fun ExampleFeatureScreen() {
-    Column {
-        ExampleFeature("This is an example feature!")
-    }
-}
\ No newline at end of file
+    Column { ExampleFeature("This is an example feature!") }
+}
diff --git a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/GalleryActivity.kt b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/GalleryActivity.kt
index ee38511..d18b454 100644
--- a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/GalleryActivity.kt
+++ b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/GalleryActivity.kt
@@ -17,11 +17,9 @@
 package com.android.systemui.compose.gallery
 
 import android.os.Bundle
-import android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS
 import androidx.activity.ComponentActivity
 import androidx.activity.compose.setContent
 import androidx.compose.foundation.isSystemInDarkTheme
-import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.SideEffect
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
diff --git a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/GalleryApp.kt b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/GalleryApp.kt
index f7d311b..c8146b8 100644
--- a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/GalleryApp.kt
+++ b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/GalleryApp.kt
@@ -67,30 +67,29 @@
     val systemFontScale = LocalDensity.current.fontScale
     var fontScale: FontScale by remember {
         mutableStateOf(
-            FontScale
-                .values()
-                .firstOrNull { it.scale == systemFontScale }
-                ?: FontScale.Normal
+            FontScale.values().firstOrNull { it.scale == systemFontScale } ?: FontScale.Normal
         )
     }
     val context = LocalContext.current
     val density = Density(context.resources.displayMetrics.density, fontScale.scale)
     val onChangeFontScale = {
-        fontScale = when (fontScale) {
-            FontScale.Small -> FontScale.Normal
-            FontScale.Normal -> FontScale.Big
-            FontScale.Big -> FontScale.Bigger
-            FontScale.Bigger -> FontScale.Small
-        }
+        fontScale =
+            when (fontScale) {
+                FontScale.Small -> FontScale.Normal
+                FontScale.Normal -> FontScale.Big
+                FontScale.Big -> FontScale.Bigger
+                FontScale.Bigger -> FontScale.Small
+            }
     }
 
     val systemLayoutDirection = LocalLayoutDirection.current
     var layoutDirection by remember { mutableStateOf(systemLayoutDirection) }
     val onChangeLayoutDirection = {
-        layoutDirection = when (layoutDirection) {
-            LayoutDirection.Ltr -> LayoutDirection.Rtl
-            LayoutDirection.Rtl -> LayoutDirection.Ltr
-        }
+        layoutDirection =
+            when (layoutDirection) {
+                LayoutDirection.Ltr -> LayoutDirection.Rtl
+                LayoutDirection.Rtl -> LayoutDirection.Ltr
+            }
     }
 
     CompositionLocalProvider(
@@ -102,12 +101,7 @@
                 Modifier.fillMaxSize(),
                 color = MaterialTheme.colorScheme.background,
             ) {
-                Column(
-                    Modifier
-                        .fillMaxSize()
-                        .systemBarsPadding()
-                        .padding(16.dp)
-                ) {
+                Column(Modifier.fillMaxSize().systemBarsPadding().padding(16.dp)) {
                     ConfigurationControls(
                         isDarkTheme,
                         fontScale,
diff --git a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/HomeScreen.kt b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/HomeScreen.kt
index d0f265c..b1869da 100644
--- a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/HomeScreen.kt
+++ b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/HomeScreen.kt
@@ -47,9 +47,7 @@
                         shape = CircleShape,
                     ) {
                         Column(
-                            Modifier
-                                .clickable { onScreenSelected(screen) }
-                                .padding(16.dp),
+                            Modifier.clickable { onScreenSelected(screen) }.padding(16.dp),
                             horizontalAlignment = Alignment.CenterHorizontally,
                         ) {
                             Text(screen.name)
@@ -58,4 +56,4 @@
                 }
             }
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/TypographyScreen.kt b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/TypographyScreen.kt
index 32191916..147025e 100644
--- a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/TypographyScreen.kt
+++ b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/TypographyScreen.kt
@@ -34,8 +34,7 @@
     val typography = MaterialTheme.typography
 
     Column(
-        Modifier
-            .fillMaxSize()
+        Modifier.fillMaxSize()
             .horizontalScroll(rememberScrollState())
             .verticalScroll(rememberScrollState()),
     ) {
diff --git a/packages/SystemUI/compose/gallery/tests/src/com/android/systemui/compose/gallery/ScreenshotsTests.kt b/packages/SystemUI/compose/gallery/tests/src/com/android/systemui/compose/gallery/ScreenshotsTests.kt
index 6fb1674..66ecc8d 100644
--- a/packages/SystemUI/compose/gallery/tests/src/com/android/systemui/compose/gallery/ScreenshotsTests.kt
+++ b/packages/SystemUI/compose/gallery/tests/src/com/android/systemui/compose/gallery/ScreenshotsTests.kt
@@ -25,17 +25,12 @@
 
 @RunWith(AndroidJUnit4::class)
 class ScreenshotsTests {
-    @get:Rule
-    val composeRule = createComposeRule()
+    @get:Rule val composeRule = createComposeRule()
 
     @Test
     fun exampleFeatureScreenshotTest() {
         // TODO(b/230832101): Wire this with the screenshot diff testing infra. We should reuse the
         // configuration of the features in the gallery app to populate the UIs.
-        composeRule.setContent {
-            SystemUITheme {
-                ExampleFeatureScreen()
-            }
-        }
+        composeRule.setContent { SystemUITheme { ExampleFeatureScreen() } }
     }
 }
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 21ba3be..ce5f22d 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -620,7 +620,8 @@
     <!-- Which face help messages to surface when fingerprint is also enrolled.
          Message ids correspond with the acquired ids in BiometricFaceConstants -->
     <integer-array name="config_face_help_msgs_when_fingerprint_enrolled">
-        <!-- for example: <item>26</item> for FACE_ACQUIRED_MOUTH_COVERING_DETECTED -->
+        <item>25</item>
+        <item>26</item>
     </integer-array>
 
     <!-- Whether the communal service should be enabled -->
diff --git a/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt b/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
index 8aa8518..a8a526a 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
@@ -37,6 +37,12 @@
     val resourceId: Int
 }
 
+interface DeviceConfigFlag<T> : Flag<T> {
+    val name: String
+    val namespace: String
+    val default: T
+}
+
 interface SysPropFlag<T> : Flag<T> {
     val name: String
     val default: T
@@ -80,6 +86,14 @@
     override val teamfood: Boolean = false
 ) : ResourceFlag<Boolean>
 
+data class DeviceConfigBooleanFlag @JvmOverloads constructor(
+    override val id: Int,
+    override val name: String,
+    override val namespace: String,
+    override val default: Boolean = false,
+    override val teamfood: Boolean = false
+) : DeviceConfigFlag<Boolean>
+
 data class SysPropBooleanFlag @JvmOverloads constructor(
     override val id: Int,
     override val name: String,
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt
index 9d6e3c2..2cee2520 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt
@@ -29,6 +29,9 @@
     fun isEnabled(flag: ResourceBooleanFlag): Boolean
 
     /** Returns a boolean value for the given flag.  */
+    fun isEnabled(flag: DeviceConfigBooleanFlag): Boolean
+
+    /** Returns a boolean value for the given flag.  */
     fun isEnabled(flag: SysPropBooleanFlag): Boolean
 
     /** Returns a string value for the given flag.  */
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
index 04df7a2..f804325 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
@@ -32,6 +32,7 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.provider.DeviceConfig;
 import android.util.Log;
 
 import androidx.annotation.NonNull;
@@ -44,6 +45,7 @@
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.statusbar.commandline.Command;
 import com.android.systemui.statusbar.commandline.CommandRegistry;
+import com.android.systemui.util.DeviceConfigProxy;
 import com.android.systemui.util.settings.SecureSettings;
 
 import java.io.PrintWriter;
@@ -81,6 +83,7 @@
     private final SecureSettings mSecureSettings;
     private final Resources mResources;
     private final SystemPropertiesHelper mSystemProperties;
+    private final DeviceConfigProxy mDeviceConfigProxy;
     private final Map<Integer, Flag<?>> mAllFlags;
     private final Map<Integer, Boolean> mBooleanFlagCache = new TreeMap<>();
     private final Map<Integer, String> mStringFlagCache = new TreeMap<>();
@@ -94,6 +97,7 @@
             SystemPropertiesHelper systemProperties,
             @Main Resources resources,
             DumpManager dumpManager,
+            DeviceConfigProxy deviceConfigProxy,
             @Named(ALL_FLAGS) Map<Integer, Flag<?>> allFlags,
             CommandRegistry commandRegistry,
             IStatusBarService barService) {
@@ -101,6 +105,7 @@
         mSecureSettings = secureSettings;
         mResources = resources;
         mSystemProperties = systemProperties;
+        mDeviceConfigProxy = deviceConfigProxy;
         mAllFlags = allFlags;
         mBarService = barService;
 
@@ -138,6 +143,18 @@
     }
 
     @Override
+    public boolean isEnabled(@NonNull DeviceConfigBooleanFlag flag) {
+        int id = flag.getId();
+        if (!mBooleanFlagCache.containsKey(id)) {
+            boolean deviceConfigValue = mDeviceConfigProxy.getBoolean(flag.getNamespace(),
+                    flag.getName(), flag.getDefault());
+            mBooleanFlagCache.put(id, readFlagValue(id, deviceConfigValue));
+        }
+
+        return mBooleanFlagCache.get(id);
+    }
+
+    @Override
     public boolean isEnabled(@NonNull SysPropBooleanFlag flag) {
         int id = flag.getId();
         if (!mBooleanFlagCache.containsKey(id)) {
@@ -297,6 +314,8 @@
             setFlagValue(flag.getId(), value, BooleanFlagSerializer.INSTANCE);
         } else if (flag instanceof ResourceBooleanFlag) {
             setFlagValue(flag.getId(), value, BooleanFlagSerializer.INSTANCE);
+        } else if (flag instanceof DeviceConfigBooleanFlag) {
+            setFlagValue(flag.getId(), value, BooleanFlagSerializer.INSTANCE);
         } else if (flag instanceof SysPropBooleanFlag) {
             // Store SysProp flags in SystemProperties where they can read by outside parties.
             mSystemProperties.setBoolean(((SysPropBooleanFlag) flag).getName(), value);
@@ -405,6 +424,10 @@
                         f.getTeamfood(),
                         readBooleanFlagOverride(f.getId()) != null);
             }
+            if (f instanceof DeviceConfigBooleanFlag) {
+                return new BooleanFlag(
+                        f.getId(), isEnabled((DeviceConfigBooleanFlag) f), f.getTeamfood());
+            }
             if (f instanceof SysPropBooleanFlag) {
                 // TODO(b/223379190): Teamfood not supported for sysprop flags yet.
                 return new BooleanFlag(
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java
index cacef16..1492a2b 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java
@@ -19,6 +19,7 @@
 import static java.util.Objects.requireNonNull;
 
 import android.content.res.Resources;
+import android.provider.DeviceConfig;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 
@@ -28,6 +29,7 @@
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.util.DeviceConfigProxy;
 
 import java.io.PrintWriter;
 import java.util.Map;
@@ -44,6 +46,7 @@
 public class FeatureFlagsRelease implements FeatureFlags, Dumpable {
     private final Resources mResources;
     private final SystemPropertiesHelper mSystemProperties;
+    private final DeviceConfigProxy mDeviceConfigProxy;
     SparseBooleanArray mBooleanCache = new SparseBooleanArray();
     SparseArray<String> mStringCache = new SparseArray<>();
 
@@ -51,9 +54,11 @@
     public FeatureFlagsRelease(
             @Main Resources resources,
             SystemPropertiesHelper systemProperties,
+            DeviceConfigProxy deviceConfigProxy,
             DumpManager dumpManager) {
         mResources = resources;
         mSystemProperties = systemProperties;
+        mDeviceConfigProxy = deviceConfigProxy;
         dumpManager.registerDumpable("SysUIFlags", this);
     }
 
@@ -79,6 +84,18 @@
     }
 
     @Override
+    public boolean isEnabled(@NonNull DeviceConfigBooleanFlag flag) {
+        int cacheIndex = mBooleanCache.indexOfKey(flag.getId());
+        if (cacheIndex < 0) {
+            boolean deviceConfigValue = mDeviceConfigProxy.getBoolean(flag.getNamespace(),
+                    flag.getName(), flag.getDefault());
+            return isEnabled(flag.getId(), deviceConfigValue);
+        }
+
+        return mBooleanCache.valueAt(cacheIndex);
+    }
+
+    @Override
     public boolean isEnabled(SysPropBooleanFlag flag) {
         int cacheIndex = mBooleanCache.indexOfKey(flag.getId());
         if (cacheIndex < 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
index 4baf251..0434dbe 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.flags;
 
+import static android.provider.DeviceConfig.NAMESPACE_WINDOW_MANAGER;
+
 import com.android.internal.annotations.Keep;
 import com.android.systemui.R;
 
@@ -170,6 +172,11 @@
     public static final SysPropBooleanFlag BUBBLES_HOME_GESTURE =
             new SysPropBooleanFlag(1101, "persist.wm.debug.bubbles_home_gesture", true);
 
+    @Keep
+    public static final DeviceConfigBooleanFlag WM_ENABLE_PARTIAL_SCREEN_SHARING =
+            new DeviceConfigBooleanFlag(1102, "record_task_content",
+                    NAMESPACE_WINDOW_MANAGER, false, true);
+
     // 1200 - predictive back
     @Keep
     public static final SysPropBooleanFlag WM_ENABLE_PREDICTIVE_BACK = new SysPropBooleanFlag(
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 8ce422a..5b6e5ce 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -83,6 +83,8 @@
 import android.widget.Toast;
 import android.window.WindowContext;
 
+import androidx.concurrent.futures.CallbackToFutureAdapter;
+
 import com.android.internal.app.ChooserActivity;
 import com.android.internal.logging.UiEventLogger;
 import com.android.internal.policy.PhoneWindow;
@@ -254,7 +256,7 @@
     private final WindowManager mWindowManager;
     private final WindowManager.LayoutParams mWindowLayoutParams;
     private final AccessibilityManager mAccessibilityManager;
-    private final MediaPlayer mCameraSound;
+    private final ListenableFuture<MediaPlayer> mCameraSound;
     private final ScrollCaptureClient mScrollCaptureClient;
     private final PhoneWindow mWindow;
     private final DisplayManager mDisplayManager;
@@ -338,13 +340,7 @@
         reloadAssets();
 
         // Setup the Camera shutter sound
-        mCameraSound = MediaPlayer.create(mContext,
-                Uri.fromFile(new File(mContext.getResources().getString(
-                        com.android.internal.R.string.config_cameraShutterSound))), null,
-                new AudioAttributes.Builder()
-                        .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
-                        .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
-                        .build(), AudioSystem.newAudioSessionId());
+        mCameraSound = loadCameraSound();
 
         mCopyBroadcastReceiver = new BroadcastReceiver() {
             @Override
@@ -442,16 +438,32 @@
         return mScreenshotView.isPendingSharedTransition();
     }
 
+    // Any cleanup needed when the service is being destroyed.
+    void onDestroy() {
+        removeWindow();
+        releaseMediaPlayer();
+        releaseContext();
+        mBgExecutor.shutdownNow();
+    }
+
     /**
      * Release the constructed window context.
      */
-    void releaseContext() {
+    private void releaseContext() {
         mContext.unregisterReceiver(mCopyBroadcastReceiver);
         mContext.release();
-        if (mCameraSound != null) {
-            mCameraSound.release();
+    }
+
+    private void releaseMediaPlayer() {
+        // Note that this may block if the sound is still being loaded (very unlikely) but we can't
+        // reliably release in the background because the service is being destroyed.
+        try {
+            MediaPlayer player = mCameraSound.get();
+            if (player != null) {
+                player.release();
+            }
+        } catch (InterruptedException | ExecutionException e) {
         }
-        mBgExecutor.shutdownNow();
     }
 
     /**
@@ -822,15 +834,42 @@
         }
     }
 
+    private ListenableFuture<MediaPlayer> loadCameraSound() {
+        // The media player creation is slow and needs on the background thread.
+        return CallbackToFutureAdapter.getFuture((completer) -> {
+            mBgExecutor.execute(() -> {
+                MediaPlayer player = MediaPlayer.create(mContext,
+                        Uri.fromFile(new File(mContext.getResources().getString(
+                                com.android.internal.R.string.config_cameraShutterSound))), null,
+                        new AudioAttributes.Builder()
+                                .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
+                                .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+                                .build(), AudioSystem.newAudioSessionId());
+                completer.set(player);
+            });
+            return "ScreenshotController#loadCameraSound";
+        });
+    }
+
+    private void playCameraSound() {
+        mCameraSound.addListener(() -> {
+            try {
+                MediaPlayer player = mCameraSound.get();
+                if (player != null) {
+                    player.start();
+                }
+            } catch (InterruptedException | ExecutionException e) {
+            }
+        }, mBgExecutor);
+    }
+
     /**
      * Save the bitmap but don't show the normal screenshot UI.. just a toast (or notification on
      * failure).
      */
     private void saveScreenshotAndToast(Consumer<Uri> finisher) {
         // Play the shutter sound to notify that we've taken a screenshot
-        if (mCameraSound != null) {
-            mCameraSound.start();
-        }
+        playCameraSound();
 
         saveScreenshotInWorkerThread(
                 /* onComplete */ finisher,
@@ -864,9 +903,7 @@
                 mScreenshotView.createScreenshotDropInAnimation(screenRect, showFlash);
 
         // Play the shutter sound to notify that we've taken a screenshot
-        if (mCameraSound != null) {
-            mCameraSound.start();
-        }
+        playCameraSound();
 
         if (DEBUG_ANIM) {
             Log.d(TAG, "starting post-screenshot animation");
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
index 90e7631..32d8203 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
@@ -153,8 +153,7 @@
     public void onDestroy() {
         super.onDestroy();
         if (mScreenshot != null) {
-            mScreenshot.removeWindow();
-            mScreenshot.releaseContext();
+            mScreenshot.onDestroy();
             mScreenshot = null;
         }
         if (DEBUG_SERVICE) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index c107f46..ee8c232 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -56,7 +56,6 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.provider.Settings;
 import android.text.TextUtils;
 import android.text.format.Formatter;
 import android.util.Log;
@@ -244,19 +243,10 @@
         mScreenLifecycle.addObserver(mScreenObserver);
 
         mCoExFaceHelpMsgIdsToShow = new HashSet<>();
-        final String msgsToShowOverride = Settings.Global.getString(mContext.getContentResolver(),
-                "coex_face_help_msgs"); // TODO: remove after UX testing b/231733975
-        if (msgsToShowOverride != null) {
-            final String[] msgIds = msgsToShowOverride.split("\\|");
-            for (String msgId : msgIds) {
-                mCoExFaceHelpMsgIdsToShow.add(Integer.parseInt(msgId));
-            }
-        } else {
-            int[] msgIds = context.getResources().getIntArray(
-                    com.android.systemui.R.array.config_face_help_msgs_when_fingerprint_enrolled);
-            for (int msgId : msgIds) {
-                mCoExFaceHelpMsgIdsToShow.add(msgId);
-            }
+        int[] msgIds = context.getResources().getIntArray(
+                com.android.systemui.R.array.config_face_help_msgs_when_fingerprint_enrolled);
+        for (int msgId : msgIds) {
+            mCoExFaceHelpMsgIdsToShow.add(msgId);
         }
 
         mHandler = new Handler(mainLooper) {
@@ -1032,7 +1022,8 @@
                 return;
             }
 
-            if (msgId == FaceManager.FACE_ERROR_TIMEOUT) {
+            if (biometricSourceType == BiometricSourceType.FACE
+                && msgId == FaceManager.FACE_ERROR_TIMEOUT) {
                 if (mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(
                         KeyguardUpdateMonitor.getCurrentUser())) {
                     // no message if fingerprint is also enrolled
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
index 68d35f9..824d3a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
@@ -34,6 +34,8 @@
 import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.statusbar.dagger.CentralSurfacesModule;
 import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.PipelineDumpable;
+import com.android.systemui.statusbar.notification.collection.PipelineDumper;
 import com.android.systemui.statusbar.phone.CentralSurfaces;
 import com.android.systemui.statusbar.phone.NotificationListenerWithPlugins;
 import com.android.systemui.util.time.SystemClock;
@@ -52,7 +54,8 @@
  */
 @SysUISingleton
 @SuppressLint("OverrideAbstract")
-public class NotificationListener extends NotificationListenerWithPlugins {
+public class NotificationListener extends NotificationListenerWithPlugins implements
+        PipelineDumpable {
     private static final String TAG = "NotificationListener";
     private static final boolean DEBUG = CentralSurfaces.DEBUG;
     private static final long MAX_RANKING_DELAY_MILLIS = 500L;
@@ -255,6 +258,11 @@
         }
     }
 
+    @Override
+    public void dumpPipeline(@NonNull PipelineDumper d) {
+        d.dump("notificationHandlers", mNotificationHandlers);
+    }
+
     private static Ranking getRankingOrTemporaryStandIn(RankingMap rankingMap, String key) {
         Ranking ranking = new Ranking();
         if (!rankingMap.getRanking(key, ranking)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
index 410593a..2b78b40 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -137,7 +137,7 @@
  */
 @MainThread
 @SysUISingleton
-public class NotifCollection implements Dumpable {
+public class NotifCollection implements Dumpable, PipelineDumpable {
     private final IStatusBarService mStatusBarService;
     private final SystemClock mClock;
     private final NotifPipelineFlags mNotifPipelineFlags;
@@ -841,6 +841,14 @@
                         "\t\t"));
     }
 
+    @Override
+    public void dumpPipeline(@NonNull PipelineDumper d) {
+        d.dump("notifCollectionListeners", mNotifCollectionListeners);
+        d.dump("lifetimeExtenders", mLifetimeExtenders);
+        d.dump("dismissInterceptors", mDismissInterceptors);
+        d.dump("buildListener", mBuildListener);
+    }
+
     private final BatchableNotificationHandler mNotifHandler = new BatchableNotificationHandler() {
         @Override
         public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/PipelineDumpable.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/PipelineDumpable.kt
new file mode 100644
index 0000000..a1aec3f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/PipelineDumpable.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection
+
+interface PipelineDumpable {
+    fun dumpPipeline(d: PipelineDumper)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/PipelineDumper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/PipelineDumper.kt
new file mode 100644
index 0000000..eca3ebf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/PipelineDumper.kt
@@ -0,0 +1,51 @@
+package com.android.systemui.statusbar.notification.collection
+
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifDismissInterceptor
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender
+import com.android.systemui.util.asIndenting
+import com.android.systemui.util.withIncreasedIndent
+import java.io.PrintWriter
+
+class PipelineDumper(pw: PrintWriter) {
+    private val ipw = pw.asIndenting()
+
+    fun println(a: Any?) = ipw.println(a)
+
+    fun dump(label: String, value: Any?) {
+        ipw.print("$label: ")
+        dump(value)
+    }
+
+    private fun dump(value: Any?) = when (value) {
+        null, is String, is Int -> ipw.println(value)
+        is Collection<*> -> dumpCollection(value)
+        else -> {
+            ipw.println(value.fullPipelineName)
+            (value as? PipelineDumpable)?.let {
+                ipw.withIncreasedIndent { it.dumpPipeline(this) }
+            }
+        }
+    }
+
+    private fun dumpCollection(values: Collection<Any?>) {
+        ipw.println(values.size)
+        ipw.withIncreasedIndent { values.forEach { dump(it) } }
+    }
+}
+
+private val Any.bareClassName: String get() {
+    val className = javaClass.name
+    val packagePrefixLength = javaClass.`package`?.name?.length?.plus(1) ?: 0
+    return className.substring(packagePrefixLength)
+}
+
+private val Any.barePipelineName: String? get() = when (this) {
+    is NotifLifetimeExtender -> name
+    is NotifDismissInterceptor -> name
+    is Pluggable<*> -> name
+    else -> null
+}
+
+private val Any.fullPipelineName: String get() =
+    barePipelineName?.let { "\"$it\" ($bareClassName)" } ?: bareClassName
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
index 2a8a672..083759c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
@@ -87,7 +87,7 @@
  */
 @MainThread
 @SysUISingleton
-public class ShadeListBuilder implements Dumpable {
+public class ShadeListBuilder implements Dumpable, PipelineDumpable {
     private final SystemClock mSystemClock;
     private final ShadeListBuilderLogger mLogger;
     private final NotificationInteractionTracker mInteractionTracker;
@@ -1397,6 +1397,21 @@
                 "\t\t"));
     }
 
+    @Override
+    public void dumpPipeline(@NonNull PipelineDumper d) {
+        d.dump("choreographer", mChoreographer);
+        d.dump("notifPreGroupFilters", mNotifPreGroupFilters);
+        d.dump("onBeforeTransformGroupsListeners", mOnBeforeTransformGroupsListeners);
+        d.dump("notifPromoters", mNotifPromoters);
+        d.dump("onBeforeSortListeners", mOnBeforeSortListeners);
+        d.dump("notifSections", mNotifSections);
+        d.dump("notifComparators", mNotifComparators);
+        d.dump("onBeforeFinalizeFilterListeners", mOnBeforeFinalizeFilterListeners);
+        d.dump("notifFinalizeFilters", mNotifFinalizeFilters);
+        d.dump("onBeforeRenderListListeners", mOnBeforeRenderListListeners);
+        d.dump("onRenderListListener", mOnRenderListListener);
+    }
+
     /** See {@link #setOnRenderListListener(OnRenderListListener)} */
     public interface OnRenderListListener {
         /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java
index 050b4c1..98f2167 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java
@@ -32,6 +32,8 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
+import com.android.systemui.statusbar.notification.collection.PipelineDumpable;
+import com.android.systemui.statusbar.notification.collection.PipelineDumper;
 import com.android.systemui.util.concurrency.DelayableExecutor;
 import com.android.systemui.util.time.SystemClock;
 
@@ -63,7 +65,7 @@
  * passed along to the NotifCollection.
  */
 @MainThread
-public class GroupCoalescer implements Dumpable {
+public class GroupCoalescer implements Dumpable, PipelineDumpable {
     private final DelayableExecutor mMainExecutor;
     private final SystemClock mClock;
     private final GroupCoalescerLogger mLogger;
@@ -314,6 +316,11 @@
         }
     }
 
+    @Override
+    public void dumpPipeline(@NonNull PipelineDumper d) {
+        d.dump("handler", mHandler);
+    }
+
     private final Comparator<CoalescedEvent> mEventComparator = (o1, o2) -> {
         int cmp = Boolean.compare(
                 o2.getSbn().getNotification().isGroupSummary(),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
index 359e202..f9b8644 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
@@ -15,24 +15,22 @@
  */
 package com.android.systemui.statusbar.notification.collection.coordinator
 
-import com.android.systemui.Dumpable
-import com.android.systemui.dump.DumpManager
 import com.android.systemui.statusbar.notification.NotifPipelineFlags
 import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.PipelineDumpable
+import com.android.systemui.statusbar.notification.collection.PipelineDumper
 import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
-import java.io.PrintWriter
 import javax.inject.Inject
 
 /**
  * Handles the attachment of [Coordinator]s to the [NotifPipeline] so that the
  * Coordinators can register their respective callbacks.
  */
-interface NotifCoordinators : Coordinator, Dumpable
+interface NotifCoordinators : Coordinator, PipelineDumpable
 
 @CoordinatorScope
 class NotifCoordinatorsImpl @Inject constructor(
-    dumpManager: DumpManager,
     notifPipelineFlags: NotifPipelineFlags,
     dataStoreCoordinator: DataStoreCoordinator,
     hideLocallyDismissedNotifsCoordinator: HideLocallyDismissedNotifsCoordinator,
@@ -66,8 +64,6 @@
      * Creates all the coordinators.
      */
     init {
-        dumpManager.registerDumpable(TAG, this)
-
         // TODO(b/208866714): formalize the system by which some coordinators may be required by the
         //  pipeline, such as this DataStoreCoordinator which cannot be removed, as it's a critical
         //  glue between the pipeline and parts of SystemUI which depend on pipeline output via the
@@ -127,15 +123,12 @@
         pipeline.setSections(mOrderedSections)
     }
 
-    override fun dump(pw: PrintWriter, args: Array<String>) {
-        pw.println()
-        pw.println("$TAG:")
-        for (c in mCoordinators) {
-            pw.println("\t${c.javaClass}")
-        }
-        for (s in mOrderedSections) {
-            pw.println("\t${s.name}")
-        }
+    /*
+     * As part of the NotifPipeline dumpable, dumps the list of coordinators; sections are omitted
+     * as they are dumped in the RenderStageManager instead.
+     */
+    override fun dumpPipeline(d: PipelineDumper) = with(d) {
+        dump("coordinators", mCoordinators)
     }
 
     companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java
index 70b1156..d1ab62c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java
@@ -18,6 +18,8 @@
 
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+
 import com.android.systemui.Dumpable;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dump.DumpManager;
@@ -26,12 +28,15 @@
 import com.android.systemui.statusbar.notification.collection.NotifCollection;
 import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl;
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
+import com.android.systemui.statusbar.notification.collection.PipelineDumpable;
+import com.android.systemui.statusbar.notification.collection.PipelineDumper;
 import com.android.systemui.statusbar.notification.collection.ShadeListBuilder;
 import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer;
 import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinators;
 import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
 import com.android.systemui.statusbar.notification.collection.render.NotifStackController;
 import com.android.systemui.statusbar.notification.collection.render.RenderStageManager;
+import com.android.systemui.statusbar.notification.collection.render.ShadeViewManager;
 import com.android.systemui.statusbar.notification.collection.render.ShadeViewManagerFactory;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 
@@ -43,7 +48,7 @@
  * Initialization code for the new notification pipeline.
  */
 @SysUISingleton
-public class NotifPipelineInitializer implements Dumpable {
+public class NotifPipelineInitializer implements Dumpable, PipelineDumpable {
     private final NotifPipeline mPipelineWrapper;
     private final GroupCoalescer mGroupCoalescer;
     private final NotifCollection mNotifCollection;
@@ -55,6 +60,9 @@
     private final ShadeViewManagerFactory mShadeViewManagerFactory;
     private final NotifPipelineFlags mNotifPipelineFlags;
 
+    /* These are saved just for dumping. */
+    private ShadeViewManager mShadeViewManager;
+    private NotificationListener mNotificationService;
 
     @Inject
     public NotifPipelineInitializer(
@@ -87,9 +95,10 @@
             NotificationRowBinderImpl rowBinder,
             NotificationListContainer listContainer,
             NotifStackController stackController) {
-
         mDumpManager.registerDumpable("NotifPipeline", this);
 
+        mNotificationService = notificationService;
+
         // Setup inflation
         if (mNotifPipelineFlags.isNewPipelineEnabled()) {
             mNotifInflater.setRowBinder(rowBinder);
@@ -100,14 +109,13 @@
 
         // Wire up pipeline
         if (mNotifPipelineFlags.isNewPipelineEnabled()) {
-            mShadeViewManagerFactory
-                    .create(listContainer, stackController)
-                    .attach(mRenderStageManager);
+            mShadeViewManager = mShadeViewManagerFactory.create(listContainer, stackController);
+            mShadeViewManager.attach(mRenderStageManager);
         }
         mRenderStageManager.attach(mListBuilder);
         mListBuilder.attach(mNotifCollection);
         mNotifCollection.attach(mGroupCoalescer);
-        mGroupCoalescer.attach(notificationService);
+        mGroupCoalescer.attach(mNotificationService);
 
         Log.d(TAG, "Notif pipeline initialized."
                 + " rendering=" + mNotifPipelineFlags.isNewPipelineEnabled());
@@ -115,8 +123,37 @@
 
     @Override
     public void dump(PrintWriter pw, String[] args) {
-        mNotifPluggableCoordinators.dump(pw, args);
-        mGroupCoalescer.dump(pw, args);
+        dumpPipeline(new PipelineDumper(pw));
+    }
+
+    @Override
+    public void dumpPipeline(@NonNull PipelineDumper d) {
+        d.println("STAGE 0: SETUP");
+        d.dump("notifPluggableCoordinators", mNotifPluggableCoordinators);
+        d.println("");
+
+        d.println("STAGE 1: LISTEN");
+        d.dump("notificationService", mNotificationService);
+        d.println("");
+
+        d.println("STAGE 2: BATCH EVENTS");
+        d.dump("groupCoalescer", mGroupCoalescer);
+        d.println("");
+
+        d.println("STAGE 3: COLLECT");
+        d.dump("notifCollection", mNotifCollection);
+        d.println("");
+
+        d.println("STAGE 4: BUILD LIST");
+        d.dump("listBuilder", mListBuilder);
+        d.println("");
+
+        d.println("STAGE 5: DISPATCH RENDER");
+        d.dump("renderStageManager", mRenderStageManager);
+        d.println("");
+
+        d.println("STAGE 6: UPDATE SHADE");
+        d.dump("shadeViewManager", mShadeViewManager);
     }
 
     private static final String TAG = "NotifPipeline";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifSection.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifSection.kt
index ea66f3b..9765e8f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifSection.kt
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.notification.collection.listbuilder
 
+import com.android.systemui.statusbar.notification.collection.PipelineDumpable
+import com.android.systemui.statusbar.notification.collection.PipelineDumper
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
 import com.android.systemui.statusbar.notification.collection.render.NodeController
@@ -24,10 +26,18 @@
 data class NotifSection(
     val sectioner: NotifSectioner,
     val index: Int
-) {
+) : PipelineDumpable {
     @PriorityBucket
     val bucket: Int = sectioner.bucket
     val label: String = "$index:$bucket:${sectioner.name}"
     val headerController: NodeController? = sectioner.headerNodeController
     val comparator: NotifComparator? = sectioner.comparator
+
+    override fun dumpPipeline(d: PipelineDumper) = with(d) {
+        dump("index", index)
+        dump("bucket", bucket)
+        dump("sectioner", sectioner)
+        dump("headerController", headerController)
+        dump("comparator", comparator)
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/DebugModeFilterProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/DebugModeFilterProvider.kt
index a0c39c6..fd5bae1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/DebugModeFilterProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/DebugModeFilterProvider.kt
@@ -16,15 +16,13 @@
 
 package com.android.systemui.statusbar.notification.collection.provider
 
-import android.content.BroadcastReceiver
-import android.content.Context
-import android.content.Intent
-import android.content.IntentFilter
 import android.os.Build
 import android.util.Log
 import com.android.systemui.Dumpable
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.commandline.Command
+import com.android.systemui.statusbar.commandline.CommandRegistry
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.util.Assert
 import com.android.systemui.util.ListenerSet
@@ -39,20 +37,19 @@
  * The only configuration is a list of allowed packages.  When this list is empty, the feature is
  * disabled.  When SystemUI starts up, this feature is disabled.
  *
- * To enabled filtering, provide the list of packages in a comma-separated list using the command:
+ * To enabled filtering, provide the space-separated list of packages using the command:
  *
- * `$ adb shell am broadcast -a com.android.systemui.action.SET_NOTIF_DEBUG_MODE
- *          --esal allowed_packages <comma-separated-packages>`
+ * `$ adb shell cmd statusbar notif-filter allowed-pkgs <package> ...`
  *
- * To disable filtering, send the action without a list:
+ * To disable filtering, send the command without any packages, or explicitly reset:
  *
- * `$ adb shell am broadcast -a com.android.systemui.action.SET_NOTIF_DEBUG_MODE`
+ * `$ adb shell cmd statusbar notif-filter reset`
  *
  * NOTE: this feature only works on debug builds, and when the broadcaster is root.
  */
 @SysUISingleton
 class DebugModeFilterProvider @Inject constructor(
-    private val context: Context,
+    private val commandRegistry: CommandRegistry,
     dumpManager: DumpManager
 ) : Dumpable {
     private var allowedPackages: List<String> = emptyList()
@@ -74,10 +71,8 @@
         val needsInitialization = listeners.isEmpty()
         listeners.addIfAbsent(listener)
         if (needsInitialization) {
-            val filter = IntentFilter().apply { addAction(ACTION_SET_NOTIF_DEBUG_MODE) }
-            val permission = NOTIF_DEBUG_MODE_PERMISSION
-            context.registerReceiver(mReceiver, filter, permission, null, Context.RECEIVER_EXPORTED)
-            Log.d(TAG, "Registered: $mReceiver")
+            commandRegistry.registerCommand("notif-filter") { NotifFilterCommand() }
+            Log.d(TAG, "Registered notif-filter command")
         }
     }
 
@@ -100,30 +95,49 @@
         }
     }
 
-    private val mReceiver: BroadcastReceiver = object : BroadcastReceiver() {
-        override fun onReceive(context: Context, intent: Intent?) {
-            val action = intent?.action
-            if (ACTION_SET_NOTIF_DEBUG_MODE == action) {
-                // TODO(b/235268992) remove
-                Log.d(TAG, "ACTION_SET_NOTIF_DEBUG_MODE enter")
-                allowedPackages = intent.extras?.getStringArrayList(EXTRA_ALLOWED_PACKAGES)
-                    ?: emptyList()
-                Log.d(TAG, "Updated allowedPackages: $allowedPackages")
-                listeners.forEach(Runnable::run)
-                // TODO(b/235268992) remove
-                Log.d(TAG, "ACTION_SET_NOTIF_DEBUG_MODE leave")
-            } else {
-                Log.d(TAG, "Malformed intent: $intent")
-            }
-        }
-    }
-
     companion object {
         private const val TAG = "DebugModeFilterProvider"
-        private const val ACTION_SET_NOTIF_DEBUG_MODE =
-            "com.android.systemui.action.SET_NOTIF_DEBUG_MODE"
-        private const val NOTIF_DEBUG_MODE_PERMISSION =
-            "com.android.systemui.permission.NOTIF_DEBUG_MODE"
-        private const val EXTRA_ALLOWED_PACKAGES = "allowed_packages"
+    }
+
+    inner class NotifFilterCommand : Command {
+        override fun execute(pw: PrintWriter, args: List<String>) {
+            when (args.firstOrNull()) {
+                "reset" -> {
+                    if (args.size > 1) {
+                        return invalidCommand(pw, "Unexpected arguments for 'reset' command")
+                    }
+                    allowedPackages = emptyList()
+                }
+                "allowed-pkgs" -> {
+                    allowedPackages = args.drop(1)
+                }
+                null -> return invalidCommand(pw, "Missing command")
+                else -> return invalidCommand(pw, "Unknown command: ${args.firstOrNull()}")
+            }
+            Log.d(TAG, "Updated allowedPackages: $allowedPackages")
+            if (allowedPackages.isEmpty()) {
+                pw.print("Resetting allowedPackages ... ")
+            } else {
+                pw.print("Updating allowedPackages: $allowedPackages ... ")
+            }
+            listeners.forEach(Runnable::run)
+            pw.println("DONE")
+        }
+
+        private fun invalidCommand(pw: PrintWriter, reason: String) {
+            pw.println("Error: $reason")
+            pw.println()
+            help(pw)
+        }
+
+        override fun help(pw: PrintWriter) {
+            pw.println("Usage: adb shell cmd statusbar notif-filter <command>")
+            pw.println("Available commands:")
+            pw.println("  reset")
+            pw.println("     Restore the default system behavior.")
+            pw.println("  allowed-pkgs <package> ...")
+            pw.println("     Hide all notification except from packages listed here.")
+            pw.println("     Providing no packages is treated as a reset.")
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt
index a9c3987..3061522 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt
@@ -20,6 +20,8 @@
 import com.android.systemui.statusbar.notification.collection.GroupEntry
 import com.android.systemui.statusbar.notification.collection.ListEntry
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.PipelineDumpable
+import com.android.systemui.statusbar.notification.collection.PipelineDumper
 import com.android.systemui.statusbar.notification.collection.ShadeListBuilder
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderEntryListener
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderGroupListener
@@ -33,7 +35,7 @@
  * provided to [setViewRenderer].
  */
 @SysUISingleton
-class RenderStageManager @Inject constructor() {
+class RenderStageManager @Inject constructor() : PipelineDumpable {
     private val onAfterRenderListListeners = mutableListOf<OnAfterRenderListListener>()
     private val onAfterRenderGroupListeners = mutableListOf<OnAfterRenderGroupListener>()
     private val onAfterRenderEntryListeners = mutableListOf<OnAfterRenderEntryListener>()
@@ -75,6 +77,13 @@
         onAfterRenderEntryListeners.add(listener)
     }
 
+    override fun dumpPipeline(d: PipelineDumper) = with(d) {
+        dump("viewRenderer", viewRenderer)
+        dump("onAfterRenderListListeners", onAfterRenderListListeners)
+        dump("onAfterRenderGroupListeners", onAfterRenderGroupListeners)
+        dump("onAfterRenderEntryListeners", onAfterRenderEntryListeners)
+    }
+
     private fun dispatchOnAfterRenderList(
         viewRenderer: NotifViewRenderer,
         entries: List<ListEntry>
@@ -139,4 +148,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RootNodeController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RootNodeController.kt
index b76169f..2073e92 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RootNodeController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RootNodeController.kt
@@ -17,6 +17,8 @@
 package com.android.systemui.statusbar.notification.collection.render
 
 import android.view.View
+import com.android.systemui.statusbar.notification.collection.PipelineDumpable
+import com.android.systemui.statusbar.notification.collection.PipelineDumper
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
 import com.android.systemui.statusbar.notification.row.ExpandableView
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer
@@ -28,7 +30,7 @@
 class RootNodeController(
     private val listContainer: NotificationListContainer,
     override val view: View
-) : NodeController {
+) : NodeController, PipelineDumpable {
     override val nodeLabel: String = "<root>"
 
     override fun getChildAt(index: Int): View? {
@@ -59,4 +61,8 @@
             listContainer.setChildTransferInProgress(false)
         }
     }
+
+    override fun dumpPipeline(d: PipelineDumper) = with(d) {
+        dump("listContainer", listContainer)
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
index 51dc728..df8e87f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
@@ -22,6 +22,8 @@
 import com.android.systemui.statusbar.notification.collection.GroupEntry
 import com.android.systemui.statusbar.notification.collection.ListEntry
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.PipelineDumpable
+import com.android.systemui.statusbar.notification.collection.PipelineDumper
 import com.android.systemui.statusbar.notification.collection.provider.SectionHeaderVisibilityProvider
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer
 import com.android.systemui.util.traceSection
@@ -43,12 +45,12 @@
     nodeSpecBuilderLogger: NodeSpecBuilderLogger,
     shadeViewDifferLogger: ShadeViewDifferLogger,
     private val viewBarn: NotifViewBarn
-) {
+) : PipelineDumpable {
     // We pass a shim view here because the listContainer may not actually have a view associated
     // with it and the differ never actually cares about the root node's view.
     private val rootController = RootNodeController(listContainer, View(context))
     private val specBuilder = NodeSpecBuilder(mediaContainerController, featureManager,
-            sectionHeaderVisibilityProvider, viewBarn, nodeSpecBuilderLogger)
+        sectionHeaderVisibilityProvider, viewBarn, nodeSpecBuilderLogger)
     private val viewDiffer = ShadeViewDiffer(rootController, shadeViewDifferLogger)
 
     /** Method for attaching this manager to the pipeline. */
@@ -56,6 +58,12 @@
         renderStageManager.setViewRenderer(viewRenderer)
     }
 
+    override fun dumpPipeline(d: PipelineDumper) = with(d) {
+        dump("rootController", rootController)
+        dump("specBuilder", specBuilder)
+        dump("viewDiffer", viewDiffer)
+    }
+
     private val viewRenderer = object : NotifViewRenderer {
 
         override fun onRenderList(notifList: List<ListEntry>) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 1e69ee6..b9a19f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -92,6 +92,8 @@
 import com.android.systemui.statusbar.notification.collection.NotifCollection;
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.PipelineDumpable;
+import com.android.systemui.statusbar.notification.collection.PipelineDumper;
 import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
 import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.OnGroupChangeListener;
 import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
@@ -1615,7 +1617,8 @@
         }
     }
 
-    private class NotificationListContainerImpl implements NotificationListContainer {
+    private class NotificationListContainerImpl implements NotificationListContainer,
+            PipelineDumpable {
 
         @Override
         public void setChildTransferInProgress(boolean childTransferInProgress) {
@@ -1761,6 +1764,12 @@
         public void setWillExpand(boolean willExpand) {
             mView.setWillExpand(willExpand);
         }
+
+        @Override
+        public void dumpPipeline(@NonNull PipelineDumper d) {
+            d.dump("NotificationStackScrollLayoutController.this",
+                    NotificationStackScrollLayoutController.this);
+        }
     }
 
     class TouchHandler implements Gefingerpoken {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 314484e..e5dc816 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -960,14 +960,16 @@
                 });
     }
 
-    private void onFinishInflate() {
+    @VisibleForTesting
+    void onFinishInflate() {
         loadDimens();
         mKeyguardStatusBar = mView.findViewById(R.id.keyguard_header);
 
         FrameLayout userAvatarContainer = null;
         KeyguardUserSwitcherView keyguardUserSwitcherView = null;
 
-        if (mKeyguardUserSwitcherEnabled && mUserManager.isUserSwitcherEnabled()) {
+        if (mKeyguardUserSwitcherEnabled && mUserManager.isUserSwitcherEnabled(
+                mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user))) {
             if (mKeyguardQsUserSwitchEnabled) {
                 ViewStub stub = mView.findViewById(R.id.keyguard_qs_user_switch_stub);
                 userAvatarContainer = (FrameLayout) stub.inflate();
@@ -1195,7 +1197,8 @@
         return view;
     }
 
-    private void reInflateViews() {
+    @VisibleForTesting
+    void reInflateViews() {
         if (DEBUG_LOGCAT) Log.d(TAG, "reInflateViews");
         // Re-inflate the status view group.
         KeyguardStatusView keyguardStatusView =
@@ -1216,7 +1219,8 @@
 
         // Re-inflate the keyguard user switcher group.
         updateUserSwitcherFlags();
-        boolean isUserSwitcherEnabled = mUserManager.isUserSwitcherEnabled();
+        boolean isUserSwitcherEnabled = mUserManager.isUserSwitcherEnabled(
+                mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user));
         boolean showQsUserSwitch = mKeyguardQsUserSwitchEnabled && isUserSwitcherEnabled;
         boolean showKeyguardUserSwitcher =
                 !mKeyguardQsUserSwitchEnabled
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt
index 1206d05..ebedbf9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt
@@ -200,6 +200,7 @@
                 containerPadding = bottomStableInsets
             } else {
                 containerPadding = 0
+                stackScrollMargin = bottomStableInsets + notificationsBottomMargin
             }
         }
         val qsContainerPadding = if (!(isQSCustomizing || isQSDetailShowing)) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt
index b43856a..51f3404 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt
@@ -26,6 +26,7 @@
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.statusbar.commandline.Command
 import com.android.systemui.statusbar.commandline.CommandRegistry
+import com.android.systemui.util.DeviceConfigProxyFake
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.argumentCaptor
 import com.android.systemui.util.mockito.capture
@@ -75,6 +76,7 @@
     private lateinit var broadcastReceiver: BroadcastReceiver
     private lateinit var clearCacheAction: Consumer<Int>
 
+    private val deviceConfig = DeviceConfigProxyFake()
     private val teamfoodableFlagA = BooleanFlag(500, false, true)
     private val teamfoodableFlagB = BooleanFlag(501, true, true)
 
@@ -90,6 +92,7 @@
             systemProperties,
             resources,
             dumpManager,
+            deviceConfig,
             flagMap,
             commandRegistry,
             barService
@@ -195,6 +198,21 @@
     }
 
     @Test
+    fun testReadDeviceConfigBooleanFlag() {
+        val namespace = "test_namespace"
+        deviceConfig.setProperty(namespace, "a", "true", false)
+        deviceConfig.setProperty(namespace, "b", "false", false)
+        deviceConfig.setProperty(namespace, "c", null, false)
+
+        assertThat(mFeatureFlagsDebug.isEnabled(DeviceConfigBooleanFlag(1, "a", namespace)))
+            .isTrue()
+        assertThat(mFeatureFlagsDebug.isEnabled(DeviceConfigBooleanFlag(2, "b", namespace)))
+            .isFalse()
+        assertThat(mFeatureFlagsDebug.isEnabled(DeviceConfigBooleanFlag(3, "c", namespace)))
+            .isFalse()
+    }
+
+    @Test
     fun testReadStringFlag() {
         whenever(flagManager.readFlagValue<String>(eq(3), any())).thenReturn("foo")
         whenever(flagManager.readFlagValue<String>(eq(4), any())).thenReturn("bar")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt
index b5deb0b..6b683f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt
@@ -20,6 +20,7 @@
 import android.test.suitebuilder.annotation.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
+import com.android.systemui.util.DeviceConfigProxyFake
 import com.android.systemui.util.mockito.any
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
@@ -44,10 +45,13 @@
     @Mock private lateinit var mSystemProperties: SystemPropertiesHelper
     @Mock private lateinit var mDumpManager: DumpManager
 
+    private val deviceConfig = DeviceConfigProxyFake()
+
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
-        mFeatureFlagsRelease = FeatureFlagsRelease(mResources, mSystemProperties, mDumpManager)
+        mFeatureFlagsRelease = FeatureFlagsRelease(mResources, mSystemProperties, deviceConfig,
+            mDumpManager)
     }
 
     @After
@@ -85,6 +89,21 @@
     }
 
     @Test
+    fun testReadDeviceConfigBooleanFlag() {
+        val namespace = "test_namespace"
+        deviceConfig.setProperty(namespace, "a", "true", false)
+        deviceConfig.setProperty(namespace, "b", "false", false)
+        deviceConfig.setProperty(namespace, "c", null, false)
+
+        assertThat(mFeatureFlagsRelease.isEnabled(DeviceConfigBooleanFlag(1, "a", namespace)))
+            .isTrue()
+        assertThat(mFeatureFlagsRelease.isEnabled(DeviceConfigBooleanFlag(2, "b", namespace)))
+            .isFalse()
+        assertThat(mFeatureFlagsRelease.isEnabled(DeviceConfigBooleanFlag(3, "c", namespace)))
+            .isFalse()
+    }
+
+    @Test
     fun testSysPropBooleanFlag() {
         val flagId = 213
         val flagName = "sys_prop_flag"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index b51b717..883e2dc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -598,18 +598,44 @@
     }
 
     @Test
-    public void doNotSendFaceHelpMessages_fingerprintEnrolled() {
+    public void sendFaceHelpMessages_fingerprintEnrolled() {
         createController();
 
         // GIVEN fingerprint enrolled
         when(mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(
                 0)).thenReturn(true);
 
-        // WHEN help messages received
+        // WHEN help messages received that are allowed to show
+        final String helpString = "helpString";
+        final int[] msgIds = new int[]{
+                BiometricFaceConstants.FACE_ACQUIRED_MOUTH_COVERING_DETECTED,
+                BiometricFaceConstants.FACE_ACQUIRED_DARK_GLASSES_DETECTED
+        };
+        Set<CharSequence> messages = new HashSet<>();
+        for (int msgId : msgIds) {
+            final String message = helpString + msgId;
+            messages.add(message);
+            mKeyguardUpdateMonitorCallback.onBiometricHelp(
+                    msgId, message, BiometricSourceType.FACE);
+        }
+
+        // THEN FACE_ACQUIRED_MOUTH_COVERING_DETECTED and DARK_GLASSES help messages shown
+        verifyIndicationMessages(INDICATION_TYPE_BIOMETRIC_MESSAGE,
+                messages);
+    }
+
+    @Test
+    public void doNotSendMostFaceHelpMessages_fingerprintEnrolled() {
+        createController();
+
+        // GIVEN fingerprint enrolled
+        when(mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(
+                0)).thenReturn(true);
+
+        // WHEN help messages received that aren't supposed to show
         final String helpString = "helpString";
         final int[] msgIds = new int[]{
                 BiometricFaceConstants.FACE_ACQUIRED_FACE_OBSCURED,
-                BiometricFaceConstants.FACE_ACQUIRED_DARK_GLASSES_DETECTED,
                 BiometricFaceConstants.FACE_ACQUIRED_TOO_RIGHT,
                 BiometricFaceConstants.FACE_ACQUIRED_TOO_LEFT,
                 BiometricFaceConstants.FACE_ACQUIRED_TOO_HIGH,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
index 018c453..d47644f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
@@ -889,7 +889,8 @@
         updateSmallestScreenWidth(300);
         when(mResources.getBoolean(
                 com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
-        when(mUserManager.isUserSwitcherEnabled()).thenReturn(true);
+        when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
+        when(mUserManager.isUserSwitcherEnabled(false)).thenReturn(true);
 
         updateSmallestScreenWidth(800);
 
@@ -897,6 +898,34 @@
     }
 
     @Test
+    public void testFinishInflate_userSwitcherDisabled_doNotInflateUserSwitchView() {
+        givenViewAttached();
+        when(mResources.getBoolean(
+                com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
+        when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
+        when(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
+                .thenReturn(false);
+
+        mNotificationPanelViewController.onFinishInflate();
+
+        verify(mUserSwitcherStubView, never()).inflate();
+    }
+
+    @Test
+    public void testReInflateViews_userSwitcherDisabled_doNotInflateUserSwitchView() {
+        givenViewAttached();
+        when(mResources.getBoolean(
+                com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
+        when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
+        when(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
+                .thenReturn(false);
+
+        mNotificationPanelViewController.reInflateViews();
+
+        verify(mUserSwitcherStubView, never()).inflate();
+    }
+
+    @Test
     public void testCanCollapsePanelOnTouch_trueForKeyGuard() {
         mStatusBarStateController.setState(KEYGUARD);
 
@@ -1298,7 +1327,8 @@
     }
 
     private void updateMultiUserSetting(boolean enabled) {
-        when(mUserManager.isUserSwitcherEnabled()).thenReturn(enabled);
+        when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
+        when(mUserManager.isUserSwitcherEnabled(false)).thenReturn(enabled);
         final ArgumentCaptor<ContentObserver> observerCaptor =
                 ArgumentCaptor.forClass(ContentObserver.class);
         verify(mContentResolver)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt
index 0032452..de40b7f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt
@@ -206,7 +206,9 @@
         given(taskbarVisible = false,
                 navigationMode = BUTTONS_NAVIGATION,
                 insets = windowInsets().withStableBottom())
-        then(expectedContainerPadding = 0, expectedQsPadding = STABLE_INSET_BOTTOM)
+        then(expectedContainerPadding = 0,
+                expectedNotificationsMargin = STABLE_INSET_BOTTOM + NOTIFICATIONS_MARGIN,
+                expectedQsPadding = STABLE_INSET_BOTTOM)
     }
 
     @Test
diff --git a/services/core/java/com/android/server/DiskStatsService.java b/services/core/java/com/android/server/DiskStatsService.java
index 5fed6d3..d537c1f 100644
--- a/services/core/java/com/android/server/DiskStatsService.java
+++ b/services/core/java/com/android/server/DiskStatsService.java
@@ -128,7 +128,7 @@
         reportFreeSpace(Environment.getMetadataDirectory(), "Metadata", pw, proto,
                 DiskStatsFreeSpaceProto.FOLDER_METADATA);
 
-        boolean fileBased = StorageManager.isFileEncryptedNativeOnly();
+        boolean fileBased = StorageManager.isFileEncrypted();
         if (protoFormat) {
             if (fileBased) {
                 proto.write(DiskStatsServiceDumpProto.ENCRYPTION,
diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java
index 59daee9..b9a0738 100644
--- a/services/core/java/com/android/server/display/PersistentDataStore.java
+++ b/services/core/java/com/android/server/display/PersistentDataStore.java
@@ -153,7 +153,7 @@
 
     @VisibleForTesting
     PersistentDataStore(Injector injector) {
-        this(injector, BackgroundThread.getHandler());
+        this(injector, new Handler(BackgroundThread.getHandler().getLooper()));
     }
 
     @VisibleForTesting
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 78cffa6..1de3e37 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -678,7 +678,7 @@
         }
 
         // Suppress all notifications on non-FBE devices for now
-        if (!StorageManager.isFileEncryptedNativeOrEmulated()) return;
+        if (!StorageManager.isFileEncrypted()) return;
 
         unlockIntent.setFlags(
                 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index d536a46..b89147e 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -563,14 +563,16 @@
         try {
             enforcePackageName(callingPackage, callingUid);
             if (targetUid != callingUid) {
-                Log.d(TAG, "tempAllowlistTargetPkgIfPossible callingPackage:"
-                        + callingPackage + " targetPackage:" + targetPackage
-                        + " reason:" + reason);
                 boolean canAllowWhileInUse = mActivityManagerLocal
                         .canAllowWhileInUsePermissionInFgs(callingPid, callingUid, callingPackage);
                 boolean canStartFgs = canAllowWhileInUse
                         || mActivityManagerLocal.canStartForegroundService(callingPid, callingUid,
                         callingPackage);
+                Log.i(TAG, "tempAllowlistTargetPkgIfPossible callingPackage:"
+                        + callingPackage + " targetPackage:" + targetPackage
+                        + " reason:" + reason
+                        + (canAllowWhileInUse ? " [WIU]" : "")
+                        + (canStartFgs ? " [FGS]" : ""));
                 if (canAllowWhileInUse) {
                     mActivityManagerLocal.tempAllowWhileInUsePermissionInFgs(targetUid,
                             MediaSessionDeviceConfig
diff --git a/services/core/java/com/android/server/pm/AppDataHelper.java b/services/core/java/com/android/server/pm/AppDataHelper.java
index ce323fc..881e466 100644
--- a/services/core/java/com/android/server/pm/AppDataHelper.java
+++ b/services/core/java/com/android/server/pm/AppDataHelper.java
@@ -318,7 +318,7 @@
      * requested by the app.
      */
     private boolean maybeMigrateAppDataLIF(AndroidPackage pkg, int userId) {
-        if (pkg.isSystem() && !StorageManager.isFileEncryptedNativeOrEmulated()
+        if (pkg.isSystem() && !StorageManager.isFileEncrypted()
                 && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) {
             final int storageTarget = pkg.isDefaultToDeviceProtectedStorage()
                     ? StorageManager.FLAG_STORAGE_DE : StorageManager.FLAG_STORAGE_CE;
@@ -390,8 +390,7 @@
         // First look for stale data that doesn't belong, and check if things
         // have changed since we did our last restorecon
         if ((flags & StorageManager.FLAG_STORAGE_CE) != 0) {
-            if (StorageManager.isFileEncryptedNativeOrEmulated()
-                    && !StorageManager.isUserKeyUnlocked(userId)) {
+            if (StorageManager.isFileEncrypted() && !StorageManager.isUserKeyUnlocked(userId)) {
                 throw new RuntimeException(
                         "Yikes, someone asked us to reconcile CE storage while " + userId
                                 + " was still locked; this would have caused massive data loss!");
@@ -493,7 +492,7 @@
      */
     public Future<?> fixAppsDataOnBoot() {
         final @StorageManager.StorageFlags int storageFlags;
-        if (StorageManager.isFileEncryptedNativeOrEmulated()) {
+        if (StorageManager.isFileEncrypted()) {
             storageFlags = StorageManager.FLAG_STORAGE_DE;
         } else {
             storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
diff --git a/services/core/java/com/android/server/pm/MovePackageHelper.java b/services/core/java/com/android/server/pm/MovePackageHelper.java
index 05f84e3..7238f47 100644
--- a/services/core/java/com/android/server/pm/MovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/MovePackageHelper.java
@@ -180,8 +180,7 @@
         // If we're moving app data around, we need all the users unlocked
         if (moveCompleteApp) {
             for (int userId : installedUserIds) {
-                if (StorageManager.isFileEncryptedNativeOrEmulated()
-                        && !StorageManager.isUserKeyUnlocked(userId)) {
+                if (StorageManager.isFileEncrypted() && !StorageManager.isUserKeyUnlocked(userId)) {
                     freezer.close();
                     throw new PackageManagerException(MOVE_FAILED_LOCKED_USER,
                             "User " + userId + " must be unlocked");
diff --git a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
index c7e7784..7b0fe9a 100644
--- a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
+++ b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
@@ -270,7 +270,6 @@
      */
     @VisibleForTesting
     public boolean isUserCredentialLocked(int userId) {
-        return StorageManager.isFileEncryptedNativeOrEmulated()
-                && !StorageManager.isUserKeyUnlocked(userId);
+        return StorageManager.isFileEncrypted() && !StorageManager.isUserKeyUnlocked(userId);
     }
 }
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index b4b8cf9..e6ab810 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -2631,7 +2631,7 @@
             latency = -1;
         }
         // File based encryption.
-        boolean fileBased = StorageManager.isFileEncryptedNativeOnly();
+        boolean fileBased = StorageManager.isFileEncrypted();
 
         //Recent disk write speed. Binder call to storaged.
         int writeSpeed = -1;
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index f53b51d..1ccdaf7 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -949,6 +949,7 @@
 
                 if (rootTask.inFreeformWindowingMode()) {
                     rootTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+                    rootTask.setBounds(null);
                 } else if (!r.supportsFreeform()) {
                     throw new IllegalStateException(
                             "This activity is currently not freeform-enabled");
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index fe0ab2b..d2ce048 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -1335,16 +1335,16 @@
                     mDisplayContent.mPinnedTaskController.setEnterPipTransaction(
                             mFinishTransaction);
                 }
+                // In the case where we are transferring the transform to the task in preparation
+                // for entering PIP, we disable the task being able to affect sysui flags otherwise
+                // it may cause a flash
+                if (mTask.getActivityType() != mTargetActivityType
+                        && mFinishTransaction.getShouldDisableCanAffectSystemUiFlags()) {
+                    mTask.setCanAffectSystemUiFlags(false);
+                }
                 mFinishTransaction = null;
                 mFinishOverlay = null;
                 pendingTransaction.apply();
-
-                // In the case where we are transferring the transform to the task in preparation 
-                // for entering PIP, we disable the task being able to affect sysui flags otherwise
-                // it may cause a flash
-                if (mTask.getActivityType() != mTargetActivityType) {
-                    mTask.setCanAffectSystemUiFlags(false);
-                }
             } else if (!mTask.isAttached()) {
                 // Apply the task's pending transaction in case it is detached and its transaction
                 // is not reachable.
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index a784bab..1ce25f3 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1536,7 +1536,7 @@
         }
 
         boolean storageManagerIsFileBasedEncryptionEnabled() {
-            return StorageManager.isFileEncryptedNativeOnly();
+            return StorageManager.isFileEncrypted();
         }
 
         Looper getMyLooper() {
diff --git a/telephony/java/android/telephony/AccessNetworkUtils.java b/telephony/java/android/telephony/AccessNetworkUtils.java
index b5d97ab..b0f207c 100644
--- a/telephony/java/android/telephony/AccessNetworkUtils.java
+++ b/telephony/java/android/telephony/AccessNetworkUtils.java
@@ -4,8 +4,8 @@
 import static android.telephony.ServiceState.DUPLEX_MODE_TDD;
 import static android.telephony.ServiceState.DUPLEX_MODE_UNKNOWN;
 
-import android.telephony.AccessNetworkConstants.EutranBandArfcnFrequency;
 import android.telephony.AccessNetworkConstants.EutranBand;
+import android.telephony.AccessNetworkConstants.EutranBandArfcnFrequency;
 import android.telephony.AccessNetworkConstants.GeranBand;
 import android.telephony.AccessNetworkConstants.GeranBandArfcnFrequency;
 import android.telephony.AccessNetworkConstants.NgranArfcnFrequency;
@@ -13,7 +13,6 @@
 import android.telephony.AccessNetworkConstants.UtranBand;
 import android.telephony.AccessNetworkConstants.UtranBandArfcnFrequency;
 import android.telephony.ServiceState.DuplexMode;
-import android.util.Log;
 
 import java.util.Arrays;
 import java.util.HashSet;
@@ -232,6 +231,110 @@
     }
 
     /**
+     * Gets the NR Operating band for a given downlink NRARFCN.
+     *
+     * <p>See 3GPP TS 38.104 Table 5.2-1 NR operating bands in FR1 and
+     * Table 5.2-2 NR operating bands in FR2
+     *
+     * @param nrarfcn The downlink NRARFCN
+     * @return Operating band number, or {@link #INVALID_BAND} if no corresponding band exists
+     */
+    public static int getOperatingBandForNrarfcn(int nrarfcn) {
+        if (nrarfcn >= 2110 && nrarfcn <= 2170) {
+            return NgranBands.BAND_1;
+        } else if (nrarfcn >= 1930 && nrarfcn <= 1990) {
+            return NgranBands.BAND_2;
+        } else if (nrarfcn >= 1805 && nrarfcn <= 1880) {
+            return NgranBands.BAND_3;
+        } else if (nrarfcn >= 869 && nrarfcn <= 894) {
+            return NgranBands.BAND_5;
+        } else if (nrarfcn >= 2620 && nrarfcn <= 2690) {
+            return NgranBands.BAND_7;
+        } else if (nrarfcn >= 925 && nrarfcn <= 960) {
+            return NgranBands.BAND_8;
+        } else if (nrarfcn >= 729 && nrarfcn <= 746) {
+            return NgranBands.BAND_12;
+        } else if (nrarfcn >= 758 && nrarfcn <= 768) {
+            return NgranBands.BAND_14;
+        } else if (nrarfcn >= 860 && nrarfcn <= 875) {
+            return NgranBands.BAND_18;
+        } else if (nrarfcn >= 791 && nrarfcn <= 821) {
+            return NgranBands.BAND_20;
+        } else if (nrarfcn >= 1930 && nrarfcn <= 1995) {
+            return NgranBands.BAND_25;
+        } else if (nrarfcn >= 859 && nrarfcn <= 894) {
+            return NgranBands.BAND_26;
+        } else if (nrarfcn >= 758 && nrarfcn <= 803) {
+            return NgranBands.BAND_28;
+        } else if (nrarfcn >= 717 && nrarfcn <= 728) {
+            return NgranBands.BAND_29;
+        } else if (nrarfcn >= 2350 && nrarfcn <= 2360) {
+            return NgranBands.BAND_30;
+        } else if (nrarfcn >= 2010 && nrarfcn <= 2025) {
+            return NgranBands.BAND_34;
+        } else if (nrarfcn >= 2570 && nrarfcn <= 2620) {
+            return NgranBands.BAND_38;
+        } else if (nrarfcn >= 1880 && nrarfcn <= 1920) {
+            return NgranBands.BAND_39;
+        } else if (nrarfcn >= 2300 && nrarfcn <= 2400) {
+            return NgranBands.BAND_40;
+        } else if (nrarfcn >= 2496 && nrarfcn <= 2690) {
+            return NgranBands.BAND_41;
+        } else if (nrarfcn >= 5150 && nrarfcn <= 5925) {
+            return NgranBands.BAND_46;
+        } else if (nrarfcn >= 3550 && nrarfcn <= 3700) {
+            return NgranBands.BAND_48;
+        } else if (nrarfcn >= 1432 && nrarfcn <= 1517) {
+            return NgranBands.BAND_50;
+        } else if (nrarfcn >= 1427 && nrarfcn <= 1432) {
+            return NgranBands.BAND_51;
+        } else if (nrarfcn >= 2483 && nrarfcn <= 2495) {
+            return NgranBands.BAND_53;
+        } else if (nrarfcn >= 2110 && nrarfcn <= 2200) {
+            return NgranBands.BAND_65; // BAND_66 has the same channels
+        } else if (nrarfcn >= 1995 && nrarfcn <= 2020) {
+            return NgranBands.BAND_70;
+        } else if (nrarfcn >= 617 && nrarfcn <= 652) {
+            return NgranBands.BAND_71;
+        } else if (nrarfcn >= 1475 && nrarfcn <= 1518) {
+            return NgranBands.BAND_74;
+        } else if (nrarfcn >= 1432 && nrarfcn <= 1517) {
+            return NgranBands.BAND_75;
+        } else if (nrarfcn >= 1427 && nrarfcn <= 1432) {
+            return NgranBands.BAND_76;
+        } else if (nrarfcn >= 3300 && nrarfcn <= 4200) {
+            return NgranBands.BAND_77;
+        } else if (nrarfcn >= 3300 && nrarfcn <= 3800) {
+            return NgranBands.BAND_78;
+        } else if (nrarfcn >= 4400 && nrarfcn <= 5000) {
+            return NgranBands.BAND_79;
+        } else if (nrarfcn >= 2496 && nrarfcn <= 2690) {
+            return NgranBands.BAND_90;
+        } else if (nrarfcn >= 1427 && nrarfcn <= 1432) {
+            return NgranBands.BAND_91;
+        } else if (nrarfcn >= 1427 && nrarfcn <= 1432) {
+            return NgranBands.BAND_92;
+        } else if (nrarfcn >= 1432 && nrarfcn <= 1517) {
+            return NgranBands.BAND_93;
+        } else if (nrarfcn >= 1427 && nrarfcn <= 1432) {
+            return NgranBands.BAND_94;
+        } else if (nrarfcn >= 1432 && nrarfcn <= 1517) {
+            return NgranBands.BAND_94;
+        } else if (nrarfcn >= 5925 && nrarfcn <= 7125) {
+            return NgranBands.BAND_96;
+        } else if (nrarfcn >= 26500 && nrarfcn <= 29500) {
+            return NgranBands.BAND_257;
+        } else if (nrarfcn >= 24250 && nrarfcn <= 27500) {
+            return NgranBands.BAND_258;
+        } else if (nrarfcn >= 37000 && nrarfcn <= 40000) {
+            return NgranBands.BAND_260;
+        } else if (nrarfcn >= 27500 && nrarfcn <= 28350) {
+            return NgranBands.BAND_261;
+        }
+        return INVALID_BAND;
+    }
+
+    /**
      * Gets the GERAN Operating band for a given ARFCN.
      *
      * <p>See 3GPP TS 45.005 clause 2 for calculation.
diff --git a/tools/processors/staledataclass/src/android/processor/staledataclass/StaleDataclassProcessor.kt b/tools/processors/staledataclass/src/android/processor/staledataclass/StaleDataclassProcessor.kt
index 2e60f64..27a8853 100644
--- a/tools/processors/staledataclass/src/android/processor/staledataclass/StaleDataclassProcessor.kt
+++ b/tools/processors/staledataclass/src/android/processor/staledataclass/StaleDataclassProcessor.kt
@@ -97,7 +97,7 @@
 
     private fun elemToString(elem: Element): String {
         return buildString {
-            append(elem.modifiers.joinToString(" ") { it.name.toLowerCase() })
+            append(elem.modifiers.joinToString(" ") { it.name.lowercase() })
             append(" ")
             append(elem.annotationMirrors.joinToString(" ", transform = { annotationToString(it) }))
             append(" ")
diff --git a/tools/protologtool/src/com/android/protolog/tool/CodeUtils.kt b/tools/protologtool/src/com/android/protolog/tool/CodeUtils.kt
index a52c804..451e514 100644
--- a/tools/protologtool/src/com/android/protolog/tool/CodeUtils.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/CodeUtils.kt
@@ -29,7 +29,7 @@
      */
     fun hash(position: String, messageString: String, logLevel: LogLevel, logGroup: LogGroup): Int {
         return (position + messageString + logLevel.name + logGroup.name)
-                .map { c -> c.toInt() }.reduce { h, c -> h * 31 + c }
+                .map { c -> c.code }.reduce { h, c -> h * 31 + c }
     }
 
     fun checkWildcardStaticImported(code: CompilationUnit, className: String, fileName: String) {