Merge "Add new MediaDrm methods"
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 3ea1d56..89ce1e5 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -6,141 +6,86 @@
     chmod 0222 /sys/kernel/debug/tracing/trace_marker
     chmod 0222 /sys/kernel/tracing/trace_marker
 
-# Allow the shell group to enable (some) kernel tracing.
-    chown root shell /sys/kernel/debug/tracing/trace_clock
-    chown root shell /sys/kernel/tracing/trace_clock
-    chown root shell /sys/kernel/debug/tracing/buffer_size_kb
-    chown root shell /sys/kernel/tracing/buffer_size_kb
-    chown root shell /sys/kernel/debug/tracing/options/overwrite
-    chown root shell /sys/kernel/tracing/options/overwrite
-    chown root shell /sys/kernel/debug/tracing/options/print-tgid
-    chown root shell /sys/kernel/tracing/options/print-tgid
-    chown root shell /sys/kernel/debug/tracing/saved_cmdlines_size
-    chown root shell /sys/kernel/tracing/saved_cmdlines_size
-    chown root shell /sys/kernel/debug/tracing/events/sched/sched_switch/enable
-    chown root shell /sys/kernel/tracing/events/sched/sched_switch/enable
-    chown root shell /sys/kernel/debug/tracing/events/sched/sched_wakeup/enable
-    chown root shell /sys/kernel/tracing/events/sched/sched_wakeup/enable
-    chown root shell /sys/kernel/debug/tracing/events/sched/sched_blocked_reason/enable
-    chown root shell /sys/kernel/tracing/events/sched/sched_blocked_reason/enable
-    chown root shell /sys/kernel/debug/tracing/events/sched/sched_cpu_hotplug/enable
-    chown root shell /sys/kernel/tracing/events/sched/sched_cpu_hotplug/enable
-    chown root shell /sys/kernel/debug/tracing/events/cgroup/enable
-    chown root shell /sys/kernel/tracing/events/cgroup/enable
-    chown root shell /sys/kernel/debug/tracing/events/power/cpu_frequency/enable
-    chown root shell /sys/kernel/tracing/events/power/cpu_frequency/enable
-    chown root shell /sys/kernel/debug/tracing/events/power/cpu_idle/enable
-    chown root shell /sys/kernel/tracing/events/power/cpu_idle/enable
-    chown root shell /sys/kernel/debug/tracing/events/power/clock_set_rate/enable
-    chown root shell /sys/kernel/tracing/events/power/clock_set_rate/enable
-    chown root shell /sys/kernel/debug/tracing/events/power/cpu_frequency_limits/enable
-    chown root shell /sys/kernel/tracing/events/power/cpu_frequency_limits/enable
-    chown root shell /sys/kernel/debug/tracing/events/cpufreq_interactive/enable
-    chown root shell /sys/kernel/tracing/events/cpufreq_interactive/enable
-    chown root shell /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin/enable
-    chown root shell /sys/kernel/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin/enable
-    chown root shell /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_end/enable
-    chown root shell /sys/kernel/tracing/events/vmscan/mm_vmscan_direct_reclaim_end/enable
-    chown root shell /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_wake/enable
-    chown root shell /sys/kernel/tracing/events/vmscan/mm_vmscan_kswapd_wake/enable
-    chown root shell /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_sleep/enable
-    chown root shell /sys/kernel/tracing/events/vmscan/mm_vmscan_kswapd_sleep/enable
-    chown root shell /sys/kernel/debug/tracing/events/binder/binder_transaction/enable
-    chown root shell /sys/kernel/tracing/events/binder/binder_transaction/enable
-    chown root shell /sys/kernel/debug/tracing/events/binder/binder_transaction_received/enable
-    chown root shell /sys/kernel/tracing/events/binder/binder_transaction_received/enable
-    chown root shell /sys/kernel/debug/tracing/events/binder/binder_lock/enable
-    chown root shell /sys/kernel/tracing/events/binder/binder_lock/enable
-    chown root shell /sys/kernel/debug/tracing/events/binder/binder_locked/enable
-    chown root shell /sys/kernel/tracing/events/binder/binder_locked/enable
-    chown root shell /sys/kernel/debug/tracing/events/binder/binder_unlock/enable
-    chown root shell /sys/kernel/tracing/events/binder/binder_unlock/enable
-    chown root shell /sys/kernel/debug/tracing/events/lowmemorykiller/enable
-    chown root shell /sys/kernel/tracing/events/lowmemorykiller/enable
+# Grant unix world read/write permissions to kernel tracepoints.
+# Access control to these files is now entirely in selinux policy.
+    chmod 0666 /sys/kernel/debug/tracing/trace_clock
+    chmod 0666 /sys/kernel/tracing/trace_clock
+    chmod 0666 /sys/kernel/debug/tracing/buffer_size_kb
+    chmod 0666 /sys/kernel/tracing/buffer_size_kb
+    chmod 0666 /sys/kernel/debug/tracing/options/overwrite
+    chmod 0666 /sys/kernel/tracing/options/overwrite
+    chmod 0666 /sys/kernel/debug/tracing/options/print-tgid
+    chmod 0666 /sys/kernel/tracing/options/print-tgid
+    chmod 0666 /sys/kernel/debug/tracing/saved_cmdlines_size
+    chmod 0666 /sys/kernel/tracing/saved_cmdlines_size
+    chmod 0666 /sys/kernel/debug/tracing/events/sched/sched_switch/enable
+    chmod 0666 /sys/kernel/tracing/events/sched/sched_switch/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/sched/sched_wakeup/enable
+    chmod 0666 /sys/kernel/tracing/events/sched/sched_wakeup/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/sched/sched_blocked_reason/enable
+    chmod 0666 /sys/kernel/tracing/events/sched/sched_blocked_reason/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/sched/sched_cpu_hotplug/enable
+    chmod 0666 /sys/kernel/tracing/events/sched/sched_cpu_hotplug/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/cgroup/enable
+    chmod 0666 /sys/kernel/tracing/events/cgroup/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/power/cpu_frequency/enable
+    chmod 0666 /sys/kernel/tracing/events/power/cpu_frequency/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/power/cpu_idle/enable
+    chmod 0666 /sys/kernel/tracing/events/power/cpu_idle/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/power/clock_set_rate/enable
+    chmod 0666 /sys/kernel/tracing/events/power/clock_set_rate/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/power/cpu_frequency_limits/enable
+    chmod 0666 /sys/kernel/tracing/events/power/cpu_frequency_limits/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/cpufreq_interactive/enable
+    chmod 0666 /sys/kernel/tracing/events/cpufreq_interactive/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin/enable
+    chmod 0666 /sys/kernel/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_end/enable
+    chmod 0666 /sys/kernel/tracing/events/vmscan/mm_vmscan_direct_reclaim_end/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_wake/enable
+    chmod 0666 /sys/kernel/tracing/events/vmscan/mm_vmscan_kswapd_wake/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_sleep/enable
+    chmod 0666 /sys/kernel/tracing/events/vmscan/mm_vmscan_kswapd_sleep/enable
+    chmod 0666 /sys/kernel/debug/tracing/tracing_on
+    chmod 0666 /sys/kernel/tracing/tracing_on
+    chmod 0666 /sys/kernel/debug/tracing/events/binder/binder_transaction/enable
+    chmod 0666 /sys/kernel/tracing/events/binder/binder_transaction/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/binder/binder_transaction_received/enable
+    chmod 0666 /sys/kernel/tracing/events/binder/binder_transaction_received/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/binder/binder_lock/enable
+    chmod 0666 /sys/kernel/tracing/events/binder/binder_lock/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/binder/binder_locked/enable
+    chmod 0666 /sys/kernel/tracing/events/binder/binder_locked/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/binder/binder_unlock/enable
+    chmod 0666 /sys/kernel/tracing/events/binder/binder_unlock/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/i2c/enable
+    chmod 0666 /sys/kernel/tracing/events/i2c/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/i2c/i2c_read/enable
+    chmod 0666 /sys/kernel/tracing/events/i2c/i2c_read/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/i2c/i2c_write/enable
+    chmod 0666 /sys/kernel/tracing/events/i2c/i2c_write/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/i2c/i2c_result/enable
+    chmod 0666 /sys/kernel/tracing/events/i2c/i2c_result/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/i2c/i2c_reply/enable
+    chmod 0666 /sys/kernel/tracing/events/i2c/i2c_reply/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/i2c/smbus_read/enable
+    chmod 0666 /sys/kernel/tracing/events/i2c/smbus_read/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/i2c/smbus_write/enable
+    chmod 0666 /sys/kernel/tracing/events/i2c/smbus_write/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/i2c/smbus_result/enable
+    chmod 0666 /sys/kernel/tracing/events/i2c/smbus_result/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/i2c/smbus_reply/enable
+    chmod 0666 /sys/kernel/tracing/events/i2c/smbus_reply/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/lowmemorykiller/enable
+    chmod 0666 /sys/kernel/tracing/events/lowmemorykiller/enable
 
-    chown root shell /sys/kernel/debug/tracing/tracing_on
-    chown root shell /sys/kernel/tracing/tracing_on
-
-    chmod 0664 /sys/kernel/debug/tracing/trace_clock
-    chmod 0664 /sys/kernel/tracing/trace_clock
-    chmod 0664 /sys/kernel/debug/tracing/buffer_size_kb
-    chmod 0664 /sys/kernel/tracing/buffer_size_kb
-    chmod 0664 /sys/kernel/debug/tracing/options/overwrite
-    chmod 0664 /sys/kernel/tracing/options/overwrite
-    chmod 0664 /sys/kernel/debug/tracing/options/print-tgid
-    chmod 0664 /sys/kernel/tracing/options/print-tgid
-    chmod 0664 /sys/kernel/debug/tracing/saved_cmdlines_size
-    chmod 0664 /sys/kernel/tracing/saved_cmdlines_size
-    chmod 0664 /sys/kernel/debug/tracing/events/sched/sched_switch/enable
-    chmod 0664 /sys/kernel/tracing/events/sched/sched_switch/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/sched/sched_wakeup/enable
-    chmod 0664 /sys/kernel/tracing/events/sched/sched_wakeup/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/sched/sched_blocked_reason/enable
-    chmod 0664 /sys/kernel/tracing/events/sched/sched_blocked_reason/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/sched/sched_cpu_hotplug/enable
-    chmod 0664 /sys/kernel/tracing/events/sched/sched_cpu_hotplug/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/cgroup/enable
-    chmod 0664 /sys/kernel/tracing/events/cgroup/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/power/cpu_frequency/enable
-    chmod 0664 /sys/kernel/tracing/events/power/cpu_frequency/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/power/cpu_idle/enable
-    chmod 0664 /sys/kernel/tracing/events/power/cpu_idle/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/power/clock_set_rate/enable
-    chmod 0664 /sys/kernel/tracing/events/power/clock_set_rate/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/power/cpu_frequency_limits/enable
-    chmod 0664 /sys/kernel/tracing/events/power/cpu_frequency_limits/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/cpufreq_interactive/enable
-    chmod 0664 /sys/kernel/tracing/events/cpufreq_interactive/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin/enable
-    chmod 0664 /sys/kernel/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_end/enable
-    chmod 0664 /sys/kernel/tracing/events/vmscan/mm_vmscan_direct_reclaim_end/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_wake/enable
-    chmod 0664 /sys/kernel/tracing/events/vmscan/mm_vmscan_kswapd_wake/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_sleep/enable
-    chmod 0664 /sys/kernel/tracing/events/vmscan/mm_vmscan_kswapd_sleep/enable
-    chmod 0664 /sys/kernel/debug/tracing/tracing_on
-    chmod 0664 /sys/kernel/tracing/tracing_on
-    chmod 0664 /sys/kernel/debug/tracing/events/binder/binder_transaction/enable
-    chmod 0664 /sys/kernel/tracing/events/binder/binder_transaction/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/binder/binder_transaction_received/enable
-    chmod 0664 /sys/kernel/tracing/events/binder/binder_transaction_received/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/binder/binder_lock/enable
-    chmod 0664 /sys/kernel/tracing/events/binder/binder_lock/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/binder/binder_locked/enable
-    chmod 0664 /sys/kernel/tracing/events/binder/binder_locked/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/binder/binder_unlock/enable
-    chmod 0664 /sys/kernel/tracing/events/binder/binder_unlock/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/i2c/enable
-    chmod 0664 /sys/kernel/tracing/events/i2c/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/i2c/i2c_read/enable
-    chmod 0664 /sys/kernel/tracing/events/i2c/i2c_read/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/i2c/i2c_write/enable
-    chmod 0664 /sys/kernel/tracing/events/i2c/i2c_write/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/i2c/i2c_result/enable
-    chmod 0664 /sys/kernel/tracing/events/i2c/i2c_result/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/i2c/i2c_reply/enable
-    chmod 0664 /sys/kernel/tracing/events/i2c/i2c_reply/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/i2c/smbus_read/enable
-    chmod 0664 /sys/kernel/tracing/events/i2c/smbus_read/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/i2c/smbus_write/enable
-    chmod 0664 /sys/kernel/tracing/events/i2c/smbus_write/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/i2c/smbus_result/enable
-    chmod 0664 /sys/kernel/tracing/events/i2c/smbus_result/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/i2c/smbus_reply/enable
-    chmod 0664 /sys/kernel/tracing/events/i2c/smbus_reply/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/lowmemorykiller/enable
-    chmod 0664 /sys/kernel/tracing/events/lowmemorykiller/enable
-
-    # Tracing disabled by default
+# Tracing disabled by default
     write /sys/kernel/debug/tracing/tracing_on 0
     write /sys/kernel/tracing/tracing_on 0
 
-# Allow only the shell group to read and truncate the kernel trace.
-    chown root shell /sys/kernel/debug/tracing/trace
-    chown root shell /sys/kernel/tracing/trace
-    chmod 0660 /sys/kernel/debug/tracing/trace
-    chmod 0660 /sys/kernel/tracing/trace
+# Read and truncate the kernel trace.
+    chmod 0666 /sys/kernel/debug/tracing/trace
+    chmod 0666 /sys/kernel/tracing/trace
 
 on property:persist.debug.atrace.boottrace=1
     start boottrace
diff --git a/cmds/atrace/atrace_userdebug.rc b/cmds/atrace/atrace_userdebug.rc
index 5fd28e2..9d632cc 100644
--- a/cmds/atrace/atrace_userdebug.rc
+++ b/cmds/atrace/atrace_userdebug.rc
@@ -1,47 +1,43 @@
 ## Permissions to allow additional system-wide tracing to the kernel trace buffer.
 ## The default list of permissions is set in frameworks/native/cmds/atrace/atrace.rc
 
-# Allow the shell group to enable kernel tracepoints:
+# Grant unix world read/write permissions to enable kernel tracepoints.
+# Access control to these files is now entirely in selinux policy.
 
 on post-fs
-    chown root shell /sys/kernel/debug/tracing/events/sync/enable
-    chown root shell /sys/kernel/debug/tracing/events/workqueue/enable
-    chown root shell /sys/kernel/debug/tracing/events/regulator/enable
-    chown root shell /sys/kernel/debug/tracing/events/pagecache/enable
+    chmod 0666 /sys/kernel/tracing/events/sync/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/sync/enable
+    chmod 0666 /sys/kernel/tracing/events/workqueue/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/workqueue/enable
+    chmod 0666 /sys/kernel/tracing/events/regulator/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/regulator/enable
+    chmod 0666 /sys/kernel/tracing/events/pagecache/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/pagecache/enable
 
     # irq
-    chown root shell /sys/kernel/debug/tracing/events/irq/enable
-    chown root shell /sys/kernel/debug/tracing/events/ipi/enable
+    chmod 0666 /sys/kernel/tracing/events/irq/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/irq/enable
+    chmod 0666 /sys/kernel/tracing/events/ipi/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/ipi/enable
 
     # disk
-    chown root shell /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_enter/enable
-    chown root shell /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_exit/enable
-    chown root shell /sys/kernel/debug/tracing/events/f2fs/f2fs_write_begin/enable
-    chown root shell /sys/kernel/debug/tracing/events/f2fs/f2fs_write_end/enable
-    chown root shell /sys/kernel/debug/tracing/events/ext4/ext4_da_write_begin/enable
-    chown root shell /sys/kernel/debug/tracing/events/ext4/ext4_da_write_end/enable
-    chown root shell /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/enable
-    chown root shell /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit/enable
-    chown root shell /sys/kernel/debug/tracing/events/block/block_rq_issue/enable
-    chown root shell /sys/kernel/debug/tracing/events/block/block_rq_complete/enable
-
-    chmod 0664 /sys/kernel/debug/tracing/events/sync/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/workqueue/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/regulator/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/pagecache/enable
-
-    # irq
-    chmod 0664 /sys/kernel/debug/tracing/events/irq/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/ipi/enable
-
-    # disk
-    chmod 0664 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_enter/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_exit/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_begin/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_end/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_begin/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_end/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/block/block_rq_issue/enable
-    chmod 0664 /sys/kernel/debug/tracing/events/block/block_rq_complete/enable
+    chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_enter/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_enter/enable
+    chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_exit/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_exit/enable
+    chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_write_begin/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_begin/enable
+    chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_write_end/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_end/enable
+    chmod 0666 /sys/kernel/tracing/events/ext4/ext4_da_write_begin/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_begin/enable
+    chmod 0666 /sys/kernel/tracing/events/ext4/ext4_da_write_end/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_end/enable
+    chmod 0666 /sys/kernel/tracing/events/ext4/ext4_sync_file_enter/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/enable
+    chmod 0666 /sys/kernel/tracing/events/ext4/ext4_sync_file_exit/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit/enable
+    chmod 0666 /sys/kernel/tracing/events/block/block_rq_issue/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_issue/enable
+    chmod 0666 /sys/kernel/tracing/events/block/block_rq_complete/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_complete/enable
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index 35cff5f..562898d 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -14,7 +14,7 @@
 // limitations under the License.
 
 cc_defaults {
-    name: "dumpstate_defaults",
+    name: "dumpstate_cflag_defaults",
     cflags: [
         "-Wall",
         "-Werror",
@@ -26,7 +26,7 @@
 
 cc_library_shared {
     name: "libdumpstateutil",
-    defaults: ["dumpstate_defaults"],
+    defaults: ["dumpstate_cflag_defaults"],
     vendor_available: true,
     vndk: {
         enabled: true,
@@ -47,7 +47,7 @@
 
 cc_library_shared {
     name: "libdumpstateaidl",
-    defaults: ["dumpstate_defaults"],
+    defaults: ["dumpstate_cflag_defaults"],
     shared_libs: [
         "libbinder",
         "libutils",
@@ -63,9 +63,9 @@
     ],
 }
 
-cc_binary {
-    name: "dumpstate",
-    defaults: ["dumpstate_defaults"],
+cc_defaults {
+    name: "dumpstate_defaults",
+    defaults: ["dumpstate_cflag_defaults"],
     shared_libs: [
         "android.hardware.dumpstate@1.0",
         "libziparchive",
@@ -82,12 +82,22 @@
         "libutils",
     ],
     srcs: [
-        "DumpstateInternal.cpp",
         "DumpstateSectionReporter.cpp",
         "DumpstateService.cpp",
-        "main.cpp",
         "utils.cpp",
+    ],
+    static_libs: [
+        "libdumpsys",
+        "libserviceutils"
+    ],
+}
+
+cc_binary {
+    name: "dumpstate",
+    defaults: ["dumpstate_defaults"],
+    srcs: [
         "dumpstate.cpp",
+        "main.cpp",
     ],
     init_rc: ["dumpstate.rc"],
 }
@@ -95,24 +105,18 @@
 cc_test {
     name: "dumpstate_test",
     defaults: ["dumpstate_defaults"],
-    shared_libs: [
-        "libziparchive",
-        "libbase",
-        "libbinder",
-        "libcutils",
-        "libdebuggerd_client",
-        "libdumpstateaidl",
-        "libdumpstateutil",
-        "libhidlbase",
-        "libhidltransport",
-        "liblog",
-        "libutils",
-    ],
     srcs: [
-        "DumpstateInternal.cpp",
-        "DumpstateService.cpp",
-        "utils.cpp",
         "tests/dumpstate_test.cpp",
     ],
     static_libs: ["libgmock"],
 }
+
+cc_test {
+    name: "dumpstate_smoke_test",
+    defaults: ["dumpstate_defaults"],
+    srcs: [
+        "dumpstate.cpp",
+        "tests/dumpstate_smoke_test.cpp",
+    ],
+    static_libs: ["libgmock"],
+}
\ No newline at end of file
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 93f8d43..ef5064c 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -25,6 +25,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/poll.h>
 #include <sys/prctl.h>
 #include <sys/resource.h>
 #include <sys/stat.h>
@@ -46,22 +47,39 @@
 #include <android/hidl/manager/1.0/IServiceManager.h>
 #include <cutils/native_handle.h>
 #include <cutils/properties.h>
+#include <dumpsys.h>
 #include <hidl/ServiceManagement.h>
 #include <openssl/sha.h>
 #include <private/android_filesystem_config.h>
 #include <private/android_logger.h>
-
+#include <serviceutils/PriorityDumper.h>
 #include "DumpstateInternal.h"
+#include "DumpstateSectionReporter.h"
 #include "DumpstateService.h"
 #include "dumpstate.h"
 
 using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
+using ::std::literals::chrono_literals::operator""ms;
+using ::std::literals::chrono_literals::operator""s;
 
 // TODO: remove once moved to namespace
+using android::defaultServiceManager;
+using android::Dumpsys;
+using android::INVALID_OPERATION;
+using android::IServiceManager;
+using android::OK;
+using android::sp;
+using android::status_t;
+using android::String16;
+using android::String8;
+using android::TIMED_OUT;
+using android::UNKNOWN_ERROR;
+using android::Vector;
 using android::os::dumpstate::CommandOptions;
 using android::os::dumpstate::DumpFileToFd;
-using android::os::dumpstate::PropertiesHelper;
+using android::os::dumpstate::DumpstateSectionReporter;
 using android::os::dumpstate::GetPidByName;
+using android::os::dumpstate::PropertiesHelper;
 
 /* read before root is shed */
 static char cmdline_buf[16384] = "(unknown)";
@@ -127,6 +145,8 @@
 
 // Must be hardcoded because dumpstate HAL implementation need SELinux access to it
 static const std::string kDumpstateBoardPath = "/bugreports/";
+static const std::string kProtoPath = "proto/";
+static const std::string kProtoExt = ".proto";
 static const std::string kDumpstateBoardFiles[] = {
     "dumpstate_board.txt",
     "dumpstate_board.bin"
@@ -221,7 +241,7 @@
         }
 
         if (ds.IsZipping() && add_to_zip) {
-            if (!ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd)) {
+            if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
                 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
             }
         } else {
@@ -657,12 +677,18 @@
     return 0;
 }
 
-/* timeout in ms */
-static unsigned long logcat_timeout(const char *name) {
-    log_id_t id = android_name_to_log_id(name);
-    unsigned long property_size = __android_logger_get_buffer_size(id);
-    /* Engineering margin is ten-fold our guess */
-    return 10 * (property_size + worst_write_perf) / worst_write_perf;
+static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
+
+/* timeout in ms to read a list of buffers */
+static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
+    unsigned long timeout_ms = 0;
+    for (const auto& buffer : buffers) {
+        log_id_t id = android_name_to_log_id(buffer.c_str());
+        unsigned long property_size = __android_logger_get_buffer_size(id);
+        /* Engineering margin is ten-fold our guess */
+        timeout_ms += 10 * (property_size + worst_write_perf) / worst_write_perf;
+    }
+    return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
 }
 
 void Dumpstate::PrintHeader() const {
@@ -708,11 +734,12 @@
       ".shb", ".sys", ".vb",  ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
 };
 
-bool Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd) {
+status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
+                                      std::chrono::milliseconds timeout = 0ms) {
     if (!IsZipping()) {
         MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
                entry_name.c_str());
-        return false;
+        return INVALID_OPERATION;
     }
     std::string valid_name = entry_name;
 
@@ -734,32 +761,55 @@
     if (err != 0) {
         MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
                ZipWriter::ErrorCodeString(err));
-        return false;
+        return UNKNOWN_ERROR;
     }
+    auto start = std::chrono::steady_clock::now();
+    auto end = start + timeout;
+    struct pollfd pfd = {fd, POLLIN};
 
     std::vector<uint8_t> buffer(65536);
     while (1) {
+        if (timeout.count() > 0) {
+            // lambda to recalculate the timeout.
+            auto time_left_ms = [end]() {
+                auto now = std::chrono::steady_clock::now();
+                auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
+                return std::max(diff.count(), 0LL);
+            };
+
+            int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
+            if (rc < 0) {
+                MYLOGE("Error in poll while adding from fd to zip entry %s:%s", entry_name.c_str(),
+                       strerror(errno));
+                return -errno;
+            } else if (rc == 0) {
+                MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms",
+                       entry_name.c_str(), strerror(errno), timeout.count());
+                return TIMED_OUT;
+            }
+        }
+
         ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
         if (bytes_read == 0) {
             break;
         } else if (bytes_read == -1) {
             MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
-            return false;
+            return -errno;
         }
         err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
         if (err) {
             MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
-            return false;
+            return UNKNOWN_ERROR;
         }
     }
 
     err = zip_writer_->FinishEntry();
     if (err != 0) {
         MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
-        return false;
+        return UNKNOWN_ERROR;
     }
 
-    return true;
+    return OK;
 }
 
 bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
@@ -770,12 +820,12 @@
         return false;
     }
 
-    return AddZipEntryFromFd(entry_name, fd.get());
+    return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
 }
 
 /* adds a file to the existing zipped bugreport */
 static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
-    return ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
+    return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
 }
 
 void Dumpstate::AddDir(const std::string& dir, bool recursive) {
@@ -831,13 +881,8 @@
     }
 }
 
-static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
-
 static void DoKernelLogcat() {
-    unsigned long timeout_ms = logcat_timeout("kernel");
-    if (timeout_ms < MINIMUM_LOGCAT_TIMEOUT_MS) {
-        timeout_ms = MINIMUM_LOGCAT_TIMEOUT_MS;
-    }
+    unsigned long timeout_ms = logcat_timeout({"kernel"});
     RunCommand(
         "KERNEL LOG",
         {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
@@ -848,25 +893,21 @@
     unsigned long timeout_ms;
     // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
     // calculate timeout
-    timeout_ms = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
-    if (timeout_ms < MINIMUM_LOGCAT_TIMEOUT_MS) {
-        timeout_ms = MINIMUM_LOGCAT_TIMEOUT_MS;
-    }
+    timeout_ms = logcat_timeout({"main", "system", "crash"});
     RunCommand("SYSTEM LOG",
                {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
                CommandOptions::WithTimeoutInMs(timeout_ms).Build());
-    timeout_ms = logcat_timeout("events");
-    if (timeout_ms < MINIMUM_LOGCAT_TIMEOUT_MS) {
-        timeout_ms = MINIMUM_LOGCAT_TIMEOUT_MS;
-    }
+    timeout_ms = logcat_timeout({"events"});
     RunCommand(
         "EVENT LOG",
         {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
         CommandOptions::WithTimeoutInMs(timeout_ms).Build());
-    timeout_ms = logcat_timeout("radio");
-    if (timeout_ms < MINIMUM_LOGCAT_TIMEOUT_MS) {
-        timeout_ms = MINIMUM_LOGCAT_TIMEOUT_MS;
-    }
+    timeout_ms = logcat_timeout({"stats"});
+    RunCommand(
+        "STATS LOG",
+        {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
+        CommandOptions::WithTimeoutInMs(timeout_ms).Build());
+    timeout_ms = logcat_timeout({"radio"});
     RunCommand(
         "RADIO LOG",
         {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
@@ -1069,11 +1110,97 @@
     RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
 }
 
+void RunDumpsysText(const std::string& title, int priority, std::chrono::milliseconds timeout,
+                    std::chrono::milliseconds service_timeout) {
+    sp<android::IServiceManager> sm = defaultServiceManager();
+    Dumpsys dumpsys(sm.get());
+    DurationReporter duration_reporter(title);
+    Vector<String16> args;
+    Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
+
+    if (!title.empty()) {
+        dprintf(STDOUT_FILENO, "------ %s (%s) ------\n", title.c_str(), "/system/bin/dumpsys");
+        fsync(STDOUT_FILENO);
+    }
+
+    auto start = std::chrono::steady_clock::now();
+    Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
+    for (const String16& service : services) {
+        std::string path(title);
+        path.append(" - ").append(String8(service).c_str());
+        DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
+        size_t bytes_written = 0;
+        status_t status = dumpsys.startDumpThread(service, args);
+        if (status == OK) {
+            dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
+            std::chrono::duration<double> elapsed_seconds;
+            status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
+                                       /* as_proto = */ false, elapsed_seconds, bytes_written);
+            section_reporter.setSize(bytes_written);
+            dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
+            bool dump_complete = (status == OK);
+            dumpsys.stopDumpThread(dump_complete);
+        }
+        section_reporter.setStatus(status);
+
+        auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
+            std::chrono::steady_clock::now() - start);
+        if (elapsed_duration > timeout) {
+            MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
+                   elapsed_duration.count());
+            break;
+        }
+    }
+}
+
+void RunDumpsysProto(const std::string& title, int priority, std::chrono::milliseconds timeout,
+                     std::chrono::milliseconds service_timeout) {
+    sp<android::IServiceManager> sm = defaultServiceManager();
+    Dumpsys dumpsys(sm.get());
+    Vector<String16> args;
+    Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
+    DurationReporter duration_reporter(title);
+
+    auto start = std::chrono::steady_clock::now();
+    Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
+    for (const String16& service : services) {
+        std::string path(kProtoPath);
+        path.append(String8(service).c_str());
+        if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
+            path.append("_CRITICAL");
+        } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
+            path.append("_HIGH");
+        }
+        path.append(kProtoExt);
+        DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
+        status_t status = dumpsys.startDumpThread(service, args);
+        if (status == OK) {
+            status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
+            bool dumpTerminated = (status == OK);
+            dumpsys.stopDumpThread(dumpTerminated);
+        }
+        ZipWriter::FileEntry file_entry;
+        ds.zip_writer_->GetLastEntry(&file_entry);
+        section_reporter.setSize(file_entry.compressed_size);
+        section_reporter.setStatus(status);
+
+        auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
+            std::chrono::steady_clock::now() - start);
+        if (elapsed_duration > timeout) {
+            MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
+                   elapsed_duration.count());
+            break;
+        }
+    }
+}
+
 // Runs dumpsys on services that must dump first and and will take less than 100ms to dump.
 static void RunDumpsysCritical() {
     if (ds.CurrentVersionSupportsPriorityDumps()) {
-        RunDumpsys("DUMPSYS CRITICAL", {"--priority", "CRITICAL"},
-                   CommandOptions::WithTimeout(5).DropRoot().Build());
+        RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
+                       /* timeout= */ 5s, /* service_timeout= */ 500ms);
+        RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
+                        /* timeout= */ 5s, /* service_timeout= */ 500ms);
     } else {
         RunDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
                    CommandOptions::WithTimeout(90).DropRoot().Build());
@@ -1085,8 +1212,13 @@
 // Runs dumpsys on services that must dump first but can take up to 250ms to dump.
 static void RunDumpsysHigh() {
     if (ds.CurrentVersionSupportsPriorityDumps()) {
-        RunDumpsys("DUMPSYS HIGH", {"--priority", "HIGH"},
-                   CommandOptions::WithTimeout(20).DropRoot().Build());
+        // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
+        // high priority. Reduce timeout once they are able to dump in a shorter time or
+        // moved to a parallel task.
+        RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
+                       /* timeout= */ 90s, /* service_timeout= */ 30s);
+        RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
+                        /* timeout= */ 5s, /* service_timeout= */ 1s);
     } else {
         RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"});
     }
@@ -1095,8 +1227,10 @@
 // Runs dumpsys on services that must dump but can take up to 10s to dump.
 static void RunDumpsysNormal() {
     if (ds.CurrentVersionSupportsPriorityDumps()) {
-        RunDumpsys("DUMPSYS NORMAL", {"--priority", "NORMAL"},
-                   CommandOptions::WithTimeout(90).DropRoot().Build());
+        RunDumpsysText("DUMPSYS", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
+                       /* timeout= */ 90s, /* service_timeout= */ 10s);
+        RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
+                        /* timeout= */ 90s, /* service_timeout= */ 10s);
     } else {
         RunDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"},
                    CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
@@ -1136,7 +1270,7 @@
                 }
                 RunCommandToFd(fd,
                         "",
-                        {"lshal", "debug", interface},
+                        {"lshal", "debug", "-E", interface},
                         CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
 
                 bool empty = 0 == lseek(fd, 0, SEEK_END);
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 843c545..2554b63 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -226,8 +226,14 @@
 
     /*
      * Adds a new entry to the existing zip file.
+     *
+     * |entry_name| destination path of the new entry.
+     * |fd| file descriptor to read from.
+     * |timeout| timeout to terminate the read if not completed. Set
+     * value of 0s (default) to disable timeout.
      */
-    bool AddZipEntryFromFd(const std::string& entry_name, int fd);
+    android::status_t AddZipEntryFromFd(const std::string& entry_name, int fd,
+                                        std::chrono::milliseconds timeout);
 
     /*
      * Adds a text entry entry to the existing zip file.
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
new file mode 100644
index 0000000..61a5ef5
--- /dev/null
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -0,0 +1,286 @@
+/*
+ * 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.
+ */
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <fcntl.h>
+#include <libgen.h>
+
+#include <android-base/file.h>
+#include <cutils/properties.h>
+#include <ziparchive/zip_archive.h>
+
+#include "dumpstate.h"
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+namespace android {
+namespace os {
+namespace dumpstate {
+
+using ::testing::Test;
+using ::std::literals::chrono_literals::operator""s;
+
+struct SectionInfo {
+    std::string name;
+    status_t status;
+    int32_t size_bytes;
+    int32_t duration_ms;
+};
+
+/**
+ * Listens to bugreport progress and updates the user by writing the progress to STDOUT. All the
+ * section details generated by dumpstate are added to a vector to be used by Tests later.
+ */
+class DumpstateListener : public IDumpstateListener {
+  public:
+    int outFd_, max_progress_;
+    std::shared_ptr<std::vector<SectionInfo>> sections_;
+    DumpstateListener(int fd, std::shared_ptr<std::vector<SectionInfo>> sections)
+        : outFd_(fd), max_progress_(5000), sections_(sections) {
+    }
+    binder::Status onProgressUpdated(int32_t progress) override {
+        dprintf(outFd_, "\rIn progress %d/%d", progress, max_progress_);
+        return binder::Status::ok();
+    }
+    binder::Status onMaxProgressUpdated(int32_t max_progress) override {
+        max_progress_ = max_progress;
+        return binder::Status::ok();
+    }
+    binder::Status onSectionComplete(const ::std::string& name, int32_t status, int32_t size_bytes,
+                                     int32_t duration_ms) override {
+        sections_->push_back({name, status, size_bytes, duration_ms});
+        return binder::Status::ok();
+    }
+    IBinder* onAsBinder() override {
+        return nullptr;
+    }
+};
+
+/**
+ * Generates bug report and provide access to the bug report file and other info for other tests.
+ * Since bug report generation is slow, the bugreport is only generated once.
+ */
+class ZippedBugreportGenerationTest : public Test {
+  public:
+    static std::shared_ptr<std::vector<SectionInfo>> sections;
+    static Dumpstate& ds;
+    static std::chrono::milliseconds duration;
+    static void SetUpTestCase() {
+        property_set("dumpstate.options", "bugreportplus");
+        // clang-format off
+        char* argv[] = {
+            (char*)"dumpstate",
+            (char*)"-d",
+            (char*)"-z",
+            (char*)"-B",
+            (char*)"-o",
+            (char*)dirname(android::base::GetExecutablePath().c_str())
+        };
+        // clang-format on
+        sp<DumpstateListener> listener(new DumpstateListener(dup(fileno(stdout)), sections));
+        ds.listener_ = listener;
+        ds.listener_name_ = "Smokey";
+        ds.report_section_ = true;
+        auto start = std::chrono::steady_clock::now();
+        run_main(ARRAY_SIZE(argv), argv);
+        auto end = std::chrono::steady_clock::now();
+        duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
+    }
+
+    static const char* getZipFilePath() {
+        return ds.GetPath(".zip").c_str();
+    }
+};
+std::shared_ptr<std::vector<SectionInfo>> ZippedBugreportGenerationTest::sections =
+    std::make_shared<std::vector<SectionInfo>>();
+Dumpstate& ZippedBugreportGenerationTest::ds = Dumpstate::GetInstance();
+std::chrono::milliseconds ZippedBugreportGenerationTest::duration = 0s;
+
+TEST_F(ZippedBugreportGenerationTest, IsGeneratedWithoutErrors) {
+    EXPECT_EQ(access(getZipFilePath(), F_OK), 0);
+}
+
+TEST_F(ZippedBugreportGenerationTest, Is3MBto30MBinSize) {
+    struct stat st;
+    EXPECT_EQ(stat(getZipFilePath(), &st), 0);
+    EXPECT_GE(st.st_size, 3000000 /* 3MB */);
+    EXPECT_LE(st.st_size, 30000000 /* 30MB */);
+}
+
+TEST_F(ZippedBugreportGenerationTest, TakesBetween30And150Seconds) {
+    EXPECT_GE(duration, 30s) << "Expected completion in more than 30s. Actual time "
+                             << duration.count() << " s.";
+    EXPECT_LE(duration, 150s) << "Expected completion in less than 150s. Actual time "
+                              << duration.count() << " s.";
+}
+
+/**
+ * Run tests on contents of zipped bug report.
+ */
+class ZippedBugReportContentsTest : public Test {
+  public:
+    ZipArchiveHandle handle;
+    void SetUp() {
+        ASSERT_EQ(OpenArchive(ZippedBugreportGenerationTest::getZipFilePath(), &handle), 0);
+    }
+    void TearDown() {
+        CloseArchive(handle);
+    }
+
+    void FileExists(const char* filename, uint32_t minsize, uint32_t maxsize) {
+        ZipEntry entry;
+        EXPECT_EQ(FindEntry(handle, ZipString(filename), &entry), 0);
+        EXPECT_GT(entry.uncompressed_length, minsize);
+        EXPECT_LT(entry.uncompressed_length, maxsize);
+    }
+};
+
+TEST_F(ZippedBugReportContentsTest, ContainsMainEntry) {
+    ZipEntry mainEntryLoc;
+    // contains main entry name file
+    EXPECT_EQ(FindEntry(handle, ZipString("main_entry.txt"), &mainEntryLoc), 0);
+
+    char* buf = new char[mainEntryLoc.uncompressed_length];
+    ExtractToMemory(handle, &mainEntryLoc, (uint8_t*)buf, mainEntryLoc.uncompressed_length);
+    delete[] buf;
+
+    // contains main entry file
+    FileExists(buf, 1000000U, 50000000U);
+}
+
+TEST_F(ZippedBugReportContentsTest, ContainsVersion) {
+    ZipEntry entry;
+    // contains main entry name file
+    EXPECT_EQ(FindEntry(handle, ZipString("version.txt"), &entry), 0);
+
+    char* buf = new char[entry.uncompressed_length + 1];
+    ExtractToMemory(handle, &entry, (uint8_t*)buf, entry.uncompressed_length);
+    buf[entry.uncompressed_length] = 0;
+    EXPECT_STREQ(buf, ZippedBugreportGenerationTest::ds.version_.c_str());
+    delete[] buf;
+}
+
+TEST_F(ZippedBugReportContentsTest, ContainsBoardSpecificFiles) {
+    FileExists("dumpstate_board.bin", 1000000U, 80000000U);
+    FileExists("dumpstate_board.txt", 100000U, 1000000U);
+}
+
+// Spot check on some files pulled from the file system
+TEST_F(ZippedBugReportContentsTest, ContainsSomeFileSystemFiles) {
+    // FS/proc/*/mountinfo size > 0
+    FileExists("FS/proc/1/mountinfo", 0U, 100000U);
+
+    // FS/data/misc/profiles/cur/0/*/primary.prof size > 0
+    FileExists("FS/data/misc/profiles/cur/0/com.android.phone/primary.prof", 0U, 100000U);
+}
+
+/**
+ * Runs tests on section data generated by dumpstate and captured by DumpstateListener.
+ */
+class BugreportSectionTest : public Test {
+  public:
+    int numMatches(const std::string& substring) {
+        int matches = 0;
+        for (auto const& section : *ZippedBugreportGenerationTest::sections) {
+            if (section.name.find(substring) != std::string::npos) {
+                matches++;
+            }
+        }
+        return matches;
+    }
+    void SectionExists(const std::string& sectionName, int minsize) {
+        for (auto const& section : *ZippedBugreportGenerationTest::sections) {
+            if (sectionName == section.name) {
+                EXPECT_GE(section.size_bytes, minsize);
+                return;
+            }
+        }
+        FAIL() << sectionName << " not found.";
+    }
+};
+
+// Test all sections are generated without timeouts or errors
+TEST_F(BugreportSectionTest, GeneratedWithoutErrors) {
+    for (auto const& section : *ZippedBugreportGenerationTest::sections) {
+        EXPECT_EQ(section.status, 0) << section.name << " failed with status " << section.status;
+    }
+}
+
+TEST_F(BugreportSectionTest, Atleast3CriticalDumpsysSectionsGenerated) {
+    int numSections = numMatches("DUMPSYS CRITICAL");
+    EXPECT_GE(numSections, 3);
+}
+
+TEST_F(BugreportSectionTest, Atleast2HighDumpsysSectionsGenerated) {
+    int numSections = numMatches("DUMPSYS HIGH");
+    EXPECT_GE(numSections, 2);
+}
+
+TEST_F(BugreportSectionTest, Atleast50NormalDumpsysSectionsGenerated) {
+    int allSections = numMatches("DUMPSYS");
+    int criticalSections = numMatches("DUMPSYS CRITICAL");
+    int highSections = numMatches("DUMPSYS HIGH");
+    int normalSections = allSections - criticalSections - highSections;
+
+    EXPECT_GE(normalSections, 50) << "Total sections less than 50 (Critical:" << criticalSections
+                                  << "High:" << highSections << "Normal:" << normalSections << ")";
+}
+
+TEST_F(BugreportSectionTest, Atleast1ProtoDumpsysSectionGenerated) {
+    int numSections = numMatches("proto/");
+    EXPECT_GE(numSections, 1);
+}
+
+// Test if some critical sections are being generated.
+TEST_F(BugreportSectionTest, CriticalSurfaceFlingerSectionGenerated) {
+    SectionExists("DUMPSYS CRITICAL - SurfaceFlinger", /* bytes= */ 10000);
+}
+
+TEST_F(BugreportSectionTest, ActivitySectionsGenerated) {
+    SectionExists("DUMPSYS CRITICAL - activity", /* bytes= */ 5000);
+    SectionExists("DUMPSYS - activity", /* bytes= */ 10000);
+}
+
+TEST_F(BugreportSectionTest, CpuinfoSectionGenerated) {
+    SectionExists("DUMPSYS CRITICAL - cpuinfo", /* bytes= */ 1000);
+}
+
+TEST_F(BugreportSectionTest, WindowSectionGenerated) {
+    SectionExists("DUMPSYS CRITICAL - window", /* bytes= */ 20000);
+}
+
+TEST_F(BugreportSectionTest, ConnectivitySectionsGenerated) {
+    SectionExists("DUMPSYS HIGH - connectivity", /* bytes= */ 5000);
+    SectionExists("DUMPSYS - connectivity", /* bytes= */ 5000);
+}
+
+TEST_F(BugreportSectionTest, MeminfoSectionGenerated) {
+    SectionExists("DUMPSYS HIGH - meminfo", /* bytes= */ 100000);
+}
+
+TEST_F(BugreportSectionTest, BatteryStatsSectionGenerated) {
+    SectionExists("DUMPSYS - batterystats", /* bytes= */ 1000);
+}
+
+TEST_F(BugreportSectionTest, WifiSectionGenerated) {
+    SectionExists("DUMPSYS - wifi", /* bytes= */ 100000);
+}
+
+}  // namespace dumpstate
+}  // namespace os
+}  // namespace android
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index ae0cc01..ca7d95e 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -283,7 +283,7 @@
     return services;
 }
 
-void Dumpsys::setServiceArgs(Vector<String16>& args, bool asProto, int priorityFlags) const {
+void Dumpsys::setServiceArgs(Vector<String16>& args, bool asProto, int priorityFlags) {
     if ((priorityFlags == IServiceManager::DUMP_FLAG_PRIORITY_ALL) ||
         (priorityFlags == IServiceManager::DUMP_FLAG_PRIORITY_NORMAL)) {
         args.add(String16("-a"));
diff --git a/cmds/dumpsys/dumpsys.h b/cmds/dumpsys/dumpsys.h
index 1d78aa4..84f3b02 100644
--- a/cmds/dumpsys/dumpsys.h
+++ b/cmds/dumpsys/dumpsys.h
@@ -49,7 +49,7 @@
      * @param priorityFlags indicates priority of dump by passing additional priority args
      * to the service
      */
-    void setServiceArgs(Vector<String16>& args, bool asProto, int priorityFlags) const;
+    static void setServiceArgs(Vector<String16>& args, bool asProto, int priorityFlags);
 
     /**
      * Starts a thread to connect to a service and get its dump output. The thread redirects
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index f787887..bc91285 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -18,17 +18,20 @@
 
 #define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER
 
+#include <algorithm>
 #include <errno.h>
-#include <inttypes.h>
 #include <fstream>
 #include <fts.h>
+#include <inttypes.h>
 #include <regex>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/capability.h>
 #include <sys/file.h>
-#include <sys/resource.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
 #include <sys/quota.h>
+#include <sys/resource.h>
 #include <sys/stat.h>
 #include <sys/statvfs.h>
 #include <sys/types.h>
@@ -41,6 +44,7 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
+#include <cutils/ashmem.h>
 #include <cutils/fs.h>
 #include <cutils/properties.h>
 #include <cutils/sched_policy.h>
@@ -84,6 +88,10 @@
 static constexpr const char* IDMAP_PREFIX = "/data/resource-cache/";
 static constexpr const char* IDMAP_SUFFIX = "@idmap";
 
+// fsverity assumes the page size is always 4096. If not, the feature can not be
+// enabled.
+static constexpr int kVerityPageSize = 4096;
+static constexpr size_t kSha256Size = 32;
 static constexpr const char* kPropApkVerityMode = "ro.apk_verity.mode";
 
 // NOTE: keep in sync with Installer
@@ -184,6 +192,12 @@
     }                                                       \
 }
 
+#define ASSERT_PAGE_SIZE_4K() {                             \
+    if (getpagesize() != kVerityPageSize) {                 \
+        return error("FSVerity only supports 4K page");     \
+    }                                                       \
+}
+
 }  // namespace
 
 status_t InstalldNativeService::start() {
@@ -1940,27 +1954,6 @@
     return ok();
 }
 
-void mkinnerdirs(char* path, int basepos, mode_t mode, int uid, int gid,
-        struct stat* statbuf)
-{
-    while (path[basepos] != 0) {
-        if (path[basepos] == '/') {
-            path[basepos] = 0;
-            if (lstat(path, statbuf) < 0) {
-                ALOGV("Making directory: %s\n", path);
-                if (mkdir(path, mode) == 0) {
-                    chown(path, uid, gid);
-                } else {
-                    ALOGW("Unable to make directory %s: %s\n", path, strerror(errno));
-                }
-            }
-            path[basepos] = '/';
-            basepos++;
-        }
-        basepos++;
-    }
-}
-
 binder::Status InstalldNativeService::linkNativeLibraryDirectory(
         const std::unique_ptr<std::string>& uuid, const std::string& packageName,
         const std::string& nativeLibPath32, int32_t userId) {
@@ -2358,15 +2351,116 @@
     return res ? ok() : error();
 }
 
-binder::Status InstalldNativeService::installApkVerity(const std::string& /*filePath*/,
-        const ::android::base::unique_fd& /*verityInput*/) {
+// This kernel feaeture is experimental.
+// TODO: remove local definition once upstreamed
+#ifndef FS_IOC_SET_FSVERITY
+struct fsverity_set {
+    __u64 offset;
+    __u64 flags;
+};
+
+struct fsverity_root_hash {
+    short root_hash_algorithm;
+    short flags;
+    __u8 reserved[4];
+    __u8 root_hash[64];
+};
+
+#define FS_IOC_MEASURE_FSVERITY        _IOW('f', 2733, struct fsverity_root_hash)
+#define FS_IOC_SET_FSVERITY            _IOW('f', 2734, struct fsverity_set)
+
+#define FSVERITY_FLAG_ENABLED          0x0001
+#endif
+
+binder::Status InstalldNativeService::installApkVerity(const std::string& filePath,
+        const ::android::base::unique_fd& verityInputAshmem) {
     ENFORCE_UID(AID_SYSTEM);
     if (!android::base::GetBoolProperty(kPropApkVerityMode, false)) {
         return ok();
     }
-    // TODO: Append verity to filePath then issue ioctl to enable
-    // it and hide the tree.  See b/30972906.
-    return error("not implemented yet");
+#if DEBUG
+    ASSERT_PAGE_SIZE_4K();
+#endif
+    // TODO: also check fsverity support in the current file system if compiled with DEBUG.
+    // TODO: change ashmem to some temporary file to support huge apk.
+    if (!ashmem_valid(verityInputAshmem.get())) {
+        return error("FD is not an ashmem");
+    }
+
+    // TODO(71871109): Validate filePath.
+    // 1. Seek to the next page boundary beyond the end of the file.
+    ::android::base::unique_fd wfd(open(filePath.c_str(), O_WRONLY | O_APPEND));
+    if (wfd.get() < 0) {
+        return error("Failed to open " + filePath + ": " + strerror(errno));
+    }
+    struct stat st;
+    if (fstat(wfd.get(), &st) < 0) {
+        return error("Failed to stat " + filePath + ": " + strerror(errno));
+    }
+    // fsverity starts from the block boundary.
+    if (lseek(wfd.get(), (st.st_size + kVerityPageSize - 1) / kVerityPageSize, SEEK_SET) < 0) {
+        return error("Failed to lseek " + filePath + ": " + strerror(errno));
+    }
+
+    // 2. Write everything in the ashmem to the file.
+    int size = ashmem_get_size_region(verityInputAshmem.get());
+    if (size < 0) {
+        return error("Failed to get ashmem size: " + std::to_string(size));
+    }
+    void* data = mmap(NULL, size, PROT_READ, MAP_SHARED, wfd.get(), 0);
+    if (data == MAP_FAILED) {
+        return error("Failed to mmap the ashmem: " + std::string(strerror(errno)));
+    }
+    int remaining = size;
+    while (remaining > 0) {
+        int ret = TEMP_FAILURE_RETRY(write(wfd.get(), data, remaining));
+        if (ret < 0) {
+            munmap(data, size);
+            return error("Failed to write to " + filePath + " (" + std::to_string(remaining) +
+                         + "/" + std::to_string(size) + "): " + strerror(errno));
+        }
+        remaining -= ret;
+    }
+    munmap(data, size);
+
+    // 3. Enable fsverity. Once it's done, the file becomes immutable.
+    struct fsverity_set config;
+    config.offset = st.st_size;
+    config.flags = FSVERITY_FLAG_ENABLED;
+    if (ioctl(wfd.get(), FS_IOC_SET_FSVERITY, &config) < 0) {
+        return error("Failed to enable fsverity on " + filePath + ": " + strerror(errno));
+    }
+    return ok();
+}
+
+binder::Status InstalldNativeService::assertFsverityRootHashMatches(const std::string& filePath,
+        const std::vector<uint8_t>& expectedHash) {
+    ENFORCE_UID(AID_SYSTEM);
+    if (!android::base::GetBoolProperty(kPropApkVerityMode, false)) {
+        return ok();
+    }
+    // TODO: also check fsverity support in the current file system if compiled with DEBUG.
+    if (expectedHash.size() != kSha256Size) {
+        return error("verity hash size should be " + std::to_string(kSha256Size) + " but is " +
+                     std::to_string(expectedHash.size()));
+    }
+
+    // TODO(71871109): Validate filePath.
+    ::android::base::unique_fd fd(open(filePath.c_str(), O_RDONLY));
+    if (fd.get() < 0) {
+        return error("Failed to open " + filePath + ": " + strerror(errno));
+    }
+
+    struct fsverity_root_hash config;
+    memset(&config, 0, sizeof(config));
+    config.root_hash_algorithm = 0;  // SHA256
+    memcpy(config.root_hash, expectedHash.data(), std::min(sizeof(config.root_hash), kSha256Size));
+    if (ioctl(fd.get(), FS_IOC_MEASURE_FSVERITY, &config) < 0) {
+        // This includes an expected failure case with no FSVerity setup. It normally happens when
+        // the apk does not contains the Merkle tree root hash.
+        return error("Failed to measure fsverity on " + filePath + ": " + strerror(errno));
+    }
+    return ok();  // hashes match
 }
 
 binder::Status InstalldNativeService::reconcileSecondaryDexFile(
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index cef62cd..887a2fc 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -120,6 +120,8 @@
             const std::unique_ptr<std::string>& outputPath);
     binder::Status installApkVerity(const std::string& filePath,
             const ::android::base::unique_fd& verityInput);
+    binder::Status assertFsverityRootHashMatches(const std::string& filePath,
+            const std::vector<uint8_t>& expectedHash);
     binder::Status reconcileSecondaryDexFile(const std::string& dexPath,
         const std::string& packageName, int32_t uid, const std::vector<std::string>& isa,
         const std::unique_ptr<std::string>& volumeUuid, int32_t storage_flag, bool* _aidl_return);
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index c819e98..3725fc0 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -82,6 +82,7 @@
     void deleteOdex(@utf8InCpp String apkPath, @utf8InCpp String instructionSet,
             @nullable @utf8InCpp String outputPath);
     void installApkVerity(@utf8InCpp String filePath, in FileDescriptor verityInput);
+    void assertFsverityRootHashMatches(@utf8InCpp String filePath, in byte[] expectedHash);
 
     boolean reconcileSecondaryDexFile(@utf8InCpp String dexPath, @utf8InCpp String pkgName,
         int uid, in @utf8InCpp String[] isas, @nullable @utf8InCpp String volume_uuid,
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 80e18d3..0f635e0 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -217,7 +217,7 @@
         const char* input_file_name, const char* output_file_name, int swap_fd,
         const char* instruction_set, const char* compiler_filter,
         bool debuggable, bool post_bootcomplete, bool background_job_compile, int profile_fd,
-        const char* class_loader_context, int target_sdk_version) {
+        const char* class_loader_context, int target_sdk_version, bool disable_hidden_api_checks) {
     static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
 
     if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
@@ -443,7 +443,8 @@
                      + (have_dex2oat_large_app_threshold ? 1 : 0)
                      + (disable_cdex ? 1 : 0)
                      + (generate_minidebug_info ? 1 : 0)
-                     + (target_sdk_version != 0 ? 2 : 0)];
+                     + (target_sdk_version != 0 ? 2 : 0)
+                     + (disable_hidden_api_checks ? 2 : 0)];
     int i = 0;
     argv[i++] = dex2oat_bin;
     argv[i++] = zip_fd_arg;
@@ -517,6 +518,10 @@
         argv[i++] = RUNTIME_ARG;
         argv[i++] = target_sdk_version_arg;
     }
+    if (disable_hidden_api_checks) {
+        argv[i++] = RUNTIME_ARG;
+        argv[i++] = "-Xno-hidden-api-checks";
+    }
 
     // Do not add after dex2oat_flags, they should override others for debugging.
     argv[i] = NULL;
@@ -1801,6 +1806,7 @@
     bool profile_guided = (dexopt_flags & DEXOPT_PROFILE_GUIDED) != 0;
     bool is_secondary_dex = (dexopt_flags & DEXOPT_SECONDARY_DEX) != 0;
     bool background_job_compile = (dexopt_flags & DEXOPT_IDLE_BACKGROUND_JOB) != 0;
+    bool disable_hidden_api_checks = (dexopt_flags & DEXOPT_DISABLE_HIDDEN_API_CHECKS) != 0;
 
     // Check if we're dealing with a secondary dex file and if we need to compile it.
     std::string oat_dir_str;
@@ -1897,7 +1903,8 @@
                     background_job_compile,
                     reference_profile_fd.get(),
                     class_loader_context,
-                    target_sdk_version);
+                    target_sdk_version,
+                    disable_hidden_api_checks);
         _exit(68);   /* only get here on exec failure */
     } else {
         int res = wait_child(pid);
diff --git a/cmds/installd/installd_constants.h b/cmds/installd/installd_constants.h
index b49057d..9b6714d 100644
--- a/cmds/installd/installd_constants.h
+++ b/cmds/installd/installd_constants.h
@@ -52,6 +52,7 @@
 // Tells the compiler that it is invoked from the background service.  This
 // controls whether extra debugging flags can be used (taking more compile time.)
 constexpr int DEXOPT_IDLE_BACKGROUND_JOB = 1 << 9;
+constexpr int DEXOPT_DISABLE_HIDDEN_API_CHECKS = 1 << 10;
 
 /* all known values for dexopt flags */
 constexpr int DEXOPT_MASK =
@@ -62,7 +63,8 @@
     | DEXOPT_SECONDARY_DEX
     | DEXOPT_FORCE
     | DEXOPT_STORAGE_CE
-    | DEXOPT_STORAGE_DE;
+    | DEXOPT_STORAGE_DE
+    | DEXOPT_DISABLE_HIDDEN_API_CHECKS;
 
 // NOTE: keep in sync with StorageManager
 constexpr int FLAG_STORAGE_DE = 1 << 0;
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index a724292..dbd7051 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -78,8 +78,10 @@
 static_assert(DEXOPT_FORCE          == 1 << 6, "DEXOPT_FORCE unexpected.");
 static_assert(DEXOPT_STORAGE_CE     == 1 << 7, "DEXOPT_STORAGE_CE unexpected.");
 static_assert(DEXOPT_STORAGE_DE     == 1 << 8, "DEXOPT_STORAGE_DE unexpected.");
+static_assert(DEXOPT_DISABLE_HIDDEN_API_CHECKS == 1 << 10,
+        "DEXOPT_DISABLE_HIDDEN_API_CHECKS unexpected");
 
-static_assert(DEXOPT_MASK           == 0x1fe, "DEXOPT_MASK unexpected.");
+static_assert(DEXOPT_MASK           == 0x5fe, "DEXOPT_MASK unexpected.");
 
 
 
@@ -621,7 +623,7 @@
             }
         }
 
-        if (param_index != 12) {
+        if (param_index != 13) {
             LOG(ERROR) << "Not enough parameters";
             return false;
         }
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index 2030997..c402c3c 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -59,6 +59,12 @@
 // The file descriptor denoted by status-fd will be closed. The rest of the parameters will
 // be passed on to otapreopt in the chroot.
 static int otapreopt_chroot(const int argc, char **arg) {
+    // Validate arguments
+    // We need the command, status channel and target slot, at a minimum.
+    if(argc < 3) {
+        PLOG(ERROR) << "Not enough arguments.";
+        exit(208);
+    }
     // Close all file descriptors. They are coming from the caller, we do not want to pass them
     // on across our fork/exec into a different domain.
     // 1) Default descriptors.
diff --git a/cmds/lshal/DebugCommand.cpp b/cmds/lshal/DebugCommand.cpp
index f371320..dd8812d 100644
--- a/cmds/lshal/DebugCommand.cpp
+++ b/cmds/lshal/DebugCommand.cpp
@@ -35,6 +35,14 @@
     if (optind >= arg.argc) {
         return USAGE;
     }
+
+    // Optargs cannnot be used because the flag should not be considered set
+    // if it should really be contained in mOptions.
+    if (std::string(arg.argv[optind]) == "-E") {
+        mExcludesParentInstances = true;
+        optind++;
+    }
+
     mInterfaceName = arg.argv[optind];
     ++optind;
     for (; optind < arg.argc; ++optind) {
@@ -59,6 +67,7 @@
 
     return mLshal.emitDebugInfo(
             pair.first, pair.second.empty() ? "default" : pair.second, mOptions,
+            mExcludesParentInstances,
             mLshal.out().buf(),
             mLshal.err());
 }
@@ -67,8 +76,9 @@
 
     static const std::string debug =
             "debug:\n"
-            "    lshal debug <interface> [options [options [...]]] \n"
+            "    lshal debug [-E] <interface> [options [options [...]]] \n"
             "        Print debug information of a specified interface.\n"
+            "        -E: excludes debug output if HAL is actually a subclass.\n"
             "        <inteface>: Format is `android.hardware.foo@1.0::IFoo/default`.\n"
             "            If instance name is missing `default` is used.\n"
             "        options: space separated options to IBase::debug.\n";
diff --git a/cmds/lshal/DebugCommand.h b/cmds/lshal/DebugCommand.h
index 9b91084..6e12008 100644
--- a/cmds/lshal/DebugCommand.h
+++ b/cmds/lshal/DebugCommand.h
@@ -43,6 +43,10 @@
     std::string mInterfaceName;
     std::vector<std::string> mOptions;
 
+    // Outputs the actual descriptor of a hal instead of the debug output
+    // if the arguments provided are a superclass of the actual hal impl.
+    bool mExcludesParentInstances;
+
     DISALLOW_COPY_AND_ASSIGN(DebugCommand);
 };
 
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index 7399692..e4b3c90 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -397,7 +397,8 @@
             emitDebugInfo = [this](const auto& iName) {
                 std::stringstream ss;
                 auto pair = splitFirst(iName, '/');
-                mLshal.emitDebugInfo(pair.first, pair.second, {}, ss,
+                mLshal.emitDebugInfo(pair.first, pair.second, {},
+                                     false /* excludesParentInstances */, ss,
                                      NullableOStream<std::ostream>(nullptr));
                 return ss.str();
             };
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index c6f28ac..8c83457 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -23,6 +23,7 @@
 #include <string>
 
 #include <hidl/ServiceManagement.h>
+#include <hidl/HidlTransportUtils.h>
 
 #include "DebugCommand.h"
 #include "ListCommand.h"
@@ -97,9 +98,11 @@
         const std::string &interfaceName,
         const std::string &instanceName,
         const std::vector<std::string> &options,
+        bool excludesParentInstances,
         std::ostream &out,
         NullableOStream<std::ostream> err) const {
     using android::hidl::base::V1_0::IBase;
+    using android::hardware::details::getDescriptor;
 
     hardware::Return<sp<IBase>> retBase = serviceManager()->get(interfaceName, instanceName);
 
@@ -120,6 +123,18 @@
         return NO_INTERFACE;
     }
 
+    if (excludesParentInstances) {
+        const std::string descriptor = getDescriptor(base.get());
+        if (descriptor.empty()) {
+            std::string msg = interfaceName + "/" + instanceName + " getDescriptor failed";
+            err << msg << std::endl;
+            LOG(ERROR) << msg;
+        }
+        if (descriptor != interfaceName) {
+            return OK;
+        }
+    }
+
     PipeRelay relay(out);
 
     if (relay.initCheck() != OK) {
diff --git a/cmds/lshal/Lshal.h b/cmds/lshal/Lshal.h
index 690f30e..9457f1e 100644
--- a/cmds/lshal/Lshal.h
+++ b/cmds/lshal/Lshal.h
@@ -51,6 +51,7 @@
             const std::string &interfaceName,
             const std::string &instanceName,
             const std::vector<std::string> &options,
+            bool excludesParentInstances,
             std::ostream &out,
             NullableOStream<std::ostream> err) const;
 
diff --git a/headers/media_plugin/media/arcvideobridge/IArcVideoBridge.h b/headers/media_plugin/media/arcvideobridge/IArcVideoBridge.h
new file mode 100644
index 0000000..b32c92e
--- /dev/null
+++ b/headers/media_plugin/media/arcvideobridge/IArcVideoBridge.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_IARC_VIDEO_BRIDGE_H
+#define ANDROID_IARC_VIDEO_BRIDGE_H
+
+#include <arc/IArcBridgeService.h>
+#include <binder/IInterface.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+class IArcVideoBridge : public IInterface {
+public:
+    DECLARE_META_INTERFACE(ArcVideoBridge);
+
+    // Returns MojoBootstrapResult for creating mojo ipc channel of
+    // VideoAcceleratorFactory.
+    virtual ::arc::MojoBootstrapResult bootstrapVideoAcceleratorFactory() = 0;
+
+    // Get the version of the remote VideoHost on Chromium side.
+    virtual int32_t hostVersion() = 0;
+};
+
+class BnArcVideoBridge : public BnInterface<IArcVideoBridge> {
+public:
+    virtual status_t onTransact(
+            uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
+};
+
+};  // namespace android
+
+#endif // ANDROID_IARC_VIDEO_BRIDGE_H
diff --git a/include/audiomanager/IAudioManager.h b/include/audiomanager/IAudioManager.h
index ce7804b..067dc5c 100644
--- a/include/audiomanager/IAudioManager.h
+++ b/include/audiomanager/IAudioManager.h
@@ -110,6 +110,11 @@
 
         /*
         DISABLE_RINGTONE_SYNC                 = IBinder::FIRST_CALL_TRANSACTION + 71,
+        GET_FOCUS_RAMP_TIME_MS                = IBinder::FIRST_CALL_TRANSACTION + 72,
+        DISPATCH_FOCUS_CHANGE                 = IBinder::FIRST_CALL_TRANSACTION + 73,
+        PLAYER_HAS_OP_PLAY_AUDIO              = IBinder::FIRST_CALL_TRANSACTION + 74,
+        SET_BLUETOOTH_A2DP_DEVICE_CONNECTION_STATE_SUPPRESS_NOISY_INTENT
+                                              = IBinder::FIRST_CALL_TRANSACTION + 75,
         */
     };
 
diff --git a/libs/binder/ActivityManager.cpp b/libs/binder/ActivityManager.cpp
index 2904718..7724bf1 100644
--- a/libs/binder/ActivityManager.cpp
+++ b/libs/binder/ActivityManager.cpp
@@ -39,7 +39,7 @@
             if (startTime == 0) {
                 startTime = uptimeMillis();
                 ALOGI("Waiting for activity service");
-            } else if ((uptimeMillis() - startTime) > 10000) {
+            } else if ((uptimeMillis() - startTime) > 1000000) {
                 ALOGW("Waiting too long for activity service, giving up");
                 service = NULL;
                 break;
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 2a07cd1..6103188 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -63,6 +63,7 @@
         "MemoryHeapBase.cpp",
         "Parcel.cpp",
         "PermissionCache.cpp",
+        "PermissionController.cpp",
         "PersistableBundle.cpp",
         "ProcessInfoService.cpp",
         "ProcessState.cpp",
@@ -94,6 +95,7 @@
         "liblog",
         "libcutils",
         "libutils",
+        "libutilscallstack",
     ],
 
     header_libs: [
diff --git a/libs/binder/IPermissionController.cpp b/libs/binder/IPermissionController.cpp
index 674bddf..ef67ab8 100644
--- a/libs/binder/IPermissionController.cpp
+++ b/libs/binder/IPermissionController.cpp
@@ -78,6 +78,18 @@
         if (reply.readExceptionCode() != 0) return false;
         return reply.readInt32() != 0;
     }
+
+    virtual int getPackageUid(const String16& package, int flags)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IPermissionController::getInterfaceDescriptor());
+        data.writeString16(package);
+        data.writeInt32(flags);
+        remote()->transact(GET_PACKAGE_UID_TRANSACTION, data, &reply);
+        // fail on exception
+        if (reply.readExceptionCode() != 0) return false;
+        return reply.readInt32();
+    }
 };
 
 IMPLEMENT_META_INTERFACE(PermissionController, "android.os.IPermissionController");
@@ -122,6 +134,16 @@
             return NO_ERROR;
         } break;
 
+        case GET_PACKAGE_UID_TRANSACTION: {
+            CHECK_INTERFACE(IPermissionController, data, reply);
+            String16 package = data.readString16();
+            int flags = data.readInt32();
+            const int uid = getPackageUid(package, flags);
+            reply->writeNoException();
+            reply->writeInt32(uid);
+            return NO_ERROR;
+        } break;
+
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/libs/binder/PermissionController.cpp b/libs/binder/PermissionController.cpp
new file mode 100644
index 0000000..25748ca
--- /dev/null
+++ b/libs/binder/PermissionController.cpp
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+#include <mutex>
+#include <binder/PermissionController.h>
+#include <binder/Binder.h>
+#include <binder/IServiceManager.h>
+
+#include <utils/SystemClock.h>
+
+namespace android {
+
+PermissionController::PermissionController()
+{
+}
+
+sp<IPermissionController> PermissionController::getService()
+{
+    std::lock_guard<Mutex> scoped_lock(mLock);
+    int64_t startTime = 0;
+    sp<IPermissionController> service = mService;
+    while (service == nullptr || !IInterface::asBinder(service)->isBinderAlive()) {
+        sp<IBinder> binder = defaultServiceManager()->checkService(String16("permission"));
+        if (binder == nullptr) {
+            // Wait for the activity service to come back...
+            if (startTime == 0) {
+                startTime = uptimeMillis();
+                ALOGI("Waiting for permission service");
+            } else if ((uptimeMillis() - startTime) > 10000) {
+                ALOGW("Waiting too long for permission service, giving up");
+                service = NULL;
+                break;
+            }
+            sleep(1);
+        } else {
+            service = interface_cast<IPermissionController>(binder);
+            mService = service;
+        }
+    }
+    return service;
+}
+
+bool PermissionController::checkPermission(const String16& permission, int32_t pid, int32_t uid)
+{
+    sp<IPermissionController> service = getService();
+    return service != NULL ? service->checkPermission(permission, pid, uid) : false;
+}
+
+void PermissionController::getPackagesForUid(const uid_t uid, Vector<String16> &packages)
+{
+    sp<IPermissionController> service = getService();
+    if (service != nullptr) {
+        service->getPackagesForUid(uid, packages);
+    }
+}
+
+bool PermissionController::isRuntimePermission(const String16& permission)
+{
+    sp<IPermissionController> service = getService();
+    return service != nullptr ? service->isRuntimePermission(permission) : false;
+}
+
+int PermissionController::getPackageUid(const String16& package, int flags)
+{
+    sp<IPermissionController> service = getService();
+    return service != nullptr ? service->getPackageUid(package, flags) : -1;
+}
+
+}; // namespace android
diff --git a/libs/binder/include/binder/IPermissionController.h b/libs/binder/include/binder/IPermissionController.h
index 25f3431..2f63677 100644
--- a/libs/binder/include/binder/IPermissionController.h
+++ b/libs/binder/include/binder/IPermissionController.h
@@ -36,10 +36,13 @@
 
     virtual bool isRuntimePermission(const String16& permission) = 0;
 
+    virtual int getPackageUid(const String16& package, int flags) = 0;
+
     enum {
         CHECK_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
         GET_PACKAGES_FOR_UID_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 1,
-        IS_RUNTIME_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 2
+        IS_RUNTIME_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 2,
+        GET_PACKAGE_UID_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 3
     };
 };
 
diff --git a/libs/binder/include/binder/PermissionController.h b/libs/binder/include/binder/PermissionController.h
new file mode 100644
index 0000000..c4c98d0
--- /dev/null
+++ b/libs/binder/include/binder/PermissionController.h
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_PERMISSION_CONTROLLER_H
+#define ANDROID_PERMISSION_CONTROLLER_H
+
+#include <binder/IPermissionController.h>
+
+#include <utils/threads.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+class PermissionController
+{
+public:
+
+    enum {
+        MATCH_SYSTEM_ONLY = 1<<16,
+        MATCH_UNINSTALLED_PACKAGES = 1<<13,
+        MATCH_FACTORY_ONLY = 1<<21,
+        MATCH_INSTANT = 1<<23
+    };
+
+    PermissionController();
+
+    bool checkPermission(const String16& permission, int32_t pid, int32_t uid);
+    void getPackagesForUid(const uid_t uid, Vector<String16>& packages);
+    bool isRuntimePermission(const String16& permission);
+    int getPackageUid(const String16& package, int flags);
+
+private:
+    Mutex mLock;
+    sp<IPermissionController> mService;
+
+    sp<IPermissionController> getService();
+};
+
+
+}; // namespace android
+// ---------------------------------------------------------------------------
+#endif // ANDROID_PERMISSION_CONTROLLER_H
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 7ee4d49..ad04d03 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -62,6 +62,9 @@
         // Allow documentation warnings
         "-Wno-documentation",
 
+        // Allow implicit instantiation for templated class function
+        "-Wno-undefined-func-template",
+
         "-DDEBUG_ONLY_CODE=0",
     ],
 
@@ -79,6 +82,7 @@
 
     srcs: [
         "BitTube.cpp",
+        "BufferHubProducer.cpp",
         "BufferItem.cpp",
         "BufferItemConsumer.cpp",
         "BufferQueue.cpp",
@@ -131,7 +135,15 @@
         "android.hardware.configstore-utils",
     ],
 
+    // TODO(b/70046255): Remove these once BufferHub is integrated into libgui.
+    static_libs: [
+        "libbufferhub",
+        "libbufferhubqueue",
+        "libpdx_default_transport",
+    ],
+
     header_libs: [
+        "libdvr_headers",
         "libnativebase_headers",
         "libgui_headers",
     ],
diff --git a/libs/gui/BufferHubProducer.cpp b/libs/gui/BufferHubProducer.cpp
new file mode 100644
index 0000000..af1f833
--- /dev/null
+++ b/libs/gui/BufferHubProducer.cpp
@@ -0,0 +1,710 @@
+/*
+ * Copyright 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.
+ */
+
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Weverything"
+#endif
+
+// The following headers are included without checking every warning.
+// TODO(b/72172820): Remove the workaround once we have enforced -Weverything
+// in these headers and their dependencies.
+#include <dvr/dvr_api.h>
+#include <gui/BufferHubProducer.h>
+
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
+#include <inttypes.h>
+#include <log/log.h>
+#include <system/window.h>
+
+namespace android {
+
+/* static */
+sp<BufferHubProducer> BufferHubProducer::Create(const std::shared_ptr<dvr::ProducerQueue>& queue) {
+    if (queue->metadata_size() != sizeof(DvrNativeBufferMetadata)) {
+        ALOGE("BufferHubProducer::Create producer's metadata size is different "
+              "than the size of DvrNativeBufferMetadata");
+        return nullptr;
+    }
+
+    sp<BufferHubProducer> producer = new BufferHubProducer;
+    producer->queue_ = queue;
+    return producer;
+}
+
+/* static */
+sp<BufferHubProducer> BufferHubProducer::Create(dvr::ProducerQueueParcelable parcelable) {
+    if (!parcelable.IsValid()) {
+        ALOGE("BufferHubProducer::Create: Invalid producer parcelable.");
+        return nullptr;
+    }
+
+    sp<BufferHubProducer> producer = new BufferHubProducer;
+    producer->queue_ = dvr::ProducerQueue::Import(parcelable.TakeChannelHandle());
+    return producer;
+}
+
+status_t BufferHubProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
+    ALOGV("requestBuffer: slot=%d", slot);
+
+    std::unique_lock<std::mutex> lock(mutex_);
+
+    if (connected_api_ == kNoConnectedApi) {
+        ALOGE("requestBuffer: BufferHubProducer has no connected producer");
+        return NO_INIT;
+    }
+
+    if (slot < 0 || slot >= max_buffer_count_) {
+        ALOGE("requestBuffer: slot index %d out of range [0, %d)", slot, max_buffer_count_);
+        return BAD_VALUE;
+    } else if (!buffers_[slot].mBufferState.isDequeued()) {
+        ALOGE("requestBuffer: slot %d is not owned by the producer (state = %s)", slot,
+              buffers_[slot].mBufferState.string());
+        return BAD_VALUE;
+    } else if (buffers_[slot].mGraphicBuffer != nullptr) {
+        ALOGE("requestBuffer: slot %d is not empty.", slot);
+        return BAD_VALUE;
+    } else if (buffers_[slot].mBufferProducer == nullptr) {
+        ALOGE("requestBuffer: slot %d is not dequeued.", slot);
+        return BAD_VALUE;
+    }
+
+    const auto& buffer_producer = buffers_[slot].mBufferProducer;
+    sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
+
+    buffers_[slot].mGraphicBuffer = graphic_buffer;
+    buffers_[slot].mRequestBufferCalled = true;
+
+    *buf = graphic_buffer;
+    return NO_ERROR;
+}
+
+status_t BufferHubProducer::setMaxDequeuedBufferCount(int max_dequeued_buffers) {
+    ALOGV("setMaxDequeuedBufferCount: max_dequeued_buffers=%d", max_dequeued_buffers);
+
+    std::unique_lock<std::mutex> lock(mutex_);
+
+    if (max_dequeued_buffers <= 0 ||
+        max_dequeued_buffers >
+                int(dvr::BufferHubQueue::kMaxQueueCapacity - kDefaultUndequeuedBuffers)) {
+        ALOGE("setMaxDequeuedBufferCount: %d out of range (0, %zu]", max_dequeued_buffers,
+              dvr::BufferHubQueue::kMaxQueueCapacity);
+        return BAD_VALUE;
+    }
+
+    // The new dequeued_buffers count should not be violated by the number
+    // of currently dequeued buffers.
+    int dequeued_count = 0;
+    for (const auto& buf : buffers_) {
+        if (buf.mBufferState.isDequeued()) {
+            dequeued_count++;
+        }
+    }
+    if (dequeued_count > max_dequeued_buffers) {
+        ALOGE("setMaxDequeuedBufferCount: the requested dequeued_buffers"
+              "count (%d) exceeds the current dequeued buffer count (%d)",
+              max_dequeued_buffers, dequeued_count);
+        return BAD_VALUE;
+    }
+
+    max_dequeued_buffer_count_ = max_dequeued_buffers;
+    return NO_ERROR;
+}
+
+status_t BufferHubProducer::setAsyncMode(bool async) {
+    if (async) {
+        // TODO(b/36724099) BufferHubQueue's consumer end always acquires the buffer
+        // automatically and behaves differently from IGraphicBufferConsumer. Thus,
+        // android::BufferQueue's async mode (a.k.a. allocating an additional buffer
+        // to prevent dequeueBuffer from being blocking) technically does not apply
+        // here.
+        //
+        // In Daydream, non-blocking producer side dequeue is guaranteed by careful
+        // buffer consumer implementations. In another word, BufferHubQueue based
+        // dequeueBuffer should never block whether setAsyncMode(true) is set or
+        // not.
+        //
+        // See: IGraphicBufferProducer::setAsyncMode and
+        // BufferQueueProducer::setAsyncMode for more about original implementation.
+        ALOGW("BufferHubProducer::setAsyncMode: BufferHubQueue should always be "
+              "asynchronous. This call makes no effact.");
+        return NO_ERROR;
+    }
+    return NO_ERROR;
+}
+
+status_t BufferHubProducer::dequeueBuffer(int* out_slot, sp<Fence>* out_fence, uint32_t width,
+                                          uint32_t height, PixelFormat format, uint64_t usage,
+                                          uint64_t* /*outBufferAge*/,
+                                          FrameEventHistoryDelta* /* out_timestamps */) {
+    ALOGV("dequeueBuffer: w=%u, h=%u, format=%d, usage=%" PRIu64, width, height, format, usage);
+
+    status_t ret;
+    std::unique_lock<std::mutex> lock(mutex_);
+
+    if (connected_api_ == kNoConnectedApi) {
+        ALOGE("dequeueBuffer: BufferQueue has no connected producer");
+        return NO_INIT;
+    }
+
+    const uint32_t kLayerCount = 1;
+    if (int32_t(queue_->capacity()) < max_dequeued_buffer_count_ + kDefaultUndequeuedBuffers) {
+        // Lazy allocation. When the capacity of |queue_| has not reached
+        // |max_dequeued_buffer_count_|, allocate new buffer.
+        // TODO(jwcai) To save memory, the really reasonable thing to do is to go
+        // over existing slots and find first existing one to dequeue.
+        ret = AllocateBuffer(width, height, kLayerCount, format, usage);
+        if (ret < 0) return ret;
+    }
+
+    size_t slot = 0;
+    std::shared_ptr<dvr::BufferProducer> buffer_producer;
+
+    for (size_t retry = 0; retry < dvr::BufferHubQueue::kMaxQueueCapacity; retry++) {
+        LocalHandle fence;
+        auto buffer_status = queue_->Dequeue(dequeue_timeout_ms_, &slot, &fence);
+        if (!buffer_status) return NO_MEMORY;
+
+        buffer_producer = buffer_status.take();
+        if (!buffer_producer) return NO_MEMORY;
+
+        if (width == buffer_producer->width() && height == buffer_producer->height() &&
+            uint32_t(format) == buffer_producer->format()) {
+            // The producer queue returns a buffer producer matches the request.
+            break;
+        }
+
+        // Needs reallocation.
+        // TODO(jwcai) Consider use VLOG instead if we find this log is not useful.
+        ALOGI("dequeueBuffer: requested buffer (w=%u, h=%u, format=%u) is different "
+              "from the buffer returned at slot: %zu (w=%u, h=%u, format=%u). Need "
+              "re-allocattion.",
+              width, height, format, slot, buffer_producer->width(), buffer_producer->height(),
+              buffer_producer->format());
+        // Mark the slot as reallocating, so that later we can set
+        // BUFFER_NEEDS_REALLOCATION when the buffer actually get dequeued.
+        buffers_[slot].mIsReallocating = true;
+
+        // Remove the old buffer once the allocation before allocating its
+        // replacement.
+        RemoveBuffer(slot);
+
+        // Allocate a new producer buffer with new buffer configs. Note that if
+        // there are already multiple buffers in the queue, the next one returned
+        // from |queue_->Dequeue| may not be the new buffer we just reallocated.
+        // Retry up to BufferHubQueue::kMaxQueueCapacity times.
+        ret = AllocateBuffer(width, height, kLayerCount, format, usage);
+        if (ret < 0) return ret;
+    }
+
+    // With the BufferHub backed solution. Buffer slot returned from
+    // |queue_->Dequeue| is guaranteed to avaiable for producer's use.
+    // It's either in free state (if the buffer has never been used before) or
+    // in queued state (if the buffer has been dequeued and queued back to
+    // BufferHubQueue).
+    LOG_ALWAYS_FATAL_IF((!buffers_[slot].mBufferState.isFree() &&
+                         !buffers_[slot].mBufferState.isQueued()),
+                        "dequeueBuffer: slot %zu is not free or queued, actual state: %s.", slot,
+                        buffers_[slot].mBufferState.string());
+
+    buffers_[slot].mBufferState.freeQueued();
+    buffers_[slot].mBufferState.dequeue();
+    ALOGV("dequeueBuffer: slot=%zu", slot);
+
+    // TODO(jwcai) Handle fence properly. |BufferHub| has full fence support, we
+    // just need to exopose that through |BufferHubQueue| once we need fence.
+    *out_fence = Fence::NO_FENCE;
+    *out_slot = int(slot);
+    ret = NO_ERROR;
+
+    if (buffers_[slot].mIsReallocating) {
+        ret |= BUFFER_NEEDS_REALLOCATION;
+        buffers_[slot].mIsReallocating = false;
+    }
+
+    return ret;
+}
+
+status_t BufferHubProducer::detachBuffer(int /* slot */) {
+    ALOGE("BufferHubProducer::detachBuffer not implemented.");
+    return INVALID_OPERATION;
+}
+
+status_t BufferHubProducer::detachNextBuffer(sp<GraphicBuffer>* /* out_buffer */,
+                                             sp<Fence>* /* out_fence */) {
+    ALOGE("BufferHubProducer::detachNextBuffer not implemented.");
+    return INVALID_OPERATION;
+}
+
+status_t BufferHubProducer::attachBuffer(int* /* out_slot */,
+                                         const sp<GraphicBuffer>& /* buffer */) {
+    // With this BufferHub backed implementation, we assume (for now) all buffers
+    // are allocated and owned by the BufferHub. Thus the attempt of transfering
+    // ownership of a buffer to the buffer queue is intentionally unsupported.
+    LOG_ALWAYS_FATAL("BufferHubProducer::attachBuffer not supported.");
+    return INVALID_OPERATION;
+}
+
+status_t BufferHubProducer::queueBuffer(int slot, const QueueBufferInput& input,
+                                        QueueBufferOutput* output) {
+    ALOGV("queueBuffer: slot %d", slot);
+
+    if (output == nullptr) {
+        return BAD_VALUE;
+    }
+
+    int64_t timestamp;
+    bool is_auto_timestamp;
+    android_dataspace dataspace;
+    Rect crop(Rect::EMPTY_RECT);
+    int scaling_mode;
+    uint32_t transform;
+    sp<Fence> fence;
+
+    input.deflate(&timestamp, &is_auto_timestamp, &dataspace, &crop, &scaling_mode, &transform,
+                  &fence);
+
+    // Check input scaling mode is valid.
+    switch (scaling_mode) {
+        case NATIVE_WINDOW_SCALING_MODE_FREEZE:
+        case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
+        case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
+        case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
+            break;
+        default:
+            ALOGE("queueBuffer: unknown scaling mode %d", scaling_mode);
+            return BAD_VALUE;
+    }
+
+    // Check input fence is valid.
+    if (fence == nullptr) {
+        ALOGE("queueBuffer: fence is NULL");
+        return BAD_VALUE;
+    }
+
+    std::unique_lock<std::mutex> lock(mutex_);
+
+    if (connected_api_ == kNoConnectedApi) {
+        ALOGE("queueBuffer: BufferQueue has no connected producer");
+        return NO_INIT;
+    }
+
+    if (slot < 0 || slot >= max_buffer_count_) {
+        ALOGE("queueBuffer: slot index %d out of range [0, %d)", slot, max_buffer_count_);
+        return BAD_VALUE;
+    } else if (!buffers_[slot].mBufferState.isDequeued()) {
+        ALOGE("queueBuffer: slot %d is not owned by the producer (state = %s)", slot,
+              buffers_[slot].mBufferState.string());
+        return BAD_VALUE;
+    } else if ((!buffers_[slot].mRequestBufferCalled || buffers_[slot].mGraphicBuffer == nullptr)) {
+        ALOGE("queueBuffer: slot %d is not requested (mRequestBufferCalled=%d, "
+              "mGraphicBuffer=%p)",
+              slot, buffers_[slot].mRequestBufferCalled, buffers_[slot].mGraphicBuffer.get());
+        return BAD_VALUE;
+    }
+
+    // Post the buffer producer with timestamp in the metadata.
+    const auto& buffer_producer = buffers_[slot].mBufferProducer;
+
+    // Check input crop is not out of boundary of current buffer.
+    Rect buffer_rect(buffer_producer->width(), buffer_producer->height());
+    Rect cropped_rect(Rect::EMPTY_RECT);
+    crop.intersect(buffer_rect, &cropped_rect);
+    if (cropped_rect != crop) {
+        ALOGE("queueBuffer: slot %d has out-of-boundary crop.", slot);
+        return BAD_VALUE;
+    }
+
+    LocalHandle fence_fd(fence->isValid() ? fence->dup() : -1);
+
+    DvrNativeBufferMetadata meta_data;
+    meta_data.timestamp = timestamp;
+    meta_data.is_auto_timestamp = int32_t(is_auto_timestamp);
+    meta_data.dataspace = int32_t(dataspace);
+    meta_data.crop_left = crop.left;
+    meta_data.crop_top = crop.top;
+    meta_data.crop_right = crop.right;
+    meta_data.crop_bottom = crop.bottom;
+    meta_data.scaling_mode = int32_t(scaling_mode);
+    meta_data.transform = int32_t(transform);
+
+    buffer_producer->PostAsync(&meta_data, fence_fd);
+    buffers_[slot].mBufferState.queue();
+
+    output->width = buffer_producer->width();
+    output->height = buffer_producer->height();
+    output->transformHint = 0; // default value, we don't use it yet.
+
+    // |numPendingBuffers| counts of the number of buffers that has been enqueued
+    // by the producer but not yet acquired by the consumer. Due to the nature
+    // of BufferHubQueue design, this is hard to trace from the producer's client
+    // side, but it's safe to assume it's zero.
+    output->numPendingBuffers = 0;
+
+    // Note that we are not setting nextFrameNumber here as it seems to be only
+    // used by surface flinger. See more at b/22802885, ag/791760.
+    output->nextFrameNumber = 0;
+
+    return NO_ERROR;
+}
+
+status_t BufferHubProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
+    ALOGV(__FUNCTION__);
+
+    std::unique_lock<std::mutex> lock(mutex_);
+
+    if (connected_api_ == kNoConnectedApi) {
+        ALOGE("cancelBuffer: BufferQueue has no connected producer");
+        return NO_INIT;
+    }
+
+    if (slot < 0 || slot >= max_buffer_count_) {
+        ALOGE("cancelBuffer: slot index %d out of range [0, %d)", slot, max_buffer_count_);
+        return BAD_VALUE;
+    } else if (!buffers_[slot].mBufferState.isDequeued()) {
+        ALOGE("cancelBuffer: slot %d is not owned by the producer (state = %s)", slot,
+              buffers_[slot].mBufferState.string());
+        return BAD_VALUE;
+    } else if (fence == nullptr) {
+        ALOGE("cancelBuffer: fence is NULL");
+        return BAD_VALUE;
+    }
+
+    auto buffer_producer = buffers_[slot].mBufferProducer;
+    queue_->Enqueue(buffer_producer, size_t(slot), 0ULL);
+    buffers_[slot].mBufferState.cancel();
+    buffers_[slot].mFence = fence;
+    ALOGV("cancelBuffer: slot %d", slot);
+
+    return NO_ERROR;
+}
+
+status_t BufferHubProducer::query(int what, int* out_value) {
+    ALOGV(__FUNCTION__);
+
+    std::unique_lock<std::mutex> lock(mutex_);
+
+    if (out_value == nullptr) {
+        ALOGE("query: out_value was NULL");
+        return BAD_VALUE;
+    }
+
+    int value = 0;
+    switch (what) {
+        case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
+            // TODO(b/36187402) This should be the maximum number of buffers that this
+            // producer queue's consumer can acquire. Set to be at least one. Need to
+            // find a way to set from the consumer side.
+            value = kDefaultUndequeuedBuffers;
+            break;
+        case NATIVE_WINDOW_BUFFER_AGE:
+            value = 0;
+            break;
+        case NATIVE_WINDOW_WIDTH:
+            value = int32_t(queue_->default_width());
+            break;
+        case NATIVE_WINDOW_HEIGHT:
+            value = int32_t(queue_->default_height());
+            break;
+        case NATIVE_WINDOW_FORMAT:
+            value = int32_t(queue_->default_format());
+            break;
+        case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
+            // BufferHubQueue is always operating in async mode, thus semantically
+            // consumer can never be running behind. See BufferQueueCore.cpp core
+            // for more information about the original meaning of this flag.
+            value = 0;
+            break;
+        case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
+            // TODO(jwcai) This is currently not implement as we don't need
+            // IGraphicBufferConsumer parity.
+            value = 0;
+            break;
+        case NATIVE_WINDOW_DEFAULT_DATASPACE:
+            // TODO(jwcai) Return the default value android::BufferQueue is using as
+            // there is no way dvr::ConsumerQueue can set it.
+            value = 0; // HAL_DATASPACE_UNKNOWN
+            break;
+        case NATIVE_WINDOW_STICKY_TRANSFORM:
+            // TODO(jwcai) Return the default value android::BufferQueue is using as
+            // there is no way dvr::ConsumerQueue can set it.
+            value = 0;
+            break;
+        case NATIVE_WINDOW_CONSUMER_IS_PROTECTED:
+            // In Daydream's implementation, the consumer end (i.e. VR Compostior)
+            // knows how to handle protected buffers.
+            value = 1;
+            break;
+        default:
+            return BAD_VALUE;
+    }
+
+    ALOGV("query: key=%d, v=%d", what, value);
+    *out_value = value;
+    return NO_ERROR;
+}
+
+status_t BufferHubProducer::connect(const sp<IProducerListener>& /* listener */, int api,
+                                    bool /* producer_controlled_by_app */,
+                                    QueueBufferOutput* output) {
+    // Consumer interaction are actually handled by buffer hub, and we need
+    // to maintain consumer operations here. We only need to perform basic input
+    // parameter checks here.
+    ALOGV(__FUNCTION__);
+
+    if (output == nullptr) {
+        return BAD_VALUE;
+    }
+
+    std::unique_lock<std::mutex> lock(mutex_);
+
+    if (connected_api_ != kNoConnectedApi) {
+        return BAD_VALUE;
+    }
+
+    if (!queue_->is_connected()) {
+        ALOGE("BufferHubProducer::connect: This BufferHubProducer is not "
+              "connected to bufferhud. Has it been taken out as a parcelable?");
+        return BAD_VALUE;
+    }
+
+    switch (api) {
+        case NATIVE_WINDOW_API_EGL:
+        case NATIVE_WINDOW_API_CPU:
+        case NATIVE_WINDOW_API_MEDIA:
+        case NATIVE_WINDOW_API_CAMERA:
+            connected_api_ = api;
+
+            output->width = queue_->default_width();
+            output->height = queue_->default_height();
+
+            // default values, we don't use them yet.
+            output->transformHint = 0;
+            output->numPendingBuffers = 0;
+            output->nextFrameNumber = 0;
+            output->bufferReplaced = false;
+
+            break;
+        default:
+            ALOGE("BufferHubProducer::connect: unknow API %d", api);
+            return BAD_VALUE;
+    }
+
+    return NO_ERROR;
+}
+
+status_t BufferHubProducer::disconnect(int api, DisconnectMode /*mode*/) {
+    // Consumer interaction are actually handled by buffer hub, and we need
+    // to maintain consumer operations here.  We only need to perform basic input
+    // parameter checks here.
+    ALOGV(__FUNCTION__);
+
+    std::unique_lock<std::mutex> lock(mutex_);
+
+    if (kNoConnectedApi == connected_api_) {
+        return NO_INIT;
+    } else if (api != connected_api_) {
+        return BAD_VALUE;
+    }
+
+    FreeAllBuffers();
+    connected_api_ = kNoConnectedApi;
+    return NO_ERROR;
+}
+
+status_t BufferHubProducer::setSidebandStream(const sp<NativeHandle>& stream) {
+    if (stream != nullptr) {
+        // TODO(jwcai) Investigate how is is used, maybe use BufferHubBuffer's
+        // metadata.
+        ALOGE("SidebandStream is not currently supported.");
+        return INVALID_OPERATION;
+    }
+    return NO_ERROR;
+}
+
+void BufferHubProducer::allocateBuffers(uint32_t /* width */, uint32_t /* height */,
+                                        PixelFormat /* format */, uint64_t /* usage */) {
+    // TODO(jwcai) |allocateBuffers| aims to preallocate up to the maximum number
+    // of buffers permitted by the current BufferQueue configuration (aka
+    // |max_buffer_count_|).
+    ALOGE("BufferHubProducer::allocateBuffers not implemented.");
+}
+
+status_t BufferHubProducer::allowAllocation(bool /* allow */) {
+    ALOGE("BufferHubProducer::allowAllocation not implemented.");
+    return INVALID_OPERATION;
+}
+
+status_t BufferHubProducer::setGenerationNumber(uint32_t generation_number) {
+    ALOGV(__FUNCTION__);
+
+    std::unique_lock<std::mutex> lock(mutex_);
+    generation_number_ = generation_number;
+    return NO_ERROR;
+}
+
+String8 BufferHubProducer::getConsumerName() const {
+    // BufferHub based implementation could have one to many producer/consumer
+    // relationship, thus |getConsumerName| from the producer side does not
+    // make any sense.
+    ALOGE("BufferHubProducer::getConsumerName not supported.");
+    return String8("BufferHubQueue::DummyConsumer");
+}
+
+status_t BufferHubProducer::setSharedBufferMode(bool shared_buffer_mode) {
+    if (shared_buffer_mode) {
+        ALOGE("BufferHubProducer::setSharedBufferMode(true) is not supported.");
+        // TODO(b/36373181) Front buffer mode for buffer hub queue as ANativeWindow.
+        return INVALID_OPERATION;
+    }
+    // Setting to default should just work as a no-op.
+    return NO_ERROR;
+}
+
+status_t BufferHubProducer::setAutoRefresh(bool auto_refresh) {
+    if (auto_refresh) {
+        ALOGE("BufferHubProducer::setAutoRefresh(true) is not supported.");
+        return INVALID_OPERATION;
+    }
+    // Setting to default should just work as a no-op.
+    return NO_ERROR;
+}
+
+status_t BufferHubProducer::setDequeueTimeout(nsecs_t timeout) {
+    ALOGV(__FUNCTION__);
+
+    std::unique_lock<std::mutex> lock(mutex_);
+    dequeue_timeout_ms_ = int(timeout / (1000 * 1000));
+    return NO_ERROR;
+}
+
+status_t BufferHubProducer::getLastQueuedBuffer(sp<GraphicBuffer>* /* out_buffer */,
+                                                sp<Fence>* /* out_fence */,
+                                                float /*out_transform_matrix*/[16]) {
+    ALOGE("BufferHubProducer::getLastQueuedBuffer not implemented.");
+    return INVALID_OPERATION;
+}
+
+void BufferHubProducer::getFrameTimestamps(FrameEventHistoryDelta* /*outDelta*/) {
+    ALOGE("BufferHubProducer::getFrameTimestamps not implemented.");
+}
+
+status_t BufferHubProducer::getUniqueId(uint64_t* out_id) const {
+    ALOGV(__FUNCTION__);
+
+    *out_id = unique_id_;
+    return NO_ERROR;
+}
+
+status_t BufferHubProducer::getConsumerUsage(uint64_t* out_usage) const {
+    ALOGV(__FUNCTION__);
+
+    // same value as returned by querying NATIVE_WINDOW_CONSUMER_USAGE_BITS
+    *out_usage = 0;
+    return NO_ERROR;
+}
+
+status_t BufferHubProducer::TakeAsParcelable(dvr::ProducerQueueParcelable* out_parcelable) {
+    if (!out_parcelable || out_parcelable->IsValid()) return BAD_VALUE;
+
+    if (connected_api_ != kNoConnectedApi) {
+        ALOGE("BufferHubProducer::TakeAsParcelable: BufferHubProducer has "
+              "connected client. Must disconnect first.");
+        return BAD_VALUE;
+    }
+
+    if (!queue_->is_connected()) {
+        ALOGE("BufferHubProducer::TakeAsParcelable: This BufferHubProducer "
+              "is not connected to bufferhud. Has it been taken out as a "
+              "parcelable?");
+        return BAD_VALUE;
+    }
+
+    auto status = queue_->TakeAsParcelable();
+    if (!status) {
+        ALOGE("BufferHubProducer::TakeAsParcelable: Failed to take out "
+              "ProducuerQueueParcelable from the producer queue, error: %s.",
+              status.GetErrorMessage().c_str());
+        return BAD_VALUE;
+    }
+
+    *out_parcelable = status.take();
+    return NO_ERROR;
+}
+
+status_t BufferHubProducer::AllocateBuffer(uint32_t width, uint32_t height, uint32_t layer_count,
+                                           PixelFormat format, uint64_t usage) {
+    auto status = queue_->AllocateBuffer(width, height, layer_count, uint32_t(format), usage);
+    if (!status) {
+        ALOGE("BufferHubProducer::AllocateBuffer: Failed to allocate buffer: %s",
+              status.GetErrorMessage().c_str());
+        return NO_MEMORY;
+    }
+
+    size_t slot = status.get();
+    auto buffer_producer = queue_->GetBuffer(slot);
+
+    LOG_ALWAYS_FATAL_IF(buffer_producer == nullptr, "Failed to get buffer producer at slot: %zu",
+                        slot);
+
+    buffers_[slot].mBufferProducer = buffer_producer;
+
+    return NO_ERROR;
+}
+
+status_t BufferHubProducer::RemoveBuffer(size_t slot) {
+    auto status = queue_->RemoveBuffer(slot);
+    if (!status) {
+        ALOGE("BufferHubProducer::RemoveBuffer: Failed to remove buffer: %s",
+              status.GetErrorMessage().c_str());
+        return INVALID_OPERATION;
+    }
+
+    // Reset in memory objects related the the buffer.
+    buffers_[slot].mBufferProducer = nullptr;
+    buffers_[slot].mGraphicBuffer = nullptr;
+    buffers_[slot].mBufferState.detachProducer();
+    return NO_ERROR;
+}
+
+status_t BufferHubProducer::FreeAllBuffers() {
+    for (size_t slot = 0; slot < dvr::BufferHubQueue::kMaxQueueCapacity; slot++) {
+        // Reset in memory objects related the the buffer.
+        buffers_[slot].mGraphicBuffer = nullptr;
+        buffers_[slot].mBufferState.reset();
+        buffers_[slot].mRequestBufferCalled = false;
+        buffers_[slot].mBufferProducer = nullptr;
+        buffers_[slot].mFence = Fence::NO_FENCE;
+    }
+
+    auto status = queue_->FreeAllBuffers();
+    if (!status) {
+        ALOGE("BufferHubProducer::FreeAllBuffers: Failed to free all buffers on "
+              "the queue: %s",
+              status.GetErrorMessage().c_str());
+    }
+
+    if (queue_->capacity() != 0 || queue_->count() != 0) {
+        LOG_ALWAYS_FATAL("BufferHubProducer::FreeAllBuffers: Not all buffers are freed.");
+    }
+
+    return NO_ERROR;
+}
+
+} // namespace android
diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp
index f7409dc..f50379b 100644
--- a/libs/gui/BufferItem.cpp
+++ b/libs/gui/BufferItem.cpp
@@ -55,7 +55,8 @@
     mSurfaceDamage(),
     mAutoRefresh(false),
     mQueuedBuffer(true),
-    mIsStale(false) {
+    mIsStale(false),
+    mApi(0) {
 }
 
 BufferItem::~BufferItem() {}
@@ -84,6 +85,7 @@
     addAligned(size, mAutoRefresh);
     addAligned(size, mQueuedBuffer);
     addAligned(size, mIsStale);
+    addAligned(size, mApi);
     return size;
 }
 
@@ -177,6 +179,7 @@
     writeAligned(buffer, size, mAutoRefresh);
     writeAligned(buffer, size, mQueuedBuffer);
     writeAligned(buffer, size, mIsStale);
+    writeAligned(buffer, size, mApi);
 
     return NO_ERROR;
 }
@@ -247,6 +250,7 @@
     readAligned(buffer, size, mAutoRefresh);
     readAligned(buffer, size, mQueuedBuffer);
     readAligned(buffer, size, mIsStale);
+    readAligned(buffer, size, mApi);
 
     return NO_ERROR;
 }
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index add857c..e583b40 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -878,6 +878,7 @@
         item.mSurfaceDamage = surfaceDamage;
         item.mQueuedBuffer = true;
         item.mAutoRefresh = mCore->mSharedBufferMode && mCore->mAutoRefresh;
+        item.mApi = mCore->mConnectedApi;
 
         mStickyTransform = stickyTransform;
 
diff --git a/libs/gui/include/gui/BufferHubProducer.h b/libs/gui/include/gui/BufferHubProducer.h
new file mode 100644
index 0000000..2ee011b
--- /dev/null
+++ b/libs/gui/include/gui/BufferHubProducer.h
@@ -0,0 +1,210 @@
+/*
+ * Copyright 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.
+ */
+
+#ifndef ANDROID_GUI_BUFFERHUBPRODUCER_H_
+#define ANDROID_GUI_BUFFERHUBPRODUCER_H_
+
+#include <gui/BufferSlot.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <private/dvr/buffer_hub_queue_client.h>
+#include <private/dvr/buffer_hub_queue_parcelable.h>
+
+namespace android {
+
+class BufferHubProducer : public BnGraphicBufferProducer {
+public:
+    static constexpr int kNoConnectedApi = -1;
+
+    // TODO(b/36187402) The actual implementation of BufferHubQueue's consumer
+    // side logic doesn't limit the number of buffer it can acquire
+    // simultaneously. We need a way for consumer logic to configure and enforce
+    // that.
+    static constexpr int kDefaultUndequeuedBuffers = 1;
+
+    // Creates a BufferHubProducer instance by importing an existing prodcuer
+    // queue.
+    static sp<BufferHubProducer> Create(const std::shared_ptr<dvr::ProducerQueue>& producer);
+
+    // Creates a BufferHubProducer instance by importing an existing prodcuer
+    // parcelable. Note that this call takes the ownership of the parcelable
+    // object and is guaranteed to succeed if parcelable object is valid.
+    static sp<BufferHubProducer> Create(dvr::ProducerQueueParcelable parcelable);
+
+    // See |IGraphicBufferProducer::requestBuffer|
+    status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override;
+
+    // For the BufferHub based implementation. All buffers in the queue are
+    // allowed to be dequeued from the consumer side. It call always returns
+    // 0 for |NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS| query. Thus setting
+    // |max_dequeued_buffers| here can be considered the same as setting queue
+    // capacity.
+    //
+    // See |IGraphicBufferProducer::setMaxDequeuedBufferCount| for more info
+    status_t setMaxDequeuedBufferCount(int max_dequeued_buffers) override;
+
+    // See |IGraphicBufferProducer::setAsyncMode|
+    status_t setAsyncMode(bool async) override;
+
+    // See |IGraphicBufferProducer::dequeueBuffer|
+    status_t dequeueBuffer(int* out_slot, sp<Fence>* out_fence, uint32_t width, uint32_t height,
+                           PixelFormat format, uint64_t usage, uint64_t* outBufferAge,
+                           FrameEventHistoryDelta* outTimestamps) override;
+
+    // See |IGraphicBufferProducer::detachBuffer|
+    status_t detachBuffer(int slot) override;
+
+    // See |IGraphicBufferProducer::detachNextBuffer|
+    status_t detachNextBuffer(sp<GraphicBuffer>* out_buffer, sp<Fence>* out_fence) override;
+
+    // See |IGraphicBufferProducer::attachBuffer|
+    status_t attachBuffer(int* out_slot, const sp<GraphicBuffer>& buffer) override;
+
+    // See |IGraphicBufferProducer::queueBuffer|
+    status_t queueBuffer(int slot, const QueueBufferInput& input,
+                         QueueBufferOutput* output) override;
+
+    // See |IGraphicBufferProducer::cancelBuffer|
+    status_t cancelBuffer(int slot, const sp<Fence>& fence) override;
+
+    // See |IGraphicBufferProducer::query|
+    status_t query(int what, int* out_value) override;
+
+    // See |IGraphicBufferProducer::connect|
+    status_t connect(const sp<IProducerListener>& listener, int api,
+                     bool producer_controlled_by_app, QueueBufferOutput* output) override;
+
+    // See |IGraphicBufferProducer::disconnect|
+    status_t disconnect(int api, DisconnectMode mode = DisconnectMode::Api) override;
+
+    // See |IGraphicBufferProducer::setSidebandStream|
+    status_t setSidebandStream(const sp<NativeHandle>& stream) override;
+
+    // See |IGraphicBufferProducer::allocateBuffers|
+    void allocateBuffers(uint32_t width, uint32_t height, PixelFormat format,
+                         uint64_t usage) override;
+
+    // See |IGraphicBufferProducer::allowAllocation|
+    status_t allowAllocation(bool allow) override;
+
+    // See |IGraphicBufferProducer::setGenerationNumber|
+    status_t setGenerationNumber(uint32_t generation_number) override;
+
+    // See |IGraphicBufferProducer::getConsumerName|
+    String8 getConsumerName() const override;
+
+    // See |IGraphicBufferProducer::setSharedBufferMode|
+    status_t setSharedBufferMode(bool shared_buffer_mode) override;
+
+    // See |IGraphicBufferProducer::setAutoRefresh|
+    status_t setAutoRefresh(bool auto_refresh) override;
+
+    // See |IGraphicBufferProducer::setDequeueTimeout|
+    status_t setDequeueTimeout(nsecs_t timeout) override;
+
+    // See |IGraphicBufferProducer::getLastQueuedBuffer|
+    status_t getLastQueuedBuffer(sp<GraphicBuffer>* out_buffer, sp<Fence>* out_fence,
+                                 float out_transform_matrix[16]) override;
+
+    // See |IGraphicBufferProducer::getFrameTimestamps|
+    void getFrameTimestamps(FrameEventHistoryDelta* /*outDelta*/) override;
+
+    // See |IGraphicBufferProducer::getUniqueId|
+    status_t getUniqueId(uint64_t* out_id) const override;
+
+    // See |IGraphicBufferProducer::getConsumerUsage|
+    status_t getConsumerUsage(uint64_t* out_usage) const override;
+
+    // Takes out the current producer as a binder parcelable object. Note that the
+    // producer must be disconnected to be exportable. After successful export,
+    // the producer queue can no longer be connected again. Returns NO_ERROR when
+    // takeout is successful and out_parcelable will hold the new parcelable
+    // object. Also note that out_parcelable cannot be NULL and must points to an
+    // invalid parcelable.
+    status_t TakeAsParcelable(dvr::ProducerQueueParcelable* out_parcelable);
+
+private:
+    using LocalHandle = pdx::LocalHandle;
+
+    // Private constructor to force use of |Create|.
+    BufferHubProducer() {}
+
+    static uint64_t genUniqueId() {
+        static std::atomic<uint32_t> counter{0};
+        static uint64_t id = static_cast<uint64_t>(getpid()) << 32;
+        return id | counter++;
+    }
+
+    // Allocate new buffer through BufferHub and add it into |queue_| for
+    // bookkeeping.
+    status_t AllocateBuffer(uint32_t width, uint32_t height, uint32_t layer_count,
+                            PixelFormat format, uint64_t usage);
+
+    // Remove a buffer via BufferHubRPC.
+    status_t RemoveBuffer(size_t slot);
+
+    // Free all buffers which are owned by the prodcuer. Note that if graphic
+    // buffers are acquired by the consumer, we can't .
+    status_t FreeAllBuffers();
+
+    // Concreate implementation backed by BufferHubBuffer.
+    std::shared_ptr<dvr::ProducerQueue> queue_;
+
+    // Mutex for thread safety.
+    std::mutex mutex_;
+
+    // Connect client API, should be one of the NATIVE_WINDOW_API_* flags.
+    int connected_api_{kNoConnectedApi};
+
+    // |max_buffer_count_| sets the capacity of the underlying buffer queue.
+    int32_t max_buffer_count_{dvr::BufferHubQueue::kMaxQueueCapacity};
+
+    // |max_dequeued_buffer_count_| set the maximum number of buffers that can
+    // be dequeued at the same momment.
+    int32_t max_dequeued_buffer_count_{1};
+
+    // Sets how long dequeueBuffer or attachBuffer will block if a buffer or
+    // slot is not yet available. The timeout is stored in milliseconds.
+    int dequeue_timeout_ms_{dvr::BufferHubQueue::kNoTimeOut};
+
+    // |generation_number_| stores the current generation number of the attached
+    // producer. Any attempt to attach a buffer with a different generation
+    // number will fail.
+    // TOOD(b/38137191) Currently not used as we don't support
+    // IGraphicBufferProducer::detachBuffer.
+    uint32_t generation_number_{0};
+
+    // |buffers_| stores the buffers that have been dequeued from
+    // |dvr::BufferHubQueue|, It is initialized to invalid buffers, and gets
+    // filled in with the result of |Dequeue|.
+    // TODO(jwcai) The buffer allocated to a slot will also be replaced if the
+    // requested buffer usage or geometry differs from that of the buffer
+    // allocated to a slot.
+    struct BufferHubSlot : public BufferSlot {
+        BufferHubSlot() : mBufferProducer(nullptr), mIsReallocating(false) {}
+        // BufferSlot comes from android framework, using m prefix to comply with
+        // the name convention with the reset of data fields from BufferSlot.
+        std::shared_ptr<dvr::BufferProducer> mBufferProducer;
+        bool mIsReallocating;
+    };
+    BufferHubSlot buffers_[dvr::BufferHubQueue::kMaxQueueCapacity];
+
+    // A uniqueId used by IGraphicBufferProducer interface.
+    const uint64_t unique_id_{genUniqueId()};
+};
+
+} // namespace android
+
+#endif // ANDROID_GUI_BUFFERHUBPRODUCER_H_
diff --git a/libs/gui/include/gui/BufferItem.h b/libs/gui/include/gui/BufferItem.h
index 7740b9f..218bb42 100644
--- a/libs/gui/include/gui/BufferItem.h
+++ b/libs/gui/include/gui/BufferItem.h
@@ -127,6 +127,9 @@
     // Indicates that this BufferItem contains a stale buffer which has already
     // been released by the BufferQueue.
     bool mIsStale;
+
+    // Indicates the API (NATIVE_WINDOW_API_xxx) that queues the buffer.
+    int mApi;
 };
 
 } // namespace android
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index cd29d4a..8060b6e 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -22,6 +22,7 @@
 #include <binder/ProcessState.h>
 #include <configstore/Utils.h>
 #include <cutils/properties.h>
+#include <inttypes.h>
 #include <gui/BufferItemConsumer.h>
 #include <gui/IDisplayEventConnection.h>
 #include <gui/IProducerListener.h>
@@ -869,7 +870,7 @@
                 (iOldFrame == NO_FRAME_INDEX) ? nullptr : &mFrames[iOldFrame];
         FrameEvents* newFrame = &mFrames[iNewFrame];
 
-        uint64_t nOldFrame = iOldFrame + 1;
+        uint64_t nOldFrame = (iOldFrame == NO_FRAME_INDEX) ? 0 : iOldFrame + 1;
         uint64_t nNewFrame = iNewFrame + 1;
 
         // Latch, Composite, and Release the frames in a plausible order.
diff --git a/libs/input/VelocityTracker.cpp b/libs/input/VelocityTracker.cpp
index 57eee12..e54f147 100644
--- a/libs/input/VelocityTracker.cpp
+++ b/libs/input/VelocityTracker.cpp
@@ -107,7 +107,7 @@
 // this is the strategy that applications will actually use.  Be very careful
 // when adjusting the default strategy because it can dramatically affect
 // (often in a bad way) the user experience.
-const char* VelocityTracker::DEFAULT_STRATEGY = "impulse";
+const char* VelocityTracker::DEFAULT_STRATEGY = "lsq2";
 
 VelocityTracker::VelocityTracker(const char* strategy) :
         mLastEventTime(0), mCurrentPointerIdBits(0), mActivePointerId(-1) {
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index ed292e7..a2712b4 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -29,7 +29,7 @@
 #include <system/graphics.h>
 
 #include <private/android/AHardwareBufferHelpers.h>
-#include <android/hardware/graphics/common/1.0/types.h>
+#include <android/hardware/graphics/common/1.1/types.h>
 
 
 static constexpr int kFdBufferSize = 128 * sizeof(int);  // 128 ints
@@ -311,6 +311,18 @@
             "HAL and AHardwareBuffer pixel format don't match");
     static_assert(HAL_PIXEL_FORMAT_BLOB == AHARDWAREBUFFER_FORMAT_BLOB,
             "HAL and AHardwareBuffer pixel format don't match");
+    static_assert(HAL_PIXEL_FORMAT_DEPTH_16 == AHARDWAREBUFFER_FORMAT_D16_UNORM,
+            "HAL and AHardwareBuffer pixel format don't match");
+    static_assert(HAL_PIXEL_FORMAT_DEPTH_24 == AHARDWAREBUFFER_FORMAT_D24_UNORM,
+            "HAL and AHardwareBuffer pixel format don't match");
+    static_assert(HAL_PIXEL_FORMAT_DEPTH_24_STENCIL_8 == AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT,
+            "HAL and AHardwareBuffer pixel format don't match");
+    static_assert(HAL_PIXEL_FORMAT_DEPTH_32F == AHARDWAREBUFFER_FORMAT_D32_FLOAT,
+            "HAL and AHardwareBuffer pixel format don't match");
+    static_assert(HAL_PIXEL_FORMAT_DEPTH_32F_STENCIL_8 == AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT,
+            "HAL and AHardwareBuffer pixel format don't match");
+    static_assert(HAL_PIXEL_FORMAT_STENCIL_8 == AHARDWAREBUFFER_FORMAT_S8_UINT,
+            "HAL and AHardwareBuffer pixel format don't match");
     static_assert(HAL_PIXEL_FORMAT_BGRA_8888 == AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM,
             "HAL and AHardwareBuffer pixel format don't match");
     static_assert(HAL_PIXEL_FORMAT_YV12 == AHARDWAREBUFFER_FORMAT_YV12,
@@ -354,6 +366,12 @@
         case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
         case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
         case AHARDWAREBUFFER_FORMAT_BLOB:
+        case AHARDWAREBUFFER_FORMAT_D16_UNORM:
+        case AHARDWAREBUFFER_FORMAT_D24_UNORM:
+        case AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT:
+        case AHARDWAREBUFFER_FORMAT_D32_FLOAT:
+        case AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT:
+        case AHARDWAREBUFFER_FORMAT_S8_UINT:
             // VNDK formats only -- unfortunately we can't differentiate from where we're called
         case AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM:
         case AHARDWAREBUFFER_FORMAT_YV12:
@@ -388,7 +406,7 @@
 }
 
 uint64_t AHardwareBuffer_convertToGrallocUsageBits(uint64_t usage) {
-    using android::hardware::graphics::common::V1_0::BufferUsage;
+    using android::hardware::graphics::common::V1_1::BufferUsage;
     static_assert(AHARDWAREBUFFER_USAGE_CPU_READ_NEVER == (uint64_t)BufferUsage::CPU_READ_NEVER,
             "gralloc and AHardwareBuffer flags don't match");
     static_assert(AHARDWAREBUFFER_USAGE_CPU_READ_RARELY == (uint64_t)BufferUsage::CPU_READ_RARELY,
@@ -413,6 +431,10 @@
             "gralloc and AHardwareBuffer flags don't match");
     static_assert(AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA == (uint64_t)BufferUsage::SENSOR_DIRECT_DATA,
             "gralloc and AHardwareBuffer flags don't match");
+    static_assert(AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP == (uint64_t)BufferUsage::GPU_CUBE_MAP,
+            "gralloc and AHardwareBuffer flags don't match");
+    static_assert(AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE == (uint64_t)BufferUsage::GPU_MIPMAP_COMPLETE,
+            "gralloc and AHardwareBuffer flags don't match");
     return usage;
 }
 
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index 29555fd..5fbb3b2 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -60,7 +60,7 @@
         "liblog",
         "libutils",
         "libui",
-        "android.hardware.graphics.common@1.0",
+        "android.hardware.graphics.common@1.1",
     ],
 
     static_libs: [
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index 52440a5..a477bf2 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -80,6 +80,48 @@
      * the buffer size in bytes.
      */
     AHARDWAREBUFFER_FORMAT_BLOB                     = 0x21,
+
+    /**
+     * Corresponding formats:
+     *   Vulkan: VK_FORMAT_D16_UNORM
+     *   OpenGL ES: GL_DEPTH_COMPONENT16
+     */
+    AHARDWAREBUFFER_FORMAT_D16_UNORM                = 0x30,
+
+    /**
+     * Corresponding formats:
+     *   Vulkan: VK_FORMAT_X8_D24_UNORM_PACK32
+     *   OpenGL ES: GL_DEPTH_COMPONENT24
+     */
+    AHARDWAREBUFFER_FORMAT_D24_UNORM                = 0x31,
+
+    /**
+     * Corresponding formats:
+     *   Vulkan: VK_FORMAT_D24_UNORM_S8_UINT
+     *   OpenGL ES: GL_DEPTH24_STENCIL8
+     */
+    AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT        = 0x32,
+
+    /**
+     * Corresponding formats:
+     *   Vulkan: VK_FORMAT_D32_SFLOAT
+     *   OpenGL ES: GL_DEPTH_COMPONENT32F
+     */
+    AHARDWAREBUFFER_FORMAT_D32_FLOAT                = 0x33,
+
+    /**
+     * Corresponding formats:
+     *   Vulkan: VK_FORMAT_D32_SFLOAT_S8_UINT
+     *   OpenGL ES: GL_DEPTH32F_STENCIL8
+     */
+    AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT        = 0x34,
+
+    /**
+     * Corresponding formats:
+     *   Vulkan: VK_FORMAT_S8_UINT
+     *   OpenGL ES: GL_STENCIL_INDEX8
+     */
+    AHARDWAREBUFFER_FORMAT_S8_UINT                  = 0x35,
 };
 
 enum {
@@ -109,10 +151,14 @@
     AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT      = 1UL << 14,
     /* The buffer will be read by a hardware video encoder */
     AHARDWAREBUFFER_USAGE_VIDEO_ENCODE           = 1UL << 16,
-    /** The buffer will be used for sensor direct data */
+    /* The buffer will be used for sensor direct data */
     AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA     = 1UL << 23,
-    /* The buffer will be used as a shader storage or uniform buffer object*/
+    /* The buffer will be used as a shader storage or uniform buffer object */
     AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER        = 1UL << 24,
+    /* The buffer will be used as a cube map texture */
+    AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP               = 1UL << 25,
+    /* The buffer contains a complete mipmap hierarchy */
+    AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE        = 1UL << 26,
 
     AHARDWAREBUFFER_USAGE_VENDOR_0  = 1ULL << 28,
     AHARDWAREBUFFER_USAGE_VENDOR_1  = 1ULL << 29,
diff --git a/libs/sensor/ISensorServer.cpp b/libs/sensor/ISensorServer.cpp
index efbbf7d..5200545 100644
--- a/libs/sensor/ISensorServer.cpp
+++ b/libs/sensor/ISensorServer.cpp
@@ -27,6 +27,7 @@
 
 #include <binder/Parcel.h>
 #include <binder/IInterface.h>
+#include <binder/IResultReceiver.h>
 
 #include <sensor/Sensor.h>
 #include <sensor/ISensorEventConnection.h>
@@ -227,6 +228,30 @@
             reply->writeInt32(ret);
             return NO_ERROR;
         }
+        case SHELL_COMMAND_TRANSACTION: {
+            int in = data.readFileDescriptor();
+            int out = data.readFileDescriptor();
+            int err = data.readFileDescriptor();
+            int argc = data.readInt32();
+            Vector<String16> args;
+            for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
+               args.add(data.readString16());
+            }
+            sp<IBinder> unusedCallback;
+            sp<IResultReceiver> resultReceiver;
+            status_t status;
+            if ((status = data.readNullableStrongBinder(&unusedCallback)) != NO_ERROR) {
+                return status;
+            }
+            if ((status = data.readNullableStrongBinder(&resultReceiver)) != NO_ERROR) {
+                return status;
+            }
+            status = shellCommand(in, out, err, args);
+            if (resultReceiver != nullptr) {
+                resultReceiver->send(status);
+            }
+            return NO_ERROR;
+        }
     }
     return BBinder::onTransact(code, data, reply, flags);
 }
diff --git a/libs/sensor/include/sensor/ISensorServer.h b/libs/sensor/include/sensor/ISensorServer.h
index edf3e0f..402678f 100644
--- a/libs/sensor/include/sensor/ISensorServer.h
+++ b/libs/sensor/include/sensor/ISensorServer.h
@@ -60,6 +60,9 @@
 class BnSensorServer : public BnInterface<ISensorServer>
 {
 public:
+    virtual status_t shellCommand(int in, int out, int err,
+                                  Vector<String16>& args) = 0;
+
     virtual status_t    onTransact( uint32_t code,
                                     const Parcel& data,
                                     Parcel* reply,
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index abe856e..f71f814 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -85,6 +85,7 @@
         "libhwbinder",
         "libsync",
         "libutils",
+        "libutilscallstack",
         "liblog",
     ],
 
diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp
index 1f746a2..60ec38c 100644
--- a/libs/ui/Gralloc2.cpp
+++ b/libs/ui/Gralloc2.cpp
@@ -20,6 +20,7 @@
 #include <hwbinder/IPCThreadState.h>
 #include <ui/Gralloc2.h>
 
+#include <inttypes.h>
 #include <log/log.h>
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wzero-length-array"
@@ -30,8 +31,40 @@
 
 namespace Gralloc2 {
 
+namespace {
+
 static constexpr Error kTransactionError = Error::NO_RESOURCES;
 
+uint64_t getValid10UsageBits() {
+    static const uint64_t valid10UsageBits = []() -> uint64_t {
+        using hardware::graphics::common::V1_0::BufferUsage;
+        uint64_t bits = 0;
+        for (const auto bit : hardware::hidl_enum_iterator<BufferUsage>()) {
+            bits = bits | bit;
+        }
+        // TODO(b/72323293): Remove this mask for EXTERNAL_DISP.
+        bits = bits | (1 << 13);
+
+        return bits;
+    }();
+    return valid10UsageBits;
+}
+
+uint64_t getValid11UsageBits() {
+    static const uint64_t valid11UsageBits = []() -> uint64_t {
+        using hardware::graphics::common::V1_1::BufferUsage;
+        uint64_t bits = 0;
+        for (const auto bit : hardware::hidl_enum_iterator<BufferUsage>()) {
+            bits = bits | bit;
+        }
+        // Return only the overlapping bits.
+        return bits & ~getValid10UsageBits();
+    }();
+    return valid11UsageBits;
+}
+
+}  // anonymous namespace
+
 void Mapper::preload() {
     android::hardware::preloadPassthroughService<hardware::graphics::mapper::V2_0::IMapper>();
 }
@@ -50,11 +83,39 @@
     mMapperV2_1 = hardware::graphics::mapper::V2_1::IMapper::castFrom(mMapper);
 }
 
+Gralloc2::Error Mapper::validateBufferDescriptorInfo(
+        const IMapper::BufferDescriptorInfo& descriptorInfo) const {
+    uint64_t validUsageBits = getValid10UsageBits();
+    if (mMapperV2_1 != nullptr) {
+        validUsageBits = validUsageBits | getValid11UsageBits();
+    }
+
+    if (descriptorInfo.usage & ~validUsageBits) {
+        ALOGE("buffer descriptor contains invalid usage bits 0x%" PRIx64,
+              descriptorInfo.usage & ~validUsageBits);
+        return Error::BAD_VALUE;
+    }
+    return Error::NONE;
+}
+
 Error Mapper::createDescriptor(
         const IMapper::BufferDescriptorInfo& descriptorInfo,
         BufferDescriptor* outDescriptor) const
 {
     Error error;
+
+    if (descriptorInfo.usage & getValid11UsageBits()) {
+        // TODO(b/66900669): Use mMapperV2_1->createDescriptorV2_1().
+        ALOGW("full support for new usage bits is unimplemented 0x%" PRIx64,
+              descriptorInfo.usage & getValid11UsageBits());
+        return Error::BAD_VALUE;
+    }
+
+    error = validateBufferDescriptorInfo(descriptorInfo);
+    if (error != Error::NONE) {
+        return error;
+    }
+
     auto ret = mMapper->createDescriptor(descriptorInfo,
             [&](const auto& tmpError, const auto& tmpDescriptor)
             {
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index 2cac287..2d8e582 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -72,6 +72,7 @@
     info.layerCount = layerCount;
     info.format = static_cast<Gralloc2::PixelFormat>(format);
     info.usage = usage;
+
     error = mMapper->validateBufferSize(bufferHandle, info, stride);
     if (error != Gralloc2::Error::NONE) {
         ALOGE("validateBufferSize(%p) failed: %d", rawHandle, error);
diff --git a/libs/ui/include/ui/Gralloc2.h b/libs/ui/include/ui/Gralloc2.h
index 69c35f7..db3f10a 100644
--- a/libs/ui/include/ui/Gralloc2.h
+++ b/libs/ui/include/ui/Gralloc2.h
@@ -20,6 +20,7 @@
 #include <string>
 
 #include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/common/1.1/types.h>
 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
 #include <android/hardware/graphics/mapper/2.1/IMapper.h>
 #include <utils/StrongPointer.h>
@@ -29,8 +30,8 @@
 namespace Gralloc2 {
 
 using hardware::graphics::allocator::V2_0::IAllocator;
-using hardware::graphics::common::V1_0::BufferUsage;
 using hardware::graphics::common::V1_0::PixelFormat;
+using hardware::graphics::common::V1_1::BufferUsage;
 using hardware::graphics::mapper::V2_0::BufferDescriptor;
 using hardware::graphics::mapper::V2_0::Error;
 using hardware::graphics::mapper::V2_0::IMapper;
@@ -80,6 +81,10 @@
     int unlock(buffer_handle_t bufferHandle) const;
 
 private:
+    // Determines whether the passed info is compatible with the mapper.
+    Error validateBufferDescriptorInfo(
+            const IMapper::BufferDescriptorInfo& descriptorInfo) const;
+
     sp<IMapper> mMapper;
     sp<hardware::graphics::mapper::V2_1::IMapper> mMapperV2_1;
 };
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index fa8e565..7ea37a7 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -59,6 +59,10 @@
     export_header_lib_headers: [
         "libnativebase_headers",
     ],
+    vendor_available: false,
+    vndk: {
+        enabled: true,
+    },
 }
 
 cc_test {
diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
index f9fd42d..f105b02 100644
--- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
+++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
@@ -2,8 +2,8 @@
 #define ANDROID_DVR_BUFFERHUB_RPC_H_
 
 #include <cutils/native_handle.h>
-#include <gui/BufferQueueDefs.h>
 #include <sys/types.h>
+#include <ui/BufferQueueDefs.h>
 
 #include <dvr/dvr_api.h>
 #include <pdx/channel_handle.h>
diff --git a/libs/vr/libbufferhubqueue/Android.bp b/libs/vr/libbufferhubqueue/Android.bp
index b9568ee..84e7427 100644
--- a/libs/vr/libbufferhubqueue/Android.bp
+++ b/libs/vr/libbufferhubqueue/Android.bp
@@ -15,7 +15,6 @@
 sourceFiles = [
     "buffer_hub_queue_client.cpp",
     "buffer_hub_queue_parcelable.cpp",
-    "buffer_hub_queue_producer.cpp",
 ]
 
 includeFiles = [
@@ -35,7 +34,6 @@
     "liblog",
     "libui",
     "libutils",
-    "libgui",
 ]
 
 headerLibraries = [
@@ -61,6 +59,10 @@
     static_libs: staticLibraries,
     shared_libs: sharedLibraries,
     header_libs: headerLibraries,
+    vendor_available: false,
+    vndk: {
+        enabled: true,
+    },
 }
 
 subdirs = ["tests"]
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
deleted file mode 100644
index ace01a6..0000000
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ /dev/null
@@ -1,729 +0,0 @@
-#include "include/private/dvr/buffer_hub_queue_producer.h"
-
-#include <dvr/dvr_api.h>
-#include <inttypes.h>
-#include <log/log.h>
-#include <system/window.h>
-
-namespace android {
-namespace dvr {
-
-/* static */
-sp<BufferHubQueueProducer> BufferHubQueueProducer::Create(
-    const std::shared_ptr<ProducerQueue>& queue) {
-  if (queue->metadata_size() != sizeof(DvrNativeBufferMetadata)) {
-    ALOGE(
-        "BufferHubQueueProducer::Create producer's metadata size is different "
-        "than the size of DvrNativeBufferMetadata");
-    return nullptr;
-  }
-
-  sp<BufferHubQueueProducer> producer = new BufferHubQueueProducer;
-  producer->queue_ = queue;
-  return producer;
-}
-
-/* static */
-sp<BufferHubQueueProducer> BufferHubQueueProducer::Create(
-    ProducerQueueParcelable parcelable) {
-  if (!parcelable.IsValid()) {
-    ALOGE("BufferHubQueueProducer::Create: Invalid producer parcelable.");
-    return nullptr;
-  }
-
-  sp<BufferHubQueueProducer> producer = new BufferHubQueueProducer;
-  producer->queue_ = ProducerQueue::Import(parcelable.TakeChannelHandle());
-  return producer;
-}
-
-status_t BufferHubQueueProducer::requestBuffer(int slot,
-                                               sp<GraphicBuffer>* buf) {
-  ALOGD_IF(TRACE, "requestBuffer: slot=%d", slot);
-
-  std::unique_lock<std::mutex> lock(mutex_);
-
-  if (connected_api_ == kNoConnectedApi) {
-    ALOGE("requestBuffer: BufferHubQueueProducer has no connected producer");
-    return NO_INIT;
-  }
-
-  if (slot < 0 || slot >= max_buffer_count_) {
-    ALOGE("requestBuffer: slot index %d out of range [0, %d)", slot,
-          max_buffer_count_);
-    return BAD_VALUE;
-  } else if (!buffers_[slot].mBufferState.isDequeued()) {
-    ALOGE("requestBuffer: slot %d is not owned by the producer (state = %s)",
-          slot, buffers_[slot].mBufferState.string());
-    return BAD_VALUE;
-  } else if (buffers_[slot].mGraphicBuffer != nullptr) {
-    ALOGE("requestBuffer: slot %d is not empty.", slot);
-    return BAD_VALUE;
-  } else if (buffers_[slot].mBufferProducer == nullptr) {
-    ALOGE("requestBuffer: slot %d is not dequeued.", slot);
-    return BAD_VALUE;
-  }
-
-  const auto& buffer_producer = buffers_[slot].mBufferProducer;
-  sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
-
-  buffers_[slot].mGraphicBuffer = graphic_buffer;
-  buffers_[slot].mRequestBufferCalled = true;
-
-  *buf = graphic_buffer;
-  return NO_ERROR;
-}
-
-status_t BufferHubQueueProducer::setMaxDequeuedBufferCount(
-    int max_dequeued_buffers) {
-  ALOGD_IF(TRACE, "setMaxDequeuedBufferCount: max_dequeued_buffers=%d",
-           max_dequeued_buffers);
-
-  std::unique_lock<std::mutex> lock(mutex_);
-
-  if (max_dequeued_buffers <= 0 ||
-      max_dequeued_buffers >
-          static_cast<int>(BufferHubQueue::kMaxQueueCapacity -
-                           kDefaultUndequeuedBuffers)) {
-    ALOGE("setMaxDequeuedBufferCount: %d out of range (0, %zu]",
-          max_dequeued_buffers, BufferHubQueue::kMaxQueueCapacity);
-    return BAD_VALUE;
-  }
-
-  // The new dequeued_buffers count should not be violated by the number
-  // of currently dequeued buffers.
-  int dequeued_count = 0;
-  for (const auto& buf : buffers_) {
-    if (buf.mBufferState.isDequeued()) {
-      dequeued_count++;
-    }
-  }
-  if (dequeued_count > max_dequeued_buffers) {
-    ALOGE(
-        "setMaxDequeuedBufferCount: the requested dequeued_buffers"
-        "count (%d) exceeds the current dequeued buffer count (%d)",
-        max_dequeued_buffers, dequeued_count);
-    return BAD_VALUE;
-  }
-
-  max_dequeued_buffer_count_ = max_dequeued_buffers;
-  return NO_ERROR;
-}
-
-status_t BufferHubQueueProducer::setAsyncMode(bool async) {
-  if (async) {
-    // TODO(b/36724099) BufferHubQueue's consumer end always acquires the buffer
-    // automatically and behaves differently from IGraphicBufferConsumer. Thus,
-    // android::BufferQueue's async mode (a.k.a. allocating an additional buffer
-    // to prevent dequeueBuffer from being blocking) technically does not apply
-    // here.
-    //
-    // In Daydream, non-blocking producer side dequeue is guaranteed by careful
-    // buffer consumer implementations. In another word, BufferHubQueue based
-    // dequeueBuffer should never block whether setAsyncMode(true) is set or
-    // not.
-    //
-    // See: IGraphicBufferProducer::setAsyncMode and
-    // BufferQueueProducer::setAsyncMode for more about original implementation.
-    ALOGW(
-        "BufferHubQueueProducer::setAsyncMode: BufferHubQueue should always be "
-        "asynchronous. This call makes no effact.");
-    return NO_ERROR;
-  }
-  return NO_ERROR;
-}
-
-status_t BufferHubQueueProducer::dequeueBuffer(
-    int* out_slot, sp<Fence>* out_fence, uint32_t width, uint32_t height,
-    PixelFormat format, uint64_t usage, uint64_t* /*outBufferAge*/,
-    FrameEventHistoryDelta* /* out_timestamps */) {
-  ALOGD_IF(TRACE, "dequeueBuffer: w=%u, h=%u, format=%d, usage=%" PRIu64, width,
-           height, format, usage);
-
-  status_t ret;
-  std::unique_lock<std::mutex> lock(mutex_);
-
-  if (connected_api_ == kNoConnectedApi) {
-    ALOGE("dequeueBuffer: BufferQueue has no connected producer");
-    return NO_INIT;
-  }
-
-  const uint32_t kLayerCount = 1;
-  if (static_cast<int32_t>(queue_->capacity()) <
-      max_dequeued_buffer_count_ + kDefaultUndequeuedBuffers) {
-    // Lazy allocation. When the capacity of |queue_| has not reached
-    // |max_dequeued_buffer_count_|, allocate new buffer.
-    // TODO(jwcai) To save memory, the really reasonable thing to do is to go
-    // over existing slots and find first existing one to dequeue.
-    ret = AllocateBuffer(width, height, kLayerCount, format, usage);
-    if (ret < 0)
-      return ret;
-  }
-
-  size_t slot;
-  std::shared_ptr<BufferProducer> buffer_producer;
-
-  for (size_t retry = 0; retry < BufferHubQueue::kMaxQueueCapacity; retry++) {
-    LocalHandle fence;
-    auto buffer_status = queue_->Dequeue(dequeue_timeout_ms_, &slot, &fence);
-    if (!buffer_status)
-      return NO_MEMORY;
-
-    buffer_producer = buffer_status.take();
-    if (!buffer_producer)
-      return NO_MEMORY;
-
-    if (width == buffer_producer->width() &&
-        height == buffer_producer->height() &&
-        static_cast<uint32_t>(format) == buffer_producer->format()) {
-      // The producer queue returns a buffer producer matches the request.
-      break;
-    }
-
-    // Needs reallocation.
-    // TODO(jwcai) Consider use VLOG instead if we find this log is not useful.
-    ALOGI(
-        "dequeueBuffer: requested buffer (w=%u, h=%u, format=%u) is different "
-        "from the buffer returned at slot: %zu (w=%u, h=%u, format=%u). Need "
-        "re-allocattion.",
-        width, height, format, slot, buffer_producer->width(),
-        buffer_producer->height(), buffer_producer->format());
-    // Mark the slot as reallocating, so that later we can set
-    // BUFFER_NEEDS_REALLOCATION when the buffer actually get dequeued.
-    buffers_[slot].mIsReallocating = true;
-
-    // Remove the old buffer once the allocation before allocating its
-    // replacement.
-    RemoveBuffer(slot);
-
-    // Allocate a new producer buffer with new buffer configs. Note that if
-    // there are already multiple buffers in the queue, the next one returned
-    // from |queue_->Dequeue| may not be the new buffer we just reallocated.
-    // Retry up to BufferHubQueue::kMaxQueueCapacity times.
-    ret = AllocateBuffer(width, height, kLayerCount, format, usage);
-    if (ret < 0)
-      return ret;
-  }
-
-  // With the BufferHub backed solution. Buffer slot returned from
-  // |queue_->Dequeue| is guaranteed to avaiable for producer's use.
-  // It's either in free state (if the buffer has never been used before) or
-  // in queued state (if the buffer has been dequeued and queued back to
-  // BufferHubQueue).
-  LOG_ALWAYS_FATAL_IF(
-      (!buffers_[slot].mBufferState.isFree() &&
-       !buffers_[slot].mBufferState.isQueued()),
-      "dequeueBuffer: slot %zu is not free or queued, actual state: %s.", slot,
-      buffers_[slot].mBufferState.string());
-
-  buffers_[slot].mBufferState.freeQueued();
-  buffers_[slot].mBufferState.dequeue();
-  ALOGD_IF(TRACE, "dequeueBuffer: slot=%zu", slot);
-
-  // TODO(jwcai) Handle fence properly. |BufferHub| has full fence support, we
-  // just need to exopose that through |BufferHubQueue| once we need fence.
-  *out_fence = Fence::NO_FENCE;
-  *out_slot = slot;
-  ret = NO_ERROR;
-
-  if (buffers_[slot].mIsReallocating) {
-    ret |= BUFFER_NEEDS_REALLOCATION;
-    buffers_[slot].mIsReallocating = false;
-  }
-
-  return ret;
-}
-
-status_t BufferHubQueueProducer::detachBuffer(int /* slot */) {
-  ALOGE("BufferHubQueueProducer::detachBuffer not implemented.");
-  return INVALID_OPERATION;
-}
-
-status_t BufferHubQueueProducer::detachNextBuffer(
-    sp<GraphicBuffer>* /* out_buffer */, sp<Fence>* /* out_fence */) {
-  ALOGE("BufferHubQueueProducer::detachNextBuffer not implemented.");
-  return INVALID_OPERATION;
-}
-
-status_t BufferHubQueueProducer::attachBuffer(
-    int* /* out_slot */, const sp<GraphicBuffer>& /* buffer */) {
-  // With this BufferHub backed implementation, we assume (for now) all buffers
-  // are allocated and owned by the BufferHub. Thus the attempt of transfering
-  // ownership of a buffer to the buffer queue is intentionally unsupported.
-  LOG_ALWAYS_FATAL("BufferHubQueueProducer::attachBuffer not supported.");
-  return INVALID_OPERATION;
-}
-
-status_t BufferHubQueueProducer::queueBuffer(int slot,
-                                             const QueueBufferInput& input,
-                                             QueueBufferOutput* output) {
-  ALOGD_IF(TRACE, "queueBuffer: slot %d", slot);
-
-  if (output == nullptr) {
-    return BAD_VALUE;
-  }
-
-  int64_t timestamp;
-  bool is_auto_timestamp;
-  android_dataspace dataspace;
-  Rect crop(Rect::EMPTY_RECT);
-  int scaling_mode;
-  uint32_t transform;
-  sp<Fence> fence;
-
-  input.deflate(&timestamp, &is_auto_timestamp, &dataspace, &crop,
-                &scaling_mode, &transform, &fence);
-
-  // Check input scaling mode is valid.
-  switch (scaling_mode) {
-    case NATIVE_WINDOW_SCALING_MODE_FREEZE:
-    case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
-    case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
-    case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
-      break;
-    default:
-      ALOGE("queueBuffer: unknown scaling mode %d", scaling_mode);
-      return BAD_VALUE;
-  }
-
-  // Check input fence is valid.
-  if (fence == nullptr) {
-    ALOGE("queueBuffer: fence is NULL");
-    return BAD_VALUE;
-  }
-
-  status_t ret;
-  std::unique_lock<std::mutex> lock(mutex_);
-
-  if (connected_api_ == kNoConnectedApi) {
-    ALOGE("queueBuffer: BufferQueue has no connected producer");
-    return NO_INIT;
-  }
-
-  if (slot < 0 || slot >= max_buffer_count_) {
-    ALOGE("queueBuffer: slot index %d out of range [0, %d)", slot,
-          max_buffer_count_);
-    return BAD_VALUE;
-  } else if (!buffers_[slot].mBufferState.isDequeued()) {
-    ALOGE("queueBuffer: slot %d is not owned by the producer (state = %s)",
-          slot, buffers_[slot].mBufferState.string());
-    return BAD_VALUE;
-  } else if ((!buffers_[slot].mRequestBufferCalled ||
-              buffers_[slot].mGraphicBuffer == nullptr)) {
-    ALOGE(
-        "queueBuffer: slot %d is not requested (mRequestBufferCalled=%d, "
-        "mGraphicBuffer=%p)",
-        slot, buffers_[slot].mRequestBufferCalled,
-        buffers_[slot].mGraphicBuffer.get());
-    return BAD_VALUE;
-  }
-
-  // Post the buffer producer with timestamp in the metadata.
-  const auto& buffer_producer = buffers_[slot].mBufferProducer;
-
-  // Check input crop is not out of boundary of current buffer.
-  Rect buffer_rect(buffer_producer->width(), buffer_producer->height());
-  Rect cropped_rect(Rect::EMPTY_RECT);
-  crop.intersect(buffer_rect, &cropped_rect);
-  if (cropped_rect != crop) {
-    ALOGE("queueBuffer: slot %d has out-of-boundary crop.", slot);
-    return BAD_VALUE;
-  }
-
-  LocalHandle fence_fd(fence->isValid() ? fence->dup() : -1);
-
-  DvrNativeBufferMetadata meta_data;
-  meta_data.timestamp = timestamp;
-  meta_data.is_auto_timestamp = static_cast<int32_t>(is_auto_timestamp);
-  meta_data.dataspace = static_cast<int32_t>(dataspace);
-  meta_data.crop_left = crop.left;
-  meta_data.crop_top = crop.top;
-  meta_data.crop_right = crop.right;
-  meta_data.crop_bottom = crop.bottom;
-  meta_data.scaling_mode = static_cast<int32_t>(scaling_mode);
-  meta_data.transform = static_cast<int32_t>(transform);
-
-  buffer_producer->PostAsync(&meta_data, fence_fd);
-  buffers_[slot].mBufferState.queue();
-
-  output->width = buffer_producer->width();
-  output->height = buffer_producer->height();
-  output->transformHint = 0;  // default value, we don't use it yet.
-
-  // |numPendingBuffers| counts of the number of buffers that has been enqueued
-  // by the producer but not yet acquired by the consumer. Due to the nature
-  // of BufferHubQueue design, this is hard to trace from the producer's client
-  // side, but it's safe to assume it's zero.
-  output->numPendingBuffers = 0;
-
-  // Note that we are not setting nextFrameNumber here as it seems to be only
-  // used by surface flinger. See more at b/22802885, ag/791760.
-  output->nextFrameNumber = 0;
-
-  return NO_ERROR;
-}
-
-status_t BufferHubQueueProducer::cancelBuffer(int slot,
-                                              const sp<Fence>& fence) {
-  ALOGD_IF(TRACE, __FUNCTION__);
-
-  std::unique_lock<std::mutex> lock(mutex_);
-
-  if (connected_api_ == kNoConnectedApi) {
-    ALOGE("cancelBuffer: BufferQueue has no connected producer");
-    return NO_INIT;
-  }
-
-  if (slot < 0 || slot >= max_buffer_count_) {
-    ALOGE("cancelBuffer: slot index %d out of range [0, %d)", slot,
-          max_buffer_count_);
-    return BAD_VALUE;
-  } else if (!buffers_[slot].mBufferState.isDequeued()) {
-    ALOGE("cancelBuffer: slot %d is not owned by the producer (state = %s)",
-          slot, buffers_[slot].mBufferState.string());
-    return BAD_VALUE;
-  } else if (fence == nullptr) {
-    ALOGE("cancelBuffer: fence is NULL");
-    return BAD_VALUE;
-  }
-
-  auto buffer_producer = buffers_[slot].mBufferProducer;
-  queue_->Enqueue(buffer_producer, slot, 0ULL);
-  buffers_[slot].mBufferState.cancel();
-  buffers_[slot].mFence = fence;
-  ALOGD_IF(TRACE, "cancelBuffer: slot %d", slot);
-
-  return NO_ERROR;
-}
-
-status_t BufferHubQueueProducer::query(int what, int* out_value) {
-  ALOGD_IF(TRACE, __FUNCTION__);
-
-  std::unique_lock<std::mutex> lock(mutex_);
-
-  if (out_value == nullptr) {
-    ALOGE("query: out_value was NULL");
-    return BAD_VALUE;
-  }
-
-  int value = 0;
-  switch (what) {
-    case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
-      // TODO(b/36187402) This should be the maximum number of buffers that this
-      // producer queue's consumer can acquire. Set to be at least one. Need to
-      // find a way to set from the consumer side.
-      value = kDefaultUndequeuedBuffers;
-      break;
-    case NATIVE_WINDOW_BUFFER_AGE:
-      value = 0;
-      break;
-    case NATIVE_WINDOW_WIDTH:
-      value = queue_->default_width();
-      break;
-    case NATIVE_WINDOW_HEIGHT:
-      value = queue_->default_height();
-      break;
-    case NATIVE_WINDOW_FORMAT:
-      value = queue_->default_format();
-      break;
-    case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
-      // BufferHubQueue is always operating in async mode, thus semantically
-      // consumer can never be running behind. See BufferQueueCore.cpp core
-      // for more information about the original meaning of this flag.
-      value = 0;
-      break;
-    case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
-      // TODO(jwcai) This is currently not implement as we don't need
-      // IGraphicBufferConsumer parity.
-      value = 0;
-      break;
-    case NATIVE_WINDOW_DEFAULT_DATASPACE:
-      // TODO(jwcai) Return the default value android::BufferQueue is using as
-      // there is no way dvr::ConsumerQueue can set it.
-      value = 0;  // HAL_DATASPACE_UNKNOWN
-      break;
-    case NATIVE_WINDOW_STICKY_TRANSFORM:
-      // TODO(jwcai) Return the default value android::BufferQueue is using as
-      // there is no way dvr::ConsumerQueue can set it.
-      value = 0;
-      break;
-    case NATIVE_WINDOW_CONSUMER_IS_PROTECTED:
-      // In Daydream's implementation, the consumer end (i.e. VR Compostior)
-      // knows how to handle protected buffers.
-      value = 1;
-      break;
-    default:
-      return BAD_VALUE;
-  }
-
-  ALOGD_IF(TRACE, "query: key=%d, v=%d", what, value);
-  *out_value = value;
-  return NO_ERROR;
-}
-
-status_t BufferHubQueueProducer::connect(
-    const sp<IProducerListener>& /* listener */, int api,
-    bool /* producer_controlled_by_app */, QueueBufferOutput* output) {
-  // Consumer interaction are actually handled by buffer hub, and we need
-  // to maintain consumer operations here. We only need to perform basic input
-  // parameter checks here.
-  ALOGD_IF(TRACE, __FUNCTION__);
-
-  if (output == nullptr) {
-    return BAD_VALUE;
-  }
-
-  std::unique_lock<std::mutex> lock(mutex_);
-
-  if (connected_api_ != kNoConnectedApi) {
-    return BAD_VALUE;
-  }
-
-  if (!queue_->is_connected()) {
-    ALOGE(
-        "BufferHubQueueProducer::connect: This BufferHubQueueProducer is not "
-        "connected to bufferhud. Has it been taken out as a parcelable?");
-    return BAD_VALUE;
-  }
-
-  switch (api) {
-    case NATIVE_WINDOW_API_EGL:
-    case NATIVE_WINDOW_API_CPU:
-    case NATIVE_WINDOW_API_MEDIA:
-    case NATIVE_WINDOW_API_CAMERA:
-      connected_api_ = api;
-
-      output->width = queue_->default_width();
-      output->height = queue_->default_height();
-
-      // default values, we don't use them yet.
-      output->transformHint = 0;
-      output->numPendingBuffers = 0;
-      output->nextFrameNumber = 0;
-      output->bufferReplaced = false;
-
-      break;
-    default:
-      ALOGE("BufferHubQueueProducer::connect: unknow API %d", api);
-      return BAD_VALUE;
-  }
-
-  return NO_ERROR;
-}
-
-status_t BufferHubQueueProducer::disconnect(int api, DisconnectMode /*mode*/) {
-  // Consumer interaction are actually handled by buffer hub, and we need
-  // to maintain consumer operations here.  We only need to perform basic input
-  // parameter checks here.
-  ALOGD_IF(TRACE, __FUNCTION__);
-
-  std::unique_lock<std::mutex> lock(mutex_);
-
-  if (kNoConnectedApi == connected_api_) {
-    return NO_INIT;
-  } else if (api != connected_api_) {
-    return BAD_VALUE;
-  }
-
-  FreeAllBuffers();
-  connected_api_ = kNoConnectedApi;
-  return NO_ERROR;
-}
-
-status_t BufferHubQueueProducer::setSidebandStream(
-    const sp<NativeHandle>& stream) {
-  if (stream != nullptr) {
-    // TODO(jwcai) Investigate how is is used, maybe use BufferHubBuffer's
-    // metadata.
-    ALOGE("SidebandStream is not currently supported.");
-    return INVALID_OPERATION;
-  }
-  return NO_ERROR;
-}
-
-void BufferHubQueueProducer::allocateBuffers(uint32_t /* width */,
-                                             uint32_t /* height */,
-                                             PixelFormat /* format */,
-                                             uint64_t /* usage */) {
-  // TODO(jwcai) |allocateBuffers| aims to preallocate up to the maximum number
-  // of buffers permitted by the current BufferQueue configuration (aka
-  // |max_buffer_count_|).
-  ALOGE("BufferHubQueueProducer::allocateBuffers not implemented.");
-}
-
-status_t BufferHubQueueProducer::allowAllocation(bool /* allow */) {
-  ALOGE("BufferHubQueueProducer::allowAllocation not implemented.");
-  return INVALID_OPERATION;
-}
-
-status_t BufferHubQueueProducer::setGenerationNumber(
-    uint32_t generation_number) {
-  ALOGD_IF(TRACE, __FUNCTION__);
-
-  std::unique_lock<std::mutex> lock(mutex_);
-  generation_number_ = generation_number;
-  return NO_ERROR;
-}
-
-String8 BufferHubQueueProducer::getConsumerName() const {
-  // BufferHub based implementation could have one to many producer/consumer
-  // relationship, thus |getConsumerName| from the producer side does not
-  // make any sense.
-  ALOGE("BufferHubQueueProducer::getConsumerName not supported.");
-  return String8("BufferHubQueue::DummyConsumer");
-}
-
-status_t BufferHubQueueProducer::setSharedBufferMode(bool shared_buffer_mode) {
-  if (shared_buffer_mode) {
-    ALOGE(
-        "BufferHubQueueProducer::setSharedBufferMode(true) is not supported.");
-    // TODO(b/36373181) Front buffer mode for buffer hub queue as ANativeWindow.
-    return INVALID_OPERATION;
-  }
-  // Setting to default should just work as a no-op.
-  return NO_ERROR;
-}
-
-status_t BufferHubQueueProducer::setAutoRefresh(bool auto_refresh) {
-  if (auto_refresh) {
-    ALOGE("BufferHubQueueProducer::setAutoRefresh(true) is not supported.");
-    return INVALID_OPERATION;
-  }
-  // Setting to default should just work as a no-op.
-  return NO_ERROR;
-}
-
-status_t BufferHubQueueProducer::setDequeueTimeout(nsecs_t timeout) {
-  ALOGD_IF(TRACE, __FUNCTION__);
-
-  std::unique_lock<std::mutex> lock(mutex_);
-  dequeue_timeout_ms_ = static_cast<int>(timeout / (1000 * 1000));
-  return NO_ERROR;
-}
-
-status_t BufferHubQueueProducer::getLastQueuedBuffer(
-    sp<GraphicBuffer>* /* out_buffer */, sp<Fence>* /* out_fence */,
-    float /*out_transform_matrix*/[16]) {
-  ALOGE("BufferHubQueueProducer::getLastQueuedBuffer not implemented.");
-  return INVALID_OPERATION;
-}
-
-void BufferHubQueueProducer::getFrameTimestamps(
-    FrameEventHistoryDelta* /*outDelta*/) {
-  ALOGE("BufferHubQueueProducer::getFrameTimestamps not implemented.");
-}
-
-status_t BufferHubQueueProducer::getUniqueId(uint64_t* out_id) const {
-  ALOGD_IF(TRACE, __FUNCTION__);
-
-  *out_id = unique_id_;
-  return NO_ERROR;
-}
-
-status_t BufferHubQueueProducer::getConsumerUsage(uint64_t* out_usage) const {
-  ALOGD_IF(TRACE, __FUNCTION__);
-
-  // same value as returned by querying NATIVE_WINDOW_CONSUMER_USAGE_BITS
-  *out_usage = 0;
-  return NO_ERROR;
-}
-
-status_t BufferHubQueueProducer::TakeAsParcelable(
-    ProducerQueueParcelable* out_parcelable) {
-  if (!out_parcelable || out_parcelable->IsValid())
-    return BAD_VALUE;
-
-  if (connected_api_ != kNoConnectedApi) {
-    ALOGE(
-        "BufferHubQueueProducer::TakeAsParcelable: BufferHubQueueProducer has "
-        "connected client. Must disconnect first.");
-    return BAD_VALUE;
-  }
-
-  if (!queue_->is_connected()) {
-    ALOGE(
-        "BufferHubQueueProducer::TakeAsParcelable: This BufferHubQueueProducer "
-        "is not connected to bufferhud. Has it been taken out as a "
-        "parcelable?");
-    return BAD_VALUE;
-  }
-
-  auto status = queue_->TakeAsParcelable();
-  if (!status) {
-    ALOGE(
-        "BufferHubQueueProducer::TakeAsParcelable: Failed to take out "
-        "ProducuerQueueParcelable from the producer queue, error: %s.",
-        status.GetErrorMessage().c_str());
-    return BAD_VALUE;
-  }
-
-  *out_parcelable = status.take();
-  return NO_ERROR;
-}
-
-status_t BufferHubQueueProducer::AllocateBuffer(uint32_t width, uint32_t height,
-                                                uint32_t layer_count,
-                                                PixelFormat format,
-                                                uint64_t usage) {
-  auto status =
-      queue_->AllocateBuffer(width, height, layer_count, format, usage);
-  if (!status) {
-    ALOGE(
-        "BufferHubQueueProducer::AllocateBuffer: Failed to allocate buffer: %s",
-        status.GetErrorMessage().c_str());
-    return NO_MEMORY;
-  }
-
-  size_t slot = status.get();
-  auto buffer_producer = queue_->GetBuffer(slot);
-
-  LOG_ALWAYS_FATAL_IF(buffer_producer == nullptr,
-                      "Failed to get buffer producer at slot: %zu", slot);
-
-  buffers_[slot].mBufferProducer = buffer_producer;
-
-  return NO_ERROR;
-}
-
-status_t BufferHubQueueProducer::RemoveBuffer(size_t slot) {
-  auto status = queue_->RemoveBuffer(slot);
-  if (!status) {
-    ALOGE("BufferHubQueueProducer::RemoveBuffer: Failed to remove buffer: %s",
-          status.GetErrorMessage().c_str());
-    return INVALID_OPERATION;
-  }
-
-  // Reset in memory objects related the the buffer.
-  buffers_[slot].mBufferProducer = nullptr;
-  buffers_[slot].mGraphicBuffer = nullptr;
-  buffers_[slot].mBufferState.detachProducer();
-  return NO_ERROR;
-}
-
-status_t BufferHubQueueProducer::FreeAllBuffers() {
-  for (size_t slot = 0; slot < BufferHubQueue::kMaxQueueCapacity; slot++) {
-    // Reset in memory objects related the the buffer.
-    buffers_[slot].mGraphicBuffer = nullptr;
-    buffers_[slot].mBufferState.reset();
-    buffers_[slot].mRequestBufferCalled = false;
-    buffers_[slot].mBufferProducer = nullptr;
-    buffers_[slot].mFence = Fence::NO_FENCE;
-  }
-
-  auto status = queue_->FreeAllBuffers();
-  if (!status) {
-    ALOGE(
-        "BufferHubQueueProducer::FreeAllBuffers: Failed to free all buffers on "
-        "the queue: %s",
-        status.GetErrorMessage().c_str());
-  }
-
-  if (queue_->capacity() != 0 || queue_->count() != 0) {
-    LOG_ALWAYS_FATAL(
-        "BufferHubQueueProducer::FreeAllBuffers: Not all buffers are freed.");
-  }
-
-  return NO_ERROR;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
index 5bab4a5..8965530 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
@@ -1,7 +1,7 @@
 #ifndef ANDROID_DVR_BUFFER_HUB_QUEUE_CLIENT_H_
 #define ANDROID_DVR_BUFFER_HUB_QUEUE_CLIENT_H_
 
-#include <gui/BufferQueueDefs.h>
+#include <ui/BufferQueueDefs.h>
 
 #include <pdx/client.h>
 #include <pdx/status.h>
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
deleted file mode 100644
index 9c85048..0000000
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
+++ /dev/null
@@ -1,202 +0,0 @@
-#ifndef ANDROID_DVR_BUFFER_HUB_QUEUE_PRODUCER_H_
-#define ANDROID_DVR_BUFFER_HUB_QUEUE_PRODUCER_H_
-
-#include <gui/IGraphicBufferProducer.h>
-#include <private/dvr/buffer_hub_queue_client.h>
-#include <private/dvr/buffer_hub_queue_parcelable.h>
-
-namespace android {
-namespace dvr {
-
-class BufferHubQueueProducer : public BnGraphicBufferProducer {
- public:
-  static constexpr int kNoConnectedApi = -1;
-
-  // TODO(b/36187402) The actual implementation of BufferHubQueue's consumer
-  // side logic doesn't limit the number of buffer it can acquire
-  // simultaneously. We need a way for consumer logic to configure and enforce
-  // that.
-  static constexpr int kDefaultUndequeuedBuffers = 1;
-
-  // Creates a BufferHubQueueProducer instance by importing an existing prodcuer
-  // queue.
-  static sp<BufferHubQueueProducer> Create(
-      const std::shared_ptr<ProducerQueue>& producer);
-
-  // Creates a BufferHubQueueProducer instance by importing an existing prodcuer
-  // parcelable. Note that this call takes the ownership of the parcelable
-  // object and is guaranteed to succeed if parcelable object is valid.
-  static sp<BufferHubQueueProducer> Create(ProducerQueueParcelable parcelable);
-
-  // See |IGraphicBufferProducer::requestBuffer|
-  status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override;
-
-  // For the BufferHub based implementation. All buffers in the queue are
-  // allowed to be dequeued from the consumer side. It call always returns
-  // 0 for |NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS| query. Thus setting
-  // |max_dequeued_buffers| here can be considered the same as setting queue
-  // capacity.
-  //
-  // See |IGraphicBufferProducer::setMaxDequeuedBufferCount| for more info
-  status_t setMaxDequeuedBufferCount(int max_dequeued_buffers) override;
-
-  // See |IGraphicBufferProducer::setAsyncMode|
-  status_t setAsyncMode(bool async) override;
-
-  // See |IGraphicBufferProducer::dequeueBuffer|
-  status_t dequeueBuffer(int* out_slot, sp<Fence>* out_fence, uint32_t width,
-                         uint32_t height, PixelFormat format, uint64_t usage,
-                         uint64_t* outBufferAge,
-                         FrameEventHistoryDelta* outTimestamps) override;
-
-  // See |IGraphicBufferProducer::detachBuffer|
-  status_t detachBuffer(int slot) override;
-
-  // See |IGraphicBufferProducer::detachNextBuffer|
-  status_t detachNextBuffer(sp<GraphicBuffer>* out_buffer,
-                            sp<Fence>* out_fence) override;
-
-  // See |IGraphicBufferProducer::attachBuffer|
-  status_t attachBuffer(int* out_slot,
-                        const sp<GraphicBuffer>& buffer) override;
-
-  // See |IGraphicBufferProducer::queueBuffer|
-  status_t queueBuffer(int slot, const QueueBufferInput& input,
-                       QueueBufferOutput* output) override;
-
-  // See |IGraphicBufferProducer::cancelBuffer|
-  status_t cancelBuffer(int slot, const sp<Fence>& fence) override;
-
-  // See |IGraphicBufferProducer::query|
-  status_t query(int what, int* out_value) override;
-
-  // See |IGraphicBufferProducer::connect|
-  status_t connect(const sp<IProducerListener>& listener, int api,
-                   bool producer_controlled_by_app,
-                   QueueBufferOutput* output) override;
-
-  // See |IGraphicBufferProducer::disconnect|
-  status_t disconnect(int api,
-                      DisconnectMode mode = DisconnectMode::Api) override;
-
-  // See |IGraphicBufferProducer::setSidebandStream|
-  status_t setSidebandStream(const sp<NativeHandle>& stream) override;
-
-  // See |IGraphicBufferProducer::allocateBuffers|
-  void allocateBuffers(uint32_t width, uint32_t height, PixelFormat format,
-                       uint64_t usage) override;
-
-  // See |IGraphicBufferProducer::allowAllocation|
-  status_t allowAllocation(bool allow) override;
-
-  // See |IGraphicBufferProducer::setGenerationNumber|
-  status_t setGenerationNumber(uint32_t generation_number) override;
-
-  // See |IGraphicBufferProducer::getConsumerName|
-  String8 getConsumerName() const override;
-
-  // See |IGraphicBufferProducer::setSharedBufferMode|
-  status_t setSharedBufferMode(bool shared_buffer_mode) override;
-
-  // See |IGraphicBufferProducer::setAutoRefresh|
-  status_t setAutoRefresh(bool auto_refresh) override;
-
-  // See |IGraphicBufferProducer::setDequeueTimeout|
-  status_t setDequeueTimeout(nsecs_t timeout) override;
-
-  // See |IGraphicBufferProducer::getLastQueuedBuffer|
-  status_t getLastQueuedBuffer(sp<GraphicBuffer>* out_buffer,
-                               sp<Fence>* out_fence,
-                               float out_transform_matrix[16]) override;
-
-  // See |IGraphicBufferProducer::getFrameTimestamps|
-  void getFrameTimestamps(FrameEventHistoryDelta* /*outDelta*/) override;
-
-  // See |IGraphicBufferProducer::getUniqueId|
-  status_t getUniqueId(uint64_t* out_id) const override;
-
-  // See |IGraphicBufferProducer::getConsumerUsage|
-  status_t getConsumerUsage(uint64_t* out_usage) const override;
-
-  // Takes out the current producer as a binder parcelable object. Note that the
-  // producer must be disconnected to be exportable. After successful export,
-  // the producer queue can no longer be connected again. Returns NO_ERROR when
-  // takeout is successful and out_parcelable will hold the new parcelable
-  // object. Also note that out_parcelable cannot be NULL and must points to an
-  // invalid parcelable.
-  status_t TakeAsParcelable(ProducerQueueParcelable* out_parcelable);
-
- private:
-  using LocalHandle = pdx::LocalHandle;
-
-  // Private constructor to force use of |Create|.
-  BufferHubQueueProducer() {}
-
-  static uint64_t genUniqueId() {
-    static std::atomic<uint32_t> counter{0};
-    static uint64_t id = static_cast<uint64_t>(getpid()) << 32;
-    return id | counter++;
-  }
-
-  // Allocate new buffer through BufferHub and add it into |queue_| for
-  // bookkeeping.
-  status_t AllocateBuffer(uint32_t width, uint32_t height, uint32_t layer_count,
-                          PixelFormat format, uint64_t usage);
-
-  // Remove a buffer via BufferHubRPC.
-  status_t RemoveBuffer(size_t slot);
-
-  // Free all buffers which are owned by the prodcuer. Note that if graphic
-  // buffers are acquired by the consumer, we can't .
-  status_t FreeAllBuffers();
-
-  // Concreate implementation backed by BufferHubBuffer.
-  std::shared_ptr<ProducerQueue> queue_;
-
-  // Mutex for thread safety.
-  std::mutex mutex_;
-
-  // Connect client API, should be one of the NATIVE_WINDOW_API_* flags.
-  int connected_api_{kNoConnectedApi};
-
-  // |max_buffer_count_| sets the capacity of the underlying buffer queue.
-  int32_t max_buffer_count_{BufferHubQueue::kMaxQueueCapacity};
-
-  // |max_dequeued_buffer_count_| set the maximum number of buffers that can
-  // be dequeued at the same momment.
-  int32_t max_dequeued_buffer_count_{1};
-
-  // Sets how long dequeueBuffer or attachBuffer will block if a buffer or
-  // slot is not yet available. The timeout is stored in milliseconds.
-  int dequeue_timeout_ms_{BufferHubQueue::kNoTimeOut};
-
-  // |generation_number_| stores the current generation number of the attached
-  // producer. Any attempt to attach a buffer with a different generation
-  // number will fail.
-  // TOOD(b/38137191) Currently not used as we don't support
-  // IGraphicBufferProducer::detachBuffer.
-  uint32_t generation_number_{0};
-
-  // |buffers_| stores the buffers that have been dequeued from
-  // |dvr::BufferHubQueue|, It is initialized to invalid buffers, and gets
-  // filled in with the result of |Dequeue|.
-  // TODO(jwcai) The buffer allocated to a slot will also be replaced if the
-  // requested buffer usage or geometry differs from that of the buffer
-  // allocated to a slot.
-  struct BufferHubSlot : public BufferSlot {
-    BufferHubSlot() : mBufferProducer(nullptr), mIsReallocating(false) {}
-    // BufferSlot comes from android framework, using m prefix to comply with
-    // the name convention with the reset of data fields from BufferSlot.
-    std::shared_ptr<BufferProducer> mBufferProducer;
-    bool mIsReallocating;
-  };
-  BufferHubSlot buffers_[BufferHubQueue::kMaxQueueCapacity];
-
-  // A uniqueId used by IGraphicBufferProducer interface.
-  const uint64_t unique_id_{genUniqueId()};
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_BUFFER_HUB_QUEUE_PRODUCER_H_
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
index 96f5404..3e96989 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
@@ -1,6 +1,5 @@
-#include <private/dvr/buffer_hub_queue_producer.h>
-
 #include <base/logging.h>
+#include <gui/BufferHubProducer.h>
 #include <gui/IProducerListener.h>
 #include <gui/Surface.h>
 #include <pdx/default_transport/channel_parcelable.h>
@@ -101,7 +100,7 @@
     auto queue = ProducerQueue::Create(config, UsagePolicy{});
     ASSERT_TRUE(queue != nullptr);
 
-    mProducer = BufferHubQueueProducer::Create(std::move(queue));
+    mProducer = BufferHubProducer::Create(std::move(queue));
     ASSERT_TRUE(mProducer != nullptr);
     mSurface = new Surface(mProducer, true);
     ASSERT_TRUE(mSurface != nullptr);
@@ -145,7 +144,7 @@
 
   const sp<IProducerListener> kDummyListener{new DummyProducerListener};
 
-  sp<BufferHubQueueProducer> mProducer;
+  sp<BufferHubProducer> mProducer;
   sp<Surface> mSurface;
 };
 
@@ -596,8 +595,8 @@
 
   // Create a new producer from the parcelable and connect to kTestApi should
   // succeed.
-  sp<BufferHubQueueProducer> new_producer =
-      BufferHubQueueProducer::Create(std::move(producer_parcelable));
+  sp<BufferHubProducer> new_producer =
+      BufferHubProducer::Create(std::move(producer_parcelable));
   ASSERT_TRUE(new_producer != nullptr);
   EXPECT_EQ(new_producer->connect(kDummyListener, kTestApi,
                                   kTestControlledByApp, &output),
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_transport_benchmark.cpp b/libs/vr/libbufferhubqueue/tests/buffer_transport_benchmark.cpp
index d4d25b0..73932c2 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_transport_benchmark.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_transport_benchmark.cpp
@@ -5,10 +5,10 @@
 #include <binder/IServiceManager.h>
 #include <dvr/dvr_api.h>
 #include <dvr/performance_client_api.h>
+#include <gui/BufferHubProducer.h>
 #include <gui/BufferItem.h>
 #include <gui/BufferItemConsumer.h>
 #include <gui/Surface.h>
-#include <private/dvr/buffer_hub_queue_producer.h>
 #include <utils/Trace.h>
 
 #include <chrono>
@@ -338,7 +338,7 @@
         }
       });
 
-      producer_ = BufferHubQueueProducer::Create(producer_queue_);
+      producer_ = BufferHubProducer::Create(producer_queue_);
     }
 
     int count_ = 0;
diff --git a/libs/vr/libdvr/Android.bp b/libs/vr/libdvr/Android.bp
index 04418d2..4f0e561 100644
--- a/libs/vr/libdvr/Android.bp
+++ b/libs/vr/libdvr/Android.bp
@@ -15,8 +15,11 @@
 
 cc_library_headers {
     name: "libdvr_headers",
-    owner: "google",
     export_include_dirs: ["include"],
+    vendor_available: false,
+    vndk: {
+        enabled: true,
+    },
 }
 
 cflags = [
diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp
index 09a49dd..c36d190 100644
--- a/libs/vr/libdvr/dvr_buffer_queue.cpp
+++ b/libs/vr/libdvr/dvr_buffer_queue.cpp
@@ -2,7 +2,7 @@
 #include "include/dvr/dvr_buffer_queue.h"
 
 #include <android/native_window.h>
-#include <private/dvr/buffer_hub_queue_producer.h>
+#include <gui/BufferHubProducer.h>
 
 #include "dvr_internal.h"
 #include "dvr_buffer_queue_internal.h"
@@ -10,7 +10,6 @@
 using namespace android;
 using android::dvr::BufferConsumer;
 using android::dvr::BufferHubBuffer;
-using android::dvr::BufferHubQueueProducer;
 using android::dvr::BufferProducer;
 using android::dvr::ConsumerQueue;
 using android::dvr::ProducerQueue;
@@ -30,8 +29,7 @@
   if (native_window_ == nullptr) {
     // Lazy creation of |native_window|, as not everyone is using
     // DvrWriteBufferQueue as an external surface.
-    sp<IGraphicBufferProducer> gbp =
-        BufferHubQueueProducer::Create(producer_queue_);
+    sp<IGraphicBufferProducer> gbp = BufferHubProducer::Create(producer_queue_);
     native_window_ = new Surface(gbp, true);
   }
 
diff --git a/libs/vr/libpdx/Android.bp b/libs/vr/libpdx/Android.bp
index 10c0b31..9b84d65 100644
--- a/libs/vr/libpdx/Android.bp
+++ b/libs/vr/libpdx/Android.bp
@@ -16,6 +16,16 @@
         "service_dispatcher.cpp",
         "status.cpp",
     ],
+    shared_libs: [
+        "libbinder",
+        "libcutils",
+        "libutils",
+        "liblog",
+    ],
+    vendor_available: false,
+    vndk: {
+        enabled: true,
+    },
 }
 
 cc_test {
diff --git a/libs/vr/libpdx_default_transport/Android.bp b/libs/vr/libpdx_default_transport/Android.bp
index cda3c95..779e3a1 100644
--- a/libs/vr/libpdx_default_transport/Android.bp
+++ b/libs/vr/libpdx_default_transport/Android.bp
@@ -12,6 +12,10 @@
     name: "pdx_default_transport_lib_defaults",
     export_include_dirs: ["private"],
     whole_static_libs: ["libpdx"],
+    vendor_available: false,
+    vndk: {
+        enabled: true,
+    },
 }
 
 cc_defaults {
diff --git a/libs/vr/libpdx_uds/Android.bp b/libs/vr/libpdx_uds/Android.bp
index d640950..79cfdf6 100644
--- a/libs/vr/libpdx_uds/Android.bp
+++ b/libs/vr/libpdx_uds/Android.bp
@@ -30,6 +30,10 @@
     whole_static_libs: [
         "libselinux",
     ],
+    vendor_available: false,
+    vndk: {
+        enabled: true,
+    },
 }
 
 cc_test {
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index 4d80e91..1c5b2d6 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -27,7 +27,6 @@
 
 staticLibraries = [
     "libsurfaceflingerincludes",
-    "libhwcomposer-command-buffer",
     "libbufferhub",
     "libbufferhubqueue",
     "libdisplay",
@@ -64,7 +63,8 @@
 ]
 
 headerLibraries = [
-    "libdvr_headers"
+    "libdvr_headers",
+    "android.hardware.graphics.composer@2.1-command-buffer",
 ]
 
 cc_library_static {
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 5d796dc..4f5d548 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -457,13 +457,6 @@
     layer.Prepare();
   }
 
-  HWC::Error error = Validate(composer_callback_->GetDisplayId());
-  if (error != HWC::Error::None) {
-    ALOGE("HardwareComposer::PostLayers: Validate failed: %s",
-          error.to_string().c_str());
-    return;
-  }
-
   // Now that we have taken in a frame from the application, we have a chance
   // to drop the frame before passing the frame along to HWC.
   // If the display driver has become backed up, we detect it here and then
@@ -504,6 +497,13 @@
   }
 #endif
 
+  HWC::Error error = Validate(composer_callback_->GetDisplayId());
+  if (error != HWC::Error::None) {
+    ALOGE("HardwareComposer::PostLayers: Validate failed: %s",
+          error.to_string().c_str());
+    return;
+  }
+
   error = Present(composer_callback_->GetDisplayId());
   if (error != HWC::Error::None) {
     ALOGE("HardwareComposer::PostLayers: Present failed: %s",
@@ -862,17 +862,13 @@
       ATRACE_INT64("sleep_time_ns", sleep_time_ns);
       if (sleep_time_ns > 0) {
         int error = SleepUntil(wakeup_time_ns);
-        ALOGE_IF(error < 0, "HardwareComposer::PostThread: Failed to sleep: %s",
+        ALOGE_IF(error < 0 && error != kPostThreadInterrupted,
+                 "HardwareComposer::PostThread: Failed to sleep: %s",
                  strerror(-error));
-        if (error == kPostThreadInterrupted) {
-          if (layer_config_changed) {
-            // If the layer config changed we need to validateDisplay() even if
-            // we're going to drop the frame, to flush the Composer object's
-            // internal command buffer and apply our layer changes.
-            Validate(composer_callback_->GetDisplayId());
-          }
-          continue;
-        }
+        // If the sleep was interrupted (error == kPostThreadInterrupted),
+        // we still go through and present this frame because we may have set
+        // layers earlier and we want to flush the Composer's internal command
+        // buffer by continuing through to validate and present.
       }
     }
 
diff --git a/services/media/arcvideobridge/Android.bp b/services/media/arcvideobridge/Android.bp
new file mode 100644
index 0000000..ed0f613
--- /dev/null
+++ b/services/media/arcvideobridge/Android.bp
@@ -0,0 +1,29 @@
+cc_library_shared {
+    name: "libarcvideobridge",
+    product_variables: {
+        arc: {
+            srcs: [
+                "IArcVideoBridge.cpp",
+            ],
+            // TODO: remove the suffix "_bp" after finishing migration to Android.bp.
+            shared_libs: [
+                "libarcbridge",
+                "libarcbridgeservice",
+                "libbinder",
+                "libchrome",
+                "liblog",
+                "libmojo_bp",
+                "libutils",
+            ],
+            cflags: [
+                "-Wall",
+                "-Werror",
+                "-Wunused",
+                "-Wunreachable-code",
+            ],
+            include_dirs: [
+                "frameworks/native/include/media/arcvideobridge",
+            ]
+        }
+    }
+}
diff --git a/services/media/arcvideobridge/IArcVideoBridge.cpp b/services/media/arcvideobridge/IArcVideoBridge.cpp
new file mode 100644
index 0000000..468b76b
--- /dev/null
+++ b/services/media/arcvideobridge/IArcVideoBridge.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "IArcVideoBridge"
+//#define LOG_NDEBUG 0
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "IArcVideoBridge.h"
+#include <binder/Parcel.h>
+#include <utils/Log.h>
+
+namespace android {
+
+enum {
+    BOOTSTRAP_VIDEO_ACCELERATOR_FACTORY = IBinder::FIRST_CALL_TRANSACTION,
+    HOST_VERSION,
+};
+
+class BpArcVideoBridge : public BpInterface<IArcVideoBridge> {
+public:
+    BpArcVideoBridge(const sp<IBinder>& impl) : BpInterface<IArcVideoBridge>(impl) { }
+
+    virtual ::arc::MojoBootstrapResult bootstrapVideoAcceleratorFactory() {
+        Parcel data, reply;
+        ALOGV("bootstrapVideoAcceleratorFactory");
+        data.writeInterfaceToken(IArcVideoBridge::getInterfaceDescriptor());
+        status_t status = remote()->transact(
+                BOOTSTRAP_VIDEO_ACCELERATOR_FACTORY, data, &reply, 0);
+        if (status != 0) {
+            ALOGE("transact failed: %d", status);
+            return arc::MojoBootstrapResult();
+        }
+        return arc::MojoBootstrapResult::createFromParcel(reply);
+    }
+
+    virtual int32_t hostVersion() {
+        Parcel data, reply;
+        ALOGV("hostVersion");
+        data.writeInterfaceToken(IArcVideoBridge::getInterfaceDescriptor());
+        status_t status = remote()->transact(HOST_VERSION, data, &reply, 0);
+        if (status != 0) {
+            ALOGE("transact failed: %d", status);
+            return false;
+        }
+        return reply.readInt32();
+    }
+};
+
+IMPLEMENT_META_INTERFACE(ArcVideoBridge, "android.os.IArcVideoBridge");
+
+status_t BnArcVideoBridge::onTransact(
+        uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
+    switch(code) {
+        case BOOTSTRAP_VIDEO_ACCELERATOR_FACTORY: {
+            ALOGV("BOOTSTRAP_VIDEO_ACCELERATOR_FACTORY");
+            CHECK_INTERFACE(IArcVideoBridge, data, reply);
+            arc::MojoBootstrapResult result = bootstrapVideoAcceleratorFactory();
+            return result.writeToParcel(reply);
+        }
+        case HOST_VERSION: {
+            ALOGV("HOST_VERSION");
+            CHECK_INTERFACE(IArcVideoBridge, data, reply);
+            reply->writeInt32(hostVersion());
+            return OK;
+        }
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+}  // namespace android
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index 0a05dd1..956844f 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -29,11 +29,11 @@
 
 SensorService::SensorEventConnection::SensorEventConnection(
         const sp<SensorService>& service, uid_t uid, String8 packageName, bool isDataInjectionMode,
-        const String16& opPackageName)
+        const String16& opPackageName, bool hasSensorAccess)
     : mService(service), mUid(uid), mWakeLockRefCount(0), mHasLooperCallbacks(false),
       mDead(false), mDataInjectionMode(isDataInjectionMode), mEventCache(NULL),
       mCacheSize(0), mMaxCacheSize(0), mPackageName(packageName), mOpPackageName(opPackageName),
-      mDestroyed(false) {
+      mDestroyed(false), mHasSensorAccess(hasSensorAccess) {
     mChannel = new BitTube(mService->mSocketBufferSize);
 #if DEBUG_CONNECTIONS
     mEventsReceived = mEventsSentFromCache = mEventsSent = 0;
@@ -223,6 +223,9 @@
         sensors_event_t* scratch,
         wp<const SensorEventConnection> const * mapFlushEventsToConnections) {
     // filter out events not for this connection
+
+    sensors_event_t* sanitizedBuffer = nullptr;
+
     int count = 0;
     Mutex::Autolock _l(mConnectionLock);
     if (scratch) {
@@ -273,24 +276,36 @@
                     if (mapFlushEventsToConnections[i] == this) {
                         scratch[count++] = buffer[i];
                     }
-                    ++i;
                 } else {
                     // Regular sensor event, just copy it to the scratch buffer.
-                    scratch[count++] = buffer[i++];
+                    if (mHasSensorAccess) {
+                        scratch[count++] = buffer[i];
+                    }
                 }
+                i++;
             } while ((i<numEvents) && ((buffer[i].sensor == sensor_handle &&
                                         buffer[i].type != SENSOR_TYPE_META_DATA) ||
                                        (buffer[i].type == SENSOR_TYPE_META_DATA  &&
                                         buffer[i].meta_data.sensor == sensor_handle)));
         }
     } else {
-        scratch = const_cast<sensors_event_t *>(buffer);
-        count = numEvents;
+        if (mHasSensorAccess) {
+            scratch = const_cast<sensors_event_t *>(buffer);
+            count = numEvents;
+        } else {
+            scratch = sanitizedBuffer = new sensors_event_t[numEvents];
+            for (size_t i = 0; i < numEvents; i++) {
+                if (buffer[i].type == SENSOR_TYPE_META_DATA) {
+                    scratch[count++] = buffer[i++];
+                }
+            }
+        }
     }
 
     sendPendingFlushEventsLocked();
     // Early return if there are no events for this connection.
     if (count == 0) {
+        delete sanitizedBuffer;
         return status_t(NO_ERROR);
     }
 
@@ -308,6 +323,7 @@
             // the max cache size that is desired.
             if (mCacheSize + count < computeMaxCacheSizeLocked()) {
                 reAllocateCacheLocked(scratch, count);
+                delete sanitizedBuffer;
                 return status_t(NO_ERROR);
             }
             // Some events need to be dropped.
@@ -326,16 +342,20 @@
             memcpy(&mEventCache[mCacheSize - numEventsDropped], scratch + remaningCacheSize,
                                             numEventsDropped * sizeof(sensors_event_t));
         }
+        delete sanitizedBuffer;
         return status_t(NO_ERROR);
     }
 
-    int index_wake_up_event = findWakeUpSensorEventLocked(scratch, count);
-    if (index_wake_up_event >= 0) {
-        scratch[index_wake_up_event].flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
-        ++mWakeLockRefCount;
+    int index_wake_up_event = -1;
+    if (mHasSensorAccess) {
+        index_wake_up_event = findWakeUpSensorEventLocked(scratch, count);
+        if (index_wake_up_event >= 0) {
+            scratch[index_wake_up_event].flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
+            ++mWakeLockRefCount;
 #if DEBUG_CONNECTIONS
-        ++mTotalAcksNeeded;
+            ++mTotalAcksNeeded;
 #endif
+        }
     }
 
     // NOTE: ASensorEvent and sensors_event_t are the same type.
@@ -364,6 +384,7 @@
         // Add this file descriptor to the looper to get a callback when this fd is available for
         // writing.
         updateLooperRegistrationLocked(mService->getLooper());
+        delete sanitizedBuffer;
         return size;
     }
 
@@ -373,9 +394,15 @@
     }
 #endif
 
+    delete sanitizedBuffer;
     return size < 0 ? status_t(size) : status_t(NO_ERROR);
 }
 
+void SensorService::SensorEventConnection::setSensorAccess(const bool hasAccess) {
+    Mutex::Autolock _l(mConnectionLock);
+    mHasSensorAccess = hasAccess;
+}
+
 void SensorService::SensorEventConnection::reAllocateCacheLocked(sensors_event_t const* scratch,
                                                                  int count) {
     sensors_event_t *eventCache_new;
@@ -437,15 +464,18 @@
     sendPendingFlushEventsLocked();
     for (int numEventsSent = 0; numEventsSent < mCacheSize;) {
         const int numEventsToWrite = helpers::min(mCacheSize - numEventsSent, maxWriteSize);
-        int index_wake_up_event =
-                  findWakeUpSensorEventLocked(mEventCache + numEventsSent, numEventsToWrite);
-        if (index_wake_up_event >= 0) {
-            mEventCache[index_wake_up_event + numEventsSent].flags |=
-                    WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
-            ++mWakeLockRefCount;
+        int index_wake_up_event = -1;
+        if (mHasSensorAccess) {
+            index_wake_up_event =
+                      findWakeUpSensorEventLocked(mEventCache + numEventsSent, numEventsToWrite);
+            if (index_wake_up_event >= 0) {
+                mEventCache[index_wake_up_event + numEventsSent].flags |=
+                        WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
+                ++mWakeLockRefCount;
 #if DEBUG_CONNECTIONS
-            ++mTotalAcksNeeded;
+                ++mTotalAcksNeeded;
 #endif
+            }
         }
 
         ssize_t size = SensorEventQueue::write(mChannel,
diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h
index 6f282cd..032721e 100644
--- a/services/sensorservice/SensorEventConnection.h
+++ b/services/sensorservice/SensorEventConnection.h
@@ -49,7 +49,8 @@
 
 public:
     SensorEventConnection(const sp<SensorService>& service, uid_t uid, String8 packageName,
-                          bool isDataInjectionMode, const String16& opPackageName);
+                          bool isDataInjectionMode, const String16& opPackageName,
+                          bool hasSensorAccess);
 
     status_t sendEvents(sensors_event_t const* buffer, size_t count, sensors_event_t* scratch,
                         wp<const SensorEventConnection> const * mapFlushEventsToConnections = NULL);
@@ -66,6 +67,8 @@
 
     uid_t getUid() const { return mUid; }
 
+    void setSensorAccess(const bool hasAccess);
+
 private:
     virtual ~SensorEventConnection();
     virtual void onFirstRef();
@@ -167,6 +170,7 @@
 
     mutable Mutex mDestroyLock;
     bool mDestroyed;
+    bool mHasSensorAccess;
 };
 
 } // namepsace android
diff --git a/services/sensorservice/SensorRegistrationInfo.h b/services/sensorservice/SensorRegistrationInfo.h
index 75e8989..bba8372 100644
--- a/services/sensorservice/SensorRegistrationInfo.h
+++ b/services/sensorservice/SensorRegistrationInfo.h
@@ -35,12 +35,12 @@
     }
 
     SensorRegistrationInfo(int32_t handle, const String8 &packageName,
-                           int32_t samplingRateNs, int32_t maxReportLatencyNs, bool activate) {
+                           int64_t samplingRateNs, int64_t maxReportLatencyNs, bool activate) {
         mSensorHandle = handle;
         mPackageName = packageName;
 
-        mSamplingRateUs = static_cast<int32_t>(samplingRateNs/1000);
-        mMaxReportLatencyUs = static_cast<int32_t>(maxReportLatencyNs/1000);
+        mSamplingRateUs = static_cast<int64_t>(samplingRateNs/1000);
+        mMaxReportLatencyUs = static_cast<int64_t>(maxReportLatencyNs/1000);
         mActivated = activate;
 
         IPCThreadState *thread = IPCThreadState::self();
@@ -82,8 +82,8 @@
     String8 mPackageName;
     pid_t   mPid;
     uid_t   mUid;
-    int32_t mSamplingRateUs;
-    int32_t mMaxReportLatencyUs;
+    int64_t mSamplingRateUs;
+    int64_t mMaxReportLatencyUs;
     bool mActivated;
     int8_t mHour, mMin, mSec;
 
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index dc491d9..c32ffb9 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -13,11 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#include <binder/ActivityManager.h>
 #include <binder/AppOpsManager.h>
 #include <binder/BinderService.h>
 #include <binder/IServiceManager.h>
 #include <binder/PermissionCache.h>
+#include <binder/PermissionController.h>
 #include <cutils/ashmem.h>
+#include <cutils/misc.h>
 #include <cutils/properties.h>
 #include <hardware/sensors.h>
 #include <hardware_legacy/power.h>
@@ -52,6 +55,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <private/android_filesystem_config.h>
+
 namespace android {
 // ---------------------------------------------------------------------------
 
@@ -75,6 +80,7 @@
 // Permissions.
 static const String16 sDumpPermission("android.permission.DUMP");
 static const String16 sLocationHardwarePermission("android.permission.LOCATION_HARDWARE");
+static const String16 sManageSensorsPermission("android.permission.MANAGE_SENSORS");
 
 SensorService::SensorService()
     : mInitCheck(NO_INIT), mSocketBufferSize(SOCKET_BUFFER_SIZE_NON_BATCHED),
@@ -274,6 +280,23 @@
 
             // priority can only be changed after run
             enableSchedFifoMode();
+
+            // Start watching UID changes to apply policy.
+            mUidPolicy = new UidPolicy(this);
+            mUidPolicy->registerSelf();
+        }
+    }
+}
+
+void SensorService::setSensorAccess(uid_t uid, bool hasAccess) {
+    SortedVector< sp<SensorEventConnection> > activeConnections;
+    populateActiveConnections(&activeConnections);
+    {
+        Mutex::Autolock _l(mLock);
+        for (size_t i = 0 ; i < activeConnections.size(); i++) {
+            if (activeConnections[i] != 0 && activeConnections[i]->getUid() == uid) {
+                activeConnections[i]->setSensorAccess(hasAccess);
+            }
         }
     }
 }
@@ -312,6 +335,7 @@
     for (auto && entry : mRecentEvent) {
         delete entry.second;
     }
+    mUidPolicy->unregisterSelf();
 }
 
 status_t SensorService::dump(int fd, const Vector<String16>& args) {
@@ -488,6 +512,82 @@
     return NO_ERROR;
 }
 
+// NOTE: This is a remote API - make sure all args are validated
+status_t SensorService::shellCommand(int in, int out, int err, Vector<String16>& args) {
+    if (!checkCallingPermission(sManageSensorsPermission, nullptr, nullptr)) {
+        return PERMISSION_DENIED;
+    }
+    if (in == BAD_TYPE || out == BAD_TYPE || err == BAD_TYPE) {
+        return BAD_VALUE;
+    }
+    if (args.size() == 3 && args[0] == String16("set-uid-state")) {
+        return handleSetUidState(args, err);
+    } else if (args.size() == 2 && args[0] == String16("reset-uid-state")) {
+        return handleResetUidState(args, err);
+    } else if (args.size() == 2 && args[0] == String16("get-uid-state")) {
+        return handleGetUidState(args, out, err);
+    } else if (args.size() == 1 && args[0] == String16("help")) {
+        printHelp(out);
+        return NO_ERROR;
+    }
+    printHelp(err);
+    return BAD_VALUE;
+}
+
+status_t SensorService::handleSetUidState(Vector<String16>& args, int err) {
+    PermissionController pc;
+    int uid = pc.getPackageUid(args[1], 0);
+    if (uid <= 0) {
+        ALOGE("Unknown package: '%s'", String8(args[1]).string());
+        dprintf(err, "Unknown package: '%s'\n", String8(args[1]).string());
+        return BAD_VALUE;
+    }
+    bool active = false;
+    if (args[2] == String16("active")) {
+        active = true;
+    } else if ((args[2] != String16("idle"))) {
+        ALOGE("Expected active or idle but got: '%s'", String8(args[2]).string());
+        return BAD_VALUE;
+    }
+    mUidPolicy->addOverrideUid(uid, active);
+    return NO_ERROR;
+}
+
+status_t SensorService::handleResetUidState(Vector<String16>& args, int err) {
+    PermissionController pc;
+    int uid = pc.getPackageUid(args[1], 0);
+    if (uid < 0) {
+        ALOGE("Unknown package: '%s'", String8(args[1]).string());
+        dprintf(err, "Unknown package: '%s'\n", String8(args[1]).string());
+        return BAD_VALUE;
+    }
+    mUidPolicy->removeOverrideUid(uid);
+    return NO_ERROR;
+}
+
+status_t SensorService::handleGetUidState(Vector<String16>& args, int out, int err) {
+    PermissionController pc;
+    int uid = pc.getPackageUid(args[1], 0);
+    if (uid < 0) {
+        ALOGE("Unknown package: '%s'", String8(args[1]).string());
+        dprintf(err, "Unknown package: '%s'\n", String8(args[1]).string());
+        return BAD_VALUE;
+    }
+    if (mUidPolicy->isUidActive(uid)) {
+        return dprintf(out, "active\n");
+    } else {
+        return dprintf(out, "idle\n");
+    }
+}
+
+status_t SensorService::printHelp(int out) {
+    return dprintf(out, "Sensor service commands:\n"
+        "  get-uid-state <PACKAGE> gets the uid state\n"
+        "  set-uid-state <PACKAGE> <active|idle> overrides the uid state\n"
+        "  reset-uid-state <PACKAGE> clears the uid state override\n"
+        "  help print this message\n");
+}
+
 //TODO: move to SensorEventConnection later
 void SensorService::cleanupAutoDisabledSensorLocked(const sp<SensorEventConnection>& connection,
         sensors_event_t const* buffer, const int count) {
@@ -677,7 +777,6 @@
             }
         }
 
-
         // Send our events to clients. Check the state of wake lock for each client and release the
         // lock if none of the clients need it.
         bool needsWakeLock = false;
@@ -939,8 +1038,9 @@
             (packageName == "") ? String8::format("unknown_package_pid_%d", pid) : packageName;
     String16 connOpPackageName =
             (opPackageName == String16("")) ? String16(connPackageName) : opPackageName;
+    bool hasSensorAccess = mUidPolicy->isUidActive(uid);
     sp<SensorEventConnection> result(new SensorEventConnection(this, uid, connPackageName,
-            requestedMode == DATA_INJECTION, connOpPackageName));
+            requestedMode == DATA_INJECTION, connOpPackageName, hasSensorAccess));
     if (requestedMode == DATA_INJECTION) {
         if (mActiveConnections.indexOf(result) < 0) {
             mActiveConnections.add(result);
@@ -1530,4 +1630,98 @@
     return false;
 }
 
+void SensorService::UidPolicy::registerSelf() {
+    ActivityManager am;
+    am.registerUidObserver(this, ActivityManager::UID_OBSERVER_GONE
+            | ActivityManager::UID_OBSERVER_IDLE
+            | ActivityManager::UID_OBSERVER_ACTIVE,
+            ActivityManager::PROCESS_STATE_UNKNOWN,
+            String16("android"));
+}
+
+void SensorService::UidPolicy::unregisterSelf() {
+    ActivityManager am;
+    am.unregisterUidObserver(this);
+}
+
+void SensorService::UidPolicy::onUidGone(__unused uid_t uid, __unused bool disabled) {
+    onUidIdle(uid, disabled);
+}
+
+void SensorService::UidPolicy::onUidActive(uid_t uid) {
+    {
+        Mutex::Autolock _l(mUidLock);
+        mActiveUids.insert(uid);
+    }
+    sp<SensorService> service = mService.promote();
+    if (service != nullptr) {
+        service->setSensorAccess(uid, true);
+    }
+}
+
+void SensorService::UidPolicy::onUidIdle(uid_t uid, __unused bool disabled) {
+    bool deleted = false;
+    {
+        Mutex::Autolock _l(mUidLock);
+        if (mActiveUids.erase(uid) > 0) {
+            deleted = true;
+        }
+    }
+    if (deleted) {
+        sp<SensorService> service = mService.promote();
+        if (service != nullptr) {
+            service->setSensorAccess(uid, false);
+        }
+    }
+}
+
+void SensorService::UidPolicy::addOverrideUid(uid_t uid, bool active) {
+    updateOverrideUid(uid, active, true);
+}
+
+void SensorService::UidPolicy::removeOverrideUid(uid_t uid) {
+    updateOverrideUid(uid, false, false);
+}
+
+void SensorService::UidPolicy::updateOverrideUid(uid_t uid, bool active, bool insert) {
+    bool wasActive = false;
+    bool isActive = false;
+    {
+        Mutex::Autolock _l(mUidLock);
+        wasActive = isUidActiveLocked(uid);
+        mOverrideUids.erase(uid);
+        if (insert) {
+            mOverrideUids.insert(std::pair<uid_t, bool>(uid, active));
+        }
+        isActive = isUidActiveLocked(uid);
+    }
+    if (wasActive != isActive) {
+        sp<SensorService> service = mService.promote();
+        if (service != nullptr) {
+            service->setSensorAccess(uid, isActive);
+        }
+    }
+}
+
+bool SensorService::UidPolicy::isUidActive(uid_t uid) {
+    // Non-app UIDs are considered always active
+    if (uid < FIRST_APPLICATION_UID) {
+        return true;
+    }
+    Mutex::Autolock _l(mUidLock);
+    return isUidActiveLocked(uid);
+}
+
+bool SensorService::UidPolicy::isUidActiveLocked(uid_t uid) {
+    // Non-app UIDs are considered always active
+    if (uid < FIRST_APPLICATION_UID) {
+        return true;
+    }
+    auto it = mOverrideUids.find(uid);
+    if (it != mOverrideUids.end()) {
+        return it->second;
+    }
+    return mActiveUids.find(uid) != mActiveUids.end();
+}
+
 }; // namespace android
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 3e18394..f71723d 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -21,6 +21,7 @@
 #include "RecentEventLogger.h"
 
 #include <binder/BinderService.h>
+#include <binder/IUidObserver.h>
 #include <cutils/compiler.h>
 #include <sensor/ISensorServer.h>
 #include <sensor/ISensorEventConnection.h>
@@ -85,6 +86,9 @@
     status_t flushSensor(const sp<SensorEventConnection>& connection,
                          const String16& opPackageName);
 
+
+    virtual status_t shellCommand(int in, int out, int err, Vector<String16>& args);
+
 private:
     friend class BinderService<SensorService>;
 
@@ -93,6 +97,40 @@
     class SensorEventAckReceiver;
     class SensorRegistrationInfo;
 
+    // If accessing a sensor we need to make sure the UID has access to it. If
+    // the app UID is idle then it cannot access sensors and gets no trigger
+    // events, no on-change events, flush event behavior does not change, and
+    // recurring events are the same as the first one delivered in idle state
+    // emulating no sensor change. As soon as the app UID transitions to an
+    // active state we will start reporting events as usual and vise versa. This
+    // approach transparently handles observing sensors while the app UID transitions
+    // between idle/active state avoiding to get stuck in a state receiving sensor
+    // data while idle or not receiving sensor data while active.
+    class UidPolicy : public BnUidObserver {
+        public:
+            explicit UidPolicy(wp<SensorService> service)
+                    : mService(service) {}
+            void registerSelf();
+            void unregisterSelf();
+
+            bool isUidActive(uid_t uid);
+
+            void onUidGone(uid_t uid, bool disabled);
+            void onUidActive(uid_t uid);
+            void onUidIdle(uid_t uid, bool disabled);
+
+            void addOverrideUid(uid_t uid, bool active);
+            void removeOverrideUid(uid_t uid);
+        private:
+            bool isUidActiveLocked(uid_t uid);
+            void updateOverrideUid(uid_t uid, bool active, bool insert);
+
+            Mutex mUidLock;
+            wp<SensorService> mService;
+            std::unordered_set<uid_t> mActiveUids;
+            std::unordered_map<uid_t, bool> mOverrideUids;
+    };
+
     enum Mode {
        // The regular operating mode where any application can register/unregister/call flush on
        // sensors.
@@ -161,7 +199,6 @@
     virtual int setOperationParameter(
             int32_t handle, int32_t type, const Vector<float> &floats, const Vector<int32_t> &ints);
     virtual status_t dump(int fd, const Vector<String16>& args);
-
     String8 getSensorName(int handle) const;
     bool isVirtualSensor(int handle) const;
     sp<SensorInterface> getSensorInterfaceFromHandle(int handle) const;
@@ -225,6 +262,18 @@
     // Enable SCHED_FIFO priority for thread
     void enableSchedFifoMode();
 
+    // Sets whether the given UID can get sensor data
+    void setSensorAccess(uid_t uid, bool hasAccess);
+
+    // Overrides the UID state as if it is idle
+    status_t handleSetUidState(Vector<String16>& args, int err);
+    // Clears the override for the UID state
+    status_t handleResetUidState(Vector<String16>& args, int err);
+    // Gets the UID state
+    status_t handleGetUidState(Vector<String16>& args, int out, int err);
+    // Prints the shell command help
+    status_t printHelp(int out);
+
     static uint8_t sHmacGlobalKey[128];
     static bool sHmacGlobalKeyIsValid;
 
@@ -257,6 +306,8 @@
 
     int mNextSensorRegIndex;
     Vector<SensorRegistrationInfo> mLastNSensorRegistrations;
+
+    sp<UidPolicy> mUidPolicy;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 5b6c1ca..6c54ec3 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -59,13 +59,15 @@
 LOCAL_CFLAGS += -fvisibility=hidden -Werror=format
 
 LOCAL_STATIC_LIBRARIES := \
-    libhwcomposer-command-buffer \
     libtrace_proto \
     libvkjson \
     libvr_manager \
     libvrflinger \
     libserviceutils
 
+LOCAL_HEADER_LIBRARIES := \
+    android.hardware.graphics.composer@2.1-command-buffer
+
 LOCAL_EXPORT_STATIC_LIBRARY_HEADERS := libserviceutils
 
 LOCAL_SHARED_LIBRARIES := \
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index d860f58..ab6a559 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -821,8 +821,17 @@
     engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), false /* disableTexture */,
                               getColor());
     engine.setSourceDataSpace(mCurrentState.dataSpace);
+
+    if (mCurrentState.dataSpace == HAL_DATASPACE_BT2020_PQ &&
+        mConsumer->getCurrentApi() == NATIVE_WINDOW_API_MEDIA &&
+        getBE().compositionInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102) {
+        engine.setSourceY410BT2020(true);
+    }
+
     engine.drawMesh(getBE().mMesh);
     engine.disableBlending();
+
+    engine.setSourceY410BT2020(false);
 }
 
 uint32_t BufferLayer::getProducerStickyTransform() const {
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index 8f5c9c7..4d9b43f 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -68,6 +68,7 @@
         mCurrentFrameNumber(0),
         mCurrentTransformToDisplayInverse(false),
         mCurrentSurfaceDamage(),
+        mCurrentApi(0),
         mDefaultWidth(1),
         mDefaultHeight(1),
         mFilteringEnabled(true),
@@ -346,6 +347,7 @@
     mCurrentFrameNumber = item.mFrameNumber;
     mCurrentTransformToDisplayInverse = item.mTransformToDisplayInverse;
     mCurrentSurfaceDamage = item.mSurfaceDamage;
+    mCurrentApi = item.mApi;
 
     computeCurrentTransformMatrixLocked();
 
@@ -469,6 +471,11 @@
     return mCurrentSurfaceDamage;
 }
 
+int BufferLayerConsumer::getCurrentApi() const {
+    Mutex::Autolock lock(mMutex);
+    return mCurrentApi;
+}
+
 sp<GraphicBuffer> BufferLayerConsumer::getCurrentBuffer(int* outSlot) const {
     Mutex::Autolock lock(mMutex);
 
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
index f473390..a0272b3 100644
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ b/services/surfaceflinger/BufferLayerConsumer.h
@@ -138,6 +138,9 @@
     // must be called from SF main thread
     const Region& getSurfaceDamage() const;
 
+    // getCurrentApi retrieves the API which queues the current buffer.
+    int getCurrentApi() const;
+
     // See GLConsumer::setDefaultBufferSize.
     status_t setDefaultBufferSize(uint32_t width, uint32_t height);
 
@@ -337,6 +340,8 @@
     // The portion of this surface that has changed since the previous frame
     Region mCurrentSurfaceDamage;
 
+    int mCurrentApi;
+
     uint32_t mDefaultWidth, mDefaultHeight;
 
     // mFilteringEnabled indicates whether the transform matrix is computed for
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index a663487..cf70529 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -76,7 +76,8 @@
         const wp<IBinder>& displayToken,
         const sp<DisplaySurface>& displaySurface,
         const sp<IGraphicBufferProducer>& producer,
-        bool supportWideColor)
+        bool supportWideColor,
+        bool supportHdr)
     : lastCompositionHadVisibleLayers(false),
       mFlinger(flinger),
       mType(type),
@@ -100,6 +101,8 @@
 
     mActiveColorMode = HAL_COLOR_MODE_NATIVE;
     mDisplayHasWideColor = supportWideColor;
+    mDisplayHasHdr = supportHdr;
+
     /*
      * Create our display's surface
      */
@@ -203,7 +206,7 @@
 }
 
 void DisplayDevice::swapBuffers(HWComposer& hwc) const {
-    if (hwc.hasClientComposition(mHwcDisplayId)) {
+    if (hwc.hasClientComposition(mHwcDisplayId) || hwc.hasFlipClientTargetRequest(mHwcDisplayId)) {
         mSurface.swapBuffers();
     }
 
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 499bf8e..a470670 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -78,7 +78,7 @@
             const wp<IBinder>& displayToken,
             const sp<DisplaySurface>& displaySurface,
             const sp<IGraphicBufferProducer>& producer,
-            bool supportWideColor);
+            bool supportWideColor, bool supportHdr);
     // clang-format on
 
     ~DisplayDevice();
@@ -128,6 +128,7 @@
     status_t beginFrame(bool mustRecompose) const;
     status_t prepareFrame(HWComposer& hwc);
     bool getWideColorSupport() const { return mDisplayHasWideColor; }
+    bool getHdrSupport() const { return mDisplayHasHdr; }
 
     void swapBuffers(HWComposer& hwc) const;
 
@@ -235,6 +236,7 @@
     // Initialized by SurfaceFlinger when the DisplayDevice is created.
     // Fed to RenderEngine during composition.
     bool mDisplayHasWideColor;
+    bool mDisplayHasHdr;
 };
 
 struct DisplayDeviceState {
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 104ca60..3d9993e 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -25,8 +25,8 @@
 
 #include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
 #include <android/hardware/graphics/composer/2.1/IComposer.h>
+#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
 #include <utils/StrongPointer.h>
-#include <IComposerCommandBuffer.h>
 
 namespace android {
 
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 1677b07..7eb3998 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -564,6 +564,20 @@
     return mDisplayData[displayId].hasDeviceComposition;
 }
 
+bool HWComposer::hasFlipClientTargetRequest(int32_t displayId) const {
+    if (displayId == DisplayDevice::DISPLAY_ID_INVALID) {
+        // Displays without a corresponding HWC display are never composed by
+        // the device
+        return false;
+    }
+    if (!isValidDisplay(displayId)) {
+        ALOGE("hasFlipClientTargetRequest: Invalid display %d", displayId);
+        return false;
+    }
+    return ((static_cast<uint32_t>(mDisplayData[displayId].displayRequests) &
+             static_cast<uint32_t>(HWC2::DisplayRequest::FlipClientTarget)) != 0);
+}
+
 bool HWComposer::hasClientComposition(int32_t displayId) const {
     if (displayId == DisplayDevice::DISPLAY_ID_INVALID) {
         // Displays without a corresponding HWC display are always composed by
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index ee0a725..2e4f5d4 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -108,6 +108,9 @@
     // does this display have layers handled by HWC
     bool hasDeviceComposition(int32_t displayId) const;
 
+    // does this display have pending request to flip client target
+    bool hasFlipClientTargetRequest(int32_t displayId) const;
+
     // does this display have layers handled by GLES
     bool hasClientComposition(int32_t displayId) const;
 
diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp
index 1b5a466..5e79e7a 100644
--- a/services/surfaceflinger/RenderEngine/Description.cpp
+++ b/services/surfaceflinger/RenderEngine/Description.cpp
@@ -61,8 +61,20 @@
     return mColorMatrix;
 }
 
-void Description::setWideGamut(bool wideGamut) {
-    mIsWideGamut = wideGamut;
+void Description::setY410BT2020(bool enable) {
+    mY410BT2020 = enable;
+}
+
+void Description::setInputTransferFunction(TransferFunction transferFunction) {
+    mInputTransferFunction = transferFunction;
+}
+
+void Description::setOutputTransferFunction(TransferFunction transferFunction) {
+    mOutputTransferFunction = transferFunction;
+}
+
+void Description::enableToneMapping(bool enable) {
+    mToneMappingEnabled = enable;
 }
 
 } /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/Description.h b/services/surfaceflinger/RenderEngine/Description.h
index 1811952..75c1981 100644
--- a/services/surfaceflinger/RenderEngine/Description.h
+++ b/services/surfaceflinger/RenderEngine/Description.h
@@ -32,6 +32,32 @@
  * Program and ProgramCache are friends and access the state directly
  */
 class Description {
+public:
+    Description() = default;
+    ~Description() = default;
+
+    void setPremultipliedAlpha(bool premultipliedAlpha);
+    void setOpaque(bool opaque);
+    void setTexture(const Texture& texture);
+    void disableTexture();
+    void setColor(const half4& color);
+    void setProjectionMatrix(const mat4& mtx);
+    void setColorMatrix(const mat4& mtx);
+    const mat4& getColorMatrix() const;
+
+    void setY410BT2020(bool enable);
+
+    enum class TransferFunction : int {
+        LINEAR,
+        SRGB,
+        ST2084,
+    };
+    void setInputTransferFunction(TransferFunction transferFunction);
+    void setOutputTransferFunction(TransferFunction transferFunction);
+
+    void enableToneMapping(bool enable);
+
+private:
     friend class Program;
     friend class ProgramCache;
 
@@ -52,21 +78,15 @@
     bool mColorMatrixEnabled = false;
     mat4 mColorMatrix;
 
-    bool mIsWideGamut = false;
+    // true if the sampled pixel values are in Y410/BT2020 rather than RGBA
+    bool mY410BT2020 = false;
 
-public:
-    Description() = default;
-    ~Description() = default;
+    // transfer functions for the input/output
+    TransferFunction mInputTransferFunction = TransferFunction::LINEAR;
+    TransferFunction mOutputTransferFunction = TransferFunction::LINEAR;
 
-    void setPremultipliedAlpha(bool premultipliedAlpha);
-    void setOpaque(bool opaque);
-    void setTexture(const Texture& texture);
-    void disableTexture();
-    void setColor(const half4& color);
-    void setProjectionMatrix(const mat4& mtx);
-    void setColorMatrix(const mat4& mtx);
-    const mat4& getColorMatrix() const;
-    void setWideGamut(bool wideGamut);
+    // tone-map the color
+    bool mToneMappingEnabled = false;
 };
 
 } /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index d1ee6f8..323cec7 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -130,14 +130,12 @@
         // Compute sRGB to DisplayP3 color transform
         // NOTE: For now, we are limiting wide-color support to
         // Display-P3 only.
-        mat3 srgbToP3 =
-                ColorSpaceConnector(ColorSpace::sRGB(), ColorSpace::DisplayP3()).getTransform();
+        mSrgbToDisplayP3 = mat4(
+                ColorSpaceConnector(ColorSpace::sRGB(), ColorSpace::DisplayP3()).getTransform());
 
-        // color transform needs to be expanded to 4x4 to be what the shader wants
-        // mat has an initializer that expands mat3 to mat4, but
-        // not an assignment operator
-        mat4 gamutTransform(srgbToP3);
-        mSrgbToDisplayP3 = gamutTransform;
+        // Compute BT2020 to DisplayP3 color transform
+        mBt2020ToDisplayP3 = mat4(
+                ColorSpaceConnector(ColorSpace::BT2020(), ColorSpace::DisplayP3()).getTransform());
     }
 }
 
@@ -235,6 +233,10 @@
     mDataSpace = source;
 }
 
+void GLES20RenderEngine::setSourceY410BT2020(bool enable) {
+    mState.setY410BT2020(enable);
+}
+
 void GLES20RenderEngine::setWideColor(bool hasWideColor) {
     ALOGV("setWideColor: %s", hasWideColor ? "true" : "false");
     mDisplayHasWideColor = hasWideColor;
@@ -324,10 +326,22 @@
 
     if (usesWideColor()) {
         Description wideColorState = mState;
-        if (mDataSpace != HAL_DATASPACE_DISPLAY_P3) {
-            wideColorState.setColorMatrix(mState.getColorMatrix() * mSrgbToDisplayP3);
-            wideColorState.setWideGamut(true);
-            ALOGV("drawMesh: gamut transform applied");
+        switch (mDataSpace) {
+            case HAL_DATASPACE_DISPLAY_P3:
+                // input matches output
+                break;
+            case HAL_DATASPACE_BT2020_PQ:
+                wideColorState.setColorMatrix(mState.getColorMatrix() * mBt2020ToDisplayP3);
+                wideColorState.setInputTransferFunction(Description::TransferFunction::ST2084);
+                wideColorState.setOutputTransferFunction(Description::TransferFunction::SRGB);
+                wideColorState.enableToneMapping(true);
+                break;
+            default:
+                wideColorState.setColorMatrix(mState.getColorMatrix() * mSrgbToDisplayP3);
+                wideColorState.setInputTransferFunction(Description::TransferFunction::SRGB);
+                wideColorState.setOutputTransferFunction(Description::TransferFunction::SRGB);
+                ALOGV("drawMesh: gamut transform applied");
+                break;
         }
         ProgramCache::getInstance().useProgram(wideColorState);
 
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index 5ee9326..f3af547 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -71,6 +71,7 @@
     // Color management related functions and state
     void setColorMode(android_color_mode mode);
     void setSourceDataSpace(android_dataspace source);
+    void setSourceY410BT2020(bool enable);
     void setWideColor(bool hasWideColor);
     bool usesWideColor();
 
@@ -85,8 +86,9 @@
     bool mUseWideColor = false;
     uint64_t mWideColorFrameCount = 0;
 
-    // Currently only supporting sRGB and DisplayP3 color spaces
+    // Currently only supporting sRGB, BT2020 and DisplayP3 color spaces
     mat4 mSrgbToDisplayP3;
+    mat4 mBt2020ToDisplayP3;
     bool mPlatformHasWideColor = false;
 
     virtual void setupLayerTexturing(const Texture& texture);
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
index 3b8ac0e..7a43ea9 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -126,9 +126,42 @@
             .set(Key::OPACITY_MASK,
                  description.mOpaque ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT)
             .set(Key::COLOR_MATRIX_MASK,
-                 description.mColorMatrixEnabled ? Key::COLOR_MATRIX_ON : Key::COLOR_MATRIX_OFF)
-            .set(Key::WIDE_GAMUT_MASK,
-                 description.mIsWideGamut ? Key::WIDE_GAMUT_ON : Key::WIDE_GAMUT_OFF);
+                 description.mColorMatrixEnabled ? Key::COLOR_MATRIX_ON : Key::COLOR_MATRIX_OFF);
+
+    needs.set(Key::Y410_BT2020_MASK,
+              description.mY410BT2020 ? Key::Y410_BT2020_ON : Key::Y410_BT2020_OFF);
+
+    if (needs.hasColorMatrix()) {
+        switch (description.mInputTransferFunction) {
+            case Description::TransferFunction::LINEAR:
+            default:
+                needs.set(Key::INPUT_TF_MASK, Key::INPUT_TF_LINEAR);
+                break;
+            case Description::TransferFunction::SRGB:
+                needs.set(Key::INPUT_TF_MASK, Key::INPUT_TF_SRGB);
+                break;
+            case Description::TransferFunction::ST2084:
+                needs.set(Key::INPUT_TF_MASK, Key::INPUT_TF_ST2084);
+                break;
+        }
+
+        switch (description.mOutputTransferFunction) {
+            case Description::TransferFunction::LINEAR:
+            default:
+                needs.set(Key::OUTPUT_TF_MASK, Key::OUTPUT_TF_LINEAR);
+                break;
+            case Description::TransferFunction::SRGB:
+                needs.set(Key::OUTPUT_TF_MASK, Key::OUTPUT_TF_SRGB);
+                break;
+            case Description::TransferFunction::ST2084:
+                needs.set(Key::OUTPUT_TF_MASK, Key::OUTPUT_TF_ST2084);
+                break;
+        }
+
+        needs.set(Key::TONE_MAPPING_MASK,
+                  description.mToneMappingEnabled ? Key::TONE_MAPPING_ON : Key::TONE_MAPPING_OFF);
+    }
+
     return needs;
 }
 
@@ -170,56 +203,186 @@
         fs << "uniform vec4 color;";
     }
 
+    if (needs.isY410BT2020()) {
+        fs << R"__SHADER__(
+            vec3 convertY410BT2020(const vec3 color) {
+                const vec3 offset = vec3(0.0625, 0.5, 0.5);
+                const mat3 transform = mat3(
+                    vec3(1.1678,  1.1678, 1.1678),
+                    vec3(   0.0, -0.1878, 2.1481),
+                    vec3(1.6836, -0.6523,   0.0));
+                // Y is in G, U is in R, and V is in B
+                return clamp(transform * (color.grb - offset), 0.0, 1.0);
+            }
+            )__SHADER__";
+    }
+
     if (needs.hasColorMatrix()) {
         fs << "uniform mat4 colorMatrix;";
-    }
-    if (needs.hasColorMatrix()) {
-        // When in wide gamut mode, the color matrix will contain a color space
-        // conversion matrix that needs to be applied in linear space
-        // When not in wide gamut, we can simply no-op the transfer functions
-        // and let the shader compiler get rid of them
-        if (needs.isWideGamut()) {
+
+        switch (needs.getInputTF()) {
+            case Key::INPUT_TF_LINEAR:
+            default:
+                fs << R"__SHADER__(
+                    vec3 EOTF(const vec3 linear) {
+                        return linear;
+                    }
+                )__SHADER__";
+                break;
+            case Key::INPUT_TF_SRGB:
+                fs << R"__SHADER__(
+                    float EOTF_sRGB(float srgb) {
+                        return srgb <= 0.04045 ? srgb / 12.92 : pow((srgb + 0.055) / 1.055, 2.4);
+                    }
+
+                    vec3 EOTF_sRGB(const vec3 srgb) {
+                        return vec3(EOTF_sRGB(srgb.r), EOTF_sRGB(srgb.g), EOTF_sRGB(srgb.b));
+                    }
+
+                    vec3 EOTF(const vec3 srgb) {
+                        return sign(srgb.rgb) * EOTF_sRGB(abs(srgb.rgb));
+                    }
+                )__SHADER__";
+                break;
+            case Key::INPUT_TF_ST2084:
+                fs << R"__SHADER__(
+                    vec3 EOTF(const highp vec3 color) {
+                        const highp float m1 = (2610.0 / 4096.0) / 4.0;
+                        const highp float m2 = (2523.0 / 4096.0) * 128.0;
+                        const highp float c1 = (3424.0 / 4096.0);
+                        const highp float c2 = (2413.0 / 4096.0) * 32.0;
+                        const highp float c3 = (2392.0 / 4096.0) * 32.0;
+
+                        highp vec3 tmp = pow(color, 1.0 / vec3(m2));
+                        tmp = max(tmp - c1, 0.0) / (c2 - c3 * tmp);
+                        return pow(tmp, 1.0 / vec3(m1));
+                    }
+                    )__SHADER__";
+                break;
+        }
+
+        switch (needs.getOutputTF()) {
+            case Key::OUTPUT_TF_LINEAR:
+            default:
+                fs << R"__SHADER__(
+                    vec3 OETF(const vec3 linear) {
+                        return linear;
+                    }
+                )__SHADER__";
+                break;
+            case Key::OUTPUT_TF_SRGB:
+                fs << R"__SHADER__(
+                    float OETF_sRGB(const float linear) {
+                        return linear <= 0.0031308 ?
+                                linear * 12.92 : (pow(linear, 1.0 / 2.4) * 1.055) - 0.055;
+                    }
+
+                    vec3 OETF_sRGB(const vec3 linear) {
+                        return vec3(OETF_sRGB(linear.r), OETF_sRGB(linear.g), OETF_sRGB(linear.b));
+                    }
+
+                    vec3 OETF(const vec3 linear) {
+                        return sign(linear.rgb) * OETF_sRGB(abs(linear.rgb));
+                    }
+                )__SHADER__";
+                break;
+            case Key::OUTPUT_TF_ST2084:
+                fs << R"__SHADER__(
+                    vec3 OETF(const vec3 linear) {
+                        const float m1 = (2610.0 / 4096.0) / 4.0;
+                        const float m2 = (2523.0 / 4096.0) * 128.0;
+                        const float c1 = (3424.0 / 4096.0);
+                        const float c2 = (2413.0 / 4096.0) * 32.0;
+                        const float c3 = (2392.0 / 4096.0) * 32.0;
+
+                        vec3 tmp = pow(linear, vec3(m1));
+                        tmp = (c1 + c2 * tmp) / (1.0 + c3 * tmp);
+                        return pow(tmp, vec3(m2));
+                    }
+                )__SHADER__";
+                break;
+        }
+
+        if (needs.hasToneMapping()) {
             fs << R"__SHADER__(
-                  float OETF_sRGB(const float linear) {
-                      return linear <= 0.0031308 ?
-                              linear * 12.92 : (pow(linear, 1.0 / 2.4) * 1.055) - 0.055;
-                  }
+                float ToneMapChannel(const float color) {
+                    const float maxLumi = 10000.0;
+                    const float maxMasteringLumi = 1000.0;
+                    const float maxContentLumi = 1000.0;
+                    const float maxInLumi = min(maxMasteringLumi, maxContentLumi);
+                    const float maxOutLumi = 500.0;
 
-                  vec3 OETF_sRGB(const vec3 linear) {
-                      return vec3(OETF_sRGB(linear.r), OETF_sRGB(linear.g), OETF_sRGB(linear.b));
-                  }
+                    // convert to nits first
+                    float nits = color * maxLumi;
 
-                  vec3 OETF_scRGB(const vec3 linear) {
-                      return sign(linear.rgb) * OETF_sRGB(abs(linear.rgb));
-                  }
+                    // clamp to max input luminance
+                    nits = clamp(nits, 0.0, maxInLumi);
 
-                  float EOTF_sRGB(float srgb) {
-                      return srgb <= 0.04045 ? srgb / 12.92 : pow((srgb + 0.055) / 1.055, 2.4);
-                  }
+                    // scale [0.0, maxInLumi] to [0.0, maxOutLumi]
+                    if (maxInLumi <= maxOutLumi) {
+                        nits *= maxOutLumi / maxInLumi;
+                    } else {
+                        // three control points
+                        const float x0 = 10.0;
+                        const float y0 = 17.0;
+                        const float x1 = maxOutLumi * 0.75;
+                        const float y1 = x1;
+                        const float x2 = x1 + (maxInLumi - x1) / 2.0;
+                        const float y2 = y1 + (maxOutLumi - y1) * 0.75;
 
-                  vec3 EOTF_sRGB(const vec3 srgb) {
-                      return vec3(EOTF_sRGB(srgb.r), EOTF_sRGB(srgb.g), EOTF_sRGB(srgb.b));
-                  }
+                        // horizontal distances between the last three control points
+                        const float h12 = x2 - x1;
+                        const float h23 = maxInLumi - x2;
+                        // tangents at the last three control points
+                        const float m1 = (y2 - y1) / h12;
+                        const float m3 = (maxOutLumi - y2) / h23;
+                        const float m2 = (m1 + m3) / 2.0;
 
-                  vec3 EOTF_scRGB(const vec3 srgb) {
-                      return sign(srgb.rgb) * EOTF_sRGB(abs(srgb.rgb));
-                  }
+                        if (nits < x0) {
+                            // scale [0.0, x0] to [0.0, y0] linearly
+                            const float slope = y0 / x0;
+                            nits *= slope;
+                        } else if (nits < x1) {
+                            // scale [x0, x1] to [y0, y1] linearly
+                            const float slope = (y1 - y0) / (x1 - x0);
+                            nits = y0 + (nits - x0) * slope;
+                        } else if (nits < x2) {
+                            // scale [x1, x2] to [y1, y2] using Hermite interp
+                            float t = (nits - x1) / h12;
+                            nits = (y1 * (1.0 + 2.0 * t) + h12 * m1 * t) * (1.0 - t) * (1.0 - t) +
+                                   (y2 * (3.0 - 2.0 * t) + h12 * m2 * (t - 1.0)) * t * t;
+                        } else {
+                            // scale [x2, maxInLumi] to [y2, maxOutLumi] using Hermite interp
+                            float t = (nits - x2) / h23;
+                            nits = (y2 * (1.0 + 2.0 * t) + h23 * m2 * t) * (1.0 - t) * (1.0 - t) +
+                                   (maxOutLumi * (3.0 - 2.0 * t) + h23 * m3 * (t - 1.0)) * t * t;
+                        }
+                    }
+
+                    // convert back to [0.0, 1.0]
+                    return nits / maxOutLumi;
+                }
+
+                vec3 ToneMap(const vec3 color) {
+                    return vec3(ToneMapChannel(color.r), ToneMapChannel(color.g),
+                                ToneMapChannel(color.b));
+                }
             )__SHADER__";
         } else {
             fs << R"__SHADER__(
-                  vec3 OETF_scRGB(const vec3 linear) {
-                      return linear;
-                  }
-
-                  vec3 EOTF_scRGB(const vec3 srgb) {
-                      return srgb;
-                  }
+                vec3 ToneMap(const vec3 color) {
+                    return color;
+                }
             )__SHADER__";
         }
     }
+
     fs << "void main(void) {" << indent;
     if (needs.isTexturing()) {
         fs << "gl_FragColor = texture2D(sampler, outTexCoords);";
+        if (needs.isY410BT2020()) {
+            fs << "gl_FragColor.rgb = convertY410BT2020(gl_FragColor.rgb);";
+        }
     } else {
         fs << "gl_FragColor.rgb = color.rgb;";
         fs << "gl_FragColor.a = 1.0;";
@@ -243,9 +406,12 @@
             // avoid divide by 0 by adding 0.5/256 to the alpha channel
             fs << "gl_FragColor.rgb = gl_FragColor.rgb / (gl_FragColor.a + 0.0019);";
         }
-        fs << "vec4 transformed = colorMatrix * vec4(EOTF_scRGB(gl_FragColor.rgb), 1);";
+        fs << "vec4 transformed = colorMatrix * vec4(ToneMap(EOTF(gl_FragColor.rgb)), 1);";
+        // the transformation from a wider colorspace to a narrower one can
+        // result in >1.0 or <0.0 pixel values
+        fs << "transformed.rgb = clamp(transformed.rgb, 0.0, 1.0);";
         // We assume the last row is always {0,0,0,1} and we skip the division by w
-        fs << "gl_FragColor.rgb = OETF_scRGB(transformed.rgb);";
+        fs << "gl_FragColor.rgb = OETF(transformed.rgb);";
         if (!needs.isOpaque() && needs.isPremultiplied()) {
             // and re-premultiply if needed after gamma correction
             fs << "gl_FragColor.rgb = gl_FragColor.rgb * (gl_FragColor.a + 0.0019);";
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.h b/services/surfaceflinger/RenderEngine/ProgramCache.h
index 54d3722..dcc8cc6 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.h
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.h
@@ -50,30 +50,53 @@
 
     public:
         enum {
-            BLEND_PREMULT = 0x00000001,
-            BLEND_NORMAL = 0x00000000,
-            BLEND_MASK = 0x00000001,
+            BLEND_SHIFT = 0,
+            BLEND_MASK = 1 << BLEND_SHIFT,
+            BLEND_PREMULT = 1 << BLEND_SHIFT,
+            BLEND_NORMAL = 0 << BLEND_SHIFT,
 
-            OPACITY_OPAQUE = 0x00000002,
-            OPACITY_TRANSLUCENT = 0x00000000,
-            OPACITY_MASK = 0x00000002,
+            OPACITY_SHIFT = 1,
+            OPACITY_MASK = 1 << OPACITY_SHIFT,
+            OPACITY_OPAQUE = 1 << OPACITY_SHIFT,
+            OPACITY_TRANSLUCENT = 0 << OPACITY_SHIFT,
 
-            ALPHA_LT_ONE = 0x00000004,
-            ALPHA_EQ_ONE = 0x00000000,
-            ALPHA_MASK = 0x00000004,
+            ALPHA_SHIFT = 2,
+            ALPHA_MASK = 1 << ALPHA_SHIFT,
+            ALPHA_LT_ONE = 1 << ALPHA_SHIFT,
+            ALPHA_EQ_ONE = 0 << ALPHA_SHIFT,
 
-            TEXTURE_OFF = 0x00000000,
-            TEXTURE_EXT = 0x00000008,
-            TEXTURE_2D = 0x00000010,
-            TEXTURE_MASK = 0x00000018,
+            TEXTURE_SHIFT = 3,
+            TEXTURE_MASK = 3 << TEXTURE_SHIFT,
+            TEXTURE_OFF = 0 << TEXTURE_SHIFT,
+            TEXTURE_EXT = 1 << TEXTURE_SHIFT,
+            TEXTURE_2D = 2 << TEXTURE_SHIFT,
 
-            COLOR_MATRIX_OFF = 0x00000000,
-            COLOR_MATRIX_ON = 0x00000020,
-            COLOR_MATRIX_MASK = 0x00000020,
+            COLOR_MATRIX_SHIFT = 5,
+            COLOR_MATRIX_MASK = 1 << COLOR_MATRIX_SHIFT,
+            COLOR_MATRIX_OFF = 0 << COLOR_MATRIX_SHIFT,
+            COLOR_MATRIX_ON = 1 << COLOR_MATRIX_SHIFT,
 
-            WIDE_GAMUT_OFF = 0x00000000,
-            WIDE_GAMUT_ON = 0x00000040,
-            WIDE_GAMUT_MASK = 0x00000040,
+            INPUT_TF_SHIFT = 6,
+            INPUT_TF_MASK = 3 << INPUT_TF_SHIFT,
+            INPUT_TF_LINEAR = 0 << INPUT_TF_SHIFT,
+            INPUT_TF_SRGB = 1 << INPUT_TF_SHIFT,
+            INPUT_TF_ST2084 = 2 << INPUT_TF_SHIFT,
+
+            OUTPUT_TF_SHIFT = 8,
+            OUTPUT_TF_MASK = 3 << OUTPUT_TF_SHIFT,
+            OUTPUT_TF_LINEAR = 0 << OUTPUT_TF_SHIFT,
+            OUTPUT_TF_SRGB = 1 << OUTPUT_TF_SHIFT,
+            OUTPUT_TF_ST2084 = 2 << OUTPUT_TF_SHIFT,
+
+            TONE_MAPPING_SHIFT = 10,
+            TONE_MAPPING_MASK = 1 << TONE_MAPPING_SHIFT,
+            TONE_MAPPING_OFF = 0 << TONE_MAPPING_SHIFT,
+            TONE_MAPPING_ON = 1 << TONE_MAPPING_SHIFT,
+
+            Y410_BT2020_SHIFT = 11,
+            Y410_BT2020_MASK = 1 << Y410_BT2020_SHIFT,
+            Y410_BT2020_OFF = 0 << Y410_BT2020_SHIFT,
+            Y410_BT2020_ON = 1 << Y410_BT2020_SHIFT,
         };
 
         inline Key() : mKey(0) {}
@@ -90,7 +113,10 @@
         inline bool isOpaque() const { return (mKey & OPACITY_MASK) == OPACITY_OPAQUE; }
         inline bool hasAlpha() const { return (mKey & ALPHA_MASK) == ALPHA_LT_ONE; }
         inline bool hasColorMatrix() const { return (mKey & COLOR_MATRIX_MASK) == COLOR_MATRIX_ON; }
-        inline bool isWideGamut() const { return (mKey & WIDE_GAMUT_MASK) == WIDE_GAMUT_ON; }
+        inline int getInputTF() const { return (mKey & INPUT_TF_MASK); }
+        inline int getOutputTF() const { return (mKey & OUTPUT_TF_MASK); }
+        inline bool hasToneMapping() const { return (mKey & TONE_MAPPING_MASK) == TONE_MAPPING_ON; }
+        inline bool isY410BT2020() const { return (mKey & Y410_BT2020_MASK) == Y410_BT2020_ON; }
 
         // this is the definition of a friend function -- not a method of class Needs
         friend inline int strictly_order_type(const Key& lhs, const Key& rhs) {
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 737b1dd..67c0d1c 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -138,6 +138,7 @@
                                     const half4& color) = 0;
     virtual void setColorMode(android_color_mode mode) = 0;
     virtual void setSourceDataSpace(android_dataspace source) = 0;
+    virtual void setSourceY410BT2020(bool enable) = 0;
     virtual void setWideColor(bool hasWideColor) = 0;
     virtual bool usesWideColor() = 0;
     virtual void setupLayerTexturing(const Texture& texture) = 0;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a91525d..974a261 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1041,7 +1041,19 @@
     std::unique_ptr<HdrCapabilities> capabilities =
             getBE().mHwc->getHdrCapabilities(displayDevice->getHwcDisplayId());
     if (capabilities) {
-        std::swap(*outCapabilities, *capabilities);
+        if (displayDevice->getWideColorSupport() && !displayDevice->getHdrSupport()) {
+            // insert HDR10 as we will force client composition for HDR10
+            // layers
+            std::vector<int32_t> types = capabilities->getSupportedHdrTypes();
+            types.push_back(HAL_HDR_HDR10);
+
+            *outCapabilities = HdrCapabilities(types,
+                    capabilities->getDesiredMaxLuminance(),
+                    capabilities->getDesiredMaxAverageLuminance(),
+                    capabilities->getDesiredMinLuminance());
+        } else {
+            *outCapabilities = std::move(*capabilities);
+        }
     } else {
         return BAD_VALUE;
     }
@@ -1793,7 +1805,7 @@
 }
 
 android_dataspace SurfaceFlinger::bestTargetDataSpace(
-        android_dataspace a, android_dataspace b) const {
+        android_dataspace a, android_dataspace b, bool hasHdr) const {
     // Only support sRGB and Display-P3 right now.
     if (a == HAL_DATASPACE_DISPLAY_P3 || b == HAL_DATASPACE_DISPLAY_P3) {
         return HAL_DATASPACE_DISPLAY_P3;
@@ -1804,6 +1816,9 @@
     if (a == HAL_DATASPACE_V0_SCRGB || b == HAL_DATASPACE_V0_SCRGB) {
         return HAL_DATASPACE_DISPLAY_P3;
     }
+    if (!hasHdr && (a == HAL_DATASPACE_BT2020_PQ || b == HAL_DATASPACE_BT2020_PQ)) {
+        return HAL_DATASPACE_DISPLAY_P3;
+    }
 
     return HAL_DATASPACE_V0_SRGB;
 }
@@ -1885,6 +1900,11 @@
                     "display %zd: %d", displayId, result);
         }
         for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+            if (layer->getDataSpace() == HAL_DATASPACE_BT2020_PQ &&
+                    !displayDevice->getHdrSupport()) {
+                layer->forceClientComposition(hwcId);
+            }
+
             if (layer->getForceClientComposition(hwcId)) {
                 ALOGV("[%s] Requesting Client composition", layer->getName().string());
                 layer->setCompositionType(hwcId, HWC2::Composition::Client);
@@ -1899,7 +1919,8 @@
             android_dataspace newDataSpace = HAL_DATASPACE_V0_SRGB;
 
             for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
-                newDataSpace = bestTargetDataSpace(layer->getDataSpace(), newDataSpace);
+                newDataSpace = bestTargetDataSpace(layer->getDataSpace(), newDataSpace,
+                        displayDevice->getHdrSupport());
                 ALOGV("layer: %s, dataspace: %s (%#x), newDataSpace: %s (%#x)",
                       layer->getName().string(), dataspaceDetails(layer->getDataSpace()).c_str(),
                       layer->getDataSpace(), dataspaceDetails(newDataSpace).c_str(), newDataSpace);
@@ -2253,9 +2274,19 @@
                         useWideColorMode = hasWideColorModes && hasWideColorDisplay;
                     }
 
+                    bool hasHdrSupport = false;
+                    std::unique_ptr<HdrCapabilities> hdrCapabilities =
+                        getHwComposer().getHdrCapabilities(state.type);
+                    if (hdrCapabilities) {
+                        const std::vector<int32_t> types = hdrCapabilities->getSupportedHdrTypes();
+                        auto iter = std::find(types.cbegin(), types.cend(), HAL_HDR_HDR10);
+                        hasHdrSupport = iter != types.cend();
+                    }
+
                     sp<DisplayDevice> hw =
                             new DisplayDevice(this, state.type, hwcId, state.isSecure, display,
-                                              dispSurface, producer, useWideColorMode);
+                                              dispSurface, producer, useWideColorMode,
+                                              hasHdrSupport);
 
                     android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE;
                     if (useWideColorMode) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 4da0803..1349bec 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -607,7 +607,8 @@
     // Given a dataSpace, returns the appropriate color_mode to use
     // to display that dataSpace.
     android_color_mode pickColorMode(android_dataspace dataSpace) const;
-    android_dataspace bestTargetDataSpace(android_dataspace a, android_dataspace b) const;
+    android_dataspace bestTargetDataSpace(android_dataspace a, android_dataspace b,
+            bool hasHdr) const;
 
     mat4 computeSaturationMatrix() const;
 
diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp
index 47c4f4a..eeb0f54 100644
--- a/services/surfaceflinger/tests/fakehwc/Android.bp
+++ b/services/surfaceflinger/tests/fakehwc/Android.bp
@@ -31,6 +31,9 @@
         "libtrace_proto",
         "libgmock"
     ],
+    header_libs: [
+        "android.hardware.graphics.composer@2.1-command-buffer",
+    ],
     cppflags: [
         "-std=c++1z",
     ],
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index 76ec42d..063d83c 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -32,6 +32,10 @@
     "libutils",
   ],
 
+  header_libs: [
+    "android.hardware.graphics.composer@2.1-command-buffer",
+  ],
+
   export_static_lib_headers: [
     "libhwcomposer-client",
   ],
diff --git a/services/vr/hardware_composer/impl/vr_composer_client.h b/services/vr/hardware_composer/impl/vr_composer_client.h
index dfc656a..63ee86f 100644
--- a/services/vr/hardware_composer/impl/vr_composer_client.h
+++ b/services/vr/hardware_composer/impl/vr_composer_client.h
@@ -17,9 +17,9 @@
 #ifndef ANDROID_DVR_HARDWARE_COMPOSER_IMPL_VR_COMPOSER_CLIENT_H
 #define ANDROID_DVR_HARDWARE_COMPOSER_IMPL_VR_COMPOSER_CLIENT_H
 
-#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
 #include <ComposerClient.h>
-#include <IComposerCommandBuffer.h>
+#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
+#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
 
 namespace android {
 namespace dvr {