Merge "Added the ability to read external batteries" into sc-dev
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 65fc46e..4dfd1d0 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -1130,23 +1130,6 @@
     return true;
 }
 
-// Updates the access times of out_oat_path based on those from apk_path.
-void update_out_oat_access_times(const char* apk_path, const char* out_oat_path) {
-    struct stat input_stat;
-    memset(&input_stat, 0, sizeof(input_stat));
-    if (stat(apk_path, &input_stat) != 0) {
-        PLOG(ERROR) << "Could not stat " << apk_path << " during dexopt";
-        return;
-    }
-
-    struct utimbuf ut;
-    ut.actime = input_stat.st_atime;
-    ut.modtime = input_stat.st_mtime;
-    if (utime(out_oat_path, &ut) != 0) {
-        PLOG(WARNING) << "Could not update access times for " << apk_path << " during dexopt";
-    }
-}
-
 // Runs (execv) dexoptanalyzer on the given arguments.
 // The analyzer will check if the dex_file needs to be (re)compiled to match the compiler_filter.
 // If this is for a profile guided compilation, profile_was_updated will tell whether or not
@@ -1843,8 +1826,6 @@
         }
     }
 
-    update_out_oat_access_times(dex_path, out_oat.path().c_str());
-
     // We've been successful, don't delete output.
     out_oat.DisableCleanup();
     out_vdex.DisableCleanup();
diff --git a/data/etc/car_core_hardware.xml b/data/etc/car_core_hardware.xml
index cc0ee82..adfd6e2 100644
--- a/data/etc/car_core_hardware.xml
+++ b/data/etc/car_core_hardware.xml
@@ -47,6 +47,12 @@
     <feature name="android.software.secure_lock_screen" />
     <feature name="android.software.input_methods" />
 
+
+    <!-- Feature to support device admins -->
+    <!-- TODO(b/178412797): not fully supported yet, CTS tests are still
+         failing. -->
+    <feature name="android.software.device_admin" />
+
     <!-- devices with GPS must include android.hardware.location.gps.xml -->
     <!-- devices with an autofocus camera and/or flash must include either
          android.hardware.camera.autofocus.xml or
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 454fbd0..3c90681 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -597,13 +597,6 @@
         return STATUS_INVALID_OPERATION;
     }
 
-    if (!binder->isRemote()) {
-        LOG(WARNING) << "A binder object at " << binder
-                     << " is being transacted on, however, this object is in the same process as "
-                        "its proxy. Transacting with this binder is expensive compared to just "
-                        "calling the corresponding functionality in the same process.";
-    }
-
     *in = new AParcel(binder);
     status_t status = (*in)->get()->writeInterfaceToken(clazz->getInterfaceDescriptor());
     binder_status_t ret = PruneStatusT(status);
diff --git a/libs/binder/rust/tests/serialization.rs b/libs/binder/rust/tests/serialization.rs
index 2ae13f4..2bf3d03 100644
--- a/libs/binder/rust/tests/serialization.rs
+++ b/libs/binder/rust/tests/serialization.rs
@@ -25,7 +25,6 @@
 use binder::parcel::ParcelFileDescriptor;
 
 use std::ffi::{c_void, CStr, CString};
-use std::panic::{self, AssertUnwindSafe};
 use std::sync::Once;
 
 #[allow(
@@ -73,22 +72,9 @@
 
 impl ReadParcelTest for () {}
 
-fn on_transact(
-    _service: &dyn ReadParcelTest,
-    code: TransactionCode,
-    parcel: &Parcel,
-    reply: &mut Parcel,
-) -> Result<()> {
-    panic::catch_unwind(AssertUnwindSafe(|| transact_inner(code, parcel, reply))).unwrap_or_else(
-        |e| {
-            eprintln!("Failure in Rust: {:?}", e.downcast_ref::<String>());
-            Err(StatusCode::FAILED_TRANSACTION)
-        },
-    )
-}
-
 #[allow(clippy::float_cmp)]
-fn transact_inner(code: TransactionCode, parcel: &Parcel, reply: &mut Parcel) -> Result<()> {
+fn on_transact(_service: &dyn ReadParcelTest, code: TransactionCode,
+               parcel: &Parcel, reply: &mut Parcel) -> Result<()> {
     match code {
         bindings::Transaction_TEST_BOOL => {
             assert_eq!(parcel.read::<bool>()?, true);
@@ -296,7 +282,7 @@
             ))?;
         }
         bindings::Transaction_TEST_FAIL => {
-            panic!("Testing expected failure");
+            return Err(StatusCode::FAILED_TRANSACTION)
         }
         _ => return Err(StatusCode::UNKNOWN_TRANSACTION),
     }
diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp
index c6c9a8f..2ad484a 100644
--- a/libs/gui/DisplayEventDispatcher.cpp
+++ b/libs/gui/DisplayEventDispatcher.cpp
@@ -36,7 +36,9 @@
 DisplayEventDispatcher::DisplayEventDispatcher(
         const sp<Looper>& looper, ISurfaceComposer::VsyncSource vsyncSource,
         ISurfaceComposer::EventRegistrationFlags eventRegistration)
-      : mLooper(looper), mReceiver(vsyncSource, eventRegistration), mWaitingForVsync(false) {
+      : mLooper(looper),
+        mReceiver(vsyncSource, eventRegistration),
+        mVsyncState(VsyncState::Unregistered) {
     ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
 }
 
@@ -66,26 +68,37 @@
 }
 
 status_t DisplayEventDispatcher::scheduleVsync() {
-    if (!mWaitingForVsync) {
-        ALOGV("dispatcher %p ~ Scheduling vsync.", this);
+    switch (mVsyncState) {
+        case VsyncState::Unregistered: {
+            ALOGV("dispatcher %p ~ Scheduling vsync.", this);
 
-        // Drain all pending events.
-        nsecs_t vsyncTimestamp;
-        PhysicalDisplayId vsyncDisplayId;
-        uint32_t vsyncCount;
-        VsyncEventData vsyncEventData;
-        if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) {
-            ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "", this,
-                  ns2ms(static_cast<nsecs_t>(vsyncTimestamp)));
+            // Drain all pending events.
+            nsecs_t vsyncTimestamp;
+            PhysicalDisplayId vsyncDisplayId;
+            uint32_t vsyncCount;
+            VsyncEventData vsyncEventData;
+            if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount,
+                                     &vsyncEventData)) {
+                ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "",
+                      this, ns2ms(static_cast<nsecs_t>(vsyncTimestamp)));
+            }
+
+            status_t status = mReceiver.setVsyncRate(1);
+            if (status) {
+                ALOGW("Failed to set vsync rate, status=%d", status);
+                return status;
+            }
+
+            mVsyncState = VsyncState::RegisteredAndWaitingForVsync;
+            break;
         }
-
-        status_t status = mReceiver.requestNextVsync();
-        if (status) {
-            ALOGW("Failed to request next vsync, status=%d", status);
-            return status;
+        case VsyncState::Registered: {
+            mVsyncState = VsyncState::RegisteredAndWaitingForVsync;
+            break;
         }
-
-        mWaitingForVsync = true;
+        case VsyncState::RegisteredAndWaitingForVsync: {
+            break;
+        }
     }
     return OK;
 }
@@ -123,8 +136,23 @@
               ", displayId=%s, count=%d, vsyncId=%" PRId64,
               this, ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount,
               vsyncEventData.id);
-        mWaitingForVsync = false;
-        dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData);
+        switch (mVsyncState) {
+            case VsyncState::Unregistered:
+                ALOGW("Received unexpected VSYNC event");
+                break;
+            case VsyncState::RegisteredAndWaitingForVsync:
+                mVsyncState = VsyncState::Registered;
+                dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData);
+                break;
+            case VsyncState::Registered:
+                status_t status = mReceiver.setVsyncRate(0);
+                if (status) {
+                    ALOGW("Failed to reset vsync rate, status=%d", status);
+                    return status;
+                }
+                mVsyncState = VsyncState::Unregistered;
+                break;
+        }
     }
 
     return 1; // keep the callback
diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h
index f446dd8..4175a49 100644
--- a/libs/gui/include/gui/DisplayEventDispatcher.h
+++ b/libs/gui/include/gui/DisplayEventDispatcher.h
@@ -52,7 +52,20 @@
 private:
     sp<Looper> mLooper;
     DisplayEventReceiver mReceiver;
-    bool mWaitingForVsync;
+    // The state of vsync event registration and whether the client is expecting
+    // an event or not.
+    enum class VsyncState {
+        // The dispatcher is not registered for vsync events.
+        Unregistered,
+        // The dispatcher is registered to receive vsync events but should not dispatch it to the
+        // client as the client is not expecting a vsync event.
+        Registered,
+
+        // The dispatcher is registered to receive vsync events and supposed to dispatch it to
+        // the client.
+        RegisteredAndWaitingForVsync,
+    };
+    VsyncState mVsyncState;
 
     std::vector<FrameRateOverride> mFrameRateOverrides;
 
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index c12a7b1..f90c130 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -303,6 +303,10 @@
     std::lock_guard<std::mutex> lock(mMutex);
 
     const auto request = rate == 0 ? VSyncRequest::None : static_cast<VSyncRequest>(rate);
+    if (request != VSyncRequest::None && connection->resyncCallback) {
+        connection->resyncCallback();
+    }
+
     if (connection->vsyncRequest != request) {
         connection->vsyncRequest = request;
         mCondition.notify_all();