Merge "dumpstate: fix retention of CAP_SYSLOG after dropping root" into main
diff --git a/Android.bp b/Android.bp
index 2520a71..119c7ea 100644
--- a/Android.bp
+++ b/Android.bp
@@ -119,3 +119,9 @@
srcs: ["aidl/android/hardware/display/IDeviceProductInfoConstants.aidl"],
path: "aidl",
}
+
+dirgroup {
+ name: "trusty_dirgroup_frameworks_native",
+ dirs: ["libs/binder"],
+ visibility: ["//trusty/vendor/google/aosp/scripts"],
+}
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index eae844c..3758b65 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -197,7 +197,9 @@
&& currentValue < sBinderProxyCountHighWatermark
&& ((trackedValue & WARNING_REACHED_MASK) == 0)) [[unlikely]] {
sTrackingMap[trackedUid] |= WARNING_REACHED_MASK;
- if (sWarningCallback) sWarningCallback(trackedUid);
+ if (sWarningCallback) {
+ *postTask = [=]() { sWarningCallback(trackedUid); };
+ }
} else if (currentValue >= sBinderProxyCountHighWatermark) {
ALOGE("Too many binder proxy objects sent to uid %d from uid %d (%d proxies held)",
getuid(), trackedUid, trackedValue);
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
index 95a5da2..ab44957 100644
--- a/libs/binder/TEST_MAPPING
+++ b/libs/binder/TEST_MAPPING
@@ -94,6 +94,9 @@
},
{
"name": "libbinder_rpc_unstable_bindgen_test"
+ },
+ {
+ "name": "binderCacheUnitTest"
}
],
"presubmit-large": [
@@ -133,9 +136,6 @@
{
"name": "binder_sdk_test",
"host": true
- },
- {
- "name": "binderCacheUnitTest"
}
],
"imports": [
diff --git a/libs/binder/aidl/android/content/pm/ApexStagedEvent.aidl b/libs/binder/aidl/android/content/pm/ApexStagedEvent.aidl
index 75f8753..9bac386 100644
--- a/libs/binder/aidl/android/content/pm/ApexStagedEvent.aidl
+++ b/libs/binder/aidl/android/content/pm/ApexStagedEvent.aidl
@@ -16,6 +16,8 @@
package android.content.pm;
+import android.content.pm.StagedApexInfo;
+
/**
* This event is designed for notification to native code listener about
* any changes to set of apex packages staged for installation on next boot.
@@ -23,5 +25,5 @@
* @hide
*/
parcelable ApexStagedEvent {
- @utf8InCpp String[] stagedApexModuleNames;
+ StagedApexInfo[] stagedApexInfos;
}
diff --git a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
index 3ddfefa..0f0be2f 100644
--- a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
+++ b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
@@ -135,13 +135,7 @@
void unregisterStagedApexObserver(in IStagedApexObserver observer);
/**
- * Get APEX module names of all APEX that are staged ready for installation
+ * Get information of staged APEXes.
*/
- @utf8InCpp String[] getStagedApexModuleNames();
-
- /**
- * Get information of APEX which is staged ready for installation.
- * Returns null if no such APEX is found.
- */
- @nullable StagedApexInfo getStagedApexInfo(in @utf8InCpp String moduleName);
+ StagedApexInfo[] getStagedApexInfos();
}
diff --git a/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl b/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl
index 949835b..8f7ad30 100644
--- a/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl
+++ b/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl
@@ -22,6 +22,7 @@
*
* @hide
*/
+@JavaDerive(equals=true)
parcelable StagedApexInfo {
@utf8InCpp String moduleName;
@utf8InCpp String diskImagePath;
diff --git a/libs/binder/include/binder/SafeInterface.h b/libs/binder/include/binder/SafeInterface.h
index c671eed..0b4f196 100644
--- a/libs/binder/include/binder/SafeInterface.h
+++ b/libs/binder/include/binder/SafeInterface.h
@@ -152,6 +152,14 @@
return callParcel("writeParcelableVector",
[&]() { return parcel->writeParcelableVector(v); });
}
+
+ status_t read(const Parcel& parcel, std::vector<bool>* v) const {
+ return callParcel("readBoolVector", [&]() { return parcel.readBoolVector(v); });
+ }
+ status_t write(Parcel* parcel, const std::vector<bool>& v) const {
+ return callParcel("writeBoolVector", [&]() { return parcel->writeBoolVector(v); });
+ }
+
status_t read(const Parcel& parcel, float* f) const {
return callParcel("readFloat", [&]() { return parcel.readFloat(f); });
}
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 8b0dda3..28a3f65 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -731,6 +731,9 @@
"liblog",
"libutils",
],
+ static_libs: [
+ "libgmock",
+ ],
test_suites: [
"general-tests",
"vts",
diff --git a/libs/binder/tests/binderSafeInterfaceTest.cpp b/libs/binder/tests/binderSafeInterfaceTest.cpp
index 0aa678d..849dc7c 100644
--- a/libs/binder/tests/binderSafeInterfaceTest.cpp
+++ b/libs/binder/tests/binderSafeInterfaceTest.cpp
@@ -40,6 +40,8 @@
#include <sys/eventfd.h>
#include <sys/prctl.h>
+#include <gmock/gmock.h>
+
using namespace std::chrono_literals; // NOLINT - google-build-using-namespace
using android::binder::unique_fd;
@@ -222,6 +224,7 @@
SetDeathToken = IBinder::FIRST_CALL_TRANSACTION,
ReturnsNoMemory,
LogicalNot,
+ LogicalNotVector,
ModifyEnum,
IncrementFlattenable,
IncrementLightFlattenable,
@@ -249,6 +252,7 @@
// These are ordered according to their corresponding methods in SafeInterface::ParcelHandler
virtual status_t logicalNot(bool a, bool* notA) const = 0;
+ virtual status_t logicalNot(const std::vector<bool>& a, std::vector<bool>* notA) const = 0;
virtual status_t modifyEnum(TestEnum a, TestEnum* b) const = 0;
virtual status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const = 0;
virtual status_t increment(const TestLightFlattenable& a,
@@ -288,7 +292,14 @@
}
status_t logicalNot(bool a, bool* notA) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
- return callRemote<decltype(&ISafeInterfaceTest::logicalNot)>(Tag::LogicalNot, a, notA);
+ using Signature = status_t (ISafeInterfaceTest::*)(bool, bool*) const;
+ return callRemote<Signature>(Tag::LogicalNot, a, notA);
+ }
+ status_t logicalNot(const std::vector<bool>& a, std::vector<bool>* notA) const override {
+ ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+ using Signature = status_t (ISafeInterfaceTest::*)(const std::vector<bool>&,
+ std::vector<bool>*) const;
+ return callRemote<Signature>(Tag::LogicalNotVector, a, notA);
}
status_t modifyEnum(TestEnum a, TestEnum* b) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
@@ -406,6 +417,14 @@
*notA = !a;
return NO_ERROR;
}
+ status_t logicalNot(const std::vector<bool>& a, std::vector<bool>* notA) const override {
+ ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+ notA->clear();
+ for (bool value : a) {
+ notA->push_back(!value);
+ }
+ return NO_ERROR;
+ }
status_t modifyEnum(TestEnum a, TestEnum* b) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
*b = (a == TestEnum::INITIAL) ? TestEnum::FINAL : TestEnum::INVALID;
@@ -513,7 +532,13 @@
return callLocal(data, reply, &ISafeInterfaceTest::returnsNoMemory);
}
case ISafeInterfaceTest::Tag::LogicalNot: {
- return callLocal(data, reply, &ISafeInterfaceTest::logicalNot);
+ using Signature = status_t (ISafeInterfaceTest::*)(bool a, bool* notA) const;
+ return callLocal<Signature>(data, reply, &ISafeInterfaceTest::logicalNot);
+ }
+ case ISafeInterfaceTest::Tag::LogicalNotVector: {
+ using Signature = status_t (ISafeInterfaceTest::*)(const std::vector<bool>& a,
+ std::vector<bool>* notA) const;
+ return callLocal<Signature>(data, reply, &ISafeInterfaceTest::logicalNot);
}
case ISafeInterfaceTest::Tag::ModifyEnum: {
return callLocal(data, reply, &ISafeInterfaceTest::modifyEnum);
@@ -639,6 +664,15 @@
ASSERT_EQ(!b, notB);
}
+TEST_F(SafeInterfaceTest, TestLogicalNotVector) {
+ const std::vector<bool> a = {true, false, true};
+ std::vector<bool> notA;
+ status_t result = mSafeInterfaceTest->logicalNot(a, ¬A);
+ ASSERT_EQ(NO_ERROR, result);
+ std::vector<bool> expected = {false, true, false};
+ ASSERT_THAT(notA, testing::ContainerEq(expected));
+}
+
TEST_F(SafeInterfaceTest, TestModifyEnum) {
const TestEnum a = TestEnum::INITIAL;
TestEnum b = TestEnum::INVALID;
diff --git a/libs/gui/tests/BufferItemConsumer_test.cpp b/libs/gui/tests/BufferItemConsumer_test.cpp
index 6880678..6564534 100644
--- a/libs/gui/tests/BufferItemConsumer_test.cpp
+++ b/libs/gui/tests/BufferItemConsumer_test.cpp
@@ -28,6 +28,7 @@
static constexpr int kHeight = 100;
static constexpr int kMaxLockedBuffers = 3;
static constexpr int kFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+static constexpr int kUsage = GRALLOC_USAGE_SW_READ_RARELY;
static constexpr int kFrameSleepUs = 30 * 1000;
class BufferItemConsumerTest : public ::testing::Test {
@@ -44,8 +45,7 @@
void SetUp() override {
BufferQueue::createBufferQueue(&mProducer, &mConsumer);
- mBIC =
- new BufferItemConsumer(mConsumer, kFormat, kMaxLockedBuffers, true);
+ mBIC = new BufferItemConsumer(mConsumer, kUsage, kMaxLockedBuffers, true);
String8 name("BufferItemConsumer_Under_Test");
mBIC->setName(name);
mBFL = new BufferFreedListener(this);
diff --git a/libs/nativewindow/rust/src/lib.rs b/libs/nativewindow/rust/src/lib.rs
index 931c311..f19b908 100644
--- a/libs/nativewindow/rust/src/lib.rs
+++ b/libs/nativewindow/rust/src/lib.rs
@@ -19,10 +19,9 @@
mod handle;
mod surface;
-pub use handle::NativeHandle;
-pub use surface::Surface;
-
pub use ffi::{AHardwareBuffer_Format, AHardwareBuffer_UsageFlags};
+pub use handle::NativeHandle;
+pub use surface::{buffer::Buffer, Surface};
use binder::{
binder_impl::{BorrowedParcel, UnstructuredParcelable},
diff --git a/libs/nativewindow/rust/src/surface.rs b/libs/nativewindow/rust/src/surface.rs
index 9eddfcd..ed52471 100644
--- a/libs/nativewindow/rust/src/surface.rs
+++ b/libs/nativewindow/rust/src/surface.rs
@@ -14,6 +14,8 @@
//! Rust wrapper for `ANativeWindow` and related types.
+pub(crate) mod buffer;
+
use binder::{
binder_impl::{BorrowedParcel, UnstructuredParcelable},
impl_deserialize_for_unstructured_parcelable, impl_serialize_for_unstructured_parcelable,
@@ -21,17 +23,18 @@
StatusCode,
};
use bitflags::bitflags;
+use buffer::Buffer;
use nativewindow_bindgen::{
ADataSpace, AHardwareBuffer_Format, ANativeWindow, ANativeWindow_acquire,
ANativeWindow_getBuffersDataSpace, ANativeWindow_getBuffersDefaultDataSpace,
- ANativeWindow_getFormat, ANativeWindow_getHeight, ANativeWindow_getWidth,
+ ANativeWindow_getFormat, ANativeWindow_getHeight, ANativeWindow_getWidth, ANativeWindow_lock,
ANativeWindow_readFromParcel, ANativeWindow_release, ANativeWindow_setBuffersDataSpace,
ANativeWindow_setBuffersGeometry, ANativeWindow_setBuffersTransform,
- ANativeWindow_writeToParcel,
+ ANativeWindow_unlockAndPost, ANativeWindow_writeToParcel, ARect,
};
use std::error::Error;
use std::fmt::{self, Debug, Display, Formatter};
-use std::ptr::{null_mut, NonNull};
+use std::ptr::{self, null_mut, NonNull};
/// Wrapper around an opaque C `ANativeWindow`.
#[derive(PartialEq, Eq)]
@@ -153,6 +156,43 @@
Ok(ADataSpace(data_space))
}
}
+
+ /// Locks the window's next drawing surface for writing, and returns it.
+ pub fn lock(&mut self, bounds: Option<&mut ARect>) -> Result<Buffer, ErrorCode> {
+ let mut buffer = buffer::EMPTY;
+ // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because
+ // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel`
+ // and we have not yet released it. The other pointers must be valid because the come from
+ // references, and aren't retained after the function returns.
+ let status = unsafe {
+ ANativeWindow_lock(
+ self.0.as_ptr(),
+ &mut buffer,
+ bounds.map(ptr::from_mut).unwrap_or(null_mut()),
+ )
+ };
+ if status != 0 {
+ return Err(ErrorCode(status));
+ }
+
+ Ok(Buffer::new(buffer, self))
+ }
+
+ /// Unlocks the window's drawing surface which was previously locked, posting the new buffer to
+ /// the display.
+ ///
+ /// This shouldn't be called directly but via the [`Buffer`], hence is not public here.
+ fn unlock_and_post(&mut self) -> Result<(), ErrorCode> {
+ // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because
+ // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel`
+ // and we have not yet released it.
+ let status = unsafe { ANativeWindow_unlockAndPost(self.0.as_ptr()) };
+ if status == 0 {
+ Ok(())
+ } else {
+ Err(ErrorCode(status))
+ }
+ }
}
impl Drop for Surface {
diff --git a/libs/nativewindow/rust/src/surface/buffer.rs b/libs/nativewindow/rust/src/surface/buffer.rs
new file mode 100644
index 0000000..a2d74d4
--- /dev/null
+++ b/libs/nativewindow/rust/src/surface/buffer.rs
@@ -0,0 +1,68 @@
+// Copyright (C) 2024 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.
+
+use super::{ErrorCode, Surface};
+use nativewindow_bindgen::{AHardwareBuffer_Format, ANativeWindow_Buffer};
+use std::ptr::null_mut;
+
+/// An empty `ANativeWindow_Buffer`.
+pub const EMPTY: ANativeWindow_Buffer = ANativeWindow_Buffer {
+ width: 0,
+ height: 0,
+ stride: 0,
+ format: 0,
+ bits: null_mut(),
+ reserved: [0; 6],
+};
+
+/// Rust wrapper for `ANativeWindow_Buffer`, representing a locked buffer from a [`Surface`].
+pub struct Buffer<'a> {
+ /// The wrapped `ANativeWindow_Buffer`.
+ pub buffer: ANativeWindow_Buffer,
+ surface: &'a mut Surface,
+}
+
+impl<'a> Buffer<'a> {
+ pub(crate) fn new(buffer: ANativeWindow_Buffer, surface: &'a mut Surface) -> Self {
+ Self { buffer, surface }
+ }
+
+ /// Unlocks the window's drawing surface which was previously locked to create this buffer,
+ /// posting the buffer to the display.
+ pub fn unlock_and_post(self) -> Result<(), ErrorCode> {
+ self.surface.unlock_and_post()
+ }
+
+ /// The number of pixels that are shown horizontally.
+ pub fn width(&self) -> i32 {
+ self.buffer.width
+ }
+
+ /// The number of pixels that are shown vertically.
+ pub fn height(&self) -> i32 {
+ self.buffer.height
+ }
+
+ /// The number of pixels that a line in the buffer takes in memory.
+ ///
+ /// This may be greater than the width.
+ pub fn stride(&self) -> i32 {
+ self.buffer.stride
+ }
+
+ /// The pixel format of the buffer.
+ pub fn format(&self) -> Result<AHardwareBuffer_Format::Type, ErrorCode> {
+ self.buffer.format.try_into().map_err(|_| ErrorCode(self.buffer.format))
+ }
+}
diff --git a/services/stats/Android.bp b/services/stats/Android.bp
index 6b99627..f698515 100644
--- a/services/stats/Android.bp
+++ b/services/stats/Android.bp
@@ -7,6 +7,11 @@
default_applicable_licenses: ["frameworks_native_license"],
}
+vintf_fragment {
+ name: "android.frameworks.stats-service.xml",
+ src: "android.frameworks.stats-service.xml",
+}
+
cc_library_shared {
name: "libstatshidl",
srcs: [
@@ -38,7 +43,7 @@
local_include_dirs: [
"include/stats",
],
- vintf_fragments: [
+ vintf_fragment_modules: [
"android.frameworks.stats-service.xml",
],
}
diff --git a/vulkan/vkjson/vkjson.cc b/vulkan/vkjson/vkjson.cc
index 0284192..bfb7bd6 100644
--- a/vulkan/vkjson/vkjson.cc
+++ b/vulkan/vkjson/vkjson.cc
@@ -1169,7 +1169,7 @@
return array;
}
-template <typename T, unsigned int N>
+template <typename T, size_t N>
inline Json::Value ToJsonValue(const T (&value)[N]) {
return ArrayToJsonValue(N, value);
}
@@ -1293,7 +1293,7 @@
return true;
}
-template <typename T, unsigned int N>
+template <typename T, size_t N>
inline bool AsValue(Json::Value* json_value, T (*value)[N]) {
return AsArray(json_value, N, *value);
}