Merge "Added logic for ACC properties to return NOT_AVAILABLE in standard CC." into main
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 1eca2a1..2e9d9ab 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -85,3 +85,4 @@
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.cas@1.1*)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/vintf/manifest/android.hardware.cas@1.1*)
$(call add-clean-step, rm -rf $(OUT_DIR)/soong/.intermediates/hardware/interfaces/wifi/1.4/android.hardware.wifi@1.4-adapter_genc++/)
+$(call add-clean-step, rm -rf $(OUT_DIR)/soong/.intermediates/hardware/interfaces/automotive/vehicle/aidl/android.hardware.automotive.vehicle-V2-ndk-source/)
diff --git a/apexkey/Android.bp b/apexkey/Android.bp
new file mode 100644
index 0000000..e74717a
--- /dev/null
+++ b/apexkey/Android.bp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+apex_key {
+ name: "com.android.hardware.key",
+ public_key: "com.android.hardware.avbpubkey",
+ private_key: "com.android.hardware.pem",
+}
+
+android_app_certificate {
+ name: "com.android.hardware.certificate",
+ certificate: "com.android.hardware",
+}
diff --git a/apexkey/com.android.hardware.avbpubkey b/apexkey/com.android.hardware.avbpubkey
new file mode 100644
index 0000000..12f0370
--- /dev/null
+++ b/apexkey/com.android.hardware.avbpubkey
Binary files differ
diff --git a/apexkey/com.android.hardware.pem b/apexkey/com.android.hardware.pem
new file mode 100644
index 0000000..4d2882b
--- /dev/null
+++ b/apexkey/com.android.hardware.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCmirL5vFcGDqg9
+JqKZwRqzPr76t8aqJSu+UOdnlmqBLmUBaeun2KwRsZiLku933m5MNv+CPnVQW7ij
+z0lv0z/qB8SXN+KAgSqRdIjL1ySQgp8ygKHu+GcvbMFj9pVuqufwSrEOY9Un1RRY
+InDDj88c/aNbCw64d1QVedgUIs5KDDLjOzkcrrbH+Th26r2YjhlRKQXCZT5jW1fY
+2gJg5LPeuM4fI63ESxFyRTY/V8E3LbAuTYKBSrHRbec22oCkL/pUilJBe2r8aNyp
+ACWEJB96uWdKmIYDCdj6r6SNzHM3S4X+l1C9/Gi9UNK8nuIAI3v2qW07S2RABAWX
+vKfE8rIKAdFmajGlHKfRe6IL9ka1/rsM1xgDr2/FgEsyRgrfJvlvvMb7ampMgTKu
+Az/hv4siSaDD2E3JrRyh3nNxTCuIABla7/jGmNz6vIdwTRJsa2RIEezkeMiUy+jp
+VyeYsWIEBmQwZ5+k6YbdrKTULaay3UJ6/YXEQY9Sbg0JL/7sjQWILwnrtab3/jsn
+iWsr59Qsaf+q3PnrWPCXT/KC8DwKi/2zSWfCX8MHreqaoozjfWXeD87lnBAhukBS
+984xWEmStJGFQG29J4sF4NmgO1I8GPqQRtoB6ghme11U2EX0vIqrDNccX12ohqgh
+CfwMXX64WV5fWscmSLZin5xK+AN+/wIDAQABAoICABLDnda1ebic/ielqrxYHYIE
+l8/31NJmzb7rrqblM6rKZ2b5YCvRJdH4iI9xRrnivdqod7FdCCq9qtgKCuQmkRT1
+Oxkumr6PzxQEZUVSQDRoAzfVdmlOY5HcVw3EQqHtb6SLRdexN9r9DwW/G6VtFpDV
+owom/Mmb6EVjLQ1XvpZpOXKQwaaRqNZvJgV//Uyq9f9G9/cnIRhguk0cgxgXrIxz
+lgW8J1/udVDCq5IHeSWWaDtPUFzw5YgLMfnkNIpLPZE45HusRCmcRwBjm9Z/m2xg
+Z1roRHEjMudL0uaHGpQoVjiRI+/D+Kkb6iKGZEBPvy/TdxMvM2RjD55BC0YNcjGv
+kXTMLwj2ke824rUPJJOYN8bJFIpOYblMcbDrxYVlDZetKOMc6EJw90xaj4za2IMS
+vWDxZx1WQPcn+B/nUvrMMOTN6MkNYKR97lmxBYP6TeCiUUytZiCF72cvvpYcdhE9
+zzOES5kVakSE8NnLTH9xAjrpAguxI9gqxeyLALhz/Rb46fgWwnhcBdqmPtez/IHb
+BgF81SSobSaBlzLcnRyrjwBRWA21DP8U/ApUkmHR/Lm1BJejzxf1hj35Hp9XUwdC
+JK7aoVnjuko/l5TPn0Bvm4pcBArG0AUL75GlRgDJTVCDZbLFR/2JZlnZ9optvN6E
+vniu3HwBRHDHn0K1DqIBAoIBAQDpdBJtyizIlZ5p6k1f0wWE/B2riPzPwv/a+ygD
+GOtzWsukyZjWHXVPjx2XY3bwlbusiqhJE1OcF+oymHTtSSv3VsqMmo2VDIj8d21T
+ycpBvV7+mcehGk6o6lGTJAiPc1wVMajmM0Co2LQb4hRvf2p8dW6+RRn5c3o288B5
+e45zpbq9+l9PMpgrmOBU3m652JmGK8JqQKeKKT96kZQVf/U3ArMif+jW2piAZnmG
+CS00el0K0RtZe/iKrFftoD27ai9GNZx/Z1p55x+9vUD15LiQ/MK0Bk/f9b24zE98
+6T07KAGPB5gXWlSs2yEk4Waufjw3JSYXs18kEoMklTA0IGGhAoIBAQC2oEwGQZI0
+oR1oL7P76FyMNjtp2T2wYnOcnGeKjp4vxZWTZNRfNUmzGqSamVE1ZPhj721sAImS
+mk1pUJbglkpP6aMDNXzA6Z50PuXfhF5+dXBrLftT1tcNo/8/ysd/iKsi1C6hWZ9L
+YYt/7uR8wazeG65jahsOKEfCrNyDBQzyoSft1qfVTvYzxUVmJRQr5S7H0c9jPTwg
+Qj+/RQsDOspsJrBC5+H0tLPkvZDdZCYvdBzVWFL7npHd0fy53TmT6kEjDwwAiE8W
+VggvzkhHOnprAiwq36nlpGo3um5Ona98dXWZ4rfELEdSUOiWCz2Gzz7IL+H8uhen
+iXQAtlAlMVyfAoIBAQDDGmlobgW9YSVyWQlvIxnCyT02pZa7P7m6VhpbdFEaJ/B3
+eLANibMH2ZCee9bkPA8LpRn9cHR4yJfGzxkxUey3mkZO+b+HqGE3tcudsdAh3tTs
+LLLk1eqVSrcAJKYu1PdJEyaXtI++TNVBVFFF2ZOyDiaOR4vsqPCjylS6cmNcDU6j
+BQLwWlVIYkxhQUACe53avumNCRm74rsVgWLkEPtrjQsOsx1xqmC3Nm0rcrHf4L+v
+kZCs2Wme42fcxQWygoydvaJb65F2vY0OcoM+vXbuXP+PmpLYljSHo+BugTLWJJog
+4fTe13RavgvWGbZJ8F/8qkRKnHLP39TQFwqhFcrhAoIBAQCZYipX+syUHVl4ftA4
+2+CW9pmR/h5cvWOCfq5L5hqf3uAQqlfgGv5qSg9DtU9KfCJOtPH/CriBA83OjRwb
+Rr7lPUJnWI4N7GjkE0u4HhHLPlGMA1OaB9AZKcsgxewmhh/OIc2EQKSUiDnE2lzX
+F0dcSH2AC8brbhNPQyX1eNF2GrpRfL77XdVUh/QQpUW61EMlGmeHXw/XvCyUNaXZ
+MZB/o0LY/q59eyO4EyrPduTHaEsrOIKByJ2UY2BSrqZEQDQzANlAvTtHdDxuAmAc
+StY0d9+mprGoKR347kDlEHUqH/EErTFQtyuzzDZ8hrZHOlrtgaHZRGbHlJ90Vasc
+gcfbAoIBAEIR0dtmd38dC7r0h0SZ7ORIvm9F8JRs+wKdWjiPfWLK3trR/jxRx6Eh
+xrrJEoRCeUmT6rc0TwUkzow5ApcEY338KmsqKVbm3iGfPpvZFEO44vBrg3280QBM
+PerIrEfidflUAE9QXNoBpvvnh2KXIOsvyN2MeY2SAyebPJQJtWzJkP35Y8fOtZkJ
+VtIhYj2wvFuobl7iuxKJG0cn4xL3OLysc03oX7Al2qA42hUCy7UMsTT6ZAPWd49+
+3gOFrqmaV3Hu5KY2HaX6Yly5ohhQWSkSL1kZMo9Uq6tTM+2HFzFU6sveFbWW/XQc
+rWnazDdd1WkHT6+nzA/NX24OzPjiUk0=
+-----END PRIVATE KEY-----
diff --git a/apexkey/com.android.hardware.pk8 b/apexkey/com.android.hardware.pk8
new file mode 100644
index 0000000..97007d2
--- /dev/null
+++ b/apexkey/com.android.hardware.pk8
Binary files differ
diff --git a/apexkey/com.android.hardware.x509.pem b/apexkey/com.android.hardware.x509.pem
new file mode 100644
index 0000000..2728a23
--- /dev/null
+++ b/apexkey/com.android.hardware.x509.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF6TCCA9ECFDAU6pJXjblHA/w9a354h2QUOharMA0GCSqGSIb3DQEBCwUAMIGv
+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
+bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
+MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTErMCkGA1UEAwwiY29t
+LmFuZHJvaWQuaGFyZHdhcmUudGhyZWFkbmV0d29yazAgFw0yMzA4MjQwNjE4MTZa
+GA80NzYxMDcyMDA2MTgxNlowga8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
+Zm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lk
+MRAwDgYDVQQLDAdBbmRyb2lkMSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJv
+aWQuY29tMSswKQYDVQQDDCJjb20uYW5kcm9pZC5oYXJkd2FyZS50aHJlYWRuZXR3
+b3JrMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5eMXZfeadUJiqZ0b
+kbXYSbzjd1opoeAVk/+LxGyBLLPy2z2EAeuUBx8HYEJhyPOyUrs3ohP6OvAtE8O4
+JeEbGBzqOymusKbve8ght7tDjUuTYsbBsKQWw1Gu/UUK7x3lc6zD+wDTK/5NUoTA
+I/5lI8Q4+NHCI1jb/uBRGSlzSO+k2A2oVUPdyaWWgGhLeEiXKo+Xy6XXduhFK1wc
+iSCgVyuQkZnbrJrGCGS1LD1MavsfBTthD3jfuOq+YqMjGjdi6xVPG3fZnwwdVNzW
+mSFwWwHif56ZAtxyZVtQOAksTqwAwGrUjhn70rw5eLBQjXIL1061cLrOZ4XlRSZj
+kHB8mwr6OQOw7isMORO0h+NNJ+5POa5V9rGylqk/hn1vzcTX62YUZy1N6b3rfGc2
+p9LA6STjvoXLeCFaSIc+LfTiHOamkg7LuLlsQ/AIoXeuaLyWAgg4ls2U8IG1Mdkz
+BClX5vMG/At6yZqHiCIbCU8V8VSCz7Rtuu+C/87G5Pwb/G1r4FHXr9x7d0qj4rWV
+u9MhdzvZWoTTnEzDA+DWPQM/ILkGdkSj0g4yC8GR/F5p7xWQ0vqyMyM/ii1KzWVs
+ZJFUxzpGX99C0mfjT2hezHzfEyisPec39PFbdxzC756yP1Le8I5qjMbjl+XeFjxO
+REoC0nDFgHEI7C5RunT1osKmpDUCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEA3HPY
++nHGFE9aFQbEsjvotuxguLMKmrgQ44yGBTr9349MPvnxGDdz1HPWs/m456k9HQxt
+1YWV+xr56NS37UDVMkqS7hzCkJe/LdMT51qvUS+hPHLzSuZNKuFAaCOb8WDa7tGQ
+MuvISlb6T7G512fUdFDRjFjnIXDLTYANzoxI3cqs2N2xQNxsL8uIJ79RWlPm2Upz
+Y5Ad55kv3EygWgirvZnSNo27E/Tt4Bo9KS0HsYXVHgWK9zHHtup1vDOntJ8bX16C
+rP7e8SELanPbUtyIUDcf14P3EFztUYBZIXO2HUSsoOTX3+Hd592h7EsnGDdlWSLU
+oreaRWCAMh4TKI/eP+1N35b8zmPMHaG+WsWjdDPrs6oNpr2MMA4U8AHGW2d6QY0N
+xZ/VhhbjbHMgmmB3Q2LXZZufbSEBawBfuFjhodfmKSgTjNCTYXtTiT/pL2w0PqEM
+v4UxrGD0uFQafFKuxQfL2LYG5tg46daRrT3BoIqLKoseTuykzW4z08NuurwsLvmy
+t7njqMxlf/tN9o+d3D3lWHQpiDJ8kC/TjgKBj7iQTCOJeShutxyR2F3R+3+kUXpP
+w7O4QfoqZDca1qtJRtew2tpmOb1hFkj/QzRi5WRx/oM/Cm0yMttYIA+4vCJeDOja
+gngrtH3jmEwMME71HDyXHlcCIIt95odXoBSBKgk=
+-----END CERTIFICATE-----
diff --git a/audio/aidl/common/StreamWorker.cpp b/audio/aidl/common/StreamWorker.cpp
index 0d2121c..8107655 100644
--- a/audio/aidl/common/StreamWorker.cpp
+++ b/audio/aidl/common/StreamWorker.cpp
@@ -106,6 +106,9 @@
std::lock_guard<std::mutex> lock(mWorkerLock);
mWorkerState = error.empty() ? WorkerState::RUNNING : WorkerState::STOPPED;
mError = error;
+#if defined(__ANDROID__)
+ mTid = pthread_gettid_np(pthread_self());
+#endif
}
mWorkerCv.notify_one();
if (!error.empty()) return;
diff --git a/audio/aidl/common/include/StreamWorker.h b/audio/aidl/common/include/StreamWorker.h
index e9c1070..efdcc81 100644
--- a/audio/aidl/common/include/StreamWorker.h
+++ b/audio/aidl/common/include/StreamWorker.h
@@ -16,6 +16,8 @@
#pragma once
+#include <sys/types.h>
+
#include <atomic>
#include <condition_variable>
#include <mutex>
@@ -52,6 +54,10 @@
std::lock_guard<std::mutex> lock(mWorkerLock);
return mError;
}
+ pid_t getTid() {
+ std::lock_guard<std::mutex> lock(mWorkerLock);
+ return mTid;
+ }
void stop();
// Direct use of 'join' assumes that the StreamLogic is not intended
// to run forever, and is guaranteed to exit by itself. This normally
@@ -78,6 +84,7 @@
std::condition_variable mWorkerCv;
WorkerState mWorkerState GUARDED_BY(mWorkerLock) = WorkerState::INITIAL;
std::string mError GUARDED_BY(mWorkerLock);
+ pid_t mTid GUARDED_BY(mWorkerLock) = -1;
// The atomic lock-free variable is used to prevent priority inversions
// that can occur when a high priority worker tries to acquire the lock
// which has been taken by a lower priority control thread which in its turn
@@ -143,6 +150,7 @@
void resume() { mThread.resume(); }
bool hasError() { return mThread.hasError(); }
std::string getError() { return mThread.getError(); }
+ pid_t getTid() { return mThread.getTid(); }
void stop() { mThread.stop(); }
void join() { mThread.join(); }
bool waitForAtLeastOneCycle() { return mThread.waitForAtLeastOneCycle(); }
diff --git a/audio/aidl/common/tests/streamworker_tests.cpp b/audio/aidl/common/tests/streamworker_tests.cpp
index f7a30b9..2b65740 100644
--- a/audio/aidl/common/tests/streamworker_tests.cpp
+++ b/audio/aidl/common/tests/streamworker_tests.cpp
@@ -87,6 +87,7 @@
TEST_P(StreamWorkerInvalidTest, Uninitialized) {
EXPECT_FALSE(worker.hasWorkerCycleCalled());
EXPECT_FALSE(worker.hasError());
+ EXPECT_LE(worker.getTid(), 0);
}
TEST_P(StreamWorkerInvalidTest, UninitializedPauseIgnored) {
@@ -105,6 +106,9 @@
EXPECT_FALSE(worker.start());
EXPECT_FALSE(worker.hasWorkerCycleCalled());
EXPECT_TRUE(worker.hasError());
+#if defined(__ANDROID__)
+ EXPECT_GT(worker.getTid(), 0);
+#endif
}
TEST_P(StreamWorkerInvalidTest, PauseIgnored) {
@@ -136,12 +140,16 @@
TEST_P(StreamWorkerTest, Uninitialized) {
EXPECT_FALSE(worker.hasWorkerCycleCalled());
EXPECT_FALSE(worker.hasError());
+ EXPECT_LE(worker.getTid(), 0);
}
TEST_P(StreamWorkerTest, Start) {
ASSERT_TRUE(worker.start());
EXPECT_TRUE(worker.waitForAtLeastOneCycle());
EXPECT_FALSE(worker.hasError());
+#if defined(__ANDROID__)
+ EXPECT_GT(worker.getTid(), 0);
+#endif
}
TEST_P(StreamWorkerTest, StartStop) {
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index 4e583a4..bb8d76f 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -82,8 +82,12 @@
"alsa/ModuleAlsa.cpp",
"alsa/StreamAlsa.cpp",
"alsa/Utils.cpp",
+ "bluetooth/DevicePortProxy.cpp",
+ "bluetooth/ModuleBluetooth.cpp",
+ "bluetooth/StreamBluetooth.cpp",
+ "primary/PrimaryMixer.cpp",
+ "primary/StreamPrimary.cpp",
"r_submix/ModuleRemoteSubmix.cpp",
- "r_submix/RemoteSubmixUtils.cpp",
"r_submix/SubmixRoute.cpp",
"r_submix/StreamRemoteSubmix.cpp",
"stub/ModuleStub.cpp",
@@ -105,7 +109,9 @@
"audio_policy_engine_configuration_aidl_default",
],
shared_libs: [
+ "android.hardware.bluetooth.audio-V3-ndk",
"libaudio_aidl_conversion_common_ndk",
+ "libbluetooth_audio_session_aidl",
"libmedia_helper",
"libstagefright_foundation",
],
@@ -136,7 +142,9 @@
"libaudioserviceexampleimpl",
],
shared_libs: [
+ "android.hardware.bluetooth.audio-V3-ndk",
"libaudio_aidl_conversion_common_ndk",
+ "libbluetooth_audio_session_aidl",
"libmedia_helper",
"libstagefright_foundation",
],
diff --git a/audio/aidl/default/Bluetooth.cpp b/audio/aidl/default/Bluetooth.cpp
index c32b538..072b89f 100644
--- a/audio/aidl/default/Bluetooth.cpp
+++ b/audio/aidl/default/Bluetooth.cpp
@@ -82,19 +82,18 @@
ndk::ScopedAStatus BluetoothA2dp::isEnabled(bool* _aidl_return) {
*_aidl_return = mEnabled;
- LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus BluetoothA2dp::setEnabled(bool in_enabled) {
mEnabled = in_enabled;
LOG(DEBUG) << __func__ << ": " << mEnabled;
+ if (mHandler) return mHandler();
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus BluetoothA2dp::supportsOffloadReconfiguration(bool* _aidl_return) {
- *_aidl_return = true;
- LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
+ *_aidl_return = false;
return ndk::ScopedAStatus::ok();
}
@@ -102,24 +101,22 @@
const std::vector<::aidl::android::hardware::audio::core::VendorParameter>& in_parameters
__unused) {
LOG(DEBUG) << __func__ << ": " << ::android::internal::ToString(in_parameters);
- return ndk::ScopedAStatus::ok();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
ndk::ScopedAStatus BluetoothLe::isEnabled(bool* _aidl_return) {
*_aidl_return = mEnabled;
- LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus BluetoothLe::setEnabled(bool in_enabled) {
mEnabled = in_enabled;
- LOG(DEBUG) << __func__ << ": " << mEnabled;
+ if (mHandler) return mHandler();
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus BluetoothLe::supportsOffloadReconfiguration(bool* _aidl_return) {
- *_aidl_return = true;
- LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
+ *_aidl_return = false;
return ndk::ScopedAStatus::ok();
}
@@ -127,7 +124,7 @@
const std::vector<::aidl::android::hardware::audio::core::VendorParameter>& in_parameters
__unused) {
LOG(DEBUG) << __func__ << ": " << ::android::internal::ToString(in_parameters);
- return ndk::ScopedAStatus::ok();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/Config.cpp b/audio/aidl/default/Config.cpp
index d1023da..308200a 100644
--- a/audio/aidl/default/Config.cpp
+++ b/audio/aidl/default/Config.cpp
@@ -27,12 +27,11 @@
namespace aidl::android::hardware::audio::core {
ndk::ScopedAStatus Config::getSurroundSoundConfig(SurroundSoundConfig* _aidl_return) {
+ static const auto& func = __func__;
static const SurroundSoundConfig surroundSoundConfig = [this]() {
- SurroundSoundConfig surroundCfg;
- if (mAudioPolicyConverter.getStatus() == ::android::OK) {
- surroundCfg = mAudioPolicyConverter.getSurroundSoundConfig();
- } else {
- LOG(WARNING) << __func__ << mAudioPolicyConverter.getError();
+ SurroundSoundConfig surroundCfg = mAudioPolicyConverter.getSurroundSoundConfig();
+ if (mAudioPolicyConverter.getStatus() != ::android::OK) {
+ LOG(WARNING) << func << ": " << mAudioPolicyConverter.getError();
}
return surroundCfg;
}();
@@ -42,21 +41,22 @@
}
ndk::ScopedAStatus Config::getEngineConfig(AudioHalEngineConfig* _aidl_return) {
+ static const auto& func = __func__;
static const AudioHalEngineConfig returnEngCfg = [this]() {
AudioHalEngineConfig engConfig;
if (mEngConfigConverter.getStatus() == ::android::OK) {
engConfig = mEngConfigConverter.getAidlEngineConfig();
} else {
- LOG(INFO) << __func__ << mEngConfigConverter.getError();
+ LOG(INFO) << func << ": " << mEngConfigConverter.getError();
if (mAudioPolicyConverter.getStatus() == ::android::OK) {
engConfig = mAudioPolicyConverter.getAidlEngineConfig();
} else {
- LOG(WARNING) << __func__ << mAudioPolicyConverter.getError();
+ LOG(WARNING) << func << ": " << mAudioPolicyConverter.getError();
}
}
// Logging full contents of the config is an overkill, just provide statistics.
- LOG(DEBUG) << "getEngineConfig: number of strategies parsed: "
- << engConfig.productStrategies.size()
+ LOG(DEBUG) << func
+ << ": number of strategies parsed: " << engConfig.productStrategies.size()
<< ", default strategy: " << engConfig.defaultProductStrategyId
<< ", number of volume groups parsed: " << engConfig.volumeGroups.size();
return engConfig;
diff --git a/audio/aidl/default/Configuration.cpp b/audio/aidl/default/Configuration.cpp
index a71c6ea..9131935 100644
--- a/audio/aidl/default/Configuration.cpp
+++ b/audio/aidl/default/Configuration.cpp
@@ -81,8 +81,6 @@
deviceExt.device.address = "bottom";
} else if (devType == AudioDeviceType::IN_MICROPHONE_BACK && connection.empty()) {
deviceExt.device.address = "back";
- } else if (devType == AudioDeviceType::IN_SUBMIX || devType == AudioDeviceType::OUT_SUBMIX) {
- deviceExt.device.address = "0";
}
deviceExt.device.type.connection = std::move(connection);
deviceExt.flags = flags;
@@ -136,7 +134,7 @@
// Device ports:
// * "Speaker", OUT_SPEAKER, default
// - no profiles specified
-// * "Built-in Mic", IN_MICROPHONE, default
+// * "Built-In Mic", IN_MICROPHONE, default
// - no profiles specified
// * "Telephony Tx", OUT_TELEPHONY_TX
// - no profiles specified
@@ -148,46 +146,35 @@
// Mix ports:
// * "primary output", PRIMARY, 1 max open, 1 max active stream
// - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
-// - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
-// * "compressed offload", DIRECT|COMPRESS_OFFLOAD|NON_BLOCKING, 1 max open, 1 max active stream
-// - profile MP3; MONO, STEREO; 44100, 48000
-// * "primary input", 2 max open, 2 max active streams
-// - profile PCM 16-bit; MONO, STEREO, FRONT_BACK;
-// 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
-// - profile PCM 24-bit; MONO, STEREO, FRONT_BACK;
-// 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
+// * "primary input", 1 max open, 1 max active stream
+// - profile PCM 16-bit; MONO, STEREO;
+// 8000, 11025, 16000, 32000, 44100, 48000
// * "telephony_tx", 1 max open, 1 max active stream
// - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
-// - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
// * "telephony_rx", 1 max open, 1 max active stream
// - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
-// - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
// * "fm_tuner", 1 max open, 1 max active stream
// - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
-// - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
//
// Routes:
-// "primary out", "compressed offload" -> "Speaker"
-// "Built-in Mic" -> "primary input"
-// "telephony_tx" -> "Telephony Tx"
+// "primary out" -> "Speaker"
+// "Built-In Mic" -> "primary input"
// "Telephony Rx" -> "telephony_rx"
+// "telephony_tx" -> "Telephony Tx"
// "FM Tuner" -> "fm_tuner"
//
// Initial port configs:
-// * "Speaker" device port: PCM 24-bit; STEREO; 48000
-// * "Built-in Mic" device port: PCM 24-bit; MONO; 48000
-// * "Telephony Tx" device port: PCM 24-bit; MONO; 48000
-// * "Telephony Rx" device port: PCM 24-bit; MONO; 48000
-// * "FM Tuner" device port: PCM 24-bit; STEREO; 48000
+// * "Speaker" device port: PCM 16-bit; STEREO; 48000
+// * "Built-In Mic" device port: PCM 16-bit; MONO; 48000
+// * "Telephony Tx" device port: PCM 16-bit; MONO; 48000
+// * "Telephony Rx" device port: PCM 16-bit; MONO; 48000
+// * "FM Tuner" device port: PCM 16-bit; STEREO; 48000
//
std::unique_ptr<Configuration> getPrimaryConfiguration() {
static const Configuration configuration = []() {
const std::vector<AudioProfile> standardPcmAudioProfiles = {
createProfile(PcmType::INT_16_BIT,
{AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
- {8000, 11025, 16000, 32000, 44100, 48000}),
- createProfile(PcmType::INT_24_BIT,
- {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
{8000, 11025, 16000, 32000, 44100, 48000})};
Configuration c;
@@ -199,17 +186,17 @@
1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
c.ports.push_back(speakerOutDevice);
c.initialConfigs.push_back(
- createPortConfig(speakerOutDevice.id, speakerOutDevice.id, PcmType::INT_24_BIT,
+ createPortConfig(speakerOutDevice.id, speakerOutDevice.id, PcmType::INT_16_BIT,
AudioChannelLayout::LAYOUT_STEREO, 48000, 0, false,
createDeviceExt(AudioDeviceType::OUT_SPEAKER, 0)));
AudioPort micInDevice =
- createPort(c.nextPortId++, "Built-in Mic", 0, true,
+ createPort(c.nextPortId++, "Built-In Mic", 0, true,
createDeviceExt(AudioDeviceType::IN_MICROPHONE,
1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
c.ports.push_back(micInDevice);
c.initialConfigs.push_back(
- createPortConfig(micInDevice.id, micInDevice.id, PcmType::INT_24_BIT,
+ createPortConfig(micInDevice.id, micInDevice.id, PcmType::INT_16_BIT,
AudioChannelLayout::LAYOUT_MONO, 48000, 0, true,
createDeviceExt(AudioDeviceType::IN_MICROPHONE, 0)));
@@ -219,7 +206,7 @@
c.ports.push_back(telephonyTxOutDevice);
c.initialConfigs.push_back(
createPortConfig(telephonyTxOutDevice.id, telephonyTxOutDevice.id,
- PcmType::INT_24_BIT, AudioChannelLayout::LAYOUT_MONO, 48000, 0,
+ PcmType::INT_16_BIT, AudioChannelLayout::LAYOUT_MONO, 48000, 0,
false, createDeviceExt(AudioDeviceType::OUT_TELEPHONY_TX, 0)));
AudioPort telephonyRxInDevice =
@@ -228,14 +215,14 @@
c.ports.push_back(telephonyRxInDevice);
c.initialConfigs.push_back(
createPortConfig(telephonyRxInDevice.id, telephonyRxInDevice.id,
- PcmType::INT_24_BIT, AudioChannelLayout::LAYOUT_MONO, 48000, 0,
+ PcmType::INT_16_BIT, AudioChannelLayout::LAYOUT_MONO, 48000, 0,
true, createDeviceExt(AudioDeviceType::IN_TELEPHONY_RX, 0)));
AudioPort fmTunerInDevice = createPort(c.nextPortId++, "FM Tuner", 0, true,
createDeviceExt(AudioDeviceType::IN_FM_TUNER, 0));
c.ports.push_back(fmTunerInDevice);
c.initialConfigs.push_back(
- createPortConfig(fmTunerInDevice.id, fmTunerInDevice.id, PcmType::INT_24_BIT,
+ createPortConfig(fmTunerInDevice.id, fmTunerInDevice.id, PcmType::INT_16_BIT,
AudioChannelLayout::LAYOUT_STEREO, 48000, 0, true,
createDeviceExt(AudioDeviceType::IN_FM_TUNER, 0)));
@@ -243,36 +230,18 @@
AudioPort primaryOutMix = createPort(c.nextPortId++, "primary output",
makeBitPositionFlagMask(AudioOutputFlags::PRIMARY),
- false, createPortMixExt(1, 1));
+ false, createPortMixExt(0, 0));
primaryOutMix.profiles.insert(primaryOutMix.profiles.begin(),
standardPcmAudioProfiles.begin(),
standardPcmAudioProfiles.end());
c.ports.push_back(primaryOutMix);
- AudioPort compressedOffloadOutMix =
- createPort(c.nextPortId++, "compressed offload",
- makeBitPositionFlagMask({AudioOutputFlags::DIRECT,
- AudioOutputFlags::COMPRESS_OFFLOAD,
- AudioOutputFlags::NON_BLOCKING}),
- false, createPortMixExt(1, 1));
- compressedOffloadOutMix.profiles.push_back(
- createProfile(::android::MEDIA_MIMETYPE_AUDIO_MPEG,
- {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
- {44100, 48000}));
- c.ports.push_back(compressedOffloadOutMix);
-
AudioPort primaryInMix =
- createPort(c.nextPortId++, "primary input", 0, true, createPortMixExt(2, 2));
+ createPort(c.nextPortId++, "primary input", 0, true, createPortMixExt(0, 0));
primaryInMix.profiles.push_back(
createProfile(PcmType::INT_16_BIT,
- {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
- AudioChannelLayout::LAYOUT_FRONT_BACK},
- {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000}));
- primaryInMix.profiles.push_back(
- createProfile(PcmType::INT_24_BIT,
- {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
- AudioChannelLayout::LAYOUT_FRONT_BACK},
- {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000}));
+ {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
+ {8000, 11025, 16000, 32000, 44100, 48000}));
c.ports.push_back(primaryInMix);
AudioPort telephonyTxOutMix =
@@ -296,10 +265,10 @@
standardPcmAudioProfiles.end());
c.ports.push_back(fmTunerInMix);
- c.routes.push_back(createRoute({primaryOutMix, compressedOffloadOutMix}, speakerOutDevice));
+ c.routes.push_back(createRoute({primaryOutMix}, speakerOutDevice));
c.routes.push_back(createRoute({micInDevice}, primaryInMix));
- c.routes.push_back(createRoute({telephonyTxOutMix}, telephonyTxOutDevice));
c.routes.push_back(createRoute({telephonyRxInDevice}, telephonyRxInMix));
+ c.routes.push_back(createRoute({telephonyTxOutMix}, telephonyTxOutDevice));
c.routes.push_back(createRoute({fmTunerInDevice}, fmTunerInMix));
c.portConfigs.insert(c.portConfigs.end(), c.initialConfigs.begin(), c.initialConfigs.end());
@@ -320,15 +289,21 @@
//
// Device ports:
// * "Remote Submix Out", OUT_SUBMIX
-// - profile PCM 24-bit; STEREO; 48000
+// - no profiles specified
// * "Remote Submix In", IN_SUBMIX
-// - profile PCM 24-bit; STEREO; 48000
+// - no profiles specified
//
// Mix ports:
-// * "r_submix output", stream count unlimited
-// - profile PCM 24-bit; STEREO; 48000
-// * "r_submix input", stream count unlimited
-// - profile PCM 24-bit; STEREO; 48000
+// * "r_submix output", unlimited max open, unlimited max active stream
+// - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+// - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+// - profile PCM 32-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+// - profile PCM 32-bit float; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+// * "r_submix input", unlimited max open, unlimited max active stream
+// - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+// - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+// - profile PCM 32-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+// - profile PCM 32-bit float; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
//
// Routes:
// "r_submix output" -> "Remote Submix Out"
@@ -337,6 +312,19 @@
std::unique_ptr<Configuration> getRSubmixConfiguration() {
static const Configuration configuration = []() {
Configuration c;
+ const std::vector<AudioProfile> standardPcmAudioProfiles{
+ createProfile(PcmType::FLOAT_32_BIT,
+ {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
+ {8000, 11025, 16000, 32000, 44100, 48000}),
+ createProfile(PcmType::INT_32_BIT,
+ {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
+ {8000, 11025, 16000, 32000, 44100, 48000}),
+ createProfile(PcmType::INT_24_BIT,
+ {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
+ {8000, 11025, 16000, 32000, 44100, 48000}),
+ createProfile(PcmType::INT_16_BIT,
+ {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
+ {8000, 11025, 16000, 32000, 44100, 48000})};
// Device ports
@@ -344,28 +332,26 @@
createPort(c.nextPortId++, "Remote Submix Out", 0, false,
createDeviceExt(AudioDeviceType::OUT_SUBMIX, 0,
AudioDeviceDescription::CONNECTION_VIRTUAL));
- rsubmixOutDevice.profiles.push_back(
- createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
c.ports.push_back(rsubmixOutDevice);
+ c.connectedProfiles[rsubmixOutDevice.id] = standardPcmAudioProfiles;
- AudioPort rsubmixInDevice = createPort(c.nextPortId++, "Remote Submix In", 0, true,
- createDeviceExt(AudioDeviceType::IN_SUBMIX, 0));
- rsubmixInDevice.profiles.push_back(
- createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
+ AudioPort rsubmixInDevice =
+ createPort(c.nextPortId++, "Remote Submix In", 0, true,
+ createDeviceExt(AudioDeviceType::IN_SUBMIX, 0,
+ AudioDeviceDescription::CONNECTION_VIRTUAL));
c.ports.push_back(rsubmixInDevice);
+ c.connectedProfiles[rsubmixInDevice.id] = standardPcmAudioProfiles;
// Mix ports
AudioPort rsubmixOutMix =
createPort(c.nextPortId++, "r_submix output", 0, false, createPortMixExt(0, 0));
- rsubmixOutMix.profiles.push_back(
- createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
+ rsubmixOutMix.profiles = standardPcmAudioProfiles;
c.ports.push_back(rsubmixOutMix);
AudioPort rsubmixInMix =
createPort(c.nextPortId++, "r_submix input", 0, true, createPortMixExt(0, 0));
- rsubmixInMix.profiles.push_back(
- createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
+ rsubmixInMix.profiles = standardPcmAudioProfiles;
c.ports.push_back(rsubmixInMix);
c.routes.push_back(createRoute({rsubmixOutMix}, rsubmixOutDevice));
@@ -479,14 +465,17 @@
// Mix ports:
// * "test output", 1 max open, 1 max active stream
// - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
-// * "compressed offload", DIRECT|COMPRESS_OFFLOAD|NON_BLOCKING, 1 max open, 1 max active stream
+// * "test fast output", 1 max open, 1 max active stream
+// - profile PCM 24-bit; STEREO; 44100, 48000
+// * "test compressed offload", DIRECT|COMPRESS_OFFLOAD|NON_BLOCKING, 1 max open, 1 max active
+// stream
// - profile MP3; MONO, STEREO; 44100, 48000
// * "test input", 2 max open, 2 max active streams
// - profile PCM 24-bit; MONO, STEREO, FRONT_BACK;
-// 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
+// 8000, 11025, 16000, 22050, 32000, 44100, 48000
//
// Routes:
-// "test output", "compressed offload" -> "Test Out"
+// "test output", "test fast output", "test compressed offload" -> "Test Out"
// "Test In" -> "test input"
//
// Initial port configs:
@@ -525,8 +514,15 @@
{8000, 11025, 16000, 32000, 44100, 48000}));
c.ports.push_back(testOutMix);
+ AudioPort testFastOutMix = createPort(c.nextPortId++, "test fast output",
+ makeBitPositionFlagMask({AudioOutputFlags::FAST}),
+ false, createPortMixExt(1, 1));
+ testFastOutMix.profiles.push_back(createProfile(
+ PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {44100, 48000}));
+ c.ports.push_back(testFastOutMix);
+
AudioPort compressedOffloadOutMix =
- createPort(c.nextPortId++, "compressed offload",
+ createPort(c.nextPortId++, "test compressed offload",
makeBitPositionFlagMask({AudioOutputFlags::DIRECT,
AudioOutputFlags::COMPRESS_OFFLOAD,
AudioOutputFlags::NON_BLOCKING}),
@@ -543,15 +539,16 @@
createProfile(PcmType::INT_16_BIT,
{AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
AudioChannelLayout::LAYOUT_FRONT_BACK},
- {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000}));
+ {8000, 11025, 16000, 22050, 32000, 44100, 48000}));
testInMIx.profiles.push_back(
createProfile(PcmType::INT_24_BIT,
{AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
AudioChannelLayout::LAYOUT_FRONT_BACK},
- {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000}));
+ {8000, 11025, 16000, 22050, 32000, 44100, 48000}));
c.ports.push_back(testInMIx);
- c.routes.push_back(createRoute({testOutMix, compressedOffloadOutMix}, testOutDevice));
+ c.routes.push_back(
+ createRoute({testOutMix, testFastOutMix, compressedOffloadOutMix}, testOutDevice));
c.routes.push_back(createRoute({testInDevice}, testInMIx));
c.portConfigs.insert(c.portConfigs.end(), c.initialConfigs.begin(), c.initialConfigs.end());
@@ -561,4 +558,94 @@
return std::make_unique<Configuration>(configuration);
}
+// Bluetooth configuration:
+//
+// Device ports:
+// * "BT A2DP Out", OUT_DEVICE, CONNECTION_BT_A2DP
+// - profile PCM 16-bit; STEREO; 44100, 48000, 88200, 96000
+// * "BT A2DP Headphones", OUT_HEADPHONE, CONNECTION_BT_A2DP
+// - profile PCM 16-bit; STEREO; 44100, 48000, 88200, 96000
+// * "BT A2DP Speaker", OUT_SPEAKER, CONNECTION_BT_A2DP
+// - profile PCM 16-bit; STEREO; 44100, 48000, 88200, 96000
+// * "BT Hearing Aid Out", OUT_HEARING_AID, CONNECTION_WIRELESS
+// - no profiles specified
+//
+// Mix ports:
+// * "a2dp output", 1 max open, 1 max active stream
+// - no profiles specified
+// * "hearing aid output", 1 max open, 1 max active stream
+// - profile PCM 16-bit; STEREO; 16000, 24000
+//
+// Routes:
+// "a2dp output" -> "BT A2DP Out"
+// "a2dp output" -> "BT A2DP Headphones"
+// "a2dp output" -> "BT A2DP Speaker"
+// "hearing aid output" -> "BT Hearing Aid Out"
+//
+std::unique_ptr<Configuration> getBluetoothConfiguration() {
+ static const Configuration configuration = []() {
+ const std::vector<AudioProfile> standardPcmAudioProfiles = {
+ createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO},
+ {44100, 48000, 88200, 96000})};
+ Configuration c;
+
+ // Device ports
+ AudioPort btOutDevice =
+ createPort(c.nextPortId++, "BT A2DP Out", 0, false,
+ createDeviceExt(AudioDeviceType::OUT_DEVICE, 0,
+ AudioDeviceDescription::CONNECTION_BT_A2DP));
+ btOutDevice.profiles.insert(btOutDevice.profiles.begin(), standardPcmAudioProfiles.begin(),
+ standardPcmAudioProfiles.end());
+ c.ports.push_back(btOutDevice);
+ c.connectedProfiles[btOutDevice.id] = standardPcmAudioProfiles;
+
+ AudioPort btOutHeadphone =
+ createPort(c.nextPortId++, "BT A2DP Headphones", 0, false,
+ createDeviceExt(AudioDeviceType::OUT_HEADPHONE, 0,
+ AudioDeviceDescription::CONNECTION_BT_A2DP));
+ btOutHeadphone.profiles.insert(btOutHeadphone.profiles.begin(),
+ standardPcmAudioProfiles.begin(),
+ standardPcmAudioProfiles.end());
+ c.ports.push_back(btOutHeadphone);
+ c.connectedProfiles[btOutHeadphone.id] = standardPcmAudioProfiles;
+
+ AudioPort btOutSpeaker =
+ createPort(c.nextPortId++, "BT A2DP Speaker", 0, false,
+ createDeviceExt(AudioDeviceType::OUT_SPEAKER, 0,
+ AudioDeviceDescription::CONNECTION_BT_A2DP));
+ btOutSpeaker.profiles.insert(btOutSpeaker.profiles.begin(),
+ standardPcmAudioProfiles.begin(),
+ standardPcmAudioProfiles.end());
+ c.ports.push_back(btOutSpeaker);
+ c.connectedProfiles[btOutSpeaker.id] = standardPcmAudioProfiles;
+
+ AudioPort btOutHearingAid =
+ createPort(c.nextPortId++, "BT Hearing Aid Out", 0, false,
+ createDeviceExt(AudioDeviceType::OUT_HEARING_AID, 0,
+ AudioDeviceDescription::CONNECTION_WIRELESS));
+ c.ports.push_back(btOutHearingAid);
+ c.connectedProfiles[btOutHearingAid.id] = std::vector<AudioProfile>(
+ {createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {16000})});
+
+ // Mix ports
+ AudioPort btOutMix =
+ createPort(c.nextPortId++, "a2dp output", 0, false, createPortMixExt(1, 1));
+ c.ports.push_back(btOutMix);
+
+ AudioPort btHearingOutMix =
+ createPort(c.nextPortId++, "hearing aid output", 0, false, createPortMixExt(1, 1));
+ btHearingOutMix.profiles.push_back(createProfile(
+ PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {16000, 24000}));
+ c.ports.push_back(btHearingOutMix);
+
+ c.routes.push_back(createRoute({btOutMix}, btOutDevice));
+ c.routes.push_back(createRoute({btOutMix}, btOutHeadphone));
+ c.routes.push_back(createRoute({btOutMix}, btOutSpeaker));
+ c.routes.push_back(createRoute({btHearingOutMix}, btOutHearingAid));
+
+ return c;
+ }();
+ return std::make_unique<Configuration>(configuration);
+}
+
} // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/EffectConfig.cpp b/audio/aidl/default/EffectConfig.cpp
index 730c0bf..4a12f8a 100644
--- a/audio/aidl/default/EffectConfig.cpp
+++ b/audio/aidl/default/EffectConfig.cpp
@@ -196,16 +196,16 @@
// see list of audio sources in audio_source_t:
// system/media/audio/include/system/audio_effects/audio_effects_conf.h
static const std::map<const std::string, AudioSource> sAudioSourceTable = {
- {MIC_SRC_TAG, AudioSource::VOICE_CALL},
- {VOICE_UL_SRC_TAG, AudioSource::VOICE_CALL},
- {VOICE_DL_SRC_TAG, AudioSource::VOICE_CALL},
+ {MIC_SRC_TAG, AudioSource::MIC},
+ {VOICE_UL_SRC_TAG, AudioSource::VOICE_UPLINK},
+ {VOICE_DL_SRC_TAG, AudioSource::VOICE_DOWNLINK},
{VOICE_CALL_SRC_TAG, AudioSource::VOICE_CALL},
- {CAMCORDER_SRC_TAG, AudioSource::VOICE_CALL},
- {VOICE_REC_SRC_TAG, AudioSource::VOICE_CALL},
- {VOICE_COMM_SRC_TAG, AudioSource::VOICE_CALL},
- {REMOTE_SUBMIX_SRC_TAG, AudioSource::VOICE_CALL},
- {UNPROCESSED_SRC_TAG, AudioSource::VOICE_CALL},
- {VOICE_PERFORMANCE_SRC_TAG, AudioSource::VOICE_CALL}};
+ {CAMCORDER_SRC_TAG, AudioSource::CAMCORDER},
+ {VOICE_REC_SRC_TAG, AudioSource::VOICE_RECOGNITION},
+ {VOICE_COMM_SRC_TAG, AudioSource::VOICE_COMMUNICATION},
+ {REMOTE_SUBMIX_SRC_TAG, AudioSource::REMOTE_SUBMIX},
+ {UNPROCESSED_SRC_TAG, AudioSource::UNPROCESSED},
+ {VOICE_PERFORMANCE_SRC_TAG, AudioSource::VOICE_PERFORMANCE}};
if (typeTag == Processing::Type::streamType) {
auto typeIter = sAudioStreamTypeTable.find(type);
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index b59bd7c..f81095e 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -26,6 +26,7 @@
#include <error/expected_utils.h>
#include "core-impl/Module.h"
+#include "core-impl/ModuleBluetooth.h"
#include "core-impl/ModulePrimary.h"
#include "core-impl/ModuleRemoteSubmix.h"
#include "core-impl/ModuleStub.h"
@@ -117,6 +118,8 @@
return ndk::SharedRefBase::make<ModuleStub>();
case Type::USB:
return ndk::SharedRefBase::make<ModuleUsb>();
+ case Type::BLUETOOTH:
+ return ndk::SharedRefBase::make<ModuleBluetooth>();
}
}
@@ -134,6 +137,9 @@
case Module::Type::USB:
os << "usb";
break;
+ case Module::Type::BLUETOOTH:
+ os << "bluetooth";
+ break;
}
return os;
}
@@ -301,6 +307,9 @@
case Type::USB:
config = std::move(internal::getUsbConfiguration());
break;
+ case Type::BLUETOOTH:
+ config = std::move(internal::getBluetoothConfiguration());
+ break;
}
return config;
}
@@ -1362,4 +1371,13 @@
return ndk::ScopedAStatus::ok();
}
+Module::BtProfileHandles Module::getBtProfileManagerHandles() {
+ return std::make_tuple(std::weak_ptr<IBluetooth>(), std::weak_ptr<IBluetoothA2dp>(),
+ std::weak_ptr<IBluetoothLe>());
+}
+
+ndk::ScopedAStatus Module::bluetoothParametersUpdated() {
+ return mStreams.bluetoothParametersUpdated();
+}
+
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/ModulePrimary.cpp b/audio/aidl/default/ModulePrimary.cpp
index 29e8126..9919c7f 100644
--- a/audio/aidl/default/ModulePrimary.cpp
+++ b/audio/aidl/default/ModulePrimary.cpp
@@ -21,7 +21,7 @@
#include <android-base/logging.h>
#include "core-impl/ModulePrimary.h"
-#include "core-impl/StreamStub.h"
+#include "core-impl/StreamPrimary.h"
#include "core-impl/Telephony.h"
using aidl::android::hardware::audio::common::SinkMetadata;
@@ -47,15 +47,15 @@
const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones,
std::shared_ptr<StreamIn>* result) {
- return createStreamInstance<StreamInStub>(result, std::move(context), sinkMetadata,
- microphones);
+ return createStreamInstance<StreamInPrimary>(result, std::move(context), sinkMetadata,
+ microphones);
}
ndk::ScopedAStatus ModulePrimary::createOutputStream(
StreamContext&& context, const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo, std::shared_ptr<StreamOut>* result) {
- return createStreamInstance<StreamOutStub>(result, std::move(context), sourceMetadata,
- offloadInfo);
+ return createStreamInstance<StreamOutPrimary>(result, std::move(context), sourceMetadata,
+ offloadInfo);
}
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp
index d2be48c..af89f5f 100644
--- a/audio/aidl/default/Stream.cpp
+++ b/audio/aidl/default/Stream.cpp
@@ -27,12 +27,16 @@
using aidl::android::hardware::audio::common::AudioOffloadMetadata;
using aidl::android::hardware::audio::common::getChannelCount;
using aidl::android::hardware::audio::common::getFrameSizeInBytes;
+using aidl::android::hardware::audio::common::isBitPositionFlagSet;
using aidl::android::hardware::audio::common::SinkMetadata;
using aidl::android::hardware::audio::common::SourceMetadata;
using aidl::android::media::audio::common::AudioDevice;
using aidl::android::media::audio::common::AudioDualMonoMode;
+using aidl::android::media::audio::common::AudioInputFlags;
+using aidl::android::media::audio::common::AudioIoFlags;
using aidl::android::media::audio::common::AudioLatencyMode;
using aidl::android::media::audio::common::AudioOffloadInfo;
+using aidl::android::media::audio::common::AudioOutputFlags;
using aidl::android::media::audio::common::AudioPlaybackRate;
using aidl::android::media::audio::common::MicrophoneDynamicInfo;
using aidl::android::media::audio::common::MicrophoneInfo;
@@ -117,7 +121,7 @@
if (isConnected) {
reply->observable.frames = mContext->getFrameCount();
reply->observable.timeNs = ::android::elapsedRealtimeNano();
- if (auto status = mDriver->getPosition(&reply->observable); status == ::android::OK) {
+ if (auto status = mDriver->refinePosition(&reply->observable); status == ::android::OK) {
return;
}
}
@@ -238,8 +242,8 @@
break;
case Tag::standby:
if (mState == StreamDescriptor::State::IDLE) {
+ populateReply(&reply, mIsConnected);
if (::android::status_t status = mDriver->standby(); status == ::android::OK) {
- populateReply(&reply, mIsConnected);
mState = StreamDescriptor::State::STANDBY;
} else {
LOG(ERROR) << __func__ << ": standby failed: " << status;
@@ -492,8 +496,8 @@
break;
case Tag::standby:
if (mState == StreamDescriptor::State::IDLE) {
+ populateReply(&reply, mIsConnected);
if (::android::status_t status = mDriver->standby(); status == ::android::OK) {
- populateReply(&reply, mIsConnected);
mState = StreamDescriptor::State::STANDBY;
} else {
LOG(ERROR) << __func__ << ": standby failed: " << status;
@@ -610,8 +614,30 @@
ndk::ScopedAStatus StreamCommonImpl::initInstance(
const std::shared_ptr<StreamCommonInterface>& delegate) {
mCommon = ndk::SharedRefBase::make<StreamCommonDelegator>(delegate);
- return mWorker->start() ? ndk::ScopedAStatus::ok()
- : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ if (!mWorker->start()) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ if (auto flags = getContext().getFlags();
+ (flags.getTag() == AudioIoFlags::Tag::input &&
+ isBitPositionFlagSet(flags.template get<AudioIoFlags::Tag::input>(),
+ AudioInputFlags::FAST)) ||
+ (flags.getTag() == AudioIoFlags::Tag::output &&
+ isBitPositionFlagSet(flags.template get<AudioIoFlags::Tag::output>(),
+ AudioOutputFlags::FAST))) {
+ // FAST workers should be run with a SCHED_FIFO scheduler, however the host process
+ // might be lacking the capability to request it, thus a failure to set is not an error.
+ pid_t workerTid = mWorker->getTid();
+ if (workerTid > 0) {
+ struct sched_param param;
+ param.sched_priority = 3; // Must match SchedulingPolicyService.PRIORITY_MAX (Java).
+ if (sched_setscheduler(workerTid, SCHED_FIFO | SCHED_RESET_ON_FORK, ¶m) != 0) {
+ PLOG(WARNING) << __func__ << ": failed to set FIFO scheduler for a fast thread";
+ }
+ } else {
+ LOG(WARNING) << __func__ << ": invalid worker tid: " << workerTid;
+ }
+ }
+ return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus StreamCommonImpl::getStreamCommonCommon(
@@ -723,6 +749,11 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus StreamCommonImpl::bluetoothParametersUpdated() {
+ LOG(DEBUG) << __func__;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
namespace {
static std::map<AudioDevice, std::string> transformMicrophones(
const std::vector<MicrophoneInfo>& microphones) {
@@ -734,12 +765,12 @@
} // namespace
StreamIn::StreamIn(StreamContext&& context, const std::vector<MicrophoneInfo>& microphones)
- : mContext(std::move(context)), mMicrophones(transformMicrophones(microphones)) {
+ : mContextInstance(std::move(context)), mMicrophones(transformMicrophones(microphones)) {
LOG(DEBUG) << __func__;
}
void StreamIn::defaultOnClose() {
- mContext.reset();
+ mContextInstance.reset();
}
ndk::ScopedAStatus StreamIn::getActiveMicrophones(
@@ -794,13 +825,39 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
+StreamInHwGainHelper::StreamInHwGainHelper(const StreamContext* context)
+ : mChannelCount(getChannelCount(context->getChannelLayout())) {}
+
+ndk::ScopedAStatus StreamInHwGainHelper::getHwGainImpl(std::vector<float>* _aidl_return) {
+ *_aidl_return = mHwGains;
+ LOG(DEBUG) << __func__ << ": returning " << ::android::internal::ToString(*_aidl_return);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StreamInHwGainHelper::setHwGainImpl(const std::vector<float>& in_channelGains) {
+ LOG(DEBUG) << __func__ << ": gains " << ::android::internal::ToString(in_channelGains);
+ if (in_channelGains.size() != mChannelCount) {
+ LOG(ERROR) << __func__
+ << ": channel count does not match stream channel count: " << mChannelCount;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ for (float gain : in_channelGains) {
+ if (gain < StreamIn::HW_GAIN_MIN || gain > StreamIn::HW_GAIN_MAX) {
+ LOG(ERROR) << __func__ << ": gain value out of range: " << gain;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ }
+ mHwGains = in_channelGains;
+ return ndk::ScopedAStatus::ok();
+}
+
StreamOut::StreamOut(StreamContext&& context, const std::optional<AudioOffloadInfo>& offloadInfo)
- : mContext(std::move(context)), mOffloadInfo(offloadInfo) {
+ : mContextInstance(std::move(context)), mOffloadInfo(offloadInfo) {
LOG(DEBUG) << __func__;
}
void StreamOut::defaultOnClose() {
- mContext.reset();
+ mContextInstance.reset();
}
ndk::ScopedAStatus StreamOut::updateOffloadMetadata(
@@ -899,4 +956,31 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
+StreamOutHwVolumeHelper::StreamOutHwVolumeHelper(const StreamContext* context)
+ : mChannelCount(getChannelCount(context->getChannelLayout())) {}
+
+ndk::ScopedAStatus StreamOutHwVolumeHelper::getHwVolumeImpl(std::vector<float>* _aidl_return) {
+ *_aidl_return = mHwVolumes;
+ LOG(DEBUG) << __func__ << ": returning " << ::android::internal::ToString(*_aidl_return);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StreamOutHwVolumeHelper::setHwVolumeImpl(
+ const std::vector<float>& in_channelVolumes) {
+ LOG(DEBUG) << __func__ << ": volumes " << ::android::internal::ToString(in_channelVolumes);
+ if (in_channelVolumes.size() != mChannelCount) {
+ LOG(ERROR) << __func__
+ << ": channel count does not match stream channel count: " << mChannelCount;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ for (float volume : in_channelVolumes) {
+ if (volume < StreamOut::HW_VOLUME_MIN || volume > StreamOut::HW_VOLUME_MAX) {
+ LOG(ERROR) << __func__ << ": volume value out of range: " << volume;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ }
+ mHwVolumes = in_channelVolumes;
+ return ndk::ScopedAStatus::ok();
+}
+
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/StreamSwitcher.cpp b/audio/aidl/default/StreamSwitcher.cpp
index 956f413..8ba15a8 100644
--- a/audio/aidl/default/StreamSwitcher.cpp
+++ b/audio/aidl/default/StreamSwitcher.cpp
@@ -31,7 +31,9 @@
namespace aidl::android::hardware::audio::core {
StreamSwitcher::StreamSwitcher(StreamContext* context, const Metadata& metadata)
- : mMetadata(metadata), mStream(new InnerStreamWrapper<StreamStub>(context, mMetadata)) {}
+ : mContext(context),
+ mMetadata(metadata),
+ mStream(new InnerStreamWrapper<StreamStub>(context, mMetadata)) {}
ndk::ScopedAStatus StreamSwitcher::closeCurrentStream(bool validateStreamState) {
if (!mStream) return ndk::ScopedAStatus::ok();
@@ -100,6 +102,10 @@
}
ndk::ScopedAStatus StreamSwitcher::addEffect(const std::shared_ptr<IEffect>& in_effect) {
+ if (in_effect == nullptr) {
+ LOG(DEBUG) << __func__ << ": null effect";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
if (mStream == nullptr) {
LOG(ERROR) << __func__ << ": stream was closed";
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
@@ -112,15 +118,18 @@
}
ndk::ScopedAStatus StreamSwitcher::removeEffect(const std::shared_ptr<IEffect>& in_effect) {
+ if (in_effect == nullptr) {
+ LOG(DEBUG) << __func__ << ": null effect";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
if (mStream == nullptr) {
LOG(ERROR) << __func__ << ": stream was closed";
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
- for (auto it = mEffects.begin(); it != mEffects.end();) {
+ for (auto it = mEffects.begin(); it != mEffects.end(); ++it) {
if ((*it)->asBinder() == in_effect->asBinder()) {
- it = mEffects.erase(it);
- } else {
- ++it;
+ mEffects.erase(it);
+ break;
}
}
return !mIsStubStream ? mStream->removeEffect(in_effect) : ndk::ScopedAStatus::ok();
@@ -191,6 +200,10 @@
}
// The delegate is null because StreamSwitcher handles IStreamCommon methods by itself.
if (ndk::ScopedAStatus status = mStream->initInstance(nullptr); !status.isOk()) {
+ if (mIsStubStream) {
+ LOG(FATAL) << __func__
+ << ": failed to initialize stub stream: " << status.getDescription();
+ }
// Need to close the current failed stream, and report an error.
// Since we can't operate without a stream implementation, put a stub in.
RETURN_STATUS_IF_ERROR(closeCurrentStream(false /*validateStreamState*/));
@@ -223,8 +236,28 @@
<< status.getDescription();
}
}
+ if (mBluetoothParametersUpdated) {
+ if (auto status = mStream->bluetoothParametersUpdated(); !status.isOk()) {
+ LOG(WARNING) << __func__
+ << ": error while updating BT parameters for a new stream: "
+ << status.getDescription();
+ }
+ }
+ mBluetoothParametersUpdated = false;
}
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus StreamSwitcher::bluetoothParametersUpdated() {
+ if (mStream == nullptr) {
+ LOG(ERROR) << __func__ << ": stream was closed";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ if (mIsStubStream) {
+ mBluetoothParametersUpdated = true;
+ return ndk::ScopedAStatus::ok();
+ }
+ return mStream->bluetoothParametersUpdated();
+}
+
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/alsa/Mixer.h b/audio/aidl/default/alsa/Mixer.h
index 78728c2..8fba1e0 100644
--- a/audio/aidl/default/alsa/Mixer.h
+++ b/audio/aidl/default/alsa/Mixer.h
@@ -72,7 +72,7 @@
std::mutex mMixerAccess;
// The mixer object is owned by ALSA and will be released when the mixer is closed.
struct mixer* const mMixer;
- // `mMixerControls` will only be initialized in constructor. After that, it wil only be
+ // `mMixerControls` will only be initialized in constructor. After that, it will only be
// read but not be modified. Each mixer_ctl object is owned by ALSA, it's life span is
// the same as of the mixer itself.
const Controls mMixerControls;
diff --git a/audio/aidl/default/alsa/StreamAlsa.cpp b/audio/aidl/default/alsa/StreamAlsa.cpp
index 00a7a84..0605d6f 100644
--- a/audio/aidl/default/alsa/StreamAlsa.cpp
+++ b/audio/aidl/default/alsa/StreamAlsa.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <cmath>
#include <limits>
#define LOG_TAG "AHAL_StreamAlsa"
@@ -29,7 +30,9 @@
StreamAlsa::StreamAlsa(StreamContext* context, const Metadata& metadata, int readWriteRetries)
: StreamCommonImpl(context, metadata),
+ mBufferSizeFrames(getContext().getBufferSizeInFrames()),
mFrameSizeBytes(getContext().getFrameSize()),
+ mSampleRate(getContext().getSampleRate()),
mIsInput(isInput(metadata)),
mConfig(alsa::getPcmConfig(getContext(), mIsInput)),
mReadWriteRetries(readWriteRetries) {}
@@ -39,17 +42,20 @@
}
::android::status_t StreamAlsa::drain(StreamDescriptor::DrainMode) {
- usleep(1000);
+ if (!mIsInput) {
+ static constexpr float kMicrosPerSecond = MICROS_PER_SECOND;
+ const size_t delayUs = static_cast<size_t>(
+ std::roundf(mBufferSizeFrames * kMicrosPerSecond / mSampleRate));
+ usleep(delayUs);
+ }
return ::android::OK;
}
::android::status_t StreamAlsa::flush() {
- usleep(1000);
return ::android::OK;
}
::android::status_t StreamAlsa::pause() {
- usleep(1000);
return ::android::OK;
}
@@ -59,6 +65,10 @@
}
::android::status_t StreamAlsa::start() {
+ if (!mAlsaDeviceProxies.empty()) {
+ // This is a resume after a pause.
+ return ::android::OK;
+ }
decltype(mAlsaDeviceProxies) alsaDeviceProxies;
for (const auto& device : getDeviceProfiles()) {
alsa::DeviceProxy proxy;
@@ -71,8 +81,7 @@
true /*require_exact_match*/);
} else {
proxy = alsa::openProxyForAttachedDevice(
- device, const_cast<struct pcm_config*>(&mConfig.value()),
- getContext().getBufferSizeInFrames());
+ device, const_cast<struct pcm_config*>(&mConfig.value()), mBufferSizeFrames);
}
if (!proxy) {
return ::android::NO_INIT;
@@ -85,13 +94,13 @@
::android::status_t StreamAlsa::transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
int32_t* latencyMs) {
+ if (mAlsaDeviceProxies.empty()) {
+ LOG(FATAL) << __func__ << ": no opened devices";
+ return ::android::NO_INIT;
+ }
const size_t bytesToTransfer = frameCount * mFrameSizeBytes;
unsigned maxLatency = 0;
if (mIsInput) {
- if (mAlsaDeviceProxies.empty()) {
- LOG(FATAL) << __func__ << ": no input devices";
- return ::android::NO_INIT;
- }
// For input case, only support single device.
proxy_read_with_retries(mAlsaDeviceProxies[0].get(), buffer, bytesToTransfer,
mReadWriteRetries);
@@ -108,11 +117,14 @@
return ::android::OK;
}
-::android::status_t StreamAlsa::getPosition(StreamDescriptor::Position* position) {
+::android::status_t StreamAlsa::refinePosition(StreamDescriptor::Position* position) {
if (mAlsaDeviceProxies.empty()) {
- LOG(FATAL) << __func__ << ": no input devices";
+ LOG(FATAL) << __func__ << ": no opened devices";
return ::android::NO_INIT;
}
+ // Since the proxy can only count transferred frames since its creation,
+ // we override its counter value with ours and let it to correct for buffered frames.
+ alsa::resetTransferredFrames(mAlsaDeviceProxies[0], position->frames);
if (mIsInput) {
if (int ret = proxy_get_capture_position(mAlsaDeviceProxies[0].get(), &position->frames,
&position->timeNs);
diff --git a/audio/aidl/default/alsa/Utils.cpp b/audio/aidl/default/alsa/Utils.cpp
index 20f7797..9dcd024 100644
--- a/audio/aidl/default/alsa/Utils.cpp
+++ b/audio/aidl/default/alsa/Utils.cpp
@@ -262,12 +262,14 @@
}
DeviceProxy makeDeviceProxy() {
- return DeviceProxy(new alsa_device_proxy, [](alsa_device_proxy* proxy) {
+ DeviceProxy proxy(new alsa_device_proxy, [](alsa_device_proxy* proxy) {
if (proxy != nullptr) {
proxy_close(proxy);
delete proxy;
}
});
+ memset(proxy.get(), 0, sizeof(alsa_device_proxy));
+ return proxy;
}
DeviceProxy openProxyForAttachedDevice(const DeviceProfile& deviceProfile,
@@ -334,6 +336,12 @@
return profile;
}
+void resetTransferredFrames(DeviceProxy& proxy, uint64_t frames) {
+ if (proxy != nullptr) {
+ proxy->transferred = frames;
+ }
+}
+
AudioFormatDescription c2aidl_pcm_format_AudioFormatDescription(enum pcm_format legacy) {
return findValueOrDefault(getPcmFormatToAudioFormatDescMap(), legacy, AudioFormatDescription());
}
diff --git a/audio/aidl/default/alsa/Utils.h b/audio/aidl/default/alsa/Utils.h
index 615e657..37414b3 100644
--- a/audio/aidl/default/alsa/Utils.h
+++ b/audio/aidl/default/alsa/Utils.h
@@ -66,6 +66,7 @@
DeviceProxy openProxyForExternalDevice(const DeviceProfile& deviceProfile,
struct pcm_config* pcmConfig, bool requireExactMatch);
std::optional<alsa_device_profile> readAlsaDeviceInfo(const DeviceProfile& deviceProfile);
+void resetTransferredFrames(DeviceProxy& proxy, uint64_t frames);
::aidl::android::media::audio::common::AudioFormatDescription
c2aidl_pcm_format_AudioFormatDescription(enum pcm_format legacy);
diff --git a/audio/aidl/default/android.hardware.audio.service-aidl.example.rc b/audio/aidl/default/android.hardware.audio.service-aidl.example.rc
index 2068735..757976f 100644
--- a/audio/aidl/default/android.hardware.audio.service-aidl.example.rc
+++ b/audio/aidl/default/android.hardware.audio.service-aidl.example.rc
@@ -3,7 +3,7 @@
user audioserver
# media gid needed for /dev/fm (radio) and for /data/misc/media (tee)
group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct wakelock context_hub
- capabilities BLOCK_SUSPEND
+ capabilities BLOCK_SUSPEND SYS_NICE
# setting RLIMIT_RTPRIO allows binder RT priority inheritance
rlimit rtprio 10 10
ioprio rt 4
diff --git a/audio/aidl/default/android.hardware.audio.service-aidl.xml b/audio/aidl/default/android.hardware.audio.service-aidl.xml
index c9d6314..9db6061 100644
--- a/audio/aidl/default/android.hardware.audio.service-aidl.xml
+++ b/audio/aidl/default/android.hardware.audio.service-aidl.xml
@@ -22,6 +22,11 @@
<hal format="aidl">
<name>android.hardware.audio.core</name>
<version>1</version>
+ <fqname>IModule/bluetooth</fqname>
+ </hal>
+ <hal format="aidl">
+ <name>android.hardware.audio.core</name>
+ <version>1</version>
<fqname>IConfig/default</fqname>
</hal>
</manifest>
diff --git a/audio/aidl/default/bluetooth/DevicePortProxy.cpp b/audio/aidl/default/bluetooth/DevicePortProxy.cpp
new file mode 100644
index 0000000..12e204a
--- /dev/null
+++ b/audio/aidl/default/bluetooth/DevicePortProxy.cpp
@@ -0,0 +1,577 @@
+/*
+ * Copyright 2023 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 "AHAL_BluetoothPortProxy"
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <audio_utils/primitives.h>
+#include <inttypes.h>
+#include <log/log.h>
+
+#include "core-impl/DevicePortProxy.h"
+
+namespace android::bluetooth::audio::aidl {
+
+namespace {
+
+// The maximum time to wait in std::condition_variable::wait_for()
+constexpr unsigned int kMaxWaitingTimeMs = 4500;
+
+} // namespace
+
+using ::aidl::android::hardware::audio::common::SinkMetadata;
+using ::aidl::android::hardware::audio::common::SourceMetadata;
+using ::aidl::android::hardware::bluetooth::audio::AudioConfiguration;
+using ::aidl::android::hardware::bluetooth::audio::BluetoothAudioSessionControl;
+using ::aidl::android::hardware::bluetooth::audio::BluetoothAudioStatus;
+using ::aidl::android::hardware::bluetooth::audio::ChannelMode;
+using ::aidl::android::hardware::bluetooth::audio::PcmConfiguration;
+using ::aidl::android::hardware::bluetooth::audio::PortStatusCallbacks;
+using ::aidl::android::hardware::bluetooth::audio::PresentationPosition;
+using ::aidl::android::hardware::bluetooth::audio::SessionType;
+using ::aidl::android::media::audio::common::AudioDeviceDescription;
+using ::aidl::android::media::audio::common::AudioDeviceType;
+using ::android::base::StringPrintf;
+
+std::ostream& operator<<(std::ostream& os, const BluetoothStreamState& state) {
+ switch (state) {
+ case BluetoothStreamState::DISABLED:
+ return os << "DISABLED";
+ case BluetoothStreamState::STANDBY:
+ return os << "STANDBY";
+ case BluetoothStreamState::STARTING:
+ return os << "STARTING";
+ case BluetoothStreamState::STARTED:
+ return os << "STARTED";
+ case BluetoothStreamState::SUSPENDING:
+ return os << "SUSPENDING";
+ case BluetoothStreamState::UNKNOWN:
+ return os << "UNKNOWN";
+ default:
+ return os << android::base::StringPrintf("%#hhx", state);
+ }
+}
+
+BluetoothAudioPortAidl::BluetoothAudioPortAidl()
+ : mCookie(::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined),
+ mState(BluetoothStreamState::DISABLED),
+ mSessionType(SessionType::UNKNOWN) {}
+
+BluetoothAudioPortAidl::~BluetoothAudioPortAidl() {
+ unregisterPort();
+}
+
+bool BluetoothAudioPortAidl::registerPort(const AudioDeviceDescription& description) {
+ if (inUse()) {
+ LOG(ERROR) << __func__ << debugMessage() << " already in use";
+ return false;
+ }
+
+ if (!initSessionType(description)) return false;
+
+ auto control_result_cb = [port = this](uint16_t cookie, bool start_resp,
+ const BluetoothAudioStatus& status) {
+ (void)start_resp;
+ port->controlResultHandler(cookie, status);
+ };
+ auto session_changed_cb = [port = this](uint16_t cookie) {
+ port->sessionChangedHandler(cookie);
+ };
+ // TODO: Add audio_config_changed_cb
+ PortStatusCallbacks cbacks = {
+ .control_result_cb_ = control_result_cb,
+ .session_changed_cb_ = session_changed_cb,
+ };
+ mCookie = BluetoothAudioSessionControl::RegisterControlResultCback(mSessionType, cbacks);
+ auto isOk = (mCookie != ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined);
+ if (isOk) {
+ std::lock_guard guard(mCvMutex);
+ mState = BluetoothStreamState::STANDBY;
+ }
+ LOG(DEBUG) << __func__ << debugMessage();
+ return isOk;
+}
+
+bool BluetoothAudioPortAidl::initSessionType(const AudioDeviceDescription& description) {
+ if (description.connection == AudioDeviceDescription::CONNECTION_BT_A2DP &&
+ (description.type == AudioDeviceType::OUT_DEVICE ||
+ description.type == AudioDeviceType::OUT_HEADPHONE ||
+ description.type == AudioDeviceType::OUT_SPEAKER)) {
+ LOG(VERBOSE) << __func__
+ << ": device=AUDIO_DEVICE_OUT_BLUETOOTH_A2DP (HEADPHONES/SPEAKER) ("
+ << description.toString() << ")";
+ mSessionType = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH;
+ } else if (description.connection == AudioDeviceDescription::CONNECTION_WIRELESS &&
+ description.type == AudioDeviceType::OUT_HEARING_AID) {
+ LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_HEARING_AID (MEDIA/VOICE) ("
+ << description.toString() << ")";
+ mSessionType = SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
+ } else if (description.connection == AudioDeviceDescription::CONNECTION_BT_LE &&
+ description.type == AudioDeviceType::OUT_HEADSET) {
+ LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLE_HEADSET (MEDIA/VOICE) ("
+ << description.toString() << ")";
+ mSessionType = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
+ } else if (description.connection == AudioDeviceDescription::CONNECTION_BT_LE &&
+ description.type == AudioDeviceType::OUT_SPEAKER) {
+ LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLE_SPEAKER (MEDIA) ("
+ << description.toString() << ")";
+ mSessionType = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
+ } else if (description.connection == AudioDeviceDescription::CONNECTION_BT_LE &&
+ description.type == AudioDeviceType::IN_HEADSET) {
+ LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_IN_BLE_HEADSET (VOICE) ("
+ << description.toString() << ")";
+ mSessionType = SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH;
+ } else if (description.connection == AudioDeviceDescription::CONNECTION_BT_LE &&
+ description.type == AudioDeviceType::OUT_BROADCAST) {
+ LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLE_BROADCAST (MEDIA) ("
+ << description.toString() << ")";
+ mSessionType = SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH;
+ } else {
+ LOG(ERROR) << __func__ << ": unknown device=" << description.toString();
+ return false;
+ }
+
+ if (!BluetoothAudioSessionControl::IsSessionReady(mSessionType)) {
+ LOG(ERROR) << __func__ << ": device=" << description.toString()
+ << ", session_type=" << toString(mSessionType) << " is not ready";
+ return false;
+ }
+ return true;
+}
+
+void BluetoothAudioPortAidl::unregisterPort() {
+ if (!inUse()) {
+ LOG(WARNING) << __func__ << ": BluetoothAudioPortAidl is not in use";
+ return;
+ }
+ BluetoothAudioSessionControl::UnregisterControlResultCback(mSessionType, mCookie);
+ mCookie = ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined;
+ LOG(VERBOSE) << __func__ << debugMessage() << " port unregistered";
+}
+
+void BluetoothAudioPortAidl::controlResultHandler(uint16_t cookie,
+ const BluetoothAudioStatus& status) {
+ std::lock_guard guard(mCvMutex);
+ if (!inUse()) {
+ LOG(ERROR) << "control_result_cb: BluetoothAudioPortAidl is not in use";
+ return;
+ }
+ if (mCookie != cookie) {
+ LOG(ERROR) << "control_result_cb: proxy of device port (cookie="
+ << StringPrintf("%#hx", cookie) << ") is corrupted";
+ return;
+ }
+ BluetoothStreamState previous_state = mState;
+ LOG(INFO) << "control_result_cb:" << debugMessage() << ", previous_state=" << previous_state
+ << ", status=" << toString(status);
+
+ switch (previous_state) {
+ case BluetoothStreamState::STARTED:
+ /* Only Suspend signal can be send in STARTED state*/
+ if (status == BluetoothAudioStatus::RECONFIGURATION ||
+ status == BluetoothAudioStatus::SUCCESS) {
+ mState = BluetoothStreamState::STANDBY;
+ } else {
+ LOG(WARNING) << StringPrintf(
+ "control_result_cb: status=%s failure for session_type= %s, cookie=%#hx, "
+ "previous_state=%#hhx",
+ toString(status).c_str(), toString(mSessionType).c_str(), mCookie,
+ previous_state);
+ }
+ break;
+ case BluetoothStreamState::STARTING:
+ if (status == BluetoothAudioStatus::SUCCESS) {
+ mState = BluetoothStreamState::STARTED;
+ } else {
+ // Set to standby since the stack may be busy switching between outputs
+ LOG(WARNING) << StringPrintf(
+ "control_result_cb: status=%s failure for session_type= %s, cookie=%#hx, "
+ "previous_state=%#hhx",
+ toString(status).c_str(), toString(mSessionType).c_str(), mCookie,
+ previous_state);
+ mState = BluetoothStreamState::STANDBY;
+ }
+ break;
+ case BluetoothStreamState::SUSPENDING:
+ if (status == BluetoothAudioStatus::SUCCESS) {
+ mState = BluetoothStreamState::STANDBY;
+ } else {
+ // It will be failed if the headset is disconnecting, and set to disable
+ // to wait for re-init again
+ LOG(WARNING) << StringPrintf(
+ "control_result_cb: status=%s failure for session_type= %s, cookie=%#hx, "
+ "previous_state=%#hhx",
+ toString(status).c_str(), toString(mSessionType).c_str(), mCookie,
+ previous_state);
+ mState = BluetoothStreamState::DISABLED;
+ }
+ break;
+ default:
+ LOG(ERROR) << "control_result_cb: unexpected previous_state="
+ << StringPrintf(
+ "control_result_cb: status=%s failure for session_type= %s, "
+ "cookie=%#hx, previous_state=%#hhx",
+ toString(status).c_str(), toString(mSessionType).c_str(), mCookie,
+ previous_state);
+ return;
+ }
+ mInternalCv.notify_all();
+}
+
+void BluetoothAudioPortAidl::sessionChangedHandler(uint16_t cookie) {
+ std::lock_guard guard(mCvMutex);
+ if (!inUse()) {
+ LOG(ERROR) << "session_changed_cb: BluetoothAudioPortAidl is not in use";
+ return;
+ }
+ if (mCookie != cookie) {
+ LOG(ERROR) << "session_changed_cb: proxy of device port (cookie="
+ << StringPrintf("%#hx", cookie) << ") is corrupted";
+ return;
+ }
+ BluetoothStreamState previous_state = mState;
+ LOG(VERBOSE) << "session_changed_cb:" << debugMessage()
+ << ", previous_state=" << previous_state;
+ mState = BluetoothStreamState::DISABLED;
+ mInternalCv.notify_all();
+}
+
+bool BluetoothAudioPortAidl::inUse() const {
+ return (mCookie != ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined);
+}
+
+bool BluetoothAudioPortAidl::getPreferredDataIntervalUs(size_t* interval_us) const {
+ if (!interval_us) {
+ LOG(ERROR) << __func__ << ": bad input arg";
+ return false;
+ }
+
+ if (!inUse()) {
+ LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+ return false;
+ }
+
+ const AudioConfiguration& hal_audio_cfg =
+ BluetoothAudioSessionControl::GetAudioConfig(mSessionType);
+ if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) {
+ LOG(ERROR) << __func__ << ": unsupported audio cfg tag";
+ return false;
+ }
+
+ *interval_us = hal_audio_cfg.get<AudioConfiguration::pcmConfig>().dataIntervalUs;
+ return true;
+}
+
+bool BluetoothAudioPortAidl::loadAudioConfig(PcmConfiguration* audio_cfg) const {
+ if (!audio_cfg) {
+ LOG(ERROR) << __func__ << ": bad input arg";
+ return false;
+ }
+
+ if (!inUse()) {
+ LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+ return false;
+ }
+
+ const AudioConfiguration& hal_audio_cfg =
+ BluetoothAudioSessionControl::GetAudioConfig(mSessionType);
+ if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) {
+ LOG(ERROR) << __func__ << ": unsupported audio cfg tag";
+ return false;
+ }
+ *audio_cfg = hal_audio_cfg.get<AudioConfiguration::pcmConfig>();
+ LOG(VERBOSE) << __func__ << debugMessage() << ", state*=" << getState() << ", PcmConfig=["
+ << audio_cfg->toString() << "]";
+ if (audio_cfg->channelMode == ChannelMode::UNKNOWN) {
+ return false;
+ }
+ return true;
+}
+
+bool BluetoothAudioPortAidl::standby() {
+ if (!inUse()) {
+ LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+ return false;
+ }
+ std::lock_guard guard(mCvMutex);
+ LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState() << " request";
+ if (mState == BluetoothStreamState::DISABLED) {
+ mState = BluetoothStreamState::STANDBY;
+ LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState() << " done";
+ return true;
+ }
+ return false;
+}
+
+bool BluetoothAudioPortAidl::condWaitState(BluetoothStreamState state) {
+ const auto waitTime = std::chrono::milliseconds(kMaxWaitingTimeMs);
+ std::unique_lock lock(mCvMutex);
+ base::ScopedLockAssertion lock_assertion(mCvMutex);
+ switch (state) {
+ case BluetoothStreamState::STARTING: {
+ LOG(VERBOSE) << __func__ << debugMessage() << " waiting for STARTED";
+ mInternalCv.wait_for(lock, waitTime, [this] {
+ base::ScopedLockAssertion lock_assertion(mCvMutex);
+ return mState != BluetoothStreamState::STARTING;
+ });
+ return mState == BluetoothStreamState::STARTED;
+ }
+ case BluetoothStreamState::SUSPENDING: {
+ LOG(VERBOSE) << __func__ << debugMessage() << " waiting for SUSPENDED";
+ mInternalCv.wait_for(lock, waitTime, [this] {
+ base::ScopedLockAssertion lock_assertion(mCvMutex);
+ return mState != BluetoothStreamState::SUSPENDING;
+ });
+ return mState == BluetoothStreamState::STANDBY;
+ }
+ default:
+ LOG(WARNING) << __func__ << debugMessage() << " waiting for KNOWN";
+ return false;
+ }
+ return false;
+}
+
+bool BluetoothAudioPortAidl::start() {
+ if (!inUse()) {
+ LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+ return false;
+ }
+ LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState()
+ << ", mono=" << (mIsStereoToMono ? "true" : "false") << " request";
+
+ {
+ std::unique_lock lock(mCvMutex);
+ base::ScopedLockAssertion lock_assertion(mCvMutex);
+ if (mState == BluetoothStreamState::STARTED) {
+ return true; // nop, return
+ } else if (mState == BluetoothStreamState::SUSPENDING ||
+ mState == BluetoothStreamState::STARTING) {
+ /* If port is in transient state, give some time to respond */
+ auto state_ = mState;
+ lock.unlock();
+ if (!condWaitState(state_)) {
+ LOG(ERROR) << __func__ << debugMessage() << ", state=" << getState() << " failure";
+ return false;
+ }
+ }
+ }
+
+ bool retval = false;
+ {
+ std::unique_lock lock(mCvMutex);
+ base::ScopedLockAssertion lock_assertion(mCvMutex);
+ if (mState == BluetoothStreamState::STARTED) {
+ retval = true;
+ } else if (mState == BluetoothStreamState::STANDBY) {
+ mState = BluetoothStreamState::STARTING;
+ lock.unlock();
+ if (BluetoothAudioSessionControl::StartStream(mSessionType)) {
+ retval = condWaitState(BluetoothStreamState::STARTING);
+ } else {
+ LOG(ERROR) << __func__ << debugMessage() << ", state=" << getState()
+ << " Hal fails";
+ }
+ }
+ }
+
+ if (retval) {
+ LOG(INFO) << __func__ << debugMessage() << ", state=" << getState()
+ << ", mono=" << (mIsStereoToMono ? "true" : "false") << " done";
+ } else {
+ LOG(ERROR) << __func__ << debugMessage() << ", state=" << getState() << " failure";
+ }
+
+ return retval; // false if any failure like timeout
+}
+
+bool BluetoothAudioPortAidl::suspend() {
+ if (!inUse()) {
+ LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+ return false;
+ }
+ LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState() << " request";
+
+ {
+ std::unique_lock lock(mCvMutex);
+ base::ScopedLockAssertion lock_assertion(mCvMutex);
+ if (mState == BluetoothStreamState::STANDBY) {
+ return true; // nop, return
+ } else if (mState == BluetoothStreamState::SUSPENDING ||
+ mState == BluetoothStreamState::STARTING) {
+ /* If port is in transient state, give some time to respond */
+ auto state_ = mState;
+ lock.unlock();
+ if (!condWaitState(state_)) {
+ LOG(ERROR) << __func__ << debugMessage() << ", state=" << getState() << " failure";
+ return false;
+ }
+ }
+ }
+
+ bool retval = false;
+ {
+ std::unique_lock lock(mCvMutex);
+ base::ScopedLockAssertion lock_assertion(mCvMutex);
+ if (mState == BluetoothStreamState::STANDBY) {
+ retval = true;
+ } else if (mState == BluetoothStreamState::STARTED) {
+ mState = BluetoothStreamState::SUSPENDING;
+ lock.unlock();
+ if (BluetoothAudioSessionControl::SuspendStream(mSessionType)) {
+ retval = condWaitState(BluetoothStreamState::SUSPENDING);
+ } else {
+ LOG(ERROR) << __func__ << debugMessage() << ", state=" << getState()
+ << " Hal fails";
+ }
+ }
+ }
+
+ if (retval) {
+ LOG(INFO) << __func__ << debugMessage() << ", state=" << getState() << " done";
+ } else {
+ LOG(ERROR) << __func__ << debugMessage() << ", state=" << getState() << " failure";
+ }
+
+ return retval; // false if any failure like timeout
+}
+
+void BluetoothAudioPortAidl::stop() {
+ if (!inUse()) {
+ LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+ return;
+ }
+ std::lock_guard guard(mCvMutex);
+ LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState() << " request";
+ if (mState != BluetoothStreamState::DISABLED) {
+ BluetoothAudioSessionControl::StopStream(mSessionType);
+ mState = BluetoothStreamState::DISABLED;
+ }
+ LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState() << " done";
+}
+
+size_t BluetoothAudioPortAidlOut::writeData(const void* buffer, size_t bytes) const {
+ if (!buffer) {
+ LOG(ERROR) << __func__ << ": bad input arg";
+ return 0;
+ }
+
+ if (!inUse()) {
+ LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+ return 0;
+ }
+
+ if (!mIsStereoToMono) {
+ return BluetoothAudioSessionControl::OutWritePcmData(mSessionType, buffer, bytes);
+ }
+
+ // WAR to mix the stereo into Mono (16 bits per sample)
+ const size_t write_frames = bytes >> 2;
+ if (write_frames == 0) return 0;
+ auto src = static_cast<const int16_t*>(buffer);
+ std::unique_ptr<int16_t[]> dst{new int16_t[write_frames]};
+ downmix_to_mono_i16_from_stereo_i16(dst.get(), src, write_frames);
+ // a frame is 16 bits, and the size of a mono frame is equal to half a stereo.
+ auto totalWrite = BluetoothAudioSessionControl::OutWritePcmData(mSessionType, dst.get(),
+ write_frames * 2);
+ return totalWrite * 2;
+}
+
+size_t BluetoothAudioPortAidlIn::readData(void* buffer, size_t bytes) const {
+ if (!buffer) {
+ LOG(ERROR) << __func__ << ": bad input arg";
+ return 0;
+ }
+
+ if (!inUse()) {
+ LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+ return 0;
+ }
+
+ return BluetoothAudioSessionControl::InReadPcmData(mSessionType, buffer, bytes);
+}
+
+bool BluetoothAudioPortAidl::getPresentationPosition(
+ PresentationPosition& presentation_position) const {
+ if (!inUse()) {
+ LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+ return false;
+ }
+ bool retval = BluetoothAudioSessionControl::GetPresentationPosition(mSessionType,
+ presentation_position);
+ LOG(VERBOSE) << __func__ << debugMessage() << ", state=" << getState()
+ << presentation_position.toString();
+
+ return retval;
+}
+
+bool BluetoothAudioPortAidl::updateSourceMetadata(const SourceMetadata& source_metadata) const {
+ if (!inUse()) {
+ LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+ return false;
+ }
+ LOG(DEBUG) << __func__ << debugMessage() << ", state=" << getState() << ", "
+ << source_metadata.tracks.size() << " track(s)";
+ if (source_metadata.tracks.size() == 0) return true;
+ return BluetoothAudioSessionControl::UpdateSourceMetadata(mSessionType, source_metadata);
+}
+
+bool BluetoothAudioPortAidl::updateSinkMetadata(const SinkMetadata& sink_metadata) const {
+ if (!inUse()) {
+ LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+ return false;
+ }
+ LOG(DEBUG) << __func__ << debugMessage() << ", state=" << getState() << ", "
+ << sink_metadata.tracks.size() << " track(s)";
+ if (sink_metadata.tracks.size() == 0) return true;
+ return BluetoothAudioSessionControl::UpdateSinkMetadata(mSessionType, sink_metadata);
+}
+
+BluetoothStreamState BluetoothAudioPortAidl::getState() const {
+ return mState;
+}
+
+bool BluetoothAudioPortAidl::setState(BluetoothStreamState state) {
+ if (!inUse()) {
+ LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
+ return false;
+ }
+ std::lock_guard guard(mCvMutex);
+ LOG(DEBUG) << __func__ << ": BluetoothAudioPortAidl old state = " << mState
+ << " new state = " << state;
+ mState = state;
+ return true;
+}
+
+bool BluetoothAudioPortAidl::isA2dp() const {
+ return mSessionType == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
+ mSessionType == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
+}
+
+bool BluetoothAudioPortAidl::isLeAudio() const {
+ return mSessionType == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
+ mSessionType == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH ||
+ mSessionType == SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+ mSessionType == SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
+ mSessionType == SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH ||
+ mSessionType == SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
+}
+
+std::string BluetoothAudioPortAidl::debugMessage() const {
+ return StringPrintf(": session_type=%s, cookie=%#hx", toString(mSessionType).c_str(), mCookie);
+}
+
+} // namespace android::bluetooth::audio::aidl
diff --git a/audio/aidl/default/bluetooth/ModuleBluetooth.cpp b/audio/aidl/default/bluetooth/ModuleBluetooth.cpp
new file mode 100644
index 0000000..bfe7ca0
--- /dev/null
+++ b/audio/aidl/default/bluetooth/ModuleBluetooth.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2023 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 "AHAL_ModuleBluetooth"
+
+#include <android-base/logging.h>
+
+#include "core-impl/ModuleBluetooth.h"
+#include "core-impl/StreamBluetooth.h"
+
+namespace aidl::android::hardware::audio::core {
+
+using aidl::android::hardware::audio::common::SinkMetadata;
+using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::media::audio::common::AudioOffloadInfo;
+using aidl::android::media::audio::common::MicrophoneInfo;
+
+ndk::ScopedAStatus ModuleBluetooth::getBluetoothA2dp(
+ std::shared_ptr<IBluetoothA2dp>* _aidl_return) {
+ if (!mBluetoothA2dp) {
+ auto handle = ndk::SharedRefBase::make<BluetoothA2dp>();
+ handle->registerHandler(std::bind(&ModuleBluetooth::bluetoothParametersUpdated, this));
+ mBluetoothA2dp = handle;
+ }
+ *_aidl_return = mBluetoothA2dp.getInstance();
+ LOG(DEBUG) << __func__ << ": returning instance of IBluetoothA2dp: " << _aidl_return->get();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ModuleBluetooth::getBluetoothLe(std::shared_ptr<IBluetoothLe>* _aidl_return) {
+ if (!mBluetoothLe) {
+ auto handle = ndk::SharedRefBase::make<BluetoothLe>();
+ handle->registerHandler(std::bind(&ModuleBluetooth::bluetoothParametersUpdated, this));
+ mBluetoothLe = handle;
+ }
+ *_aidl_return = mBluetoothLe.getInstance();
+ LOG(DEBUG) << __func__ << ": returning instance of IBluetoothLe: " << _aidl_return->get();
+ return ndk::ScopedAStatus::ok();
+}
+
+Module::BtProfileHandles ModuleBluetooth::getBtProfileManagerHandles() {
+ return std::make_tuple(std::weak_ptr<IBluetooth>(), mBluetoothA2dp.getInstance(),
+ mBluetoothLe.getInstance());
+}
+
+ndk::ScopedAStatus ModuleBluetooth::getMicMute(bool* _aidl_return __unused) {
+ LOG(DEBUG) << __func__ << ": is not supported";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus ModuleBluetooth::setMicMute(bool in_mute __unused) {
+ LOG(DEBUG) << __func__ << ": is not supported";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus ModuleBluetooth::createInputStream(
+ StreamContext&& context, const SinkMetadata& sinkMetadata,
+ const std::vector<MicrophoneInfo>& microphones, std::shared_ptr<StreamIn>* result) {
+ return createStreamInstance<StreamInBluetooth>(result, std::move(context), sinkMetadata,
+ microphones, getBtProfileManagerHandles());
+}
+
+ndk::ScopedAStatus ModuleBluetooth::createOutputStream(
+ StreamContext&& context, const SourceMetadata& sourceMetadata,
+ const std::optional<AudioOffloadInfo>& offloadInfo, std::shared_ptr<StreamOut>* result) {
+ return createStreamInstance<StreamOutBluetooth>(result, std::move(context), sourceMetadata,
+ offloadInfo, getBtProfileManagerHandles());
+}
+
+ndk::ScopedAStatus ModuleBluetooth::onMasterMuteChanged(bool) {
+ LOG(DEBUG) << __func__ << ": is not supported";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus ModuleBluetooth::onMasterVolumeChanged(float) {
+ LOG(DEBUG) << __func__ << ": is not supported";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/bluetooth/StreamBluetooth.cpp b/audio/aidl/default/bluetooth/StreamBluetooth.cpp
new file mode 100644
index 0000000..91a33c2
--- /dev/null
+++ b/audio/aidl/default/bluetooth/StreamBluetooth.cpp
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2023 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 "AHAL_StreamBluetooth"
+
+#include <Utils.h>
+#include <android-base/logging.h>
+#include <audio_utils/clock.h>
+
+#include "BluetoothAudioSessionControl.h"
+#include "core-impl/StreamBluetooth.h"
+
+namespace aidl::android::hardware::audio::core {
+
+using ::aidl::android::hardware::audio::common::SinkMetadata;
+using ::aidl::android::hardware::audio::common::SourceMetadata;
+using ::aidl::android::hardware::audio::core::VendorParameter;
+using ::aidl::android::hardware::bluetooth::audio::ChannelMode;
+using ::aidl::android::hardware::bluetooth::audio::PcmConfiguration;
+using ::aidl::android::hardware::bluetooth::audio::PresentationPosition;
+using ::aidl::android::media::audio::common::AudioChannelLayout;
+using ::aidl::android::media::audio::common::AudioDevice;
+using ::aidl::android::media::audio::common::AudioDeviceAddress;
+using ::aidl::android::media::audio::common::AudioFormatDescription;
+using ::aidl::android::media::audio::common::AudioFormatType;
+using ::aidl::android::media::audio::common::AudioOffloadInfo;
+using ::aidl::android::media::audio::common::MicrophoneDynamicInfo;
+using ::aidl::android::media::audio::common::MicrophoneInfo;
+using ::android::bluetooth::audio::aidl::BluetoothAudioPortAidl;
+using ::android::bluetooth::audio::aidl::BluetoothAudioPortAidlIn;
+using ::android::bluetooth::audio::aidl::BluetoothAudioPortAidlOut;
+using ::android::bluetooth::audio::aidl::BluetoothStreamState;
+
+constexpr int kBluetoothDefaultInputBufferMs = 20;
+constexpr int kBluetoothDefaultOutputBufferMs = 10;
+// constexpr int kBluetoothSpatializerOutputBufferMs = 10;
+
+size_t getFrameCount(uint64_t durationUs, uint32_t sampleRate) {
+ return (durationUs * sampleRate) / 1000000;
+}
+
+// pcm configuration params are not really used by the module
+StreamBluetooth::StreamBluetooth(StreamContext* context, const Metadata& metadata,
+ Module::BtProfileHandles&& btHandles)
+ : StreamCommonImpl(context, metadata),
+ mSampleRate(getContext().getSampleRate()),
+ mChannelLayout(getContext().getChannelLayout()),
+ mFormat(getContext().getFormat()),
+ mFrameSizeBytes(getContext().getFrameSize()),
+ mIsInput(isInput(metadata)),
+ mBluetoothA2dp(std::move(std::get<Module::BtInterface::BTA2DP>(btHandles))),
+ mBluetoothLe(std::move(std::get<Module::BtInterface::BTLE>(btHandles))) {
+ mPreferredDataIntervalUs =
+ mIsInput ? kBluetoothDefaultInputBufferMs : kBluetoothDefaultOutputBufferMs;
+ mPreferredFrameCount = getFrameCount(mPreferredDataIntervalUs, mSampleRate);
+ mIsInitialized = false;
+ mIsReadyToClose = false;
+}
+
+::android::status_t StreamBluetooth::init() {
+ return ::android::OK; // defering this till we get AudioDeviceDescription
+}
+
+const StreamCommonInterface::ConnectedDevices& StreamBluetooth::getConnectedDevices() const {
+ std::lock_guard guard(mLock);
+ return StreamCommonImpl::getConnectedDevices();
+}
+
+ndk::ScopedAStatus StreamBluetooth::setConnectedDevices(
+ const std::vector<AudioDevice>& connectedDevices) {
+ if (mIsInput && connectedDevices.size() > 1) {
+ LOG(ERROR) << __func__ << ": wrong device size(" << connectedDevices.size()
+ << ") for input stream";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ }
+ for (const auto& connectedDevice : connectedDevices) {
+ if (connectedDevice.address.getTag() != AudioDeviceAddress::mac) {
+ LOG(ERROR) << __func__ << ": bad device address" << connectedDevice.address.toString();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ }
+ std::lock_guard guard(mLock);
+ RETURN_STATUS_IF_ERROR(StreamCommonImpl::setConnectedDevices(connectedDevices));
+ mIsInitialized = false; // updated connected device list, need initialization
+ return ndk::ScopedAStatus::ok();
+}
+
+::android::status_t StreamBluetooth::drain(StreamDescriptor::DrainMode) {
+ usleep(1000);
+ return ::android::OK;
+}
+
+::android::status_t StreamBluetooth::flush() {
+ usleep(1000);
+ return ::android::OK;
+}
+
+::android::status_t StreamBluetooth::pause() {
+ return standby();
+}
+
+::android::status_t StreamBluetooth::transfer(void* buffer, size_t frameCount,
+ size_t* actualFrameCount, int32_t* latencyMs) {
+ std::lock_guard guard(mLock);
+ if (!mIsInitialized || mIsReadyToClose) {
+ // 'setConnectedDevices' has been called or stream is ready to close, so no transfers
+ *actualFrameCount = 0;
+ *latencyMs = StreamDescriptor::LATENCY_UNKNOWN;
+ return ::android::OK;
+ }
+ *actualFrameCount = 0;
+ *latencyMs = 0;
+ for (auto proxy : mBtDeviceProxies) {
+ if (!proxy->start()) {
+ LOG(ERROR) << __func__ << ": state = " << proxy->getState() << " failed to start ";
+ return -EIO;
+ }
+ const size_t fc = std::min(frameCount, mPreferredFrameCount);
+ const size_t bytesToTransfer = fc * mFrameSizeBytes;
+ if (mIsInput) {
+ const size_t totalRead = proxy->readData(buffer, bytesToTransfer);
+ *actualFrameCount = std::max(*actualFrameCount, totalRead / mFrameSizeBytes);
+ } else {
+ const size_t totalWrite = proxy->writeData(buffer, bytesToTransfer);
+ *actualFrameCount = std::max(*actualFrameCount, totalWrite / mFrameSizeBytes);
+ }
+ PresentationPosition presentation_position;
+ if (!proxy->getPresentationPosition(presentation_position)) {
+ LOG(ERROR) << __func__ << ": getPresentationPosition returned error ";
+ return ::android::UNKNOWN_ERROR;
+ }
+ *latencyMs =
+ std::max(*latencyMs, (int32_t)(presentation_position.remoteDeviceAudioDelayNanos /
+ NANOS_PER_MILLISECOND));
+ }
+ return ::android::OK;
+}
+
+::android::status_t StreamBluetooth::initialize() {
+ if (!::aidl::android::hardware::bluetooth::audio::BluetoothAudioSession::IsAidlAvailable()) {
+ LOG(ERROR) << __func__ << ": IBluetoothAudioProviderFactory service not available";
+ return ::android::UNKNOWN_ERROR;
+ }
+ if (StreamCommonImpl::getConnectedDevices().empty()) {
+ LOG(ERROR) << __func__ << ", has no connected devices";
+ return ::android::NO_INIT;
+ }
+ // unregister older proxies (if any)
+ for (auto proxy : mBtDeviceProxies) {
+ proxy->stop();
+ proxy->unregisterPort();
+ }
+ mBtDeviceProxies.clear();
+ for (auto it = StreamCommonImpl::getConnectedDevices().begin();
+ it != StreamCommonImpl::getConnectedDevices().end(); ++it) {
+ std::shared_ptr<BluetoothAudioPortAidl> proxy =
+ mIsInput ? std::shared_ptr<BluetoothAudioPortAidl>(
+ std::make_shared<BluetoothAudioPortAidlIn>())
+ : std::shared_ptr<BluetoothAudioPortAidl>(
+ std::make_shared<BluetoothAudioPortAidlOut>());
+ if (proxy->registerPort(it->type)) {
+ LOG(ERROR) << __func__ << ": cannot init HAL";
+ return ::android::UNKNOWN_ERROR;
+ }
+ PcmConfiguration config;
+ if (!proxy->loadAudioConfig(&config)) {
+ LOG(ERROR) << __func__ << ": state=" << proxy->getState()
+ << " failed to get audio config";
+ return ::android::UNKNOWN_ERROR;
+ }
+ // TODO: Ensure minimum duration for spatialized output?
+ // WAR to support Mono / 16 bits per sample as the Bluetooth stack required
+ if (!mIsInput && config.channelMode == ChannelMode::MONO && config.bitsPerSample == 16) {
+ proxy->forcePcmStereoToMono(true);
+ config.channelMode = ChannelMode::STEREO;
+ LOG(INFO) << __func__ << ": force channels = to be AUDIO_CHANNEL_OUT_STEREO";
+ }
+ if (!checkConfigParams(config)) {
+ LOG(ERROR) << __func__ << " checkConfigParams failed";
+ return ::android::UNKNOWN_ERROR;
+ }
+ mBtDeviceProxies.push_back(std::move(proxy));
+ }
+ mIsInitialized = true;
+ return ::android::OK;
+}
+
+bool StreamBluetooth::checkConfigParams(
+ ::aidl::android::hardware::bluetooth::audio::PcmConfiguration& config) {
+ if ((int)mSampleRate != config.sampleRateHz) {
+ LOG(ERROR) << __func__ << ": Sample Rate mismatch, stream val = " << mSampleRate
+ << " hal val = " << config.sampleRateHz;
+ return false;
+ }
+ auto channelCount = aidl::android::hardware::audio::common::getChannelCount(mChannelLayout);
+ if ((config.channelMode == ChannelMode::MONO && channelCount != 1) ||
+ (config.channelMode == ChannelMode::STEREO && channelCount != 2)) {
+ LOG(ERROR) << __func__ << ": Channel count mismatch, stream val = " << channelCount
+ << " hal val = " << toString(config.channelMode);
+ return false;
+ }
+ if (mFormat.type != AudioFormatType::PCM) {
+ LOG(ERROR) << __func__ << ": unexpected format type "
+ << aidl::android::media::audio::common::toString(mFormat.type);
+ return false;
+ }
+ int8_t bps = aidl::android::hardware::audio::common::getPcmSampleSizeInBytes(mFormat.pcm) * 8;
+ if (bps != config.bitsPerSample) {
+ LOG(ERROR) << __func__ << ": bits per sample mismatch, stream val = " << bps
+ << " hal val = " << config.bitsPerSample;
+ return false;
+ }
+ if (config.dataIntervalUs > 0) {
+ mPreferredDataIntervalUs =
+ std::min((int32_t)mPreferredDataIntervalUs, config.dataIntervalUs);
+ mPreferredFrameCount = getFrameCount(mPreferredDataIntervalUs, mSampleRate);
+ }
+ return true;
+}
+
+ndk::ScopedAStatus StreamBluetooth::prepareToClose() {
+ std::lock_guard guard(mLock);
+ mIsReadyToClose = true;
+ return ndk::ScopedAStatus::ok();
+}
+
+::android::status_t StreamBluetooth::standby() {
+ std::lock_guard guard(mLock);
+ if (!mIsInitialized) {
+ if (auto status = initialize(); status != ::android::OK) return status;
+ }
+ for (auto proxy : mBtDeviceProxies) {
+ if (!proxy->suspend()) {
+ LOG(ERROR) << __func__ << ": state = " << proxy->getState() << " failed to stand by ";
+ return -EIO;
+ }
+ }
+ return ::android::OK;
+}
+
+::android::status_t StreamBluetooth::start() {
+ std::lock_guard guard(mLock);
+ if (!mIsInitialized) return initialize();
+ return ::android::OK;
+}
+
+void StreamBluetooth::shutdown() {
+ std::lock_guard guard(mLock);
+ for (auto proxy : mBtDeviceProxies) {
+ proxy->stop();
+ proxy->unregisterPort();
+ }
+ mBtDeviceProxies.clear();
+}
+
+ndk::ScopedAStatus StreamBluetooth::updateMetadataCommon(const Metadata& metadata) {
+ std::lock_guard guard(mLock);
+ if (!mIsInitialized) return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ bool isOk = true;
+ if (isInput(metadata)) {
+ isOk = mBtDeviceProxies[0]->updateSinkMetadata(std::get<SinkMetadata>(metadata));
+ } else {
+ for (auto proxy : mBtDeviceProxies) {
+ if (!proxy->updateSourceMetadata(std::get<SourceMetadata>(metadata))) isOk = false;
+ }
+ }
+ return isOk ? ndk::ScopedAStatus::ok()
+ : ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus StreamBluetooth::bluetoothParametersUpdated() {
+ if (mIsInput) {
+ LOG(WARNING) << __func__ << ": not handled";
+ return ndk::ScopedAStatus::ok();
+ }
+ auto applyParam = [](const std::shared_ptr<BluetoothAudioPortAidl>& proxy,
+ bool isEnabled) -> bool {
+ if (!isEnabled) {
+ if (proxy->suspend()) return proxy->setState(BluetoothStreamState::DISABLED);
+ return false;
+ }
+ return proxy->standby();
+ };
+ bool hasA2dpParam, enableA2dp;
+ auto btA2dp = mBluetoothA2dp.lock();
+ hasA2dpParam = btA2dp != nullptr && btA2dp->isEnabled(&enableA2dp).isOk();
+ bool hasLeParam, enableLe;
+ auto btLe = mBluetoothLe.lock();
+ hasLeParam = btLe != nullptr && btLe->isEnabled(&enableLe).isOk();
+ std::unique_lock lock(mLock);
+ ::android::base::ScopedLockAssertion lock_assertion(mLock);
+ if (!mIsInitialized) {
+ LOG(WARNING) << __func__ << ": init not done";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ for (auto proxy : mBtDeviceProxies) {
+ if ((hasA2dpParam && proxy->isA2dp() && !applyParam(proxy, enableA2dp)) ||
+ (hasLeParam && proxy->isLeAudio() && !applyParam(proxy, enableLe))) {
+ LOG(DEBUG) << __func__ << ": applyParam failed";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ }
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+StreamInBluetooth::StreamInBluetooth(StreamContext&& context, const SinkMetadata& sinkMetadata,
+ const std::vector<MicrophoneInfo>& microphones,
+ Module::BtProfileHandles&& btProfileHandles)
+ : StreamIn(std::move(context), microphones),
+ StreamBluetooth(&mContextInstance, sinkMetadata, std::move(btProfileHandles)) {}
+
+ndk::ScopedAStatus StreamInBluetooth::getActiveMicrophones(
+ std::vector<MicrophoneDynamicInfo>* _aidl_return __unused) {
+ LOG(DEBUG) << __func__ << ": not supported";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+StreamOutBluetooth::StreamOutBluetooth(StreamContext&& context,
+ const SourceMetadata& sourceMetadata,
+ const std::optional<AudioOffloadInfo>& offloadInfo,
+ Module::BtProfileHandles&& btProfileHandles)
+ : StreamOut(std::move(context), offloadInfo),
+ StreamBluetooth(&mContextInstance, sourceMetadata, std::move(btProfileHandles)) {}
+
+} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/config/audioPolicy/engine/api/current.txt b/audio/aidl/default/config/audioPolicy/engine/api/current.txt
index 59574f3..063b05d 100644
--- a/audio/aidl/default/config/audioPolicy/engine/api/current.txt
+++ b/audio/aidl/default/config/audioPolicy/engine/api/current.txt
@@ -209,11 +209,13 @@
public enum UsageEnumType {
method @NonNull public String getRawName();
enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_ALARM;
+ enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_ANNOUNCEMENT;
enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE;
enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_ASSISTANCE_SONIFICATION;
enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_ASSISTANT;
enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_CALL_ASSISTANT;
+ enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_EMERGENCY;
enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_GAME;
enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_MEDIA;
enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_NOTIFICATION;
@@ -222,7 +224,9 @@
enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST;
enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_NOTIFICATION_EVENT;
enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
+ enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_SAFETY;
enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_UNKNOWN;
+ enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_VEHICLE_STATUS;
enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_VIRTUAL_SOURCE;
enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_VOICE_COMMUNICATION;
enum_constant public static final android.audio.policy.engine.configuration.UsageEnumType AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
diff --git a/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd b/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd
index b58a6c8..40396bb 100644
--- a/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd
+++ b/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd
@@ -359,6 +359,10 @@
<xs:enumeration value="AUDIO_USAGE_VIRTUAL_SOURCE"/>
<xs:enumeration value="AUDIO_USAGE_ASSISTANT"/>
<xs:enumeration value="AUDIO_USAGE_CALL_ASSISTANT"/>
+ <xs:enumeration value="AUDIO_USAGE_EMERGENCY" />
+ <xs:enumeration value="AUDIO_USAGE_SAFETY" />
+ <xs:enumeration value="AUDIO_USAGE_VEHICLE_STATUS" />
+ <xs:enumeration value="AUDIO_USAGE_ANNOUNCEMENT" />
</xs:restriction>
</xs:simpleType>
diff --git a/audio/aidl/default/include/core-impl/Bluetooth.h b/audio/aidl/default/include/core-impl/Bluetooth.h
index 10e9045..44899bc 100644
--- a/audio/aidl/default/include/core-impl/Bluetooth.h
+++ b/audio/aidl/default/include/core-impl/Bluetooth.h
@@ -22,6 +22,15 @@
namespace aidl::android::hardware::audio::core {
+class ParamChangeHandler {
+ public:
+ ParamChangeHandler() = default;
+ void registerHandler(std::function<ndk::ScopedAStatus()> handler) { mHandler = handler; }
+
+ protected:
+ std::function<ndk::ScopedAStatus()> mHandler = nullptr;
+};
+
class Bluetooth : public BnBluetooth {
public:
Bluetooth();
@@ -34,7 +43,7 @@
HfpConfig mHfpConfig;
};
-class BluetoothA2dp : public BnBluetoothA2dp {
+class BluetoothA2dp : public BnBluetoothA2dp, public ParamChangeHandler {
public:
BluetoothA2dp() = default;
@@ -49,7 +58,7 @@
bool mEnabled = false;
};
-class BluetoothLe : public BnBluetoothLe {
+class BluetoothLe : public BnBluetoothLe, public ParamChangeHandler {
public:
BluetoothLe() = default;
diff --git a/audio/aidl/default/include/core-impl/Configuration.h b/audio/aidl/default/include/core-impl/Configuration.h
index 25bf7af..6277c38 100644
--- a/audio/aidl/default/include/core-impl/Configuration.h
+++ b/audio/aidl/default/include/core-impl/Configuration.h
@@ -47,5 +47,6 @@
std::unique_ptr<Configuration> getRSubmixConfiguration();
std::unique_ptr<Configuration> getStubConfiguration();
std::unique_ptr<Configuration> getUsbConfiguration();
+std::unique_ptr<Configuration> getBluetoothConfiguration();
} // namespace aidl::android::hardware::audio::core::internal
diff --git a/audio/aidl/default/include/core-impl/DevicePortProxy.h b/audio/aidl/default/include/core-impl/DevicePortProxy.h
new file mode 100644
index 0000000..13b8c91
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/DevicePortProxy.h
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2023 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.
+ */
+
+#pragma once
+
+#include <condition_variable>
+#include <mutex>
+
+#include <android-base/thread_annotations.h>
+
+#include <aidl/android/hardware/audio/common/SinkMetadata.h>
+#include <aidl/android/hardware/audio/common/SourceMetadata.h>
+#include <aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.h>
+#include <aidl/android/hardware/bluetooth/audio/PcmConfiguration.h>
+#include <aidl/android/hardware/bluetooth/audio/SessionType.h>
+#include <aidl/android/media/audio/common/AudioDeviceDescription.h>
+
+#include "BluetoothAudioSessionControl.h"
+
+namespace android::bluetooth::audio::aidl {
+
+enum class BluetoothStreamState : uint8_t {
+ DISABLED = 0, // This stream is closing or Bluetooth profiles (A2DP/LE) is disabled
+ STANDBY,
+ STARTING,
+ STARTED,
+ SUSPENDING,
+ UNKNOWN,
+};
+
+std::ostream& operator<<(std::ostream& os, const BluetoothStreamState& state);
+
+/**
+ * Proxy for Bluetooth Audio HW Module to communicate with Bluetooth Audio
+ * Session Control. All methods are not thread safe, so users must acquire a
+ * lock. Note: currently, getState() of DevicePortProxy is only used for
+ * verbose logging, it is not locked, so the state may not be synchronized.
+ */
+class BluetoothAudioPort {
+ public:
+ BluetoothAudioPort() = default;
+ virtual ~BluetoothAudioPort() = default;
+
+ /**
+ * Fetch output control / data path of BluetoothAudioPort and setup
+ * callbacks into BluetoothAudioProvider. If registerPort() returns false, the audio
+ * HAL must delete this BluetoothAudioPort and return EINVAL to caller
+ */
+ virtual bool registerPort(
+ const ::aidl::android::media::audio::common::AudioDeviceDescription&) = 0;
+
+ /**
+ * Unregister this BluetoothAudioPort from BluetoothAudioSessionControl.
+ * Audio HAL must delete this BluetoothAudioPort after calling this.
+ */
+ virtual void unregisterPort() = 0;
+
+ /**
+ * When the Audio framework / HAL tries to query audio config about format,
+ * channel mask and sample rate, it uses this function to fetch from the
+ * Bluetooth stack
+ */
+ virtual bool loadAudioConfig(
+ ::aidl::android::hardware::bluetooth::audio::PcmConfiguration*) const = 0;
+
+ /**
+ * WAR to support Mono mode / 16 bits per sample
+ */
+ virtual void forcePcmStereoToMono(bool) = 0;
+
+ /**
+ * When the Audio framework / HAL wants to change the stream state, it invokes
+ * these 4 functions to control the Bluetooth stack (Audio Control Path).
+ * Note: standby(), start() and suspend() will return true when there are no errors.
+
+ * Called by Audio framework / HAL to change the state to stand by. When A2DP/LE profile is
+ * disabled, the port is first set to STANDBY by calling suspend and then mState is set to
+ * DISABLED. To reset the state back to STANDBY this method is called.
+ */
+ virtual bool standby() = 0;
+
+ /**
+ * Called by Audio framework / HAL to start the stream
+ */
+ virtual bool start() = 0;
+
+ /**
+ * Called by Audio framework / HAL to suspend the stream
+ */
+ virtual bool suspend() = 0;
+
+ /**
+ * Called by Audio framework / HAL to stop the stream
+ */
+ virtual void stop() = 0;
+
+ /**
+ * Called by the Audio framework / HAL to fetch information about audio frames
+ * presented to an external sink, or frames presented fror an internal sink
+ */
+ virtual bool getPresentationPosition(
+ ::aidl::android::hardware::bluetooth::audio::PresentationPosition&) const = 0;
+
+ /**
+ * Called by the Audio framework / HAL when the metadata of the stream's
+ * source has been changed.
+ */
+ virtual bool updateSourceMetadata(
+ const ::aidl::android::hardware::audio::common::SourceMetadata&) const {
+ return false;
+ }
+
+ /**
+ * Called by the Audio framework / HAL when the metadata of the stream's
+ * sink has been changed.
+ */
+ virtual bool updateSinkMetadata(
+ const ::aidl::android::hardware::audio::common::SinkMetadata&) const {
+ return false;
+ }
+
+ /**
+ * Return the current BluetoothStreamState
+ */
+ virtual BluetoothStreamState getState() const = 0;
+
+ /**
+ * Set the current BluetoothStreamState
+ */
+ virtual bool setState(BluetoothStreamState) = 0;
+
+ virtual bool isA2dp() const = 0;
+
+ virtual bool isLeAudio() const = 0;
+
+ virtual bool getPreferredDataIntervalUs(size_t*) const = 0;
+
+ virtual size_t writeData(const void*, size_t) const { return 0; }
+
+ virtual size_t readData(void*, size_t) const { return 0; }
+};
+
+class BluetoothAudioPortAidl : public BluetoothAudioPort {
+ public:
+ BluetoothAudioPortAidl();
+ virtual ~BluetoothAudioPortAidl();
+
+ bool registerPort(const ::aidl::android::media::audio::common::AudioDeviceDescription&
+ description) override;
+
+ void unregisterPort() override;
+
+ bool loadAudioConfig(::aidl::android::hardware::bluetooth::audio::PcmConfiguration* audio_cfg)
+ const override;
+
+ void forcePcmStereoToMono(bool force) override { mIsStereoToMono = force; }
+
+ bool standby() override;
+ bool start() override;
+ bool suspend() override;
+ void stop() override;
+
+ bool getPresentationPosition(::aidl::android::hardware::bluetooth::audio::PresentationPosition&
+ presentation_position) const override;
+
+ bool updateSourceMetadata(const ::aidl::android::hardware::audio::common::SourceMetadata&
+ sourceMetadata) const override;
+
+ bool updateSinkMetadata(const ::aidl::android::hardware::audio::common::SinkMetadata&
+ sinkMetadata) const override;
+
+ /**
+ * Return the current BluetoothStreamState
+ * Note: This method is used for logging, does not lock, so value returned may not be latest
+ */
+ BluetoothStreamState getState() const override NO_THREAD_SAFETY_ANALYSIS;
+
+ bool setState(BluetoothStreamState state) override;
+
+ bool isA2dp() const override;
+
+ bool isLeAudio() const override;
+
+ bool getPreferredDataIntervalUs(size_t* interval_us) const override;
+
+ protected:
+ uint16_t mCookie;
+ BluetoothStreamState mState GUARDED_BY(mCvMutex);
+ ::aidl::android::hardware::bluetooth::audio::SessionType mSessionType;
+ // WR to support Mono: True if fetching Stereo and mixing into Mono
+ bool mIsStereoToMono = false;
+
+ bool inUse() const;
+
+ std::string debugMessage() const;
+
+ private:
+ // start()/suspend() report state change status via callback. Wait until kMaxWaitingTimeMs or a
+ // state change after a call to start()/suspend() and analyse the returned status. Below mutex,
+ // conditional variable serves this purpose.
+ mutable std::mutex mCvMutex;
+ std::condition_variable mInternalCv GUARDED_BY(mCvMutex);
+
+ // Check and initialize session type for |devices| If failed, this
+ // BluetoothAudioPortAidl is not initialized and must be deleted.
+ bool initSessionType(
+ const ::aidl::android::media::audio::common::AudioDeviceDescription& description);
+
+ bool condWaitState(BluetoothStreamState state);
+
+ void controlResultHandler(
+ uint16_t cookie,
+ const ::aidl::android::hardware::bluetooth::audio::BluetoothAudioStatus& status);
+ void sessionChangedHandler(uint16_t cookie);
+};
+
+class BluetoothAudioPortAidlOut : public BluetoothAudioPortAidl {
+ public:
+ // The audio data path to the Bluetooth stack (Software encoding)
+ size_t writeData(const void* buffer, size_t bytes) const override;
+};
+
+class BluetoothAudioPortAidlIn : public BluetoothAudioPortAidl {
+ public:
+ // The audio data path from the Bluetooth stack (Software decoded)
+ size_t readData(void* buffer, size_t bytes) const override;
+};
+
+} // namespace android::bluetooth::audio::aidl
\ No newline at end of file
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index 539221d..fb3eef2 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -33,12 +33,17 @@
public:
// This value is used for all AudioPatches and reported by all streams.
static constexpr int32_t kLatencyMs = 10;
- enum Type : int { DEFAULT, R_SUBMIX, STUB, USB };
+ enum Type : int { DEFAULT, R_SUBMIX, STUB, USB, BLUETOOTH };
+ enum BtInterface : int { BTCONF, BTA2DP, BTLE };
static std::shared_ptr<Module> createInstance(Type type);
explicit Module(Type type) : mType(type) {}
+ typedef std::tuple<std::weak_ptr<IBluetooth>, std::weak_ptr<IBluetoothA2dp>,
+ std::weak_ptr<IBluetoothLe>>
+ BtProfileHandles;
+
protected:
// The vendor extension done via inheritance can override interface methods and augment
// a call to the base implementation.
@@ -185,6 +190,7 @@
virtual std::unique_ptr<internal::Configuration> initializeConfig();
// Utility and helper functions accessible to subclasses.
+ ndk::ScopedAStatus bluetoothParametersUpdated();
void cleanUpPatch(int32_t patchId);
ndk::ScopedAStatus createStreamContext(
int32_t in_portConfigId, int64_t in_bufferSizeFrames,
@@ -196,6 +202,7 @@
std::set<int32_t> findConnectedPortConfigIds(int32_t portConfigId);
ndk::ScopedAStatus findPortIdForNewStream(
int32_t in_portConfigId, ::aidl::android::media::audio::common::AudioPort** port);
+ virtual BtProfileHandles getBtProfileManagerHandles();
internal::Configuration& getConfig();
const ConnectedDevicePorts& getConnectedDevicePorts() const { return mConnectedDevicePorts; }
bool getMasterMute() const { return mMasterMute; }
diff --git a/audio/aidl/default/include/core-impl/ModuleBluetooth.h b/audio/aidl/default/include/core-impl/ModuleBluetooth.h
new file mode 100644
index 0000000..68b4e6b
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/ModuleBluetooth.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include "core-impl/Bluetooth.h"
+#include "core-impl/Module.h"
+
+namespace aidl::android::hardware::audio::core {
+
+class ModuleBluetooth final : public Module {
+ public:
+ ModuleBluetooth() : Module(Type::BLUETOOTH) {}
+
+ private:
+ BtProfileHandles getBtProfileManagerHandles() override;
+
+ ndk::ScopedAStatus getBluetoothA2dp(std::shared_ptr<IBluetoothA2dp>* _aidl_return) override;
+ ndk::ScopedAStatus getBluetoothLe(std::shared_ptr<IBluetoothLe>* _aidl_return) override;
+ ndk::ScopedAStatus getMicMute(bool* _aidl_return) override;
+ ndk::ScopedAStatus setMicMute(bool in_mute) override;
+
+ ndk::ScopedAStatus createInputStream(
+ StreamContext&& context,
+ const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+ const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
+ std::shared_ptr<StreamIn>* result) override;
+ ndk::ScopedAStatus createOutputStream(
+ StreamContext&& context,
+ const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+ const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+ offloadInfo,
+ std::shared_ptr<StreamOut>* result) override;
+ ndk::ScopedAStatus onMasterMuteChanged(bool mute) override;
+ ndk::ScopedAStatus onMasterVolumeChanged(float volume) override;
+
+ ChildInterface<IBluetoothA2dp> mBluetoothA2dp;
+ ChildInterface<IBluetoothLe> mBluetoothLe;
+};
+
+} // namespace aidl::android::hardware::audio::core
\ No newline at end of file
diff --git a/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h b/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h
index e87be3d..c4bf7b9 100644
--- a/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h
+++ b/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h
@@ -26,8 +26,6 @@
private:
// IModule interfaces
- ndk::ScopedAStatus getTelephony(std::shared_ptr<ITelephony>* _aidl_return) override;
- ndk::ScopedAStatus getBluetooth(std::shared_ptr<IBluetooth>* _aidl_return) override;
ndk::ScopedAStatus getMicMute(bool* _aidl_return) override;
ndk::ScopedAStatus setMicMute(bool in_mute) override;
@@ -49,9 +47,6 @@
const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sources,
const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sinks)
override;
- void onExternalDeviceConnectionChanged(
- const ::aidl::android::media::audio::common::AudioPort& audioPort,
- bool connected) override;
ndk::ScopedAStatus onMasterMuteChanged(bool mute) override;
ndk::ScopedAStatus onMasterVolumeChanged(float volume) override;
};
diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
index fa2b760..a02655f 100644
--- a/audio/aidl/default/include/core-impl/Stream.h
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -195,10 +195,10 @@
virtual ::android::status_t start() = 0;
virtual ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
int32_t* latencyMs) = 0;
- // No need to implement 'getPosition' unless the driver can provide more precise
+ // No need to implement 'refinePosition' unless the driver can provide more precise
// data than just total frame count. For example, the driver may correctly account
// for any intermediate buffers.
- virtual ::android::status_t getPosition(StreamDescriptor::Position* /*position*/) {
+ virtual ::android::status_t refinePosition(StreamDescriptor::Position* /*position*/) {
return ::android::OK;
}
virtual void shutdown() = 0; // This function is only called once.
@@ -262,6 +262,7 @@
virtual void setIsConnected(bool isConnected) = 0;
virtual StreamDescriptor::State setClosed() = 0;
virtual bool start() = 0;
+ virtual pid_t getTid() = 0;
virtual void stop() = 0;
};
@@ -277,8 +278,10 @@
void setIsConnected(bool isConnected) override { WorkerImpl::setIsConnected(isConnected); }
StreamDescriptor::State setClosed() override { return WorkerImpl::setClosed(); }
bool start() override {
- return WorkerImpl::start(WorkerImpl::kThreadName, ANDROID_PRIORITY_AUDIO);
+ // This is an "audio service thread," must have elevated priority.
+ return WorkerImpl::start(WorkerImpl::kThreadName, ANDROID_PRIORITY_URGENT_AUDIO);
}
+ pid_t getTid() override { return WorkerImpl::getTid(); }
void stop() override { return WorkerImpl::stop(); }
};
@@ -354,6 +357,7 @@
virtual const ConnectedDevices& getConnectedDevices() const = 0;
virtual ndk::ScopedAStatus setConnectedDevices(
const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) = 0;
+ virtual ndk::ScopedAStatus bluetoothParametersUpdated() = 0;
};
// This is equivalent to automatically generated 'IStreamCommonDelegator' but uses
@@ -454,6 +458,7 @@
ndk::ScopedAStatus setConnectedDevices(
const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
override;
+ ndk::ScopedAStatus bluetoothParametersUpdated() override;
protected:
static StreamWorkerInterface::CreateInstance getDefaultInWorkerCreator() {
@@ -505,10 +510,21 @@
StreamIn(StreamContext&& context,
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
- StreamContext mContext;
+ StreamContext mContextInstance;
const std::map<::aidl::android::media::audio::common::AudioDevice, std::string> mMicrophones;
};
+class StreamInHwGainHelper {
+ protected:
+ explicit StreamInHwGainHelper(const StreamContext* context);
+
+ ndk::ScopedAStatus getHwGainImpl(std::vector<float>* _aidl_return);
+ ndk::ScopedAStatus setHwGainImpl(const std::vector<float>& in_channelGains);
+
+ const size_t mChannelCount;
+ std::vector<float> mHwGains;
+};
+
class StreamOut : virtual public StreamCommonInterface, public BnStreamOut {
protected:
void defaultOnClose();
@@ -550,11 +566,22 @@
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
offloadInfo);
- StreamContext mContext;
+ StreamContext mContextInstance;
const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo> mOffloadInfo;
std::optional<::aidl::android::hardware::audio::common::AudioOffloadMetadata> mOffloadMetadata;
};
+class StreamOutHwVolumeHelper {
+ protected:
+ explicit StreamOutHwVolumeHelper(const StreamContext* context);
+
+ ndk::ScopedAStatus getHwVolumeImpl(std::vector<float>* _aidl_return);
+ ndk::ScopedAStatus setHwVolumeImpl(const std::vector<float>& in_channelVolumes);
+
+ const size_t mChannelCount;
+ std::vector<float> mHwVolumes;
+};
+
// The recommended way to create a stream instance.
// 'StreamImpl' is the concrete stream implementation, 'StreamInOrOut' is either 'StreamIn' or
// 'StreamOut', the rest are the arguments forwarded to the constructor of 'StreamImpl'.
@@ -584,6 +611,11 @@
if (s) return s->setConnectedDevices(devices);
return ndk::ScopedAStatus::ok();
}
+ ndk::ScopedAStatus bluetoothParametersUpdated() {
+ auto s = mStream.lock();
+ if (s) return s->bluetoothParametersUpdated();
+ return ndk::ScopedAStatus::ok();
+ }
private:
std::weak_ptr<StreamCommonInterface> mStream;
@@ -612,6 +644,14 @@
}
return ndk::ScopedAStatus::ok();
}
+ ndk::ScopedAStatus bluetoothParametersUpdated() {
+ bool isOk = true;
+ for (auto& it : mStreams) {
+ if (!it.second.bluetoothParametersUpdated().isOk()) isOk = false;
+ }
+ return isOk ? ndk::ScopedAStatus::ok()
+ : ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ }
private:
// Maps port ids and port config ids to streams. Multimap because a port
diff --git a/audio/aidl/default/include/core-impl/StreamAlsa.h b/audio/aidl/default/include/core-impl/StreamAlsa.h
index f98a922..2c3b284 100644
--- a/audio/aidl/default/include/core-impl/StreamAlsa.h
+++ b/audio/aidl/default/include/core-impl/StreamAlsa.h
@@ -41,14 +41,16 @@
::android::status_t start() override;
::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
int32_t* latencyMs) override;
- ::android::status_t getPosition(StreamDescriptor::Position* position) override;
+ ::android::status_t refinePosition(StreamDescriptor::Position* position) override;
void shutdown() override;
protected:
// Called from 'start' to initialize 'mAlsaDeviceProxies', the vector must be non-empty.
virtual std::vector<alsa::DeviceProfile> getDeviceProfiles() = 0;
+ const size_t mBufferSizeFrames;
const size_t mFrameSizeBytes;
+ const int mSampleRate;
const bool mIsInput;
const std::optional<struct pcm_config> mConfig;
const int mReadWriteRetries;
diff --git a/audio/aidl/default/include/core-impl/StreamBluetooth.h b/audio/aidl/default/include/core-impl/StreamBluetooth.h
new file mode 100644
index 0000000..c2f8c1d
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/StreamBluetooth.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <mutex>
+#include <vector>
+
+#include <aidl/android/hardware/audio/core/IBluetooth.h>
+#include <aidl/android/hardware/audio/core/IBluetoothA2dp.h>
+#include <aidl/android/hardware/audio/core/IBluetoothLe.h>
+
+#include "core-impl/DevicePortProxy.h"
+#include "core-impl/Module.h"
+#include "core-impl/Stream.h"
+
+namespace aidl::android::hardware::audio::core {
+
+class StreamBluetooth : public StreamCommonImpl {
+ public:
+ StreamBluetooth(StreamContext* context, const Metadata& metadata,
+ Module::BtProfileHandles&& btHandles);
+ // Methods of 'DriverInterface'.
+ ::android::status_t init() override;
+ ::android::status_t drain(StreamDescriptor::DrainMode) override;
+ ::android::status_t flush() override;
+ ::android::status_t pause() override;
+ ::android::status_t standby() override;
+ ::android::status_t start() override;
+ ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
+ int32_t* latencyMs) override;
+ void shutdown() override;
+
+ // Overridden methods of 'StreamCommonImpl', called on a Binder thread.
+ ndk::ScopedAStatus updateMetadataCommon(const Metadata& metadata) override;
+ ndk::ScopedAStatus prepareToClose() override;
+ const ConnectedDevices& getConnectedDevices() const override;
+ ndk::ScopedAStatus setConnectedDevices(const ConnectedDevices& devices) override;
+ ndk::ScopedAStatus bluetoothParametersUpdated() override;
+
+ private:
+ // Audio Pcm Config
+ const uint32_t mSampleRate;
+ const ::aidl::android::media::audio::common::AudioChannelLayout mChannelLayout;
+ const ::aidl::android::media::audio::common::AudioFormatDescription mFormat;
+ const size_t mFrameSizeBytes;
+ const bool mIsInput;
+ const std::weak_ptr<IBluetoothA2dp> mBluetoothA2dp;
+ const std::weak_ptr<IBluetoothLe> mBluetoothLe;
+ size_t mPreferredDataIntervalUs;
+ size_t mPreferredFrameCount;
+
+ mutable std::mutex mLock;
+ bool mIsInitialized GUARDED_BY(mLock);
+ bool mIsReadyToClose GUARDED_BY(mLock);
+ std::vector<std::shared_ptr<::android::bluetooth::audio::aidl::BluetoothAudioPortAidl>>
+ mBtDeviceProxies GUARDED_BY(mLock);
+
+ ::android::status_t initialize() REQUIRES(mLock);
+ bool checkConfigParams(::aidl::android::hardware::bluetooth::audio::PcmConfiguration& config);
+};
+
+class StreamInBluetooth final : public StreamIn, public StreamBluetooth {
+ public:
+ friend class ndk::SharedRefBase;
+ StreamInBluetooth(
+ StreamContext&& context,
+ const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+ const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones,
+ Module::BtProfileHandles&& btHandles);
+
+ private:
+ void onClose(StreamDescriptor::State) override { defaultOnClose(); }
+ ndk::ScopedAStatus getActiveMicrophones(
+ std::vector<::aidl::android::media::audio::common::MicrophoneDynamicInfo>* _aidl_return)
+ override;
+};
+
+class StreamOutBluetooth final : public StreamOut, public StreamBluetooth {
+ public:
+ friend class ndk::SharedRefBase;
+ StreamOutBluetooth(
+ StreamContext&& context,
+ const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+ const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+ offloadInfo,
+ Module::BtProfileHandles&& btHandles);
+
+ private:
+ void onClose(StreamDescriptor::State) override { defaultOnClose(); }
+};
+
+} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/StreamPrimary.h b/audio/aidl/default/include/core-impl/StreamPrimary.h
new file mode 100644
index 0000000..b3ddd0b
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/StreamPrimary.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <vector>
+
+#include "StreamAlsa.h"
+#include "StreamSwitcher.h"
+
+namespace aidl::android::hardware::audio::core {
+
+class StreamPrimary : public StreamAlsa {
+ public:
+ StreamPrimary(StreamContext* context, const Metadata& metadata);
+
+ protected:
+ std::vector<alsa::DeviceProfile> getDeviceProfiles() override;
+
+ const bool mIsInput;
+};
+
+class StreamInPrimary final : public StreamIn, public StreamSwitcher, public StreamInHwGainHelper {
+ public:
+ friend class ndk::SharedRefBase;
+ StreamInPrimary(
+ StreamContext&& context,
+ const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+ const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
+
+ private:
+ static bool useStubStream(const ::aidl::android::media::audio::common::AudioDevice& device);
+
+ DeviceSwitchBehavior switchCurrentStream(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
+ override;
+ std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+ StreamContext* context, const Metadata& metadata) override;
+ void onClose(StreamDescriptor::State) override { defaultOnClose(); }
+
+ ndk::ScopedAStatus getHwGain(std::vector<float>* _aidl_return) override;
+ ndk::ScopedAStatus setHwGain(const std::vector<float>& in_channelGains) override;
+};
+
+class StreamOutPrimary final : public StreamOut,
+ public StreamSwitcher,
+ public StreamOutHwVolumeHelper {
+ public:
+ friend class ndk::SharedRefBase;
+ StreamOutPrimary(StreamContext&& context,
+ const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+ const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+ offloadInfo);
+
+ private:
+ static bool useStubStream(const ::aidl::android::media::audio::common::AudioDevice& device);
+
+ DeviceSwitchBehavior switchCurrentStream(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
+ override;
+ std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+ StreamContext* context, const Metadata& metadata) override;
+ void onClose(StreamDescriptor::State) override { defaultOnClose(); }
+
+ ndk::ScopedAStatus getHwVolume(std::vector<float>* _aidl_return) override;
+ ndk::ScopedAStatus setHwVolume(const std::vector<float>& in_channelVolumes) override;
+};
+
+} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h b/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
index b39583e..94404a1 100644
--- a/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
+++ b/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
@@ -20,16 +20,16 @@
#include <vector>
#include "core-impl/Stream.h"
+#include "core-impl/StreamSwitcher.h"
#include "r_submix/SubmixRoute.h"
namespace aidl::android::hardware::audio::core {
-using aidl::android::hardware::audio::core::r_submix::AudioConfig;
-using aidl::android::hardware::audio::core::r_submix::SubmixRoute;
-
class StreamRemoteSubmix : public StreamCommonImpl {
public:
- StreamRemoteSubmix(StreamContext* context, const Metadata& metadata);
+ StreamRemoteSubmix(
+ StreamContext* context, const Metadata& metadata,
+ const ::aidl::android::media::audio::common::AudioDeviceAddress& deviceAddress);
::android::status_t init() override;
::android::status_t drain(StreamDescriptor::DrainMode) override;
@@ -39,7 +39,7 @@
::android::status_t start() override;
::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
int32_t* latencyMs) override;
- ::android::status_t getPosition(StreamDescriptor::Position* position) override;
+ ::android::status_t refinePosition(StreamDescriptor::Position* position) override;
void shutdown() override;
// Overridden methods of 'StreamCommonImpl', called on a Binder thread.
@@ -51,16 +51,17 @@
::android::status_t outWrite(void* buffer, size_t frameCount, size_t* actualFrameCount);
::android::status_t inRead(void* buffer, size_t frameCount, size_t* actualFrameCount);
- const int mPortId;
+ const ::aidl::android::media::audio::common::AudioDeviceAddress mDeviceAddress;
const bool mIsInput;
- AudioConfig mStreamConfig;
- std::shared_ptr<SubmixRoute> mCurrentRoute = nullptr;
+ r_submix::AudioConfig mStreamConfig;
+ std::shared_ptr<r_submix::SubmixRoute> mCurrentRoute = nullptr;
// Mutex lock to protect vector of submix routes, each of these submix routes have their mutex
// locks and none of the mutex locks should be taken together.
static std::mutex sSubmixRoutesLock;
- static std::map<int32_t, std::shared_ptr<SubmixRoute>> sSubmixRoutes
- GUARDED_BY(sSubmixRoutesLock);
+ static std::map<::aidl::android::media::audio::common::AudioDeviceAddress,
+ std::shared_ptr<r_submix::SubmixRoute>>
+ sSubmixRoutes GUARDED_BY(sSubmixRoutesLock);
// limit for number of read error log entries to avoid spamming the logs
static constexpr int kMaxReadErrorLogs = 5;
@@ -72,7 +73,7 @@
static constexpr int kReadAttemptSleepUs = 5000;
};
-class StreamInRemoteSubmix final : public StreamIn, public StreamRemoteSubmix {
+class StreamInRemoteSubmix final : public StreamIn, public StreamSwitcher {
public:
friend class ndk::SharedRefBase;
StreamInRemoteSubmix(
@@ -81,13 +82,19 @@
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
private:
+ DeviceSwitchBehavior switchCurrentStream(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
+ override;
+ std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+ StreamContext* context, const Metadata& metadata) override;
void onClose(StreamDescriptor::State) override { defaultOnClose(); }
ndk::ScopedAStatus getActiveMicrophones(
std::vector<::aidl::android::media::audio::common::MicrophoneDynamicInfo>* _aidl_return)
override;
};
-class StreamOutRemoteSubmix final : public StreamOut, public StreamRemoteSubmix {
+class StreamOutRemoteSubmix final : public StreamOut, public StreamSwitcher {
public:
friend class ndk::SharedRefBase;
StreamOutRemoteSubmix(
@@ -97,6 +104,12 @@
offloadInfo);
private:
+ DeviceSwitchBehavior switchCurrentStream(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
+ override;
+ std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+ StreamContext* context, const Metadata& metadata) override;
void onClose(StreamDescriptor::State) override { defaultOnClose(); }
};
diff --git a/audio/aidl/default/include/core-impl/StreamStub.h b/audio/aidl/default/include/core-impl/StreamStub.h
index a8a3fc4..3857e0e 100644
--- a/audio/aidl/default/include/core-impl/StreamStub.h
+++ b/audio/aidl/default/include/core-impl/StreamStub.h
@@ -35,6 +35,7 @@
void shutdown() override;
private:
+ const size_t mBufferSizeFrames;
const size_t mFrameSizeBytes;
const int mSampleRate;
const bool mIsAsynchronous;
diff --git a/audio/aidl/default/include/core-impl/StreamSwitcher.h b/audio/aidl/default/include/core-impl/StreamSwitcher.h
index e462481..5764ad6 100644
--- a/audio/aidl/default/include/core-impl/StreamSwitcher.h
+++ b/audio/aidl/default/include/core-impl/StreamSwitcher.h
@@ -20,7 +20,7 @@
namespace aidl::android::hardware::audio::core {
-// 'StreamSwitcher' is implementation of 'StreamCommonInterface' which allows
+// 'StreamSwitcher' is an implementation of 'StreamCommonInterface' which allows
// dynamically switching the underlying stream implementation based on currently
// connected devices. This is achieved by replacing inheritance from
// 'StreamCommonImpl' with owning an instance of it. StreamSwitcher must be
@@ -86,7 +86,8 @@
template <typename T>
class InnerStreamWrapper : public T, public StreamCommonInterfaceEx {
public:
- InnerStreamWrapper(StreamContext* context, const Metadata& metadata) : T(context, metadata) {}
+ template <typename... Args>
+ InnerStreamWrapper(Args&&... args) : T(std::forward<Args>(args)...) {}
StreamDescriptor::State getStatePriorToClosing() const override { return mStatePriorToClosing; }
private:
@@ -128,6 +129,7 @@
ndk::ScopedAStatus setConnectedDevices(
const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
override;
+ ndk::ScopedAStatus bluetoothParametersUpdated() override;
protected:
// Since switching a stream requires closing down the current stream, StreamSwitcher
@@ -186,6 +188,7 @@
std::optional<int32_t> mHwAvSyncId;
std::vector<VndParam> mMissedParameters;
std::vector<std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>> mEffects;
+ bool mBluetoothParametersUpdated = false;
};
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/StreamUsb.h b/audio/aidl/default/include/core-impl/StreamUsb.h
index 74e30ff..608f27d 100644
--- a/audio/aidl/default/include/core-impl/StreamUsb.h
+++ b/audio/aidl/default/include/core-impl/StreamUsb.h
@@ -59,7 +59,7 @@
override;
};
-class StreamOutUsb final : public StreamOut, public StreamUsb {
+class StreamOutUsb final : public StreamOut, public StreamUsb, public StreamOutHwVolumeHelper {
public:
friend class ndk::SharedRefBase;
StreamOutUsb(StreamContext&& context,
@@ -71,9 +71,6 @@
void onClose(StreamDescriptor::State) override { defaultOnClose(); }
ndk::ScopedAStatus getHwVolume(std::vector<float>* _aidl_return) override;
ndk::ScopedAStatus setHwVolume(const std::vector<float>& in_channelVolumes) override;
-
- const int mChannelCount;
- std::vector<float> mHwVolumes;
};
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/XmlConverter.h b/audio/aidl/default/include/core-impl/XmlConverter.h
index a68a6fd..383ea24 100644
--- a/audio/aidl/default/include/core-impl/XmlConverter.h
+++ b/audio/aidl/default/include/core-impl/XmlConverter.h
@@ -53,10 +53,16 @@
const ::android::status_t& status) {
std::string errorMessage;
if (status != ::android::OK) {
- if (!isReadableConfigFile) {
- errorMessage = "Could not read requested config file:" + configFilePath;
+ if (configFilePath.empty()) {
+ errorMessage = "No audio configuration files found";
+ } else if (!isReadableConfigFile) {
+ errorMessage = std::string("Could not read requested XML config file: \"")
+ .append(configFilePath)
+ .append("\"");
} else {
- errorMessage = "Invalid config file: " + configFilePath;
+ errorMessage = std::string("Invalid XML config file: \"")
+ .append(configFilePath)
+ .append("\"");
}
}
return errorMessage;
diff --git a/audio/aidl/default/main.cpp b/audio/aidl/default/main.cpp
index 93fb366..a0c0fab 100644
--- a/audio/aidl/default/main.cpp
+++ b/audio/aidl/default/main.cpp
@@ -65,7 +65,8 @@
return std::make_pair(module, moduleBinder);
};
auto modules = {createModule(Module::Type::DEFAULT), createModule(Module::Type::R_SUBMIX),
- createModule(Module::Type::USB), createModule(Module::Type::STUB)};
+ createModule(Module::Type::USB), createModule(Module::Type::STUB),
+ createModule(Module::Type::BLUETOOTH)};
(void)modules;
ABinderProcess_joinThreadPool();
diff --git a/audio/aidl/default/primary/PrimaryMixer.cpp b/audio/aidl/default/primary/PrimaryMixer.cpp
new file mode 100644
index 0000000..577d010
--- /dev/null
+++ b/audio/aidl/default/primary/PrimaryMixer.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 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 "AHAL_PrimaryMixer"
+
+#include "PrimaryMixer.h"
+
+namespace aidl::android::hardware::audio::core::primary {
+
+// static
+PrimaryMixer& PrimaryMixer::getInstance() {
+ static PrimaryMixer gInstance;
+ return gInstance;
+}
+
+} // namespace aidl::android::hardware::audio::core::primary
diff --git a/audio/aidl/default/primary/PrimaryMixer.h b/audio/aidl/default/primary/PrimaryMixer.h
new file mode 100644
index 0000000..3806428
--- /dev/null
+++ b/audio/aidl/default/primary/PrimaryMixer.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <map>
+#include <memory>
+#include <mutex>
+#include <vector>
+
+#include <android-base/thread_annotations.h>
+#include <android/binder_auto_utils.h>
+
+#include "alsa/Mixer.h"
+
+namespace aidl::android::hardware::audio::core::primary {
+
+class PrimaryMixer : public alsa::Mixer {
+ public:
+ static constexpr int kAlsaCard = 0;
+ static constexpr int kAlsaDevice = 0;
+
+ static PrimaryMixer& getInstance();
+
+ private:
+ PrimaryMixer() : alsa::Mixer(kAlsaCard) {}
+};
+
+} // namespace aidl::android::hardware::audio::core::primary
diff --git a/audio/aidl/default/primary/StreamPrimary.cpp b/audio/aidl/default/primary/StreamPrimary.cpp
new file mode 100644
index 0000000..e01be8a
--- /dev/null
+++ b/audio/aidl/default/primary/StreamPrimary.cpp
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2023 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 <limits>
+
+#define LOG_TAG "AHAL_StreamPrimary"
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <error/expected_utils.h>
+
+#include "PrimaryMixer.h"
+#include "core-impl/StreamPrimary.h"
+#include "core-impl/StreamStub.h"
+
+using aidl::android::hardware::audio::common::SinkMetadata;
+using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioDeviceDescription;
+using aidl::android::media::audio::common::AudioDeviceType;
+using aidl::android::media::audio::common::AudioOffloadInfo;
+using aidl::android::media::audio::common::MicrophoneInfo;
+using android::base::GetBoolProperty;
+
+namespace aidl::android::hardware::audio::core {
+
+StreamPrimary::StreamPrimary(StreamContext* context, const Metadata& metadata)
+ : StreamAlsa(context, metadata, 3 /*readWriteRetries*/), mIsInput(isInput(metadata)) {}
+
+std::vector<alsa::DeviceProfile> StreamPrimary::getDeviceProfiles() {
+ static const std::vector<alsa::DeviceProfile> kBuiltInSource{
+ alsa::DeviceProfile{.card = primary::PrimaryMixer::kAlsaCard,
+ .device = primary::PrimaryMixer::kAlsaDevice,
+ .direction = PCM_IN,
+ .isExternal = false}};
+ static const std::vector<alsa::DeviceProfile> kBuiltInSink{
+ alsa::DeviceProfile{.card = primary::PrimaryMixer::kAlsaCard,
+ .device = primary::PrimaryMixer::kAlsaDevice,
+ .direction = PCM_OUT,
+ .isExternal = false}};
+ return mIsInput ? kBuiltInSource : kBuiltInSink;
+}
+
+StreamInPrimary::StreamInPrimary(StreamContext&& context, const SinkMetadata& sinkMetadata,
+ const std::vector<MicrophoneInfo>& microphones)
+ : StreamIn(std::move(context), microphones),
+ StreamSwitcher(&mContextInstance, sinkMetadata),
+ StreamInHwGainHelper(&mContextInstance) {}
+
+bool StreamInPrimary::useStubStream(const AudioDevice& device) {
+ static const bool kSimulateInput =
+ GetBoolProperty("ro.boot.audio.tinyalsa.simulate_input", false);
+ return kSimulateInput || device.type.type == AudioDeviceType::IN_TELEPHONY_RX ||
+ device.type.type == AudioDeviceType::IN_FM_TUNER ||
+ device.type.connection == AudioDeviceDescription::CONNECTION_BUS;
+}
+
+StreamSwitcher::DeviceSwitchBehavior StreamInPrimary::switchCurrentStream(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
+ LOG(DEBUG) << __func__;
+ if (devices.size() > 1) {
+ LOG(ERROR) << __func__ << ": primary stream can only be connected to one device, got: "
+ << devices.size();
+ return DeviceSwitchBehavior::UNSUPPORTED_DEVICES;
+ }
+ if (devices.empty() || useStubStream(devices[0]) == isStubStream()) {
+ return DeviceSwitchBehavior::USE_CURRENT_STREAM;
+ }
+ return DeviceSwitchBehavior::CREATE_NEW_STREAM;
+}
+
+std::unique_ptr<StreamCommonInterfaceEx> StreamInPrimary::createNewStream(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+ StreamContext* context, const Metadata& metadata) {
+ if (devices.empty()) {
+ LOG(FATAL) << __func__ << ": called with empty devices"; // see 'switchCurrentStream'
+ }
+ if (useStubStream(devices[0])) {
+ return std::unique_ptr<StreamCommonInterfaceEx>(
+ new InnerStreamWrapper<StreamStub>(context, metadata));
+ }
+ return std::unique_ptr<StreamCommonInterfaceEx>(
+ new InnerStreamWrapper<StreamPrimary>(context, metadata));
+}
+
+ndk::ScopedAStatus StreamInPrimary::getHwGain(std::vector<float>* _aidl_return) {
+ if (isStubStream()) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ }
+ return getHwGainImpl(_aidl_return);
+}
+
+ndk::ScopedAStatus StreamInPrimary::setHwGain(const std::vector<float>& in_channelGains) {
+ if (isStubStream()) {
+ LOG(DEBUG) << __func__ << ": gains " << ::android::internal::ToString(in_channelGains);
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ }
+ auto currentGains = mHwGains;
+ RETURN_STATUS_IF_ERROR(setHwGainImpl(in_channelGains));
+ if (in_channelGains.size() < 1) {
+ LOG(FATAL) << __func__ << ": unexpected gain vector size: " << in_channelGains.size();
+ }
+ if (auto status = primary::PrimaryMixer::getInstance().setMicGain(in_channelGains[0]);
+ !status.isOk()) {
+ mHwGains = currentGains;
+ return status;
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+StreamOutPrimary::StreamOutPrimary(StreamContext&& context, const SourceMetadata& sourceMetadata,
+ const std::optional<AudioOffloadInfo>& offloadInfo)
+ : StreamOut(std::move(context), offloadInfo),
+ StreamSwitcher(&mContextInstance, sourceMetadata),
+ StreamOutHwVolumeHelper(&mContextInstance) {}
+
+bool StreamOutPrimary::useStubStream(const AudioDevice& device) {
+ static const bool kSimulateOutput =
+ GetBoolProperty("ro.boot.audio.tinyalsa.ignore_output", false);
+ return kSimulateOutput || device.type.type == AudioDeviceType::OUT_TELEPHONY_TX ||
+ device.type.connection == AudioDeviceDescription::CONNECTION_BUS;
+}
+
+StreamSwitcher::DeviceSwitchBehavior StreamOutPrimary::switchCurrentStream(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
+ LOG(DEBUG) << __func__;
+ if (devices.size() > 1) {
+ LOG(ERROR) << __func__ << ": primary stream can only be connected to one device, got: "
+ << devices.size();
+ return DeviceSwitchBehavior::UNSUPPORTED_DEVICES;
+ }
+ if (devices.empty() || useStubStream(devices[0]) == isStubStream()) {
+ return DeviceSwitchBehavior::USE_CURRENT_STREAM;
+ }
+ return DeviceSwitchBehavior::CREATE_NEW_STREAM;
+}
+
+std::unique_ptr<StreamCommonInterfaceEx> StreamOutPrimary::createNewStream(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+ StreamContext* context, const Metadata& metadata) {
+ if (devices.empty()) {
+ LOG(FATAL) << __func__ << ": called with empty devices"; // see 'switchCurrentStream'
+ }
+ if (useStubStream(devices[0])) {
+ return std::unique_ptr<StreamCommonInterfaceEx>(
+ new InnerStreamWrapper<StreamStub>(context, metadata));
+ }
+ return std::unique_ptr<StreamCommonInterfaceEx>(
+ new InnerStreamWrapper<StreamPrimary>(context, metadata));
+}
+
+ndk::ScopedAStatus StreamOutPrimary::getHwVolume(std::vector<float>* _aidl_return) {
+ if (isStubStream()) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ }
+ return getHwVolumeImpl(_aidl_return);
+}
+
+ndk::ScopedAStatus StreamOutPrimary::setHwVolume(const std::vector<float>& in_channelVolumes) {
+ if (isStubStream()) {
+ LOG(DEBUG) << __func__ << ": volumes " << ::android::internal::ToString(in_channelVolumes);
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ }
+ auto currentVolumes = mHwVolumes;
+ RETURN_STATUS_IF_ERROR(setHwVolumeImpl(in_channelVolumes));
+ if (auto status = primary::PrimaryMixer::getInstance().setVolumes(in_channelVolumes);
+ !status.isOk()) {
+ mHwVolumes = currentVolumes;
+ return status;
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp b/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp
index 9be7837..adea877 100644
--- a/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp
+++ b/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp
@@ -19,8 +19,8 @@
#include <vector>
#include <android-base/logging.h>
+#include <error/expected_utils.h>
-#include "RemoteSubmixUtils.h"
#include "core-impl/ModuleRemoteSubmix.h"
#include "core-impl/StreamRemoteSubmix.h"
@@ -33,18 +33,6 @@
namespace aidl::android::hardware::audio::core {
-ndk::ScopedAStatus ModuleRemoteSubmix::getTelephony(std::shared_ptr<ITelephony>* _aidl_return) {
- *_aidl_return = nullptr;
- LOG(DEBUG) << __func__ << ": returning null";
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus ModuleRemoteSubmix::getBluetooth(std::shared_ptr<IBluetooth>* _aidl_return) {
- *_aidl_return = nullptr;
- LOG(DEBUG) << __func__ << ": returning null";
- return ndk::ScopedAStatus::ok();
-}
-
ndk::ScopedAStatus ModuleRemoteSubmix::getMicMute(bool* _aidl_return __unused) {
LOG(DEBUG) << __func__ << ": is not supported";
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
@@ -70,23 +58,26 @@
}
ndk::ScopedAStatus ModuleRemoteSubmix::populateConnectedDevicePort(AudioPort* audioPort) {
- LOG(VERBOSE) << __func__ << ": Profiles already populated by Configuration";
- for (auto profile : audioPort->profiles) {
- for (auto channelMask : profile.channelMasks) {
- if (!r_submix::isChannelMaskSupported(channelMask)) {
- LOG(ERROR) << __func__ << ": the profile " << profile.name
- << " has unsupported channel mask : " << channelMask.toString();
- return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
- }
- }
- for (auto sampleRate : profile.sampleRates) {
- if (!r_submix::isSampleRateSupported(sampleRate)) {
- LOG(ERROR) << __func__ << ": the profile " << profile.name
- << " has unsupported sample rate : " << sampleRate;
- return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
- }
- }
+ // Find the corresponding mix port and copy its profiles.
+ std::vector<AudioRoute> routes;
+ // At this moment, the port has the same ID as the template port, see connectExternalDevice.
+ RETURN_STATUS_IF_ERROR(getAudioRoutesForAudioPort(audioPort->id, &routes));
+ if (routes.empty()) {
+ LOG(ERROR) << __func__ << ": no routes found for the port " << audioPort->toString();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
+ const auto& route = *routes.begin();
+ AudioPort mixPort;
+ if (route.sinkPortId == audioPort->id) {
+ if (route.sourcePortIds.empty()) {
+ LOG(ERROR) << __func__ << ": invalid route " << route.toString();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ RETURN_STATUS_IF_ERROR(getAudioPort(*route.sourcePortIds.begin(), &mixPort));
+ } else {
+ RETURN_STATUS_IF_ERROR(getAudioPort(route.sinkPortId, &mixPort));
+ }
+ audioPort->profiles = mixPort.profiles;
return ndk::ScopedAStatus::ok();
}
@@ -106,12 +97,6 @@
return ndk::ScopedAStatus::ok();
}
-void ModuleRemoteSubmix::onExternalDeviceConnectionChanged(
- const ::aidl::android::media::audio::common::AudioPort& audioPort __unused,
- bool connected __unused) {
- LOG(DEBUG) << __func__ << ": do nothing and return";
-}
-
ndk::ScopedAStatus ModuleRemoteSubmix::onMasterMuteChanged(bool __unused) {
LOG(DEBUG) << __func__ << ": is not supported";
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
diff --git a/audio/aidl/default/r_submix/RemoteSubmixUtils.cpp b/audio/aidl/default/r_submix/RemoteSubmixUtils.cpp
deleted file mode 100644
index 2f5d17d..0000000
--- a/audio/aidl/default/r_submix/RemoteSubmixUtils.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2023 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 <vector>
-
-#include "RemoteSubmixUtils.h"
-
-namespace aidl::android::hardware::audio::core::r_submix {
-
-bool isChannelMaskSupported(const AudioChannelLayout& channelMask) {
- const static std::vector<AudioChannelLayout> kSupportedChannelMask = {
- AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
- AudioChannelLayout::LAYOUT_MONO),
- AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
- AudioChannelLayout::LAYOUT_STEREO)};
-
- if (std::find(kSupportedChannelMask.begin(), kSupportedChannelMask.end(), channelMask) !=
- kSupportedChannelMask.end()) {
- return true;
- }
- return false;
-}
-
-bool isSampleRateSupported(int sampleRate) {
- const static std::vector<int> kSupportedSampleRates = {8000, 11025, 12000, 16000, 22050,
- 24000, 32000, 44100, 48000};
-
- if (std::find(kSupportedSampleRates.begin(), kSupportedSampleRates.end(), sampleRate) !=
- kSupportedSampleRates.end()) {
- return true;
- }
- return false;
-}
-
-} // namespace aidl::android::hardware::audio::core::r_submix
diff --git a/audio/aidl/default/r_submix/RemoteSubmixUtils.h b/audio/aidl/default/r_submix/RemoteSubmixUtils.h
deleted file mode 100644
index 952a992..0000000
--- a/audio/aidl/default/r_submix/RemoteSubmixUtils.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2023 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.
- */
-
-#pragma once
-
-#include <aidl/android/media/audio/common/AudioChannelLayout.h>
-#include <aidl/android/media/audio/common/AudioFormatDescription.h>
-
-using aidl::android::media::audio::common::AudioChannelLayout;
-
-namespace aidl::android::hardware::audio::core::r_submix {
-
-bool isChannelMaskSupported(const AudioChannelLayout& channelMask);
-
-bool isSampleRateSupported(int sampleRate);
-
-} // namespace aidl::android::hardware::audio::core::r_submix
diff --git a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
index 9537ebc..3134b86 100644
--- a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
+++ b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
@@ -23,15 +23,18 @@
using aidl::android::hardware::audio::common::SinkMetadata;
using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::hardware::audio::core::r_submix::SubmixRoute;
+using aidl::android::media::audio::common::AudioDeviceAddress;
using aidl::android::media::audio::common::AudioOffloadInfo;
using aidl::android::media::audio::common::MicrophoneDynamicInfo;
using aidl::android::media::audio::common::MicrophoneInfo;
namespace aidl::android::hardware::audio::core {
-StreamRemoteSubmix::StreamRemoteSubmix(StreamContext* context, const Metadata& metadata)
+StreamRemoteSubmix::StreamRemoteSubmix(StreamContext* context, const Metadata& metadata,
+ const AudioDeviceAddress& deviceAddress)
: StreamCommonImpl(context, metadata),
- mPortId(context->getPortId()),
+ mDeviceAddress(deviceAddress),
mIsInput(isInput(metadata)) {
mStreamConfig.frameSize = context->getFrameSize();
mStreamConfig.format = context->getFormat();
@@ -40,13 +43,14 @@
}
std::mutex StreamRemoteSubmix::sSubmixRoutesLock;
-std::map<int32_t, std::shared_ptr<SubmixRoute>> StreamRemoteSubmix::sSubmixRoutes;
+std::map<AudioDeviceAddress, std::shared_ptr<SubmixRoute>> StreamRemoteSubmix::sSubmixRoutes;
::android::status_t StreamRemoteSubmix::init() {
{
std::lock_guard guard(sSubmixRoutesLock);
- if (sSubmixRoutes.find(mPortId) != sSubmixRoutes.end()) {
- mCurrentRoute = sSubmixRoutes[mPortId];
+ auto routeItr = sSubmixRoutes.find(mDeviceAddress);
+ if (routeItr != sSubmixRoutes.end()) {
+ mCurrentRoute = routeItr->second;
}
}
// If route is not available for this port, add it.
@@ -59,7 +63,7 @@
}
{
std::lock_guard guard(sSubmixRoutesLock);
- sSubmixRoutes.emplace(mPortId, mCurrentRoute);
+ sSubmixRoutes.emplace(mDeviceAddress, mCurrentRoute);
}
} else {
if (!mCurrentRoute->isStreamConfigValid(mIsInput, mStreamConfig)) {
@@ -116,8 +120,9 @@
std::shared_ptr<SubmixRoute> route = nullptr;
{
std::lock_guard guard(sSubmixRoutesLock);
- if (sSubmixRoutes.find(mPortId) != sSubmixRoutes.end()) {
- route = sSubmixRoutes[mPortId];
+ auto routeItr = sSubmixRoutes.find(mDeviceAddress);
+ if (routeItr != sSubmixRoutes.end()) {
+ route = routeItr->second;
}
}
if (route != nullptr) {
@@ -146,7 +151,7 @@
LOG(DEBUG) << __func__ << ": pipe destroyed";
std::lock_guard guard(sSubmixRoutesLock);
- sSubmixRoutes.erase(mPortId);
+ sSubmixRoutes.erase(mDeviceAddress);
}
mCurrentRoute.reset();
}
@@ -179,7 +184,7 @@
: outWrite(buffer, frameCount, actualFrameCount));
}
-::android::status_t StreamRemoteSubmix::getPosition(StreamDescriptor::Position* position) {
+::android::status_t StreamRemoteSubmix::refinePosition(StreamDescriptor::Position* position) {
sp<MonoPipeReader> source = mCurrentRoute->getSource();
if (source == nullptr) {
return ::android::NO_INIT;
@@ -275,14 +280,18 @@
size_t* actualFrameCount) {
// about to read from audio source
sp<MonoPipeReader> source = mCurrentRoute->getSource();
- if (source == nullptr) {
- int readErrorCount = mCurrentRoute->notifyReadError();
- if (readErrorCount < kMaxReadErrorLogs) {
- LOG(ERROR)
- << __func__
- << ": no audio pipe yet we're trying to read! (not all errors will be logged)";
+ if (source == nullptr || source->availableToRead() == 0) {
+ if (source == nullptr) {
+ int readErrorCount = mCurrentRoute->notifyReadError();
+ if (readErrorCount < kMaxReadErrorLogs) {
+ LOG(ERROR) << __func__
+ << ": no audio pipe yet we're trying to read! (not all errors will be "
+ "logged)";
+ } else {
+ LOG(ERROR) << __func__ << ": Read errors " << readErrorCount;
+ }
} else {
- LOG(ERROR) << __func__ << ": Read errors " << readErrorCount;
+ LOG(INFO) << __func__ << ": no data to read yet, providing empty data";
}
const size_t delayUs = static_cast<size_t>(
std::roundf(frameCount * MICROS_PER_SECOND / mStreamConfig.sampleRate));
@@ -339,11 +348,9 @@
// recording (including this call): it's converted to usec and compared to how long we've been
// recording for, which gives us how long we must wait to sync the projected recording time, and
// the observed recording time.
- static constexpr float kScaleFactor = .8f;
- const size_t projectedVsObservedOffsetUs =
- kScaleFactor * (static_cast<size_t>(std::roundf((readCounterFrames * MICROS_PER_SECOND /
- mStreamConfig.sampleRate) -
- recordDurationUs.count())));
+ const int projectedVsObservedOffsetUs =
+ std::roundf((readCounterFrames * MICROS_PER_SECOND / mStreamConfig.sampleRate) -
+ recordDurationUs.count());
LOG(VERBOSE) << __func__ << ": record duration " << recordDurationUs.count()
<< " microseconds, will wait: " << projectedVsObservedOffsetUs << " microseconds";
@@ -356,8 +363,7 @@
StreamInRemoteSubmix::StreamInRemoteSubmix(StreamContext&& context,
const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones)
- : StreamIn(std::move(context), microphones),
- StreamRemoteSubmix(&(StreamIn::mContext), sinkMetadata) {}
+ : StreamIn(std::move(context), microphones), StreamSwitcher(&mContextInstance, sinkMetadata) {}
ndk::ScopedAStatus StreamInRemoteSubmix::getActiveMicrophones(
std::vector<MicrophoneDynamicInfo>* _aidl_return) {
@@ -366,10 +372,66 @@
return ndk::ScopedAStatus::ok();
}
+StreamSwitcher::DeviceSwitchBehavior StreamInRemoteSubmix::switchCurrentStream(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
+ // This implementation effectively postpones stream creation until
+ // receiving the first call to 'setConnectedDevices' with a non-empty list.
+ if (isStubStream()) {
+ if (devices.size() == 1) {
+ auto deviceDesc = devices.front().type;
+ if (deviceDesc.type ==
+ ::aidl::android::media::audio::common::AudioDeviceType::IN_SUBMIX) {
+ return DeviceSwitchBehavior::CREATE_NEW_STREAM;
+ }
+ LOG(ERROR) << __func__ << ": Device type " << toString(deviceDesc.type)
+ << " not supported";
+ } else {
+ LOG(ERROR) << __func__ << ": Only single device supported.";
+ }
+ return DeviceSwitchBehavior::UNSUPPORTED_DEVICES;
+ }
+ return DeviceSwitchBehavior::USE_CURRENT_STREAM;
+}
+
+std::unique_ptr<StreamCommonInterfaceEx> StreamInRemoteSubmix::createNewStream(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+ StreamContext* context, const Metadata& metadata) {
+ return std::unique_ptr<StreamCommonInterfaceEx>(
+ new InnerStreamWrapper<StreamRemoteSubmix>(context, metadata, devices.front().address));
+}
+
StreamOutRemoteSubmix::StreamOutRemoteSubmix(StreamContext&& context,
const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo)
: StreamOut(std::move(context), offloadInfo),
- StreamRemoteSubmix(&(StreamOut::mContext), sourceMetadata) {}
+ StreamSwitcher(&mContextInstance, sourceMetadata) {}
+
+StreamSwitcher::DeviceSwitchBehavior StreamOutRemoteSubmix::switchCurrentStream(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
+ // This implementation effectively postpones stream creation until
+ // receiving the first call to 'setConnectedDevices' with a non-empty list.
+ if (isStubStream()) {
+ if (devices.size() == 1) {
+ auto deviceDesc = devices.front().type;
+ if (deviceDesc.type ==
+ ::aidl::android::media::audio::common::AudioDeviceType::OUT_SUBMIX) {
+ return DeviceSwitchBehavior::CREATE_NEW_STREAM;
+ }
+ LOG(ERROR) << __func__ << ": Device type " << toString(deviceDesc.type)
+ << " not supported";
+ } else {
+ LOG(ERROR) << __func__ << ": Only single device supported.";
+ }
+ return DeviceSwitchBehavior::UNSUPPORTED_DEVICES;
+ }
+ return DeviceSwitchBehavior::USE_CURRENT_STREAM;
+}
+
+std::unique_ptr<StreamCommonInterfaceEx> StreamOutRemoteSubmix::createNewStream(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+ StreamContext* context, const Metadata& metadata) {
+ return std::unique_ptr<StreamCommonInterfaceEx>(
+ new InnerStreamWrapper<StreamRemoteSubmix>(context, metadata, devices.front().address));
+}
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/stub/StreamStub.cpp b/audio/aidl/default/stub/StreamStub.cpp
index 66f4605..660a51e 100644
--- a/audio/aidl/default/stub/StreamStub.cpp
+++ b/audio/aidl/default/stub/StreamStub.cpp
@@ -33,6 +33,7 @@
StreamStub::StreamStub(StreamContext* context, const Metadata& metadata)
: StreamCommonImpl(context, metadata),
+ mBufferSizeFrames(getContext().getBufferSizeInFrames()),
mFrameSizeBytes(getContext().getFrameSize()),
mSampleRate(getContext().getSampleRate()),
mIsAsynchronous(!!getContext().getAsyncCallback()),
@@ -40,7 +41,6 @@
::android::status_t StreamStub::init() {
mIsInitialized = true;
- usleep(500);
return ::android::OK;
}
@@ -48,7 +48,16 @@
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
- usleep(500);
+ if (!mIsInput) {
+ if (!mIsAsynchronous) {
+ static constexpr float kMicrosPerSecond = MICROS_PER_SECOND;
+ const size_t delayUs = static_cast<size_t>(
+ std::roundf(mBufferSizeFrames * kMicrosPerSecond / mSampleRate));
+ usleep(delayUs);
+ } else {
+ usleep(500);
+ }
+ }
return ::android::OK;
}
@@ -56,7 +65,6 @@
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
- usleep(500);
return ::android::OK;
}
@@ -64,7 +72,6 @@
if (!mIsInitialized) {
LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
}
- usleep(500);
return ::android::OK;
}
@@ -120,11 +127,10 @@
StreamInStub::StreamInStub(StreamContext&& context, const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones)
- : StreamIn(std::move(context), microphones), StreamStub(&(StreamIn::mContext), sinkMetadata) {}
+ : StreamIn(std::move(context), microphones), StreamStub(&mContextInstance, sinkMetadata) {}
StreamOutStub::StreamOutStub(StreamContext&& context, const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo)
- : StreamOut(std::move(context), offloadInfo),
- StreamStub(&(StreamOut::mContext), sourceMetadata) {}
+ : StreamOut(std::move(context), offloadInfo), StreamStub(&mContextInstance, sourceMetadata) {}
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/usb/StreamUsb.cpp b/audio/aidl/default/usb/StreamUsb.cpp
index 9684a87..b60b4fd 100644
--- a/audio/aidl/default/usb/StreamUsb.cpp
+++ b/audio/aidl/default/usb/StreamUsb.cpp
@@ -18,14 +18,11 @@
#define LOG_TAG "AHAL_StreamUsb"
#include <android-base/logging.h>
-
-#include <Utils.h>
#include <error/expected_utils.h>
#include "UsbAlsaMixerControl.h"
#include "core-impl/StreamUsb.h"
-using aidl::android::hardware::audio::common::getChannelCount;
using aidl::android::hardware::audio::common::SinkMetadata;
using aidl::android::hardware::audio::common::SourceMetadata;
using aidl::android::media::audio::common::AudioDevice;
@@ -85,7 +82,7 @@
StreamInUsb::StreamInUsb(StreamContext&& context, const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones)
- : StreamIn(std::move(context), microphones), StreamUsb(&(StreamIn::mContext), sinkMetadata) {}
+ : StreamIn(std::move(context), microphones), StreamUsb(&mContextInstance, sinkMetadata) {}
ndk::ScopedAStatus StreamInUsb::getActiveMicrophones(
std::vector<MicrophoneDynamicInfo>* _aidl_return __unused) {
@@ -96,15 +93,16 @@
StreamOutUsb::StreamOutUsb(StreamContext&& context, const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo)
: StreamOut(std::move(context), offloadInfo),
- StreamUsb(&(StreamOut::mContext), sourceMetadata),
- mChannelCount(getChannelCount(getContext().getChannelLayout())) {}
+ StreamUsb(&mContextInstance, sourceMetadata),
+ StreamOutHwVolumeHelper(&mContextInstance) {}
ndk::ScopedAStatus StreamOutUsb::getHwVolume(std::vector<float>* _aidl_return) {
- *_aidl_return = mHwVolumes;
- return ndk::ScopedAStatus::ok();
+ return getHwVolumeImpl(_aidl_return);
}
ndk::ScopedAStatus StreamOutUsb::setHwVolume(const std::vector<float>& in_channelVolumes) {
+ auto currentVolumes = mHwVolumes;
+ RETURN_STATUS_IF_ERROR(setHwVolumeImpl(in_channelVolumes));
// Avoid using mConnectedDeviceProfiles because it requires a lock.
for (const auto& device : getConnectedDevices()) {
if (auto deviceProfile = alsa::getDeviceProfile(device, mIsInput);
@@ -114,11 +112,11 @@
!result.isOk()) {
LOG(ERROR) << __func__
<< ": failed to set volume for device address=" << *deviceProfile;
+ mHwVolumes = currentVolumes;
return result;
}
}
}
- mHwVolumes = in_channelVolumes;
return ndk::ScopedAStatus::ok();
}
diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index 852255d..f7cf4ce 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -55,6 +55,7 @@
"VtsHalAudioCoreConfigTargetTest.cpp",
"VtsHalAudioCoreModuleTargetTest.cpp",
],
+ test_config: "VtsHalAudioCoreTargetTest.xml",
}
cc_test {
diff --git a/audio/aidl/vts/ModuleConfig.cpp b/audio/aidl/vts/ModuleConfig.cpp
index 8c448a8..7213034 100644
--- a/audio/aidl/vts/ModuleConfig.cpp
+++ b/audio/aidl/vts/ModuleConfig.cpp
@@ -30,6 +30,7 @@
using aidl::android::hardware::audio::common::isBitPositionFlagSet;
using aidl::android::hardware::audio::core::IModule;
using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioDeviceDescription;
using aidl::android::media::audio::common::AudioDeviceType;
using aidl::android::media::audio::common::AudioEncapsulationMode;
using aidl::android::media::audio::common::AudioFormatDescription;
@@ -96,7 +97,10 @@
} else {
mAttachedSinkDevicePorts.insert(port.id);
}
- } else if (port.profiles.empty()) {
+ } else if (devicePort.device.type.connection != AudioDeviceDescription::CONNECTION_VIRTUAL
+ // The "virtual" connection is used for remote submix which is a dynamic
+ // device but it can be connected and used w/o external hardware.
+ && port.profiles.empty()) {
mExternalDevicePorts.insert(port.id);
}
}
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index 0012cd5..8a8998e 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -1379,7 +1379,7 @@
<< "At least two mix ports have PRIMARY flag set: " << primaryMixPort.value()
<< " and " << port.id;
primaryMixPort = port.id;
- EXPECT_EQ(1, mixPort.maxOpenStreamCount)
+ EXPECT_GE(mixPort.maxOpenStreamCount, 0)
<< "Primary mix port " << port.id << " can not have maxOpenStreamCount "
<< mixPort.maxOpenStreamCount;
}
@@ -1627,14 +1627,17 @@
if (ports.empty()) {
GTEST_SKIP() << "No external devices in the module.";
}
- AudioPort ignored;
WithDebugFlags doNotSimulateConnections = WithDebugFlags::createNested(*debug);
doNotSimulateConnections.flags().simulateDeviceConnections = false;
ASSERT_NO_FATAL_FAILURE(doNotSimulateConnections.SetUp(module.get()));
for (const auto& port : ports) {
- AudioPort portWithData = GenerateUniqueDeviceAddress(port);
- EXPECT_STATUS(EX_ILLEGAL_STATE, module->connectExternalDevice(portWithData, &ignored))
- << "static port " << portWithData.toString();
+ AudioPort portWithData = GenerateUniqueDeviceAddress(port), connectedPort;
+ ScopedAStatus status = module->connectExternalDevice(portWithData, &connectedPort);
+ EXPECT_STATUS(EX_ILLEGAL_STATE, status) << "static port " << portWithData.toString();
+ if (status.isOk()) {
+ EXPECT_IS_OK(module->disconnectExternalDevice(connectedPort.id))
+ << "when disconnecting device port ID " << connectedPort.id;
+ }
}
}
@@ -3189,10 +3192,17 @@
std::string mUnexpectedTransition;
};
-enum { NAMED_CMD_NAME, NAMED_CMD_DELAY_MS, NAMED_CMD_STREAM_TYPE, NAMED_CMD_CMDS };
+enum {
+ NAMED_CMD_NAME,
+ NAMED_CMD_DELAY_MS,
+ NAMED_CMD_STREAM_TYPE,
+ NAMED_CMD_CMDS,
+ NAMED_CMD_VALIDATE_POS_INCREASE
+};
enum class StreamTypeFilter { ANY, SYNC, ASYNC };
using NamedCommandSequence =
- std::tuple<std::string, int, StreamTypeFilter, std::shared_ptr<StateSequence>>;
+ std::tuple<std::string, int /*cmdDelayMs*/, StreamTypeFilter,
+ std::shared_ptr<StateSequence>, bool /*validatePositionIncrease*/>;
enum { PARAM_MODULE_NAME, PARAM_CMD_SEQ, PARAM_SETUP_SEQ };
using StreamIoTestParameters =
std::tuple<std::string /*moduleName*/, NamedCommandSequence, bool /*useSetupSequence2*/>;
@@ -3236,10 +3246,14 @@
ASSERT_NO_FATAL_FAILURE(delayTransientStates.SetUp(module.get()));
const auto& commandsAndStates =
std::get<NAMED_CMD_CMDS>(std::get<PARAM_CMD_SEQ>(GetParam()));
+ const bool validatePositionIncrease =
+ std::get<NAMED_CMD_VALIDATE_POS_INCREASE>(std::get<PARAM_CMD_SEQ>(GetParam()));
if (!std::get<PARAM_SETUP_SEQ>(GetParam())) {
- ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(portConfig, commandsAndStates));
+ ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(portConfig, commandsAndStates,
+ validatePositionIncrease));
} else {
- ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(portConfig, commandsAndStates));
+ ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(portConfig, commandsAndStates,
+ validatePositionIncrease));
}
if (isNonBlocking) {
// Also try running the same sequence with "aosp.forceTransientBurst" set.
@@ -3250,11 +3264,11 @@
if (forceTransientBurst.SetUpNoChecks(module.get(), true /*failureExpected*/)
.isOk()) {
if (!std::get<PARAM_SETUP_SEQ>(GetParam())) {
- ASSERT_NO_FATAL_FAILURE(
- RunStreamIoCommandsImplSeq1(portConfig, commandsAndStates));
+ ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(
+ portConfig, commandsAndStates, validatePositionIncrease));
} else {
- ASSERT_NO_FATAL_FAILURE(
- RunStreamIoCommandsImplSeq2(portConfig, commandsAndStates));
+ ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(
+ portConfig, commandsAndStates, validatePositionIncrease));
}
}
} else if (!IOTraits<Stream>::is_input) {
@@ -3267,11 +3281,11 @@
if (forceSynchronousDrain.SetUpNoChecks(module.get(), true /*failureExpected*/)
.isOk()) {
if (!std::get<PARAM_SETUP_SEQ>(GetParam())) {
- ASSERT_NO_FATAL_FAILURE(
- RunStreamIoCommandsImplSeq1(portConfig, commandsAndStates));
+ ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(
+ portConfig, commandsAndStates, validatePositionIncrease));
} else {
- ASSERT_NO_FATAL_FAILURE(
- RunStreamIoCommandsImplSeq2(portConfig, commandsAndStates));
+ ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(
+ portConfig, commandsAndStates, validatePositionIncrease));
}
}
}
@@ -3285,11 +3299,13 @@
// Set up a patch first, then open a stream.
void RunStreamIoCommandsImplSeq1(const AudioPortConfig& portConfig,
- std::shared_ptr<StateSequence> commandsAndStates) {
+ std::shared_ptr<StateSequence> commandsAndStates,
+ bool validatePositionIncrease) {
auto devicePorts = moduleConfig->getAttachedDevicesPortsForMixPort(
IOTraits<Stream>::is_input, portConfig);
ASSERT_FALSE(devicePorts.empty());
auto devicePortConfig = moduleConfig->getSingleConfigForDevicePort(devicePorts[0]);
+ SCOPED_TRACE(devicePortConfig.toString());
WithAudioPatch patch(IOTraits<Stream>::is_input, portConfig, devicePortConfig);
ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
@@ -3307,14 +3323,17 @@
EXPECT_FALSE(worker.hasError()) << worker.getError();
EXPECT_EQ("", driver.getUnexpectedStateTransition());
if (ValidateObservablePosition(devicePortConfig)) {
- EXPECT_TRUE(driver.hasObservablePositionIncrease());
+ if (validatePositionIncrease) {
+ EXPECT_TRUE(driver.hasObservablePositionIncrease());
+ }
EXPECT_FALSE(driver.hasRetrogradeObservablePosition());
}
}
// Open a stream, then set up a patch for it.
void RunStreamIoCommandsImplSeq2(const AudioPortConfig& portConfig,
- std::shared_ptr<StateSequence> commandsAndStates) {
+ std::shared_ptr<StateSequence> commandsAndStates,
+ bool validatePositionIncrease) {
WithStream<Stream> stream(portConfig);
ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
StreamLogicDefaultDriver driver(commandsAndStates,
@@ -3326,6 +3345,7 @@
IOTraits<Stream>::is_input, portConfig);
ASSERT_FALSE(devicePorts.empty());
auto devicePortConfig = moduleConfig->getSingleConfigForDevicePort(devicePorts[0]);
+ SCOPED_TRACE(devicePortConfig.toString());
WithAudioPatch patch(IOTraits<Stream>::is_input, stream.getPortConfig(), devicePortConfig);
ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
@@ -3336,7 +3356,9 @@
EXPECT_FALSE(worker.hasError()) << worker.getError();
EXPECT_EQ("", driver.getUnexpectedStateTransition());
if (ValidateObservablePosition(devicePortConfig)) {
- EXPECT_TRUE(driver.hasObservablePositionIncrease());
+ if (validatePositionIncrease) {
+ EXPECT_TRUE(driver.hasObservablePositionIncrease());
+ }
EXPECT_FALSE(driver.hasRetrogradeObservablePosition());
}
}
@@ -3673,22 +3695,28 @@
using State = StreamDescriptor::State;
auto d = std::make_unique<StateDag>();
StateDag::Node last = d->makeFinalNode(State::ACTIVE);
- StateDag::Node active = d->makeNode(State::ACTIVE, kBurstCommand, last);
+ // Use a couple of bursts to ensure that the driver starts reporting the position.
+ StateDag::Node active2 = d->makeNode(State::ACTIVE, kBurstCommand, last);
+ StateDag::Node active = d->makeNode(State::ACTIVE, kBurstCommand, active2);
StateDag::Node idle = d->makeNode(State::IDLE, kBurstCommand, active);
if (!isSync) {
// Allow optional routing via the TRANSFERRING state on bursts.
- active.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, last));
+ active2.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, last));
+ active.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, active2));
idle.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, active));
}
d->makeNode(State::STANDBY, kStartCommand, idle);
return std::make_shared<StateSequenceFollower>(std::move(d));
}
static const NamedCommandSequence kReadSeq =
- std::make_tuple(std::string("Read"), 0, StreamTypeFilter::ANY, makeBurstCommands(true));
+ std::make_tuple(std::string("Read"), 0, StreamTypeFilter::ANY, makeBurstCommands(true),
+ true /*validatePositionIncrease*/);
static const NamedCommandSequence kWriteSyncSeq =
- std::make_tuple(std::string("Write"), 0, StreamTypeFilter::SYNC, makeBurstCommands(true));
+ std::make_tuple(std::string("Write"), 0, StreamTypeFilter::SYNC, makeBurstCommands(true),
+ true /*validatePositionIncrease*/);
static const NamedCommandSequence kWriteAsyncSeq =
- std::make_tuple(std::string("Write"), 0, StreamTypeFilter::ASYNC, makeBurstCommands(false));
+ std::make_tuple(std::string("Write"), 0, StreamTypeFilter::ASYNC, makeBurstCommands(false),
+ true /*validatePositionIncrease*/);
std::shared_ptr<StateSequence> makeAsyncDrainCommands(bool isInput) {
using State = StreamDescriptor::State;
@@ -3716,11 +3744,12 @@
}
return std::make_shared<StateSequenceFollower>(std::move(d));
}
-static const NamedCommandSequence kWriteDrainAsyncSeq =
- std::make_tuple(std::string("WriteDrain"), kStreamTransientStateTransitionDelayMs,
- StreamTypeFilter::ASYNC, makeAsyncDrainCommands(false));
-static const NamedCommandSequence kDrainInSeq = std::make_tuple(
- std::string("Drain"), 0, StreamTypeFilter::ANY, makeAsyncDrainCommands(true));
+static const NamedCommandSequence kWriteDrainAsyncSeq = std::make_tuple(
+ std::string("WriteDrain"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
+ makeAsyncDrainCommands(false), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kDrainInSeq =
+ std::make_tuple(std::string("Drain"), 0, StreamTypeFilter::ANY,
+ makeAsyncDrainCommands(true), false /*validatePositionIncrease*/);
std::shared_ptr<StateSequence> makeDrainOutCommands(bool isSync) {
using State = StreamDescriptor::State;
@@ -3740,10 +3769,12 @@
d->makeNode(State::STANDBY, kStartCommand, idle);
return std::make_shared<StateSequenceFollower>(std::move(d));
}
-static const NamedCommandSequence kDrainOutSyncSeq = std::make_tuple(
- std::string("Drain"), 0, StreamTypeFilter::SYNC, makeDrainOutCommands(true));
-static const NamedCommandSequence kDrainOutAsyncSeq = std::make_tuple(
- std::string("Drain"), 0, StreamTypeFilter::ASYNC, makeDrainOutCommands(false));
+static const NamedCommandSequence kDrainOutSyncSeq =
+ std::make_tuple(std::string("Drain"), 0, StreamTypeFilter::SYNC, makeDrainOutCommands(true),
+ false /*validatePositionIncrease*/);
+static const NamedCommandSequence kDrainOutAsyncSeq =
+ std::make_tuple(std::string("Drain"), 0, StreamTypeFilter::ASYNC,
+ makeDrainOutCommands(false), false /*validatePositionIncrease*/);
std::shared_ptr<StateSequence> makeDrainPauseOutCommands(bool isSync) {
using State = StreamDescriptor::State;
@@ -3764,12 +3795,12 @@
d->makeNode(State::STANDBY, kStartCommand, idle);
return std::make_shared<StateSequenceFollower>(std::move(d));
}
-static const NamedCommandSequence kDrainPauseOutSyncSeq =
- std::make_tuple(std::string("DrainPause"), kStreamTransientStateTransitionDelayMs,
- StreamTypeFilter::SYNC, makeDrainPauseOutCommands(true));
-static const NamedCommandSequence kDrainPauseOutAsyncSeq =
- std::make_tuple(std::string("DrainPause"), kStreamTransientStateTransitionDelayMs,
- StreamTypeFilter::ASYNC, makeDrainPauseOutCommands(false));
+static const NamedCommandSequence kDrainPauseOutSyncSeq = std::make_tuple(
+ std::string("DrainPause"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::SYNC,
+ makeDrainPauseOutCommands(true), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kDrainPauseOutAsyncSeq = std::make_tuple(
+ std::string("DrainPause"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
+ makeDrainPauseOutCommands(false), false /*validatePositionIncrease*/);
// This sequence also verifies that the capture / presentation position is not reset on standby.
std::shared_ptr<StateSequence> makeStandbyCommands(bool isInput, bool isSync) {
@@ -3810,13 +3841,15 @@
}
return std::make_shared<StateSequenceFollower>(std::move(d));
}
-static const NamedCommandSequence kStandbyInSeq = std::make_tuple(
- std::string("Standby"), 0, StreamTypeFilter::ANY, makeStandbyCommands(true, false));
-static const NamedCommandSequence kStandbyOutSyncSeq = std::make_tuple(
- std::string("Standby"), 0, StreamTypeFilter::SYNC, makeStandbyCommands(false, true));
-static const NamedCommandSequence kStandbyOutAsyncSeq =
- std::make_tuple(std::string("Standby"), kStreamTransientStateTransitionDelayMs,
- StreamTypeFilter::ASYNC, makeStandbyCommands(false, false));
+static const NamedCommandSequence kStandbyInSeq =
+ std::make_tuple(std::string("Standby"), 0, StreamTypeFilter::ANY,
+ makeStandbyCommands(true, false), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kStandbyOutSyncSeq =
+ std::make_tuple(std::string("Standby"), 0, StreamTypeFilter::SYNC,
+ makeStandbyCommands(false, true), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kStandbyOutAsyncSeq = std::make_tuple(
+ std::string("Standby"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
+ makeStandbyCommands(false, false), false /*validatePositionIncrease*/);
std::shared_ptr<StateSequence> makePauseCommands(bool isInput, bool isSync) {
using State = StreamDescriptor::State;
@@ -3851,13 +3884,15 @@
}
return std::make_shared<StateSequenceFollower>(std::move(d));
}
-static const NamedCommandSequence kPauseInSeq = std::make_tuple(
- std::string("Pause"), 0, StreamTypeFilter::ANY, makePauseCommands(true, false));
-static const NamedCommandSequence kPauseOutSyncSeq = std::make_tuple(
- std::string("Pause"), 0, StreamTypeFilter::SYNC, makePauseCommands(false, true));
-static const NamedCommandSequence kPauseOutAsyncSeq =
- std::make_tuple(std::string("Pause"), kStreamTransientStateTransitionDelayMs,
- StreamTypeFilter::ASYNC, makePauseCommands(false, false));
+static const NamedCommandSequence kPauseInSeq =
+ std::make_tuple(std::string("Pause"), 0, StreamTypeFilter::ANY,
+ makePauseCommands(true, false), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kPauseOutSyncSeq =
+ std::make_tuple(std::string("Pause"), 0, StreamTypeFilter::SYNC,
+ makePauseCommands(false, true), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kPauseOutAsyncSeq = std::make_tuple(
+ std::string("Pause"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
+ makePauseCommands(false, false), false /*validatePositionIncrease*/);
std::shared_ptr<StateSequence> makeFlushCommands(bool isInput, bool isSync) {
using State = StreamDescriptor::State;
@@ -3884,13 +3919,15 @@
}
return std::make_shared<StateSequenceFollower>(std::move(d));
}
-static const NamedCommandSequence kFlushInSeq = std::make_tuple(
- std::string("Flush"), 0, StreamTypeFilter::ANY, makeFlushCommands(true, false));
-static const NamedCommandSequence kFlushOutSyncSeq = std::make_tuple(
- std::string("Flush"), 0, StreamTypeFilter::SYNC, makeFlushCommands(false, true));
-static const NamedCommandSequence kFlushOutAsyncSeq =
- std::make_tuple(std::string("Flush"), kStreamTransientStateTransitionDelayMs,
- StreamTypeFilter::ASYNC, makeFlushCommands(false, false));
+static const NamedCommandSequence kFlushInSeq =
+ std::make_tuple(std::string("Flush"), 0, StreamTypeFilter::ANY,
+ makeFlushCommands(true, false), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kFlushOutSyncSeq =
+ std::make_tuple(std::string("Flush"), 0, StreamTypeFilter::SYNC,
+ makeFlushCommands(false, true), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kFlushOutAsyncSeq = std::make_tuple(
+ std::string("Flush"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
+ makeFlushCommands(false, false), false /*validatePositionIncrease*/);
std::shared_ptr<StateSequence> makeDrainPauseFlushOutCommands(bool isSync) {
using State = StreamDescriptor::State;
@@ -3911,10 +3948,12 @@
}
static const NamedCommandSequence kDrainPauseFlushOutSyncSeq =
std::make_tuple(std::string("DrainPauseFlush"), kStreamTransientStateTransitionDelayMs,
- StreamTypeFilter::SYNC, makeDrainPauseFlushOutCommands(true));
+ StreamTypeFilter::SYNC, makeDrainPauseFlushOutCommands(true),
+ false /*validatePositionIncrease*/);
static const NamedCommandSequence kDrainPauseFlushOutAsyncSeq =
std::make_tuple(std::string("DrainPauseFlush"), kStreamTransientStateTransitionDelayMs,
- StreamTypeFilter::ASYNC, makeDrainPauseFlushOutCommands(false));
+ StreamTypeFilter::ASYNC, makeDrainPauseFlushOutCommands(false),
+ false /*validatePositionIncrease*/);
// Note, this isn't the "official" enum printer, it is only used to make the test name suffix.
std::string PrintStreamFilterToString(StreamTypeFilter filter) {
diff --git a/audio/aidl/vts/VtsHalAudioCoreTargetTest.xml b/audio/aidl/vts/VtsHalAudioCoreTargetTest.xml
index dfc1039..9d3adc1 100644
--- a/audio/aidl/vts/VtsHalAudioCoreTargetTest.xml
+++ b/audio/aidl/vts/VtsHalAudioCoreTargetTest.xml
@@ -25,6 +25,11 @@
<option name="teardown-command" value="setprop vts.native_server.on 0"/>
</target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="VtsHalAudioCoreTargetTest->/data/local/tmp/VtsHalAudioCoreTargetTest" />
+ </target_preparer>
+
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="VtsHalAudioCoreTargetTest" />
diff --git a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
index 8084a59..225640e 100644
--- a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
@@ -134,17 +134,18 @@
/**
* @brief Check at least support list of effect must be supported by aosp:
* https://developer.android.com/reference/android/media/audiofx/AudioEffect
+ *
+ * For Android 13, they are: Equalizer, LoudnessEnhancer, Visualizer, and DynamicsProcessing.
+ * https://source.android.com/docs/compatibility/13/android-13-cdd#552_audio_effects
*/
-TEST_P(EffectFactoryTest, ExpectAllAospEffectTypes) {
+TEST_P(EffectFactoryTest, SupportMandatoryEffectTypes) {
std::vector<Descriptor> descs;
- std::set<AudioUuid> typeUuidSet(
- {aidl::android::hardware::audio::effect::getEffectTypeUuidBassBoost(),
- aidl::android::hardware::audio::effect::getEffectTypeUuidEqualizer(),
- aidl::android::hardware::audio::effect::getEffectTypeUuidEnvReverb(),
- aidl::android::hardware::audio::effect::getEffectTypeUuidPresetReverb(),
- aidl::android::hardware::audio::effect::getEffectTypeUuidDynamicsProcessing(),
- aidl::android::hardware::audio::effect::getEffectTypeUuidHapticGenerator(),
- aidl::android::hardware::audio::effect::getEffectTypeUuidVirtualizer()});
+ std::set<AudioUuid> typeUuidSet({
+ aidl::android::hardware::audio::effect::getEffectTypeUuidEqualizer(),
+ aidl::android::hardware::audio::effect::getEffectTypeUuidDynamicsProcessing(),
+ aidl::android::hardware::audio::effect::getEffectTypeUuidLoudnessEnhancer(),
+ aidl::android::hardware::audio::effect::getEffectTypeUuidVisualizer(),
+ });
EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &descs));
EXPECT_TRUE(descs.size() >= typeUuidSet.size());
@@ -305,4 +306,4 @@
ABinderProcess_setThreadPoolMaxThreadCount(1);
ABinderProcess_startThreadPool();
return RUN_ALL_TESTS();
-}
\ No newline at end of file
+}
diff --git a/audio/core/all-versions/default/ParametersUtil.cpp b/audio/core/all-versions/default/ParametersUtil.cpp
index e21eff2..4d8a208 100644
--- a/audio/core/all-versions/default/ParametersUtil.cpp
+++ b/audio/core/all-versions/default/ParametersUtil.cpp
@@ -51,7 +51,7 @@
Result retval = getParam(name, &halValue);
*value = false;
if (retval == Result::OK) {
- if (halValue.empty()) {
+ if (halValue.length() == 0) {
return Result::NOT_SUPPORTED;
}
*value = !(halValue == AudioParameter::valueOff);
@@ -97,17 +97,17 @@
retval = getHalStatusToResult(status);
break;
}
- result[i].key = halKey.string();
- result[i].value = halValue.string();
+ result[i].key = halKey.c_str();
+ result[i].value = halValue.c_str();
}
cb(retval, result);
}
std::unique_ptr<AudioParameter> ParametersUtil::getParams(const AudioParameter& keys) {
String8 paramsAndValues;
- char* halValues = halGetParameters(keys.keysToString().string());
+ char* halValues = halGetParameters(keys.keysToString().c_str());
if (halValues != NULL) {
- paramsAndValues.setTo(halValues);
+ paramsAndValues = halValues;
free(halValues);
} else {
paramsAndValues.clear();
@@ -163,7 +163,7 @@
}
Result ParametersUtil::setParams(const AudioParameter& param) {
- int halStatus = halSetParameters(param.toString().string());
+ int halStatus = halSetParameters(param.toString().c_str());
return util::analyzeStatus(halStatus);
}
diff --git a/audio/core/all-versions/default/Stream.cpp b/audio/core/all-versions/default/Stream.cpp
index 8e85a8b..c11b675 100644
--- a/audio/core/all-versions/default/Stream.cpp
+++ b/audio/core/all-versions/default/Stream.cpp
@@ -114,7 +114,7 @@
SampleRateSet halSampleRates;
if (result == Result::OK) {
halSampleRates =
- samplingRatesFromString(halListValue.string(), AudioParameter::valueListSeparator);
+ samplingRatesFromString(halListValue.c_str(), AudioParameter::valueListSeparator);
sampleRates = hidl_vec<uint32_t>(halSampleRates.begin(), halSampleRates.end());
// Legacy get_parameter does not return a status_t, thus can not advertise of failure.
// Note that this method must succeed (non empty list) if the format is supported.
@@ -140,7 +140,7 @@
ChannelMaskSet halChannelMasks;
if (result == Result::OK) {
halChannelMasks =
- channelMasksFromString(halListValue.string(), AudioParameter::valueListSeparator);
+ channelMasksFromString(halListValue.c_str(), AudioParameter::valueListSeparator);
channelMasks.resize(halChannelMasks.size());
size_t i = 0;
for (auto channelMask : halChannelMasks) {
@@ -182,7 +182,7 @@
hidl_vec<AudioFormat> formats;
FormatVector halFormats;
if (result == Result::OK) {
- halFormats = formatsFromString(halListValue.string(), AudioParameter::valueListSeparator);
+ halFormats = formatsFromString(halListValue.c_str(), AudioParameter::valueListSeparator);
formats.resize(halFormats.size());
for (size_t i = 0; i < halFormats.size(); ++i) {
formats[i] = AudioFormat(halFormats[i]);
@@ -226,7 +226,7 @@
// Ensure that the separator is one character, despite that it's defined as a C string.
static_assert(sizeof(AUDIO_PARAMETER_VALUE_LIST_SEPARATOR) == 2);
std::vector<std::string> halFormats =
- splitString(halListValue.string(), AUDIO_PARAMETER_VALUE_LIST_SEPARATOR[0]);
+ splitString(halListValue.c_str(), AUDIO_PARAMETER_VALUE_LIST_SEPARATOR[0]);
hidl_vec<AudioFormat> formats;
(void)HidlUtils::audioFormatsFromHal(halFormats, &formats);
std::vector<AudioProfile> tempProfiles;
@@ -241,7 +241,7 @@
result = getParam(AudioParameter::keyStreamSupportedSamplingRates, &halListValue, context);
if (result != Result::OK) break;
std::vector<std::string> halSampleRates =
- splitString(halListValue.string(), AUDIO_PARAMETER_VALUE_LIST_SEPARATOR[0]);
+ splitString(halListValue.c_str(), AUDIO_PARAMETER_VALUE_LIST_SEPARATOR[0]);
hidl_vec<uint32_t> sampleRates;
sampleRates.resize(halSampleRates.size());
for (size_t i = 0; i < sampleRates.size(); ++i) {
@@ -251,7 +251,7 @@
result = getParam(AudioParameter::keyStreamSupportedChannels, &halListValue, context);
if (result != Result::OK) break;
std::vector<std::string> halChannelMasks =
- splitString(halListValue.string(), AUDIO_PARAMETER_VALUE_LIST_SEPARATOR[0]);
+ splitString(halListValue.c_str(), AUDIO_PARAMETER_VALUE_LIST_SEPARATOR[0]);
hidl_vec<AudioChannelMask> channelMasks;
(void)HidlUtils::audioChannelMasksFromHal(halChannelMasks, &channelMasks);
// Create a profile.
diff --git a/audio/effect/all-versions/default/Effect.cpp b/audio/effect/all-versions/default/Effect.cpp
index 5aecd32..4a9e144 100644
--- a/audio/effect/all-versions/default/Effect.cpp
+++ b/audio/effect/all-versions/default/Effect.cpp
@@ -315,7 +315,7 @@
Effect::~Effect() {
ATRACE_CALL();
- (void)close();
+ auto [_, handle] = closeImpl();
if (mProcessThread.get()) {
ATRACE_NAME("mProcessThread->join");
status_t status = mProcessThread->join();
@@ -328,11 +328,10 @@
mInBuffer.clear();
mOutBuffer.clear();
#if MAJOR_VERSION <= 5
- int status = EffectRelease(mHandle);
- ALOGW_IF(status, "Error releasing effect %p: %s", mHandle, strerror(-status));
+ int status = EffectRelease(handle);
+ ALOGW_IF(status, "Error releasing effect %p: %s", handle, strerror(-status));
#endif
- EffectMap::getInstance().remove(mHandle);
- mHandle = 0;
+ EffectMap::getInstance().remove(handle);
}
// static
@@ -459,7 +458,19 @@
}
}
-void Effect::getConfigImpl(int commandCode, const char* commandName, GetConfigCallback cb) {
+#define RETURN_IF_EFFECT_CLOSED() \
+ if (mHandle == kInvalidEffectHandle) { \
+ return Result::INVALID_STATE; \
+ }
+#define RETURN_RESULT_IF_EFFECT_CLOSED(result) \
+ if (mHandle == kInvalidEffectHandle) { \
+ _hidl_cb(Result::INVALID_STATE, result); \
+ return Void(); \
+ }
+
+Return<void> Effect::getConfigImpl(int commandCode, const char* commandName,
+ GetConfigCallback _hidl_cb) {
+ RETURN_RESULT_IF_EFFECT_CLOSED(EffectConfig());
uint32_t halResultSize = sizeof(effect_config_t);
effect_config_t halConfig{};
status_t status =
@@ -468,7 +479,8 @@
if (status == OK) {
status = EffectUtils::effectConfigFromHal(halConfig, mIsInput, &config);
}
- cb(analyzeCommandStatus(commandName, sContextCallToCommand, status), config);
+ _hidl_cb(analyzeCommandStatus(commandName, sContextCallToCommand, status), config);
+ return Void();
}
Result Effect::getCurrentConfigImpl(uint32_t featureId, uint32_t configSize,
@@ -530,6 +542,7 @@
}
Return<void> Effect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) {
+ RETURN_RESULT_IF_EFFECT_CLOSED(StatusMQ::Descriptor());
status_t status;
// Create message queue.
if (mStatusMQ) {
@@ -576,6 +589,7 @@
Return<Result> Effect::setProcessBuffers(const AudioBuffer& inBuffer,
const AudioBuffer& outBuffer) {
+ RETURN_IF_EFFECT_CLOSED();
AudioBufferManager& manager = AudioBufferManager::getInstance();
sp<AudioBufferWrapper> tempInBuffer, tempOutBuffer;
if (!manager.wrap(inBuffer, &tempInBuffer)) {
@@ -600,6 +614,7 @@
}
Result Effect::sendCommand(int commandCode, const char* commandName, uint32_t size, void* data) {
+ RETURN_IF_EFFECT_CLOSED();
status_t status = (*mHandle)->command(mHandle, commandCode, size, data, 0, NULL);
return analyzeCommandStatus(commandName, sContextCallToCommand, status);
}
@@ -611,6 +626,7 @@
Result Effect::sendCommandReturningData(int commandCode, const char* commandName, uint32_t size,
void* data, uint32_t* replySize, void* replyData) {
+ RETURN_IF_EFFECT_CLOSED();
uint32_t expectedReplySize = *replySize;
status_t status = (*mHandle)->command(mHandle, commandCode, size, data, replySize, replyData);
if (status == OK && *replySize != expectedReplySize) {
@@ -635,6 +651,7 @@
uint32_t size, void* data, uint32_t* replySize,
void* replyData, uint32_t minReplySize,
CommandSuccessCallback onSuccess) {
+ RETURN_IF_EFFECT_CLOSED();
status_t status = (*mHandle)->command(mHandle, commandCode, size, data, replySize, replyData);
Result retval;
if (status == OK && minReplySize >= sizeof(uint32_t) && *replySize >= minReplySize) {
@@ -792,13 +809,11 @@
}
Return<void> Effect::getConfig(getConfig_cb _hidl_cb) {
- getConfigImpl(EFFECT_CMD_GET_CONFIG, "GET_CONFIG", _hidl_cb);
- return Void();
+ return getConfigImpl(EFFECT_CMD_GET_CONFIG, "GET_CONFIG", _hidl_cb);
}
Return<void> Effect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
- getConfigImpl(EFFECT_CMD_GET_CONFIG_REVERSE, "GET_CONFIG_REVERSE", _hidl_cb);
- return Void();
+ return getConfigImpl(EFFECT_CMD_GET_CONFIG_REVERSE, "GET_CONFIG_REVERSE", _hidl_cb);
}
Return<void> Effect::getSupportedAuxChannelsConfigs(uint32_t maxConfigs,
@@ -845,6 +860,7 @@
}
Return<void> Effect::getDescriptor(getDescriptor_cb _hidl_cb) {
+ RETURN_RESULT_IF_EFFECT_CLOSED(EffectDescriptor());
effect_descriptor_t halDescriptor;
memset(&halDescriptor, 0, sizeof(effect_descriptor_t));
status_t status = (*mHandle)->get_descriptor(mHandle, &halDescriptor);
@@ -858,6 +874,10 @@
Return<void> Effect::command(uint32_t commandId, const hidl_vec<uint8_t>& data,
uint32_t resultMaxSize, command_cb _hidl_cb) {
+ if (mHandle == kInvalidEffectHandle) {
+ _hidl_cb(-ENODATA, hidl_vec<uint8_t>());
+ return Void();
+ }
uint32_t halDataSize;
std::unique_ptr<uint8_t[]> halData = hidlVecToHal(data, &halDataSize);
uint32_t halResultSize = resultMaxSize;
@@ -942,26 +962,33 @@
halCmd.size(), &halCmd[0]);
}
-Return<Result> Effect::close() {
+std::tuple<Result, effect_handle_t> Effect::closeImpl() {
if (mStopProcessThread.load(std::memory_order_relaxed)) { // only this thread modifies
- return Result::INVALID_STATE;
+ return {Result::INVALID_STATE, kInvalidEffectHandle};
}
mStopProcessThread.store(true, std::memory_order_release);
if (mEfGroup) {
mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_QUIT));
}
+ effect_handle_t handle = mHandle;
+ mHandle = kInvalidEffectHandle;
#if MAJOR_VERSION <= 5
- return Result::OK;
+ return {Result::OK, handle};
#elif MAJOR_VERSION >= 6
// No need to join the processing thread, it is part of the API contract that the client
// must finish processing before closing the effect.
- Result retval =
- analyzeStatus("EffectRelease", "", sContextCallFunction, EffectRelease(mHandle));
- EffectMap::getInstance().remove(mHandle);
- return retval;
+ Result retval = analyzeStatus("EffectRelease", "", sContextCallFunction, EffectRelease(handle));
+ EffectMap::getInstance().remove(handle);
+ return {retval, handle};
#endif
}
+Return<Result> Effect::close() {
+ RETURN_IF_EFFECT_CLOSED();
+ auto [result, _] = closeImpl();
+ return result;
+}
+
Return<void> Effect::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /* options */) {
if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
uint32_t cmdData = fd->data[0];
diff --git a/audio/effect/all-versions/default/Effect.h b/audio/effect/all-versions/default/Effect.h
index 5d8dccc..2bcecec 100644
--- a/audio/effect/all-versions/default/Effect.h
+++ b/audio/effect/all-versions/default/Effect.h
@@ -23,6 +23,7 @@
#include <atomic>
#include <memory>
+#include <tuple>
#include <vector>
#include <fmq/EventFlag.h>
@@ -186,6 +187,7 @@
// Sets the limit on the maximum size of vendor-provided data structures.
static constexpr size_t kMaxDataSize = 1 << 20;
+ static constexpr effect_handle_t kInvalidEffectHandle = nullptr;
static const char* sContextResultOfCommand;
static const char* sContextCallToCommand;
@@ -208,6 +210,7 @@
static size_t alignedSizeIn(size_t s);
template <typename T>
std::unique_ptr<uint8_t[]> hidlVecToHal(const hidl_vec<T>& vec, uint32_t* halDataSize);
+ std::tuple<Result, effect_handle_t> closeImpl();
void effectAuxChannelsConfigFromHal(const channel_config_t& halConfig,
EffectAuxChannelsConfig* config);
static void effectAuxChannelsConfigToHal(const EffectAuxChannelsConfig& config,
@@ -218,7 +221,8 @@
const void** valueData, std::vector<uint8_t>* halParamBuffer);
Result analyzeCommandStatus(const char* commandName, const char* context, status_t status);
- void getConfigImpl(int commandCode, const char* commandName, GetConfigCallback cb);
+ Return<void> getConfigImpl(int commandCode, const char* commandName,
+ GetConfigCallback _hidl_cb);
Result getCurrentConfigImpl(uint32_t featureId, uint32_t configSize,
GetCurrentConfigSuccessCallback onSuccess);
Result getSupportedConfigsImpl(uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
diff --git a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
index d95bb06..ff84f9d 100644
--- a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
@@ -169,13 +169,15 @@
0xfe3199be, 0xaed0, 0x413f, 0x87bb,
std::array<uint8_t, 6>{{0x11, 0x26, 0x0e, 0xb6, 0x3c, 0xf1}}};
-enum { PARAM_FACTORY_NAME, PARAM_EFFECT_UUID };
-using EffectParameter = std::tuple<std::string, Uuid>;
+enum { PARAM_FACTORY_NAME, PARAM_EFFECT_UUID, PARAM_USE_AFTER_CLOSE };
+using EffectParameter = std::tuple<std::string, Uuid, bool>;
static inline std::string EffectParameterToString(
const ::testing::TestParamInfo<EffectParameter>& info) {
- return ::android::hardware::PrintInstanceNameToString(::testing::TestParamInfo<std::string>{
- std::get<PARAM_FACTORY_NAME>(info.param), info.index});
+ std::string prefix = std::get<PARAM_USE_AFTER_CLOSE>(info.param) ? "UseAfterClose_" : "";
+ return prefix.append(
+ ::android::hardware::PrintInstanceNameToString(::testing::TestParamInfo<std::string>{
+ std::get<PARAM_FACTORY_NAME>(info.param), info.index}));
}
// The main test class for Audio Effect HIDL HAL.
@@ -191,6 +193,13 @@
Return<Result> ret = effect->init();
ASSERT_TRUE(ret.isOk());
ASSERT_EQ(Result::OK, ret);
+
+ useAfterClose = std::get<PARAM_USE_AFTER_CLOSE>(GetParam());
+ if (useAfterClose) {
+ Return<Result> ret = effect->close();
+ ASSERT_TRUE(ret.isOk());
+ ASSERT_EQ(Result::OK, ret);
+ }
}
void TearDown() override {
@@ -205,14 +214,34 @@
Uuid getEffectType() const { return std::get<PARAM_EFFECT_UUID>(GetParam()); }
+ void checkResult(const Result& result);
+ void checkResultForUseAfterClose(const Result& result);
void findAndCreateEffect(const Uuid& type);
void findEffectInstance(const Uuid& type, Uuid* uuid);
void getChannelCount(uint32_t* channelCount);
sp<IEffectsFactory> effectsFactory;
sp<IEffect> effect;
+ bool useAfterClose;
};
+void AudioEffectHidlTest::checkResult(const Result& result) {
+ if (!useAfterClose) {
+ ASSERT_EQ(Result::OK, result);
+ } else {
+ ASSERT_NO_FATAL_FAILURE(checkResultForUseAfterClose(result));
+ }
+}
+
+void AudioEffectHidlTest::checkResultForUseAfterClose(const Result& result) {
+ if (useAfterClose) {
+ // The actual error does not matter. It's important that the effect did not crash
+ // while executing any command after a call to "close", and that the returned status
+ // is not OK.
+ ASSERT_NE(Result::OK, result);
+ }
+}
+
void AudioEffectHidlTest::findAndCreateEffect(const Uuid& type) {
Uuid effectUuid;
ASSERT_NO_FATAL_FAILURE(findEffectInstance(type, &effectUuid));
@@ -257,7 +286,11 @@
}
});
ASSERT_TRUE(ret.isOk());
- ASSERT_EQ(Result::OK, retval);
+ ASSERT_NO_FATAL_FAILURE(checkResult(retval));
+ if (useAfterClose) {
+ *channelCount = 1;
+ return;
+ }
#if MAJOR_VERSION <= 6
ASSERT_TRUE(audio_channel_mask_is_valid(
static_cast<audio_channel_mask_t>(currentConfig.outputCfg.channels)));
@@ -276,7 +309,7 @@
description("Verify that an effect can be closed");
Return<Result> ret = effect->close();
EXPECT_TRUE(ret.isOk());
- EXPECT_EQ(Result::OK, ret);
+ ASSERT_NO_FATAL_FAILURE(checkResult(ret));
}
TEST_P(AudioEffectHidlTest, GetDescriptor) {
@@ -290,7 +323,8 @@
}
});
EXPECT_TRUE(ret.isOk());
- EXPECT_EQ(Result::OK, retval);
+ ASSERT_NO_FATAL_FAILURE(checkResult(retval));
+ if (useAfterClose) return;
EXPECT_EQ(getEffectType(), actualType);
}
@@ -307,7 +341,8 @@
}
});
EXPECT_TRUE(ret.isOk());
- EXPECT_EQ(Result::OK, retval);
+ EXPECT_NO_FATAL_FAILURE(checkResult(retval));
+ if (useAfterClose) return;
Return<Result> ret2 = effect->setConfig(currentConfig, nullptr, nullptr);
EXPECT_TRUE(ret2.isOk());
EXPECT_EQ(Result::OK, ret2);
@@ -336,7 +371,8 @@
}
});
EXPECT_TRUE(ret.isOk());
- EXPECT_EQ(Result::OK, retval);
+ EXPECT_NO_FATAL_FAILURE(checkResult(retval));
+ if (useAfterClose) return;
for (const auto& invalidInputCfg : generateInvalidConfigs(currentConfig.inputCfg)) {
EffectConfig invalidConfig = currentConfig;
invalidConfig.inputCfg = invalidInputCfg;
@@ -356,27 +392,35 @@
TEST_P(AudioEffectHidlTest, GetConfigReverse) {
description("Verify that GetConfigReverse does not crash");
- Return<void> ret = effect->getConfigReverse([&](Result, const EffectConfig&) {});
+ Result retval = Result::OK;
+ Return<void> ret = effect->getConfigReverse([&](Result r, const EffectConfig&) { retval = r; });
EXPECT_TRUE(ret.isOk());
+ EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(retval));
}
TEST_P(AudioEffectHidlTest, GetSupportedAuxChannelsConfigs) {
description("Verify that GetSupportedAuxChannelsConfigs does not crash");
+ Result retval = Result::OK;
Return<void> ret = effect->getSupportedAuxChannelsConfigs(
- 0, [&](Result, const hidl_vec<EffectAuxChannelsConfig>&) {});
+ 0, [&](Result r, const hidl_vec<EffectAuxChannelsConfig>&) { retval = r; });
EXPECT_TRUE(ret.isOk());
+ EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(retval));
}
TEST_P(AudioEffectHidlTest, GetAuxChannelsConfig) {
description("Verify that GetAuxChannelsConfig does not crash");
- Return<void> ret = effect->getAuxChannelsConfig([&](Result, const EffectAuxChannelsConfig&) {});
+ Result retval = Result::OK;
+ Return<void> ret = effect->getAuxChannelsConfig(
+ [&](Result r, const EffectAuxChannelsConfig&) { retval = r; });
EXPECT_TRUE(ret.isOk());
+ EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(retval));
}
TEST_P(AudioEffectHidlTest, SetAuxChannelsConfig) {
description("Verify that SetAuxChannelsConfig does not crash");
Return<Result> ret = effect->setAuxChannelsConfig(EffectAuxChannelsConfig());
EXPECT_TRUE(ret.isOk());
+ EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(ret));
}
// Not generated automatically because AudioBuffer contains
@@ -427,45 +471,56 @@
description("Verify that Reset preserves effect configuration");
Result retval = Result::NOT_INITIALIZED;
EffectConfig originalConfig;
- Return<void> ret = effect->getConfig([&](Result r, const EffectConfig& conf) {
- retval = r;
- if (r == Result::OK) {
- originalConfig = conf;
- }
- });
- ASSERT_TRUE(ret.isOk());
- ASSERT_EQ(Result::OK, retval);
+ if (!useAfterClose) {
+ Return<void> ret = effect->getConfig([&](Result r, const EffectConfig& conf) {
+ retval = r;
+ if (r == Result::OK) {
+ originalConfig = conf;
+ }
+ });
+ ASSERT_TRUE(ret.isOk());
+ ASSERT_EQ(Result::OK, retval);
+ }
Return<Result> ret2 = effect->reset();
EXPECT_TRUE(ret2.isOk());
- EXPECT_EQ(Result::OK, ret2);
- EffectConfig configAfterReset;
- ret = effect->getConfig([&](Result r, const EffectConfig& conf) {
- retval = r;
- if (r == Result::OK) {
- configAfterReset = conf;
- }
- });
- EXPECT_EQ(originalConfig, configAfterReset);
+ EXPECT_NO_FATAL_FAILURE(checkResult(ret2));
+ if (!useAfterClose) {
+ EffectConfig configAfterReset;
+ Return<void> ret = effect->getConfig([&](Result r, const EffectConfig& conf) {
+ retval = r;
+ if (r == Result::OK) {
+ configAfterReset = conf;
+ }
+ });
+ EXPECT_EQ(originalConfig, configAfterReset);
+ }
}
TEST_P(AudioEffectHidlTest, DisableEnableDisable) {
description("Verify Disable -> Enable -> Disable sequence for an effect");
Return<Result> ret = effect->disable();
EXPECT_TRUE(ret.isOk());
- // Note: some legacy effects may return -EINVAL (INVALID_ARGUMENTS),
- // more canonical is to return -ENOSYS (NOT_SUPPORTED)
- EXPECT_TRUE(ret == Result::NOT_SUPPORTED || ret == Result::INVALID_ARGUMENTS);
+ if (!useAfterClose) {
+ // Note: some legacy effects may return -EINVAL (INVALID_ARGUMENTS),
+ // more canonical is to return -ENOSYS (NOT_SUPPORTED)
+ EXPECT_TRUE(ret == Result::NOT_SUPPORTED || ret == Result::INVALID_ARGUMENTS);
+ } else {
+ EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(ret));
+ }
ret = effect->enable();
EXPECT_TRUE(ret.isOk());
- EXPECT_EQ(Result::OK, ret);
+ EXPECT_NO_FATAL_FAILURE(checkResult(ret));
ret = effect->disable();
EXPECT_TRUE(ret.isOk());
- EXPECT_EQ(Result::OK, ret);
+ EXPECT_NO_FATAL_FAILURE(checkResult(ret));
}
#if MAJOR_VERSION >= 7
TEST_P(AudioEffectHidlTest, SetDeviceInvalidDeviceAddress) {
description("Verify that invalid device address is rejected by SetDevice");
+ if (useAfterClose) {
+ GTEST_SKIP() << "Does not make sense for the useAfterClose case";
+ }
DeviceAddress device{.deviceType = "random_string"};
Return<Result> ret = effect->setDevice(device);
EXPECT_TRUE(ret.isOk());
@@ -482,13 +537,13 @@
Return<Result> ret = effect->setDevice(device);
#endif
EXPECT_TRUE(ret.isOk());
- EXPECT_EQ(Result::OK, ret);
+ EXPECT_NO_FATAL_FAILURE(checkResult(ret));
}
TEST_P(AudioEffectHidlTest, SetAndGetVolume) {
description("Verify that SetAndGetVolume method works for an effect");
uint32_t channelCount;
- getChannelCount(&channelCount);
+ ASSERT_NO_FATAL_FAILURE(getChannelCount(&channelCount));
hidl_vec<uint32_t> volumes;
volumes.resize(channelCount);
for (uint32_t i = 0; i < channelCount; ++i) {
@@ -498,13 +553,13 @@
Return<void> ret =
effect->setAndGetVolume(volumes, [&](Result r, const hidl_vec<uint32_t>&) { retval = r; });
EXPECT_TRUE(ret.isOk());
- EXPECT_EQ(Result::OK, retval);
+ EXPECT_NO_FATAL_FAILURE(checkResult(retval));
}
TEST_P(AudioEffectHidlTest, VolumeChangeNotification) {
description("Verify that effect accepts VolumeChangeNotification");
uint32_t channelCount;
- getChannelCount(&channelCount);
+ ASSERT_NO_FATAL_FAILURE(getChannelCount(&channelCount));
hidl_vec<uint32_t> volumes;
volumes.resize(channelCount);
for (uint32_t i = 0; i < channelCount; ++i) {
@@ -512,25 +567,29 @@
}
Return<Result> ret = effect->volumeChangeNotification(volumes);
EXPECT_TRUE(ret.isOk());
- EXPECT_EQ(Result::OK, ret);
+ EXPECT_NO_FATAL_FAILURE(checkResult(ret));
}
TEST_P(AudioEffectHidlTest, SetAudioMode) {
description("Verify that SetAudioMode works for an effect");
Return<Result> ret = effect->setAudioMode(AudioMode::NORMAL);
EXPECT_TRUE(ret.isOk());
- EXPECT_EQ(Result::OK, ret);
+ EXPECT_NO_FATAL_FAILURE(checkResult(ret));
}
TEST_P(AudioEffectHidlTest, SetConfigReverse) {
description("Verify that SetConfigReverse does not crash");
Return<Result> ret = effect->setConfigReverse(EffectConfig(), nullptr, nullptr);
EXPECT_TRUE(ret.isOk());
+ EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(ret));
}
#if MAJOR_VERSION >= 7
TEST_P(AudioEffectHidlTest, SetInputDeviceInvalidDeviceAddress) {
description("Verify that invalid device address is rejected by SetInputDevice");
+ if (useAfterClose) {
+ GTEST_SKIP() << "Does not make sense for the useAfterClose case";
+ }
DeviceAddress device{.deviceType = "random_string"};
Return<Result> ret = effect->setInputDevice(device);
EXPECT_TRUE(ret.isOk());
@@ -548,11 +607,15 @@
Return<Result> ret = effect->setInputDevice(device);
#endif
EXPECT_TRUE(ret.isOk());
+ EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(ret));
}
#if MAJOR_VERSION >= 7
TEST_P(AudioEffectHidlTest, SetInvalidAudioSource) {
description("Verify that an invalid audio source is rejected by SetAudioSource");
+ if (useAfterClose) {
+ GTEST_SKIP() << "Does not make sense for the useAfterClose case";
+ }
Return<Result> ret = effect->setAudioSource("random_string");
ASSERT_TRUE(ret.isOk());
EXPECT_TRUE(ret == Result::INVALID_ARGUMENTS || ret == Result::NOT_SUPPORTED)
@@ -568,12 +631,14 @@
Return<Result> ret = effect->setAudioSource(toString(xsd::AudioSource::AUDIO_SOURCE_MIC));
#endif
EXPECT_TRUE(ret.isOk());
+ EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(ret));
}
TEST_P(AudioEffectHidlTest, Offload) {
description("Verify that calling Offload method does not crash");
Return<Result> ret = effect->offload(EffectOffloadParameter{});
EXPECT_TRUE(ret.isOk());
+ EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(ret));
}
TEST_P(AudioEffectHidlTest, PrepareForProcessing) {
@@ -582,7 +647,7 @@
Return<void> ret = effect->prepareForProcessing(
[&](Result r, const MQDescriptorSync<Result>&) { retval = r; });
EXPECT_TRUE(ret.isOk());
- EXPECT_EQ(Result::OK, retval);
+ EXPECT_NO_FATAL_FAILURE(checkResult(retval));
}
TEST_P(AudioEffectHidlTest, SetProcessBuffers) {
@@ -601,7 +666,7 @@
ASSERT_TRUE(success);
Return<Result> ret2 = effect->setProcessBuffers(buffer, buffer);
EXPECT_TRUE(ret2.isOk());
- EXPECT_EQ(Result::OK, ret2);
+ EXPECT_NO_FATAL_FAILURE(checkResult(ret2));
}
TEST_P(AudioEffectHidlTest, Command) {
@@ -615,6 +680,7 @@
description("Verify that SetParameter does not crash");
Return<Result> ret = effect->setParameter(hidl_vec<uint8_t>(), hidl_vec<uint8_t>());
EXPECT_TRUE(ret.isOk());
+ EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(ret));
}
TEST_P(AudioEffectHidlTest, GetParameter) {
@@ -630,6 +696,9 @@
if (!isNewDeviceLaunchingOnTPlus) {
GTEST_SKIP() << "The test only applies to devices launching on T or later";
}
+ if (useAfterClose) {
+ GTEST_SKIP() << "Does not make sense for the useAfterClose case";
+ }
// Use a non-empty parameter to avoid being rejected by any earlier checks.
hidl_vec<uint8_t> parameter;
parameter.resize(16);
@@ -647,16 +716,20 @@
TEST_P(AudioEffectHidlTest, GetSupportedConfigsForFeature) {
description("Verify that GetSupportedConfigsForFeature does not crash");
+ Result retval = Result::OK;
Return<void> ret = effect->getSupportedConfigsForFeature(
- 0, 0, 0, [&](Result, uint32_t, const hidl_vec<uint8_t>&) {});
+ 0, 0, 0, [&](Result r, uint32_t, const hidl_vec<uint8_t>&) { retval = r; });
EXPECT_TRUE(ret.isOk());
+ EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(retval));
}
TEST_P(AudioEffectHidlTest, GetCurrentConfigForFeature) {
description("Verify that GetCurrentConfigForFeature does not crash");
- Return<void> ret =
- effect->getCurrentConfigForFeature(0, 0, [&](Result, const hidl_vec<uint8_t>&) {});
+ Result retval = Result::OK;
+ Return<void> ret = effect->getCurrentConfigForFeature(
+ 0, 0, [&](Result r, const hidl_vec<uint8_t>&) { retval = r; });
EXPECT_TRUE(ret.isOk());
+ EXPECT_NO_FATAL_FAILURE(checkResultForUseAfterClose(retval));
}
TEST_P(AudioEffectHidlTest, SetCurrentConfigForFeature) {
@@ -671,6 +744,9 @@
if (!isNewDeviceLaunchingOnTPlus) {
GTEST_SKIP() << "The test only applies to devices launching on T or later";
}
+ if (useAfterClose) {
+ GTEST_SKIP() << "Does not make sense for the useAfterClose case";
+ }
// Use very large size to ensure that the service does not crash.
const uint32_t veryLargeConfigSize = std::numeric_limits<uint32_t>::max() - 100;
Result retval = Result::OK;
@@ -687,6 +763,9 @@
if (!isNewDeviceLaunchingOnTPlus) {
GTEST_SKIP() << "The test only applies to devices launching on T or later";
}
+ if (useAfterClose) {
+ GTEST_SKIP() << "Does not make sense for the useAfterClose case";
+ }
// Use very large size to ensure that the service does not crash.
const uint32_t veryLargeConfigSize = std::numeric_limits<uint32_t>::max() - 100;
Result retval = Result::OK;
@@ -729,7 +808,8 @@
}
});
ASSERT_TRUE(ret.isOk());
- ASSERT_EQ(Result::OK, retval);
+ ASSERT_NO_FATAL_FAILURE(checkResult(retval));
+ if (useAfterClose) *numBands = 1;
}
void EqualizerAudioEffectHidlTest::getLevelRange(int16_t* minLevel, int16_t* maxLevel) {
@@ -742,7 +822,11 @@
}
});
ASSERT_TRUE(ret.isOk());
- ASSERT_EQ(Result::OK, retval);
+ ASSERT_NO_FATAL_FAILURE(checkResult(retval));
+ if (useAfterClose) {
+ *minLevel = 0;
+ *maxLevel = 255;
+ }
}
void EqualizerAudioEffectHidlTest::getBandFrequencyRange(uint16_t band, uint32_t* minFreq,
@@ -757,7 +841,7 @@
}
});
ASSERT_TRUE(ret.isOk());
- ASSERT_EQ(Result::OK, retval);
+ ASSERT_NO_FATAL_FAILURE(checkResult(retval));
ret = equalizer->getBandCenterFrequency(band, [&](Result r, uint32_t center) {
retval = r;
if (retval == Result::OK) {
@@ -765,7 +849,12 @@
}
});
ASSERT_TRUE(ret.isOk());
- ASSERT_EQ(Result::OK, retval);
+ ASSERT_NO_FATAL_FAILURE(checkResult(retval));
+ if (useAfterClose) {
+ *minFreq = 20;
+ *centerFreq = 10000;
+ *maxFreq = 20000;
+ }
}
void EqualizerAudioEffectHidlTest::getPresetCount(size_t* count) {
@@ -777,37 +866,38 @@
}
});
ASSERT_TRUE(ret.isOk());
- ASSERT_EQ(Result::OK, retval);
+ ASSERT_NO_FATAL_FAILURE(checkResult(retval));
+ if (useAfterClose) *count = 1;
}
TEST_P(EqualizerAudioEffectHidlTest, GetNumBands) {
description("Verify that Equalizer effect reports at least one band");
uint16_t numBands = 0;
- getNumBands(&numBands);
+ ASSERT_NO_FATAL_FAILURE(getNumBands(&numBands));
EXPECT_GT(numBands, 0);
}
TEST_P(EqualizerAudioEffectHidlTest, GetLevelRange) {
description("Verify that Equalizer effect reports adequate band level range");
int16_t minLevel = 0x7fff, maxLevel = 0;
- getLevelRange(&minLevel, &maxLevel);
+ ASSERT_NO_FATAL_FAILURE(getLevelRange(&minLevel, &maxLevel));
EXPECT_GT(maxLevel, minLevel);
}
TEST_P(EqualizerAudioEffectHidlTest, GetSetBandLevel) {
description("Verify that manipulating band levels works for Equalizer effect");
uint16_t numBands = 0;
- getNumBands(&numBands);
+ ASSERT_NO_FATAL_FAILURE(getNumBands(&numBands));
ASSERT_GT(numBands, 0);
int16_t levels[3]{0x7fff, 0, 0};
- getLevelRange(&levels[0], &levels[2]);
+ ASSERT_NO_FATAL_FAILURE(getLevelRange(&levels[0], &levels[2]));
ASSERT_GT(levels[2], levels[0]);
levels[1] = (levels[2] + levels[0]) / 2;
for (uint16_t i = 0; i < numBands; ++i) {
for (size_t j = 0; j < ARRAY_SIZE(levels); ++j) {
Return<Result> ret = equalizer->setBandLevel(i, levels[j]);
EXPECT_TRUE(ret.isOk());
- EXPECT_EQ(Result::OK, ret);
+ EXPECT_NO_FATAL_FAILURE(checkResult(ret));
Result retval = Result::NOT_INITIALIZED;
int16_t actualLevel;
Return<void> ret2 = equalizer->getBandLevel(i, [&](Result r, int16_t l) {
@@ -817,8 +907,10 @@
}
});
EXPECT_TRUE(ret2.isOk());
- EXPECT_EQ(Result::OK, retval);
- EXPECT_EQ(levels[j], actualLevel);
+ EXPECT_NO_FATAL_FAILURE(checkResult(retval));
+ if (!useAfterClose) {
+ EXPECT_EQ(levels[j], actualLevel);
+ }
}
}
}
@@ -826,11 +918,11 @@
TEST_P(EqualizerAudioEffectHidlTest, GetBandCenterFrequencyAndRange) {
description("Verify that Equalizer effect reports adequate band frequency range");
uint16_t numBands = 0;
- getNumBands(&numBands);
+ ASSERT_NO_FATAL_FAILURE(getNumBands(&numBands));
ASSERT_GT(numBands, 0);
for (uint16_t i = 0; i < numBands; ++i) {
uint32_t minFreq = 0xffffffff, centerFreq = 0xffffffff, maxFreq = 0xffffffff;
- getBandFrequencyRange(i, &minFreq, ¢erFreq, &maxFreq);
+ ASSERT_NO_FATAL_FAILURE(getBandFrequencyRange(i, &minFreq, ¢erFreq, &maxFreq));
// Note: NXP legacy implementation reports "1" as upper bound for last band,
// so this check fails.
EXPECT_GE(maxFreq, centerFreq);
@@ -841,7 +933,7 @@
TEST_P(EqualizerAudioEffectHidlTest, GetBandForFrequency) {
description("Verify that Equalizer effect supports GetBandForFrequency correctly");
uint16_t numBands = 0;
- getNumBands(&numBands);
+ ASSERT_NO_FATAL_FAILURE(getNumBands(&numBands));
ASSERT_GT(numBands, 0);
for (uint16_t i = 0; i < numBands; ++i) {
uint32_t freqs[3]{0, 0, 0};
@@ -861,8 +953,10 @@
}
});
EXPECT_TRUE(ret.isOk());
- EXPECT_EQ(Result::OK, retval);
- EXPECT_EQ(i, actualBand) << "Frequency: " << freqs[j];
+ EXPECT_NO_FATAL_FAILURE(checkResult(retval));
+ if (!useAfterClose) {
+ EXPECT_EQ(i, actualBand) << "Frequency: " << freqs[j];
+ }
}
}
}
@@ -870,19 +964,19 @@
TEST_P(EqualizerAudioEffectHidlTest, GetPresetNames) {
description("Verify that Equalizer effect reports at least one preset");
size_t presetCount;
- getPresetCount(&presetCount);
+ ASSERT_NO_FATAL_FAILURE(getPresetCount(&presetCount));
EXPECT_GT(presetCount, 0u);
}
TEST_P(EqualizerAudioEffectHidlTest, GetSetCurrentPreset) {
description("Verify that manipulating the current preset for Equalizer effect");
size_t presetCount;
- getPresetCount(&presetCount);
+ ASSERT_NO_FATAL_FAILURE(getPresetCount(&presetCount));
ASSERT_GT(presetCount, 0u);
for (uint16_t i = 0; i < presetCount; ++i) {
Return<Result> ret = equalizer->setCurrentPreset(i);
EXPECT_TRUE(ret.isOk());
- EXPECT_EQ(Result::OK, ret);
+ EXPECT_NO_FATAL_FAILURE(checkResult(ret));
Result retval = Result::NOT_INITIALIZED;
uint16_t actualPreset = 0xffff;
Return<void> ret2 = equalizer->getCurrentPreset([&](Result r, uint16_t p) {
@@ -892,8 +986,10 @@
}
});
EXPECT_TRUE(ret2.isOk());
- EXPECT_EQ(Result::OK, retval);
- EXPECT_EQ(i, actualPreset);
+ EXPECT_NO_FATAL_FAILURE(checkResult(retval));
+ if (!useAfterClose) {
+ EXPECT_EQ(i, actualPreset);
+ }
}
}
@@ -904,7 +1000,7 @@
using AllProperties =
::android::hardware::audio::effect::CPP_VERSION::IEqualizerEffect::AllProperties;
uint16_t numBands = 0;
- getNumBands(&numBands);
+ ASSERT_NO_FATAL_FAILURE(getNumBands(&numBands));
ASSERT_GT(numBands, 0);
AllProperties props;
props.bandLevels.resize(numBands);
@@ -919,7 +1015,7 @@
props.curPreset = -1;
Return<Result> ret = equalizer->setAllProperties(props);
EXPECT_TRUE(ret.isOk());
- EXPECT_EQ(Result::OK, ret);
+ EXPECT_NO_FATAL_FAILURE(checkResult(ret));
Return<void> ret2 = equalizer->getAllProperties([&](Result r, AllProperties p) {
retval = r;
if (retval == Result::OK) {
@@ -927,14 +1023,16 @@
}
});
EXPECT_TRUE(ret2.isOk());
- EXPECT_EQ(Result::OK, retval);
- EXPECT_EQ(props.bandLevels, actualProps.bandLevels);
+ EXPECT_NO_FATAL_FAILURE(checkResult(retval));
+ if (!useAfterClose) {
+ EXPECT_EQ(props.bandLevels, actualProps.bandLevels);
+ }
// Verify setting of the current preset via properties.
props.curPreset = 0; // Assuming there is at least one preset.
ret = equalizer->setAllProperties(props);
EXPECT_TRUE(ret.isOk());
- EXPECT_EQ(Result::OK, ret);
+ EXPECT_NO_FATAL_FAILURE(checkResult(ret));
ret2 = equalizer->getAllProperties([&](Result r, AllProperties p) {
retval = r;
if (retval == Result::OK) {
@@ -942,8 +1040,10 @@
}
});
EXPECT_TRUE(ret2.isOk());
- EXPECT_EQ(Result::OK, retval);
- EXPECT_EQ(props.curPreset, actualProps.curPreset);
+ EXPECT_NO_FATAL_FAILURE(checkResult(retval));
+ if (!useAfterClose) {
+ EXPECT_EQ(props.curPreset, actualProps.curPreset);
+ }
}
// The main test class for Equalizer Audio Effect HIDL HAL.
@@ -971,7 +1071,7 @@
const int32_t gain = 100;
Return<Result> ret = enhancer->setTargetGain(gain);
EXPECT_TRUE(ret.isOk());
- EXPECT_EQ(Result::OK, ret);
+ EXPECT_NO_FATAL_FAILURE(checkResult(ret));
int32_t actualGain = 0;
Result retval;
Return<void> ret2 = enhancer->getTargetGain([&](Result r, int32_t g) {
@@ -981,8 +1081,10 @@
}
});
EXPECT_TRUE(ret2.isOk());
- EXPECT_EQ(Result::OK, retval);
- EXPECT_EQ(gain, actualGain);
+ EXPECT_NO_FATAL_FAILURE(checkResult(retval));
+ if (!useAfterClose) {
+ EXPECT_EQ(gain, actualGain);
+ }
}
INSTANTIATE_TEST_SUITE_P(EffectsFactory, AudioEffectsFactoryHidlTest,
@@ -993,25 +1095,29 @@
Equalizer_IEffect, AudioEffectHidlTest,
::testing::Combine(::testing::ValuesIn(::android::hardware::getAllHalInstanceNames(
IEffectsFactory::descriptor)),
- ::testing::Values(EQUALIZER_EFFECT_TYPE)),
+ ::testing::Values(EQUALIZER_EFFECT_TYPE),
+ ::testing::Values(false, true) /*useAfterClose*/),
EffectParameterToString);
INSTANTIATE_TEST_SUITE_P(
LoudnessEnhancer_IEffect, AudioEffectHidlTest,
::testing::Combine(::testing::ValuesIn(::android::hardware::getAllHalInstanceNames(
IEffectsFactory::descriptor)),
- ::testing::Values(LOUDNESS_ENHANCER_EFFECT_TYPE)),
+ ::testing::Values(LOUDNESS_ENHANCER_EFFECT_TYPE),
+ ::testing::Values(false, true) /*useAfterClose*/),
EffectParameterToString);
INSTANTIATE_TEST_SUITE_P(
Equalizer, EqualizerAudioEffectHidlTest,
::testing::Combine(::testing::ValuesIn(::android::hardware::getAllHalInstanceNames(
IEffectsFactory::descriptor)),
- ::testing::Values(EQUALIZER_EFFECT_TYPE)),
+ ::testing::Values(EQUALIZER_EFFECT_TYPE),
+ ::testing::Values(false, true) /*useAfterClose*/),
EffectParameterToString);
INSTANTIATE_TEST_SUITE_P(
LoudnessEnhancer, LoudnessEnhancerAudioEffectHidlTest,
::testing::Combine(::testing::ValuesIn(::android::hardware::getAllHalInstanceNames(
IEffectsFactory::descriptor)),
- ::testing::Values(LOUDNESS_ENHANCER_EFFECT_TYPE)),
+ ::testing::Values(LOUDNESS_ENHANCER_EFFECT_TYPE),
+ ::testing::Values(false, true) /*useAfterClose*/),
EffectParameterToString);
// When the VTS test runs on a device lacking the corresponding HAL version the parameter
// list is empty, this isn't a problem.
diff --git a/audio/policy/1.0/xml/api/current.txt b/audio/policy/1.0/xml/api/current.txt
index 84a2b71..01d77d7 100644
--- a/audio/policy/1.0/xml/api/current.txt
+++ b/audio/policy/1.0/xml/api/current.txt
@@ -209,11 +209,13 @@
public enum UsageEnumType {
method public String getRawName();
enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_ALARM;
+ enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_ANNOUNCEMENT;
enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE;
enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_ASSISTANCE_SONIFICATION;
enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_ASSISTANT;
enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_CALL_ASSISTANT;
+ enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_EMERGENCY;
enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_GAME;
enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_MEDIA;
enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_NOTIFICATION;
@@ -222,7 +224,9 @@
enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST;
enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_NOTIFICATION_EVENT;
enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
+ enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_SAFETY;
enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_UNKNOWN;
+ enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_VEHICLE_STATUS;
enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_VIRTUAL_SOURCE;
enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_VOICE_COMMUNICATION;
enum_constant public static final audio.policy.V1_0.UsageEnumType AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
diff --git a/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd b/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd
index b58a6c8..40396bb 100644
--- a/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd
+++ b/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd
@@ -359,6 +359,10 @@
<xs:enumeration value="AUDIO_USAGE_VIRTUAL_SOURCE"/>
<xs:enumeration value="AUDIO_USAGE_ASSISTANT"/>
<xs:enumeration value="AUDIO_USAGE_CALL_ASSISTANT"/>
+ <xs:enumeration value="AUDIO_USAGE_EMERGENCY" />
+ <xs:enumeration value="AUDIO_USAGE_SAFETY" />
+ <xs:enumeration value="AUDIO_USAGE_VEHICLE_STATUS" />
+ <xs:enumeration value="AUDIO_USAGE_ANNOUNCEMENT" />
</xs:restriction>
</xs:simpleType>
diff --git a/authsecret/aidl/default/Android.bp b/authsecret/aidl/default/Android.bp
index 7ce83fd..7e6e48b 100644
--- a/authsecret/aidl/default/Android.bp
+++ b/authsecret/aidl/default/Android.bp
@@ -26,16 +26,60 @@
cc_binary {
name: "android.hardware.authsecret-service.example",
relative_install_path: "hw",
- init_rc: ["android.hardware.authsecret-service.example.rc"],
- vintf_fragments: ["android.hardware.authsecret-service.example.xml"],
vendor: true,
srcs: [
"service.cpp",
"AuthSecret.cpp",
],
shared_libs: [
+ "libbinder_ndk",
+ "liblog",
+ ],
+ static_libs: [
"android.hardware.authsecret-V1-ndk",
"libbase",
- "libbinder_ndk",
+ ],
+ stl: "c++_static",
+}
+
+prebuilt_etc {
+ name: "android.hardware.authsecret-service.example.rc",
+ src: "android.hardware.authsecret-service.example.rc",
+ installable: false,
+}
+
+prebuilt_etc {
+ name: "android.hardware.authsecret-service.example.xml",
+ src: "android.hardware.authsecret-service.example.xml",
+ sub_dir: "vintf",
+ installable: false,
+}
+
+apex_key {
+ name: "com.android.hardware.authsecret.key",
+ public_key: "com.android.hardware.authsecret.avbpubkey",
+ private_key: "com.android.hardware.authsecret.pem",
+}
+
+android_app_certificate {
+ name: "com.android.hardware.authsecret.certificate",
+ certificate: "com.android.hardware.authsecret",
+}
+
+apex {
+ name: "com.android.hardware.authsecret",
+ manifest: "manifest.json",
+ file_contexts: "file_contexts",
+ key: "com.android.hardware.authsecret.key",
+ certificate: ":com.android.hardware.authsecret.certificate",
+ updatable: false,
+ vendor: true,
+
+ binaries: [
+ "android.hardware.authsecret-service.example",
+ ],
+ prebuilts: [
+ "android.hardware.authsecret-service.example.rc", // init_rc
+ "android.hardware.authsecret-service.example.xml", // vintf_fragments
],
}
diff --git a/authsecret/aidl/default/android.hardware.authsecret-service.example.rc b/authsecret/aidl/default/android.hardware.authsecret-service.example.rc
index fef6e24..9f51837 100644
--- a/authsecret/aidl/default/android.hardware.authsecret-service.example.rc
+++ b/authsecret/aidl/default/android.hardware.authsecret-service.example.rc
@@ -1,4 +1,4 @@
-service vendor.authsecret_default /vendor/bin/hw/android.hardware.authsecret-service.example
+service vendor.authsecret_default /apex/com.android.hardware.authsecret/bin/hw/android.hardware.authsecret-service.example
class hal
user hsm
group hsm
diff --git a/authsecret/aidl/default/com.android.hardware.authsecret.avbpubkey b/authsecret/aidl/default/com.android.hardware.authsecret.avbpubkey
new file mode 100644
index 0000000..2fb5f0b
--- /dev/null
+++ b/authsecret/aidl/default/com.android.hardware.authsecret.avbpubkey
Binary files differ
diff --git a/authsecret/aidl/default/com.android.hardware.authsecret.pem b/authsecret/aidl/default/com.android.hardware.authsecret.pem
new file mode 100644
index 0000000..644868c
--- /dev/null
+++ b/authsecret/aidl/default/com.android.hardware.authsecret.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJQQIBADANBgkqhkiG9w0BAQEFAASCCSswggknAgEAAoICAQCkkrpV5StewKq6
+HOog0IkbBRAtuChTsQjE1yQY6VXF/f/QWc2L0++pe0PTNzuKJZuqD05tgLYBxsFl
+QSLMKoUnGkQshVHxFLCls0CQo/umgygydxyVNW5cTdDDbl0VHrYcJJSWBobfy/hh
+dizJVET6HMQLY0shKM9CcdFDRqvM+WB6ceBxcFsxwm8r5qcB6CCeIDsPuBBo5Mpa
+NlVbaMBc/qrSRFLqLiVph6Goycg0Zk5+i1A4VBTJoHlOQwgX4uMdlNoAnaf1rLIm
+Qn2zNfcfeZ3BoiwKv8qMsvLNotaN+oIYLi4t21JcPsroByI+Ps5Gia17BhQvbbXx
+3eRShBn6/YcxcMQmCPoN5JbqeyzcE9f0grh3I8ubf1+ZAW0dL2r6QRM6uo6T4Jf7
+BFiMVB0RjTzfo8ngwgPLIm/aXU2O8IG8sILO1s1iOaQb23E2PveF1B7EOmFzW8x3
+xSQQLwn83zY+V+BTZs/Dfgv+M3omctsLS7lgGuvSx9KHV+EnbRMoIYa/2fx5KUxP
+kC3rGpR2BRHZibm3tBlHmdkzOsaHaoQy2fLtqK39Au+cL05O5VpOYObBN2wOlKUO
+iWLS79YoaWAKUZtZKwQNu1jpmK0OMgCeC13QSTz2AuPgL6XEuCUpcmblX3KMsu5w
+MK79Yke/V61cQ71e5qI0vr3IXjcjywIDAQABAoICAAYZ0GGNyNFO6CVVHBLSWDrR
+sbtYJ9qOZgpSBWsM/1qDI4AYTCfiV/Ca+rUyR3lEEqS3w4sIqfaf5Rx5US5rZxs/
+fIZ//L0orLG/1uVlxtbx5sQUKVGYtPokAli0VywIwuyBKKb1H/vc5lzKkjd2ccYp
+2dSoPilBB4npiT3quUS0e/CeFxltdlv+XrusZcWK0ua5wCbBho406RF2ESz90Z/A
+6xk3YjF/O3DRj9sfe9YBcuh7BqLH7ytYURbnIj4scYnvsjMypP7VA5eqgFlr5zjZ
++9CpT+OoH3yex6R65GRIBJmb4KdfiYqU41W9qfXPwzrXMMCuRYJKmWOZe7TZY9Mc
+V46jaDgLgKxe+mI4CLi2auKFE4KL8x68KSqa22y2dEjWwBPiT7If6v0ZL4CiAy9n
+SNHFaceMY3l485vaZEtXxusRB/UGDZnAXr9NqBVm4YVAfOaEnJNDSqvYefM5iyOG
+yQZ7dCXS9Ey4JvVlceA6mybj2JSx20QS2wN/tcyZjWsjM0f/sIHAJRS6KhEqCIfX
+4L8d5nXJ1wvnBFvcfboSERkPOTQsuipsvn9uj8Zs9QWNYYRSyleptL+ce8fBqed6
+9ryErCuB9lpVTjUsOiaIibtGdePleQb10club1B/4vsgPl5wvTPRNCTmpOCP3pSf
+Rei2x4z1VGFOBwd3MiTtAoIBAQDiQCsK87Zs8E5cwc0CqeMWstWHvJLTkj2B42OI
+Zrbr6ByRixuLpWgVWtJJLKbLXPN83wl8eksv3+Ba+yi17uafhXX7M1O5RlOzvTHt
+bbFPeysB3KEmNt96dRDRKYY3z0KHJxCRWKKZjZjp8Usf3TuKi9Xbque8o2n1LKKB
+KANRC4xtHmUesl6d4S4iAfIkq5/nA4ocuJ2qd/2t3nc6yhPPRrP9+4sUPYdqBEUz
+ds9isqt5erUybstCoHRgsEwWo/9ew8Dyj1TCIDTSqRt1/0QnEVm77bgBrA8P66HI
+KKFVoo/MLQSw5V+CDZwTJNlPQwrG9tyrSkcMFgLSRzi+7d/3AoIBAQC6Nm5Ztiad
+zm/1jM89uHmvedimKCKKG6+Eom5D96PduP76uRr65s6Usn0QCZ4Jvou0xnbtCP1K
+lzVI1+v6EiIQyWX0y1bd0UJDdyYo4Ck2nqOh0vgw+cBO70faV50J5QA2mS/wFdw0
+PvykQpPYGiIfv1MMHWA+rPDzMtf1uUQ18vzzN7RaZll88pletC7mc7qgBaucQVvB
+/qzOZSwhiaSSvXS1sFKfkqLqpJ3x9748D74MIwDD2i3fRxxfqPcgrG3B7xxIKVgd
+CYoFjeC9inZbnwvPmtaKzROJknsuJA21s/ckkSiWJJbjbyymVc1hWNhoMbtSPopa
+OOJ7u695Ls3NAoIBADtRE3fVmXhKMGFFNhiCrdTfoffqSpxJdPK+yPOT6lVDD2ph
+DCG6heVDYGpq2HfssLGGUBhgf6HXkhyISI4aSkB8Xwgy1rp2Y6915McYwSnTYt0k
+GOPJ8yFJ29TajCPJpOmGJmPU1xxm8TY0WrvJ5rhWHQVwcz0Tos3ym9A8y1HOM0zQ
+cTZxETlXNh8YX4GZtVx9oxIQnNV6i/mvn5a8MCFhqgLmlfoCf6Qd5n6toYWAzlAV
+CbhlL8kSBDDtR6WP7X3M2KM/TLtwcijgySBQgm+zrtEEa/+UOoa0AkBV1qZ67jRb
+gSVXnYidRNQIDykmrIapZgVKfgH/K1Ix9gCooNUCggEAeSMzwnS2xm4nc2w43YQG
+1VrEz8LIRWQhWH16kgilt3XDmkOVA6fmt+EtbqNzBg/JPr7lWupALKgVZ9/fiX0G
+YDlEdG1bg03Ad7cpQeohpYCqHnnqL6IpsrAC5E2ewXMSInKhNuRhrjNTk2AkYa8O
+h+ylD/qERAGpdeybhSUS9K2wVGDmmPCAQsJnd65r3EtpGvTVYP87vAX7UQGMJf0u
+7K8HH7Mm7Nwt08tnXKO4Q8ZR8f9LXh2vPdM66Bg5PC4v8LumgGM1CR7NhTN5ApTy
+zkO3IUUvUHh8v0BlleyqZow+uLEd4B7Jcgc+2q5yv2NW1OGVZLl+s5bR74B3dLQ3
++QKCAQBtxqTUKaRE/g+paQByORt0mFuXhO5UyfEBpg6l7+aUS4wTGMeKKDCFjTME
+lDjEK7eiAAOgN3AJYQ+r6831pm3hg6DG5lpxTKUuz2eMqMHk3LVlDFkH6BZF3Jxg
+XxWP1Abi88hK3nnbuGrt6rlUxvJRdWaJcF5nXybJzPMpvzPcDjAg5fCT11vZQsRl
+piAO6NjAECwUOaBHSHPvIXO9fWu4zY03rhg9px+dkutydSJ/6B3jq33q1CzHDQMd
+bklkBBrLu9inpuvETbhVK6IWP2zMHzdViR58M+xd5rg2E3GBQePyd6mjOB+7p7Gd
+hUHo4XX1/r2CDceZTmOjaZP/MQOJ
+-----END PRIVATE KEY-----
diff --git a/authsecret/aidl/default/com.android.hardware.authsecret.pk8 b/authsecret/aidl/default/com.android.hardware.authsecret.pk8
new file mode 100644
index 0000000..1453366
--- /dev/null
+++ b/authsecret/aidl/default/com.android.hardware.authsecret.pk8
Binary files differ
diff --git a/authsecret/aidl/default/com.android.hardware.authsecret.x509.pem b/authsecret/aidl/default/com.android.hardware.authsecret.x509.pem
new file mode 100644
index 0000000..71fe854
--- /dev/null
+++ b/authsecret/aidl/default/com.android.hardware.authsecret.x509.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF4zCCA8sCFH8r8uUt7ZiBGNZm/OxNbzMI34N3MA0GCSqGSIb3DQEBCwUAMIGs
+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
+bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
+MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEoMCYGA1UEAwwfY29t
+LmFuZHJvaWQuaGFyZHdhcmUuYXV0aHNlY3JldDAgFw0yMzA4MTgwNzA3MDFaGA80
+NzYxMDcxNDA3MDcwMVowgawxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9y
+bmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAw
+DgYDVQQLDAdBbmRyb2lkMSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQu
+Y29tMSgwJgYDVQQDDB9jb20uYW5kcm9pZC5oYXJkd2FyZS5hdXRoc2VjcmV0MIIC
+IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1+ml99ip2TVpYdJXxqVnizLg
+/DAnOUy5rZE+mCpjua1zyHl7GFFnseq6GO5wftptWekcC9fVSPxg1YS+RVduRcNz
+rt3mCsJ60DexaHrElITc1GCC1vzyt9cg6UtmdYg+OXSPlfWZE2T7OLfGWrhU56El
+IFt1eQDu5RDBOHZ2/N30KmKXv3yhpdl5un/kaC6q6p1PPih0aYXT2PrHsyN17wBl
+smhhpWNg/OAzFhWKwFcSTLMCOAI+pjqWKqXmjQ1awBly+lLAtHEBxxEUDMD6Z4lv
+2OGftL9bdseb1Wbj2bgj22bkfwWj5Yu77ilz5H27aLxQouQsmSfBkVgLq6seQMzd
+ovg+MOFb9iyWgcWkGg7eKdSzjfzCKQ/d2GOxEqwGofEYUOxYM1+a0Fnb7vUtgT/v
+I4tJCgXxAMFtsYGySC+gBhNx7vqLfo/8gtcZjJL6PRtRJ2V7hF9x3xKFa2/6qOLn
+UD/R5z+uwzaEqom+AmmmKNdWtn58nBns7EGq/3KVPcb7CSi9Xf6CCJiV+AmRaBSx
+2CtLt1fBX46LM3bV+iw7ZFAYAAXE3j6FgpM/PlozQjl61TuomHQP1ILmu/988tiF
+FMbuRH6mI0u4VOkDBUg9lxmjr0uAVmysWmzkRrAKydzedsuG5WG6hy2ZcD+lCV05
+JzvE6pB65OaIEPB5cMECAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAozFo1vOIy/Js
+/EU5oRtSGSIoWCNIn7EYQ68jVHQk2ZhklVH2jW+6WVGmreOjPz5iWeDb0fC4KVtH
+MPXJ1Vd+GfvDysrnW5mDBzlI1O2xv/BWYeHt+RFWghhH/NFHaTQqDJpdOZXMZM4F
+dwFefxLchcXftE9jihHJXJ4k0cxC03Kpd0caZE7b67W1YQdJhU9mZx6CP1A3MdWU
+f48QIsmHgejkihtGNDRheBRzNdpHPhdOjYIWhOeAHh/xnm7PVZBMXmZeNW7MrAS0
++lN99r7Xj3eqtSdrMrrob845PWYsATA/a8ouUuTT7812fl8tZx69xb8wV5hNztDj
+srOxxJbjt1uwcSp67f2K91D97CQuMMPnOt1oFEXT+5QtLEiybXKfkshwO7VVDoIg
+owMLoKIiA2Xr+rZn7CEBeTrqQuRJfJEI+k/49zg2zWQIKGQAz8iaO0l95Hk5kPTE
+A5i9qxhn0UqC6a4Dkj8ybQOACzVA06IsbbYdprfzURQHjcUiSrEzjrwWxkkX/9El
+Z0CJAtkXx4pMxo5s6zt26ZPC3cxWB7aageWSC4xDbKuQP5VCNVg1nWymg6nF4Xk9
+d7n7yvSNH6fAZrpmZo7o7CBxCb4QN8j7TpyuaPd7nzyCyR6aGbh7fz8xksukvj6w
+ZSbAAy5uw4hyUwTTpyPyw+qQxI7O/PU=
+-----END CERTIFICATE-----
diff --git a/authsecret/aidl/default/file_contexts b/authsecret/aidl/default/file_contexts
new file mode 100644
index 0000000..8e79f26
--- /dev/null
+++ b/authsecret/aidl/default/file_contexts
@@ -0,0 +1,3 @@
+(/.*)? u:object_r:vendor_file:s0
+/etc(/.*)? u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.authsecret-service\.example u:object_r:hal_authsecret_default_exec:s0
\ No newline at end of file
diff --git a/authsecret/aidl/default/manifest.json b/authsecret/aidl/default/manifest.json
new file mode 100644
index 0000000..ad5a45b
--- /dev/null
+++ b/authsecret/aidl/default/manifest.json
@@ -0,0 +1,4 @@
+{
+ "name": "com.android.hardware.authsecret",
+ "version": 1
+}
diff --git a/automotive/vehicle/Android.bp b/automotive/vehicle/Android.bp
index c0d71d7..f0abbcf 100644
--- a/automotive/vehicle/Android.bp
+++ b/automotive/vehicle/Android.bp
@@ -22,6 +22,6 @@
name: "VehicleHalInterfaceDefaults",
static_libs: [
"android.hardware.automotive.vehicle-V2-ndk",
- "android.hardware.automotive.vehicle.property-V2-ndk",
+ "android.hardware.automotive.vehicle.property-V3-ndk",
],
}
diff --git a/automotive/vehicle/aidl/aidl_test/Android.bp b/automotive/vehicle/aidl/aidl_test/Android.bp
index 44d7445..79ac309 100644
--- a/automotive/vehicle/aidl/aidl_test/Android.bp
+++ b/automotive/vehicle/aidl/aidl_test/Android.bp
@@ -52,7 +52,7 @@
],
static_libs: [
"android.hardware.automotive.vehicle-V2-java",
- "android.hardware.automotive.vehicle.property-V2-java",
+ "android.hardware.automotive.vehicle.property-V3-java",
"androidx.test.runner",
"truth-prebuilt",
],
diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
index 90588aa..e740da7 100644
--- a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
@@ -24,6 +24,8 @@
#include "VehicleServer.grpc.pb.h"
#include "VehicleServer.pb.h"
+#include <grpc++/grpc++.h>
+
#include <atomic>
#include <chrono>
#include <condition_variable>
diff --git a/automotive/vehicle/aidl_property/Android.bp b/automotive/vehicle/aidl_property/Android.bp
index 19fa4a3..db96382 100644
--- a/automotive/vehicle/aidl_property/Android.bp
+++ b/automotive/vehicle/aidl_property/Android.bp
@@ -28,7 +28,7 @@
// This HAL was originally part of android.hardware.automotive.vehicle
"android/hardware/automotive/vehicle/*.aidl",
],
- frozen: true,
+ frozen: false,
stability: "vintf",
backend: {
cpp: {
@@ -52,7 +52,6 @@
version: "2",
imports: [],
},
-
],
}
diff --git a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl
index 44c9d54..a24f515 100644
--- a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl
+++ b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl
@@ -34,6 +34,7 @@
package android.hardware.automotive.vehicle;
@Backing(type="int") @VintfStability
enum VehicleAreaSeat {
+ UNKNOWN = 0x0000,
ROW_1_LEFT = 0x0001,
ROW_1_CENTER = 0x0002,
ROW_1_RIGHT = 0x0004,
diff --git a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl
index 89d50ea..e70fb22 100644
--- a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl
+++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl
@@ -22,6 +22,7 @@
@VintfStability
@Backing(type="int")
enum VehicleAreaSeat {
+ UNKNOWN = 0x0000,
ROW_1_LEFT = 0x0001,
ROW_1_CENTER = 0x0002,
ROW_1_RIGHT = 0x0004,
diff --git a/automotive/vehicle/vhal_static_cpp_lib.mk b/automotive/vehicle/vhal_static_cpp_lib.mk
index 995589c..bffa076 100644
--- a/automotive/vehicle/vhal_static_cpp_lib.mk
+++ b/automotive/vehicle/vhal_static_cpp_lib.mk
@@ -17,4 +17,4 @@
LOCAL_STATIC_LIBRARIES += \
android.hardware.automotive.vehicle-V2-ndk \
- android.hardware.automotive.vehicle.property-V2-ndk
+ android.hardware.automotive.vehicle.property-V3-ndk
diff --git a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
index 9f9ca96..54076c8 100644
--- a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
+++ b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
@@ -52,6 +52,14 @@
const keymaster::HardwareAuthToken& hat,
const std::future<void>& cancel) {
BEGIN_OP(0);
+
+ // Do proper HAT verification in the real implementation.
+ if (hat.mac.empty()) {
+ LOG(ERROR) << "Fail: hat";
+ cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
+ return;
+ }
+
updateContext(WorkMode::kEnroll, cb, const_cast<std::future<void>&>(cancel), 0, hat);
}
@@ -112,17 +120,10 @@
}
bool FakeFingerprintEngine::onEnrollFingerDown(ISessionCallback* cb,
- const keymaster::HardwareAuthToken& hat,
+ const keymaster::HardwareAuthToken&,
const std::future<void>& cancel) {
BEGIN_OP(getLatency(FingerprintHalProperties::operation_enroll_latency()));
- // Do proper HAT verification in the real implementation.
- if (hat.mac.empty()) {
- LOG(ERROR) << "Fail: hat";
- cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
- return true;
- }
-
// Force error-out
auto err = FingerprintHalProperties::operation_enroll_error().value_or(0);
if (err != 0) {
@@ -384,6 +385,11 @@
cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
return;
}
+ clearLockout(cb);
+ isLockoutTimerAborted = true;
+}
+
+void FakeFingerprintEngine::clearLockout(ISessionCallback* cb) {
FingerprintHalProperties::lockout(false);
cb->onLockoutCleared();
mLockoutTracker.reset();
@@ -573,13 +579,34 @@
if (lockoutMode == FakeLockoutTracker::LockoutMode::kPermanent) {
LOG(ERROR) << "Fail: lockout permanent";
cb->onLockoutPermanent();
+ isLockoutTimerAborted = true;
return true;
} else if (lockoutMode == FakeLockoutTracker::LockoutMode::kTimed) {
int64_t timeLeft = mLockoutTracker.getLockoutTimeLeft();
LOG(ERROR) << "Fail: lockout timed " << timeLeft;
cb->onLockoutTimed(timeLeft);
+ if (isLockoutTimerSupported && !isLockoutTimerStarted) startLockoutTimer(timeLeft, cb);
return true;
}
return false;
}
+
+void FakeFingerprintEngine::startLockoutTimer(int64_t timeout, ISessionCallback* cb) {
+ BEGIN_OP(0);
+ std::function<void(ISessionCallback*)> action =
+ std::bind(&FakeFingerprintEngine::lockoutTimerExpired, this, std::placeholders::_1);
+ std::thread([timeout, action, cb]() {
+ std::this_thread::sleep_for(std::chrono::milliseconds(timeout));
+ action(cb);
+ }).detach();
+
+ isLockoutTimerStarted = true;
+}
+void FakeFingerprintEngine::lockoutTimerExpired(ISessionCallback* cb) {
+ if (!isLockoutTimerAborted) {
+ clearLockout(cb);
+ }
+ isLockoutTimerStarted = false;
+ isLockoutTimerAborted = false;
+}
} // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/FakeFingerprintEngineSide.cpp b/biometrics/fingerprint/aidl/default/FakeFingerprintEngineSide.cpp
index 6982072..a78cdcd 100644
--- a/biometrics/fingerprint/aidl/default/FakeFingerprintEngineSide.cpp
+++ b/biometrics/fingerprint/aidl/default/FakeFingerprintEngineSide.cpp
@@ -27,6 +27,10 @@
namespace aidl::android::hardware::biometrics::fingerprint {
+FakeFingerprintEngineSide::FakeFingerprintEngineSide() : FakeFingerprintEngine() {
+ isLockoutTimerSupported = true;
+}
+
SensorLocation FakeFingerprintEngineSide::defaultSensorLocation() {
return SensorLocation{.sensorLocationX = defaultSensorLocationX,
.sensorLocationY = defaultSensorLocationY,
diff --git a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
index a06b786..2450115 100644
--- a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
+++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
@@ -114,8 +114,20 @@
std::vector<std::vector<int32_t>>& res);
int32_t getRandomInRange(int32_t bound1, int32_t bound2);
bool checkSensorLockout(ISessionCallback*);
+ void clearLockout(ISessionCallback* cb);
FakeLockoutTracker mLockoutTracker;
+
+ protected:
+ // lockout timer
+ void lockoutTimerExpired(ISessionCallback* cb);
+ bool isLockoutTimerSupported;
+ bool isLockoutTimerStarted;
+ bool isLockoutTimerAborted;
+
+ public:
+ void startLockoutTimer(int64_t timeout, ISessionCallback* cb);
+ bool getLockoutTimerStarted() { return isLockoutTimerStarted; }
};
} // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineSide.h b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineSide.h
index c2fc005..67a3ebc 100644
--- a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineSide.h
+++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineSide.h
@@ -28,7 +28,7 @@
static constexpr int32_t defaultSensorLocationY = 600;
static constexpr int32_t defaultSensorRadius = 150;
- FakeFingerprintEngineSide() : FakeFingerprintEngine() {}
+ FakeFingerprintEngineSide();
~FakeFingerprintEngineSide() {}
virtual SensorLocation defaultSensorLocation() override;
diff --git a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
index bc235a6..fe405f4 100644
--- a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
@@ -93,9 +93,13 @@
return ndk::ScopedAStatus::ok();
};
ndk::ScopedAStatus onLockoutTimed(int64_t /* timeout */) override {
+ mLockoutTimed = true;
return ndk::ScopedAStatus::ok();
}
- ndk::ScopedAStatus onLockoutCleared() override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus onLockoutCleared() override {
+ mLockoutCleared = true;
+ return ndk::ScopedAStatus::ok();
+ }
ndk::ScopedAStatus onSessionClosed() override { return ndk::ScopedAStatus::ok(); }
Error mError = Error::UNKNOWN;
@@ -110,6 +114,8 @@
bool mAuthenticateFailed = false;
bool mAuthenticatorIdInvalidated = false;
bool mLockoutPermanent = false;
+ bool mLockoutTimed = false;
+ bool mLockoutCleared = false;
int mInteractionDetectedCount = 0;
int32_t mLastAcquiredInfo = -1;
int32_t mLastAcquiredVendorCode = -1;
@@ -499,6 +505,13 @@
ASSERT_TRUE(latencySet.size() > 95);
}
+TEST_F(FakeFingerprintEngineTest, lockoutTimer) {
+ mEngine.startLockoutTimer(200, mCallback.get());
+ ASSERT_TRUE(mEngine.getLockoutTimerStarted());
+ std::this_thread::sleep_for(std::chrono::milliseconds(210));
+ ASSERT_FALSE(mEngine.getLockoutTimerStarted());
+ ASSERT_TRUE(mCallback->mLockoutCleared);
+}
} // namespace aidl::android::hardware::biometrics::fingerprint
int main(int argc, char** argv) {
diff --git a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.xml b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.xml
index 6010c60..c23d687 100644
--- a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.xml
+++ b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.xml
@@ -19,8 +19,6 @@
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
</target_preparer>
- <target_preparer class="com.android.tradefed.targetprep.StopServicesSetup">
- </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
<option name="run-command" value="settings put global ble_scan_always_enabled 0" />
@@ -31,6 +29,9 @@
<option name="teardown-command" value="settings put global ble_scan_always_enabled 1" />
</target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.StopServicesSetup">
+ </target_preparer>
+
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="VtsHalBluetoothV1_0TargetTest->/data/local/tmp/VtsHalBluetoothV1_0TargetTest" />
diff --git a/bluetooth/aidl/default/BluetoothHci.cpp b/bluetooth/aidl/default/BluetoothHci.cpp
index 782122f..013ab7f 100644
--- a/bluetooth/aidl/default/BluetoothHci.cpp
+++ b/bluetooth/aidl/default/BluetoothHci.cpp
@@ -55,6 +55,19 @@
void OnDeath(void* cookie);
+std::optional<std::string> GetSystemProperty(const std::string& property) {
+ std::array<char, PROPERTY_VALUE_MAX> value_array{0};
+ auto value_len = property_get(property.c_str(), value_array.data(), nullptr);
+ if (value_len <= 0) {
+ return std::nullopt;
+ }
+ return std::string(value_array.data(), value_len);
+}
+
+bool starts_with(const std::string& str, const std::string& prefix) {
+ return str.compare(0, prefix.length(), prefix) == 0;
+}
+
class BluetoothDeathRecipient {
public:
BluetoothDeathRecipient(BluetoothHci* hci) : mHci(hci) {}
@@ -232,8 +245,19 @@
mDeathRecipient->LinkToDeath(mCb);
- // TODO: This should not be necessary when the device implements rfkill.
- reset();
+ // TODO: HCI Reset on emulators since the bluetooth controller
+ // cannot be powered on/off during the HAL setup; and the stack
+ // might received spurious packets/events during boottime.
+ // Proper solution would be to use bt-virtio or vsock to better
+ // control the link to rootcanal and the controller lifetime.
+ const std::string kBoardProperty = "ro.product.board";
+ const std::string kCuttlefishBoard = "cutf";
+ auto board_name = GetSystemProperty(kBoardProperty);
+ if (board_name.has_value() && (
+ starts_with(board_name.value(), "cutf") ||
+ starts_with(board_name.value(), "goldfish"))) {
+ reset();
+ }
mH4 = std::make_shared<H4Protocol>(
mFd,
diff --git a/bluetooth/audio/aidl/Android.bp b/bluetooth/audio/aidl/Android.bp
index 32f8cca..1028fae 100644
--- a/bluetooth/audio/aidl/Android.bp
+++ b/bluetooth/audio/aidl/Android.bp
@@ -24,12 +24,13 @@
aidl_interface {
name: "android.hardware.bluetooth.audio",
vendor_available: true,
+ host_supported: true,
srcs: ["android/hardware/bluetooth/audio/*.aidl"],
stability: "vintf",
imports: [
"android.hardware.common-V2",
"android.hardware.common.fmq-V1",
- "android.hardware.audio.common-V1",
+ "android.hardware.audio.common-V2",
],
backend: {
cpp: {
@@ -69,7 +70,7 @@
imports: [
"android.hardware.common-V2",
"android.hardware.common.fmq-V1",
- "android.hardware.audio.common-V1",
+ "android.hardware.audio.common-V2",
],
},
diff --git a/bluetooth/audio/aidl/vts/Android.bp b/bluetooth/audio/aidl/vts/Android.bp
index 3e6953f..fa85fa8 100644
--- a/bluetooth/audio/aidl/vts/Android.bp
+++ b/bluetooth/audio/aidl/vts/Android.bp
@@ -16,7 +16,7 @@
tidy_timeout_srcs: ["VtsHalBluetoothAudioTargetTest.cpp"],
srcs: ["VtsHalBluetoothAudioTargetTest.cpp"],
static_libs: [
- "android.hardware.audio.common-V1-ndk",
+ "android.hardware.audio.common-V2-ndk",
"android.hardware.bluetooth.audio-V3-ndk",
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
diff --git a/bluetooth/audio/utils/Android.bp b/bluetooth/audio/utils/Android.bp
index 2cba61e..a09e7fe 100644
--- a/bluetooth/audio/utils/Android.bp
+++ b/bluetooth/audio/utils/Android.bp
@@ -36,6 +36,7 @@
cc_library_shared {
name: "libbluetooth_audio_session_aidl",
vendor: true,
+ host_supported: true,
srcs: [
"aidl_session/BluetoothAudioCodecs.cpp",
"aidl_session/BluetoothAudioSession.cpp",
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
index ee5527e..0bcafa3 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
@@ -20,6 +20,7 @@
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android/binder_manager.h>
+#include <hardware/audio.h>
#include "BluetoothAudioSession.h"
@@ -440,6 +441,16 @@
void BluetoothAudioSession::ReportLowLatencyModeAllowedChanged(bool allowed) {
std::lock_guard<std::recursive_mutex> guard(mutex_);
low_latency_allowed_ = allowed;
+ // TODO(b/294498919): Remove this after there is API to update latency mode
+ // after audio session started. If low_latency_allowed_ is true, the session
+ // can support LOW_LATENCY and FREE LatencyMode.
+ if (low_latency_allowed_) {
+ if (std::find(latency_modes_.begin(), latency_modes_.end(),
+ LatencyMode::LOW_LATENCY) == latency_modes_.end()) {
+ LOG(INFO) << __func__ << " - insert LOW_LATENCY LatencyMode";
+ latency_modes_.push_back(LatencyMode::LOW_LATENCY);
+ }
+ }
if (observers_.empty()) {
LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
<< " has NO port state observer";
@@ -476,23 +487,9 @@
void BluetoothAudioSession::UpdateSourceMetadata(
const struct source_metadata& source_metadata) {
- std::lock_guard<std::recursive_mutex> guard(mutex_);
- if (!IsSessionReady()) {
- LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
- << " has NO session";
- return;
- }
-
ssize_t track_count = source_metadata.track_count;
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
<< track_count << " track(s)";
- if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
- session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
- session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
- session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
- return;
- }
-
SourceMetadata hal_source_metadata;
hal_source_metadata.tracks.resize(track_count);
for (int i = 0; i < track_count; i++) {
@@ -509,33 +506,14 @@
<< toString(hal_source_metadata.tracks[i].contentType)
<< ", gain=" << hal_source_metadata.tracks[i].gain;
}
-
- auto hal_retval = stack_iface_->updateSourceMetadata(hal_source_metadata);
- if (!hal_retval.isOk()) {
- LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
- << toString(session_type_) << " failed";
- }
+ UpdateSourceMetadata(hal_source_metadata);
}
void BluetoothAudioSession::UpdateSinkMetadata(
const struct sink_metadata& sink_metadata) {
- std::lock_guard<std::recursive_mutex> guard(mutex_);
- if (!IsSessionReady()) {
- LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
- << " has NO session";
- return;
- }
-
ssize_t track_count = sink_metadata.track_count;
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
<< track_count << " track(s)";
- if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
- session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
- session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
- session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
- return;
- }
-
SinkMetadata hal_sink_metadata;
hal_sink_metadata.tracks.resize(track_count);
for (int i = 0; i < track_count; i++) {
@@ -550,12 +528,57 @@
<< ", dest_device_address="
<< sink_metadata.tracks[i].dest_device_address;
}
+ UpdateSinkMetadata(hal_sink_metadata);
+}
+
+bool BluetoothAudioSession::UpdateSourceMetadata(
+ const SourceMetadata& hal_source_metadata) {
+ std::lock_guard<std::recursive_mutex> guard(mutex_);
+ if (!IsSessionReady()) {
+ LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+ << " has NO session";
+ return false;
+ }
+
+ if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
+ session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+ session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
+ session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+ return false;
+ }
+
+ auto hal_retval = stack_iface_->updateSourceMetadata(hal_source_metadata);
+ if (!hal_retval.isOk()) {
+ LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+ << toString(session_type_) << " failed";
+ return false;
+ }
+ return true;
+}
+
+bool BluetoothAudioSession::UpdateSinkMetadata(
+ const SinkMetadata& hal_sink_metadata) {
+ std::lock_guard<std::recursive_mutex> guard(mutex_);
+ if (!IsSessionReady()) {
+ LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+ << " has NO session";
+ return false;
+ }
+
+ if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
+ session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+ session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
+ session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+ return false;
+ }
auto hal_retval = stack_iface_->updateSinkMetadata(hal_sink_metadata);
if (!hal_retval.isOk()) {
LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
<< toString(session_type_) << " failed";
+ return false;
}
+ return true;
}
std::vector<LatencyMode> BluetoothAudioSession::GetSupportedLatencyModes() {
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h
index 5bf17bd..103a9ea 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h
@@ -23,12 +23,15 @@
#include <aidl/android/hardware/bluetooth/audio/LatencyMode.h>
#include <aidl/android/hardware/bluetooth/audio/SessionType.h>
#include <fmq/AidlMessageQueue.h>
-#include <hardware/audio.h>
#include <mutex>
#include <unordered_map>
#include <vector>
+// To avoid inclusion of hardware/audio.h
+struct sink_metadata;
+struct source_metadata;
+
namespace aidl {
namespace android {
namespace hardware {
@@ -183,6 +186,9 @@
bool GetPresentationPosition(PresentationPosition& presentation_position);
void UpdateSourceMetadata(const struct source_metadata& source_metadata);
void UpdateSinkMetadata(const struct sink_metadata& sink_metadata);
+ // New versions for AIDL-only clients.
+ bool UpdateSourceMetadata(const SourceMetadata& hal_source_metadata);
+ bool UpdateSinkMetadata(const SinkMetadata& hal_sink_metadata);
std::vector<LatencyMode> GetSupportedLatencyModes();
void SetLatencyMode(const LatencyMode& latency_mode);
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h
index 0782c82..7ae0353 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h
@@ -156,6 +156,26 @@
}
}
+ static bool UpdateSourceMetadata(const SessionType& session_type,
+ const SourceMetadata& source_metadata) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ return session_ptr->UpdateSourceMetadata(source_metadata);
+ }
+ return false;
+ }
+
+ static bool UpdateSinkMetadata(const SessionType& session_type,
+ const SinkMetadata& sink_metadata) {
+ std::shared_ptr<BluetoothAudioSession> session_ptr =
+ BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ return session_ptr->UpdateSinkMetadata(sink_metadata);
+ }
+ return false;
+ }
+
static std::vector<LatencyMode> GetSupportedLatencyModes(
const SessionType& session_type) {
std::shared_ptr<BluetoothAudioSession> session_ptr =
diff --git a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp
index a4664f1..3d92ee7 100644
--- a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp
+++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp
@@ -583,7 +583,7 @@
*total_bytes_readed = presentation_position.transmittedOctets;
if (data_position)
*data_position = {
- .tv_sec = static_cast<__kernel_old_time_t>(
+ .tv_sec = static_cast<long>(
presentation_position.transmittedOctetsTimestamp.tvSec),
.tv_nsec = static_cast<long>(
presentation_position.transmittedOctetsTimestamp.tvNSec)};
diff --git a/broadcastradio/aidl/default/BroadcastRadio.cpp b/broadcastradio/aidl/default/BroadcastRadio.cpp
index 4d097c1..8584921 100644
--- a/broadcastradio/aidl/default/BroadcastRadio.cpp
+++ b/broadcastradio/aidl/default/BroadcastRadio.cpp
@@ -115,7 +115,8 @@
}
BroadcastRadio::~BroadcastRadio() {
- mThread.reset();
+ mTuningThread.reset();
+ mProgramListThread.reset();
}
ScopedAStatus BroadcastRadio::getAmFmRegionConfig(bool full, AmFmRegionConfig* returnConfigs) {
@@ -239,7 +240,7 @@
callback->onCurrentProgramInfoChanged(programInfo);
};
auto cancelTask = [program, callback]() { callback->onTuneFailed(Result::CANCELED, program); };
- mThread->schedule(task, cancelTask, kTuneDelayTimeMs);
+ mTuningThread->schedule(task, cancelTask, kTuneDelayTimeMs);
return ScopedAStatus::ok();
}
@@ -267,7 +268,7 @@
callback->onTuneFailed(Result::TIMEOUT, {});
};
- mThread->schedule(task, cancelTask, kSeekDelayTimeMs);
+ mTuningThread->schedule(task, cancelTask, kSeekDelayTimeMs);
return ScopedAStatus::ok();
}
@@ -300,7 +301,7 @@
}
callback->onCurrentProgramInfoChanged(programInfo);
};
- mThread->schedule(task, cancelTask, kSeekDelayTimeMs);
+ mTuningThread->schedule(task, cancelTask, kSeekDelayTimeMs);
return ScopedAStatus::ok();
}
@@ -355,15 +356,15 @@
callback->onCurrentProgramInfoChanged(programInfo);
};
auto cancelTask = [callback]() { callback->onTuneFailed(Result::CANCELED, {}); };
- mThread->schedule(task, cancelTask, kStepDelayTimeMs);
+ mTuningThread->schedule(task, cancelTask, kStepDelayTimeMs);
return ScopedAStatus::ok();
}
void BroadcastRadio::cancelLocked() {
- LOG(DEBUG) << __func__ << ": cancelling current operations...";
+ LOG(DEBUG) << __func__ << ": cancelling current tuning operations...";
- mThread->cancelAll();
+ mTuningThread->cancelAll();
if (mCurrentProgram.primaryId.type != IdentifierType::INVALID) {
mIsTuneCompleted = true;
}
@@ -388,6 +389,8 @@
lock_guard<mutex> lk(mMutex);
+ cancelProgramListUpdateLocked();
+
const auto& list = mVirtualRadio.getProgramList();
vector<VirtualProgram> filteredList;
std::copy_if(list.begin(), list.end(), std::back_inserter(filteredList), filterCb);
@@ -410,14 +413,20 @@
callback->onProgramListUpdated(chunk);
};
- mThread->schedule(task, kListDelayTimeS);
+ mProgramListThread->schedule(task, kListDelayTimeS);
return ScopedAStatus::ok();
}
+void BroadcastRadio::cancelProgramListUpdateLocked() {
+ LOG(DEBUG) << __func__ << ": cancelling current program list update operations...";
+ mProgramListThread->cancelAll();
+}
+
ScopedAStatus BroadcastRadio::stopProgramListUpdates() {
LOG(DEBUG) << __func__ << ": requested program list updates to stop...";
- // TODO(b/243681584) Implement stop program list updates method
+ lock_guard<mutex> lk(mMutex);
+ cancelProgramListUpdateLocked();
return ScopedAStatus::ok();
}
diff --git a/broadcastradio/aidl/default/BroadcastRadio.h b/broadcastradio/aidl/default/BroadcastRadio.h
index 092776f..0f818ce 100644
--- a/broadcastradio/aidl/default/BroadcastRadio.h
+++ b/broadcastradio/aidl/default/BroadcastRadio.h
@@ -68,7 +68,9 @@
const VirtualRadio& mVirtualRadio;
std::mutex mMutex;
AmFmRegionConfig mAmFmConfig GUARDED_BY(mMutex);
- std::unique_ptr<::android::WorkerThread> mThread GUARDED_BY(mMutex) =
+ std::unique_ptr<::android::WorkerThread> mTuningThread GUARDED_BY(mMutex) =
+ std::unique_ptr<::android::WorkerThread>(new ::android::WorkerThread());
+ std::unique_ptr<::android::WorkerThread> mProgramListThread GUARDED_BY(mMutex) =
std::unique_ptr<::android::WorkerThread>(new ::android::WorkerThread());
bool mIsTuneCompleted GUARDED_BY(mMutex) = true;
Properties mProperties GUARDED_BY(mMutex);
@@ -81,6 +83,7 @@
std::optional<AmFmBandRange> getAmFmRangeLocked() const;
void cancelLocked();
ProgramInfo tuneInternalLocked(const ProgramSelector& sel);
+ void cancelProgramListUpdateLocked();
binder_status_t cmdHelp(int fd) const;
binder_status_t cmdTune(int fd, const char** args, uint32_t numArgs);
diff --git a/camera/common/default/CameraMetadata.cpp b/camera/common/default/CameraMetadata.cpp
index ed56261..3252e3c 100644
--- a/camera/common/default/CameraMetadata.cpp
+++ b/camera/common/default/CameraMetadata.cpp
@@ -258,7 +258,7 @@
return res;
}
// string.size() doesn't count the null termination character.
- return updateImpl(tag, (const void*)string.string(), string.size() + 1);
+ return updateImpl(tag, (const void*)string.c_str(), string.size() + 1);
}
status_t CameraMetadata::update(const camera_metadata_ro_entry& entry) {
@@ -455,7 +455,7 @@
for (size_t i = 0; i < totalSectionCount; ++i) {
const char* str = (i < ANDROID_SECTION_COUNT)
? camera_metadata_section_names[i]
- : (*vendorSections)[i - ANDROID_SECTION_COUNT].string();
+ : (*vendorSections)[i - ANDROID_SECTION_COUNT].c_str();
ALOGV("%s: Trying to match against section '%s'", __FUNCTION__, str);
diff --git a/camera/common/default/CameraParameters.cpp b/camera/common/default/CameraParameters.cpp
index 37e28a2..3689c90 100644
--- a/camera/common/default/CameraParameters.cpp
+++ b/camera/common/default/CameraParameters.cpp
@@ -204,7 +204,7 @@
}
void CameraParameters::unflatten(const String8& params) {
- const char* a = params.string();
+ const char* a = params.c_str();
const char* b;
mMap.clear();
@@ -263,7 +263,7 @@
const char* CameraParameters::get(const char* key) const {
String8 v = mMap.valueFor(String8(key));
if (v.length() == 0) return 0;
- return v.string();
+ return v.c_str();
}
int CameraParameters::getInt(const char* key) const {
@@ -429,7 +429,7 @@
String8 k, v;
k = mMap.keyAt(i);
v = mMap.valueAt(i);
- ALOGD("%s: %s\n", k.string(), v.string());
+ ALOGD("%s: %s\n", k.c_str(), v.c_str());
}
}
@@ -443,10 +443,10 @@
String8 k, v;
k = mMap.keyAt(i);
v = mMap.valueAt(i);
- snprintf(buffer, 255, "\t%s: %s\n", k.string(), v.string());
+ snprintf(buffer, 255, "\t%s: %s\n", k.c_str(), v.c_str());
result.append(buffer);
}
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
return NO_ERROR;
}
diff --git a/camera/common/default/VendorTagDescriptor.cpp b/camera/common/default/VendorTagDescriptor.cpp
index 1282bd0..fba9caa 100644
--- a/camera/common/default/VendorTagDescriptor.cpp
+++ b/camera/common/default/VendorTagDescriptor.cpp
@@ -97,7 +97,7 @@
if (index < 0) {
return VENDOR_SECTION_NAME_ERR;
}
- return mSections[mTagToSectionMap.valueAt(index)].string();
+ return mSections[mTagToSectionMap.valueAt(index)].c_str();
}
ssize_t VendorTagDescriptor::getSectionIndex(uint32_t tag) const {
@@ -109,7 +109,7 @@
if (index < 0) {
return VENDOR_TAG_NAME_ERR;
}
- return mTagToNameMap.valueAt(index).string();
+ return mTagToNameMap.valueAt(index).c_str();
}
int VendorTagDescriptor::getTagType(uint32_t tag) const {
@@ -128,13 +128,13 @@
/*out*/ uint32_t* tag) const {
ssize_t index = mReverseMapping.indexOfKey(section);
if (index < 0) {
- ALOGE("%s: Section '%s' does not exist.", __FUNCTION__, section.string());
+ ALOGE("%s: Section '%s' does not exist.", __FUNCTION__, section.c_str());
return BAD_VALUE;
}
ssize_t nameIndex = mReverseMapping[index]->indexOfKey(name);
if (nameIndex < 0) {
- ALOGE("%s: Tag name '%s' does not exist.", __FUNCTION__, name.string());
+ ALOGE("%s: Tag name '%s' does not exist.", __FUNCTION__, name.c_str());
return BAD_VALUE;
}
@@ -167,7 +167,7 @@
const char* typeName =
(type >= 0 && type < NUM_TYPES) ? camera_metadata_type_names[type] : "UNKNOWN";
dprintf(fd, "%*s0x%x (%s) with type %d (%s) defined in section %s\n", indentation + 2, "",
- tag, name.string(), type, typeName, sectionName.string());
+ tag, name.c_str(), type, typeName, sectionName.c_str());
}
}
diff --git a/camera/device/default/ExternalCameraDeviceSession.cpp b/camera/device/default/ExternalCameraDeviceSession.cpp
index c962974..95a36f0 100644
--- a/camera/device/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/default/ExternalCameraDeviceSession.cpp
@@ -224,10 +224,6 @@
}
void ExternalCameraDeviceSession::closeOutputThread() {
- closeOutputThreadImpl();
-}
-
-void ExternalCameraDeviceSession::closeOutputThreadImpl() {
if (mOutputThread != nullptr) {
mOutputThread->flush();
mOutputThread->requestExitAndWait();
@@ -235,6 +231,13 @@
}
}
+void ExternalCameraDeviceSession::closeBufferRequestThread() {
+ if (mBufferRequestThread != nullptr) {
+ mBufferRequestThread->requestExitAndWait();
+ mBufferRequestThread.reset();
+ }
+}
+
Status ExternalCameraDeviceSession::initStatus() const {
Mutex::Autolock _l(mLock);
Status status = Status::OK;
@@ -248,7 +251,7 @@
ExternalCameraDeviceSession::~ExternalCameraDeviceSession() {
if (!isClosed()) {
ALOGE("ExternalCameraDeviceSession deleted before close!");
- close(/*callerIsDtor*/ true);
+ closeImpl();
}
}
@@ -1411,19 +1414,16 @@
}
ScopedAStatus ExternalCameraDeviceSession::close() {
- close(false);
+ closeImpl();
return fromStatus(Status::OK);
}
-void ExternalCameraDeviceSession::close(bool callerIsDtor) {
+void ExternalCameraDeviceSession::closeImpl() {
Mutex::Autolock _il(mInterfaceLock);
bool closed = isClosed();
if (!closed) {
- if (callerIsDtor) {
- closeOutputThreadImpl();
- } else {
- closeOutputThread();
- }
+ closeOutputThread();
+ closeBufferRequestThread();
Mutex::Autolock _l(mLock);
// free all buffers
diff --git a/camera/device/default/ExternalCameraDeviceSession.h b/camera/device/default/ExternalCameraDeviceSession.h
index e7eb799..836266f 100644
--- a/camera/device/default/ExternalCameraDeviceSession.h
+++ b/camera/device/default/ExternalCameraDeviceSession.h
@@ -240,9 +240,9 @@
// To init/close different version of output thread
void initOutputThread();
void closeOutputThread();
- void closeOutputThreadImpl();
+ void closeBufferRequestThread();
- void close(bool callerIsDtor);
+ void closeImpl();
Status initStatus() const;
status_t initDefaultRequests();
diff --git a/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp b/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp
index 7c3b982..69318c7 100644
--- a/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp
+++ b/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp
@@ -439,7 +439,7 @@
}
mVendorTagSections.resize(numSections);
for (size_t s = 0; s < numSections; s++) {
- mVendorTagSections[s].sectionName = (*sectionNames)[s].string();
+ mVendorTagSections[s].sectionName = (*sectionNames)[s].c_str();
mVendorTagSections[s].tags = tagsBySection[s];
}
return true;
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 339a142..c8e683c 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -244,7 +244,7 @@
std::string* deviceVersion, std::string* cameraId) {
::android::String8 pattern;
pattern.appendFormat(kDeviceNameRE, providerType.c_str());
- std::regex e(pattern.string());
+ std::regex e(pattern.c_str());
std::string deviceNameStd(deviceName.c_str());
std::smatch sm;
if (std::regex_match(deviceNameStd, sm, e)) {
@@ -8801,8 +8801,7 @@
void CameraHidlTest::setParameters(
const sp<::android::hardware::camera::device::V1_0::ICameraDevice> &device,
const CameraParameters &cameraParams) {
- Return<Status> returnStatus = device->setParameters(
- cameraParams.flatten().string());
+ Return<Status> returnStatus = device->setParameters(cameraParams.flatten().c_str());
ASSERT_TRUE(returnStatus.isOk());
ASSERT_EQ(Status::OK, returnStatus);
}
diff --git a/cas/1.0/default/android.hardware.cas@1.0-service-lazy.rc b/cas/1.0/default/android.hardware.cas@1.0-service-lazy.rc
index 622ee8f..1a08ebc 100644
--- a/cas/1.0/default/android.hardware.cas@1.0-service-lazy.rc
+++ b/cas/1.0/default/android.hardware.cas@1.0-service-lazy.rc
@@ -5,5 +5,6 @@
class hal
user media
group mediadrm drmrpc
+ capabilities SYS_NICE
ioprio rt 4
task_profiles ProcessCapacityHigh
diff --git a/cas/1.0/default/android.hardware.cas@1.0-service.rc b/cas/1.0/default/android.hardware.cas@1.0-service.rc
index 5df4825..a65160a 100644
--- a/cas/1.0/default/android.hardware.cas@1.0-service.rc
+++ b/cas/1.0/default/android.hardware.cas@1.0-service.rc
@@ -2,5 +2,6 @@
class hal
user media
group mediadrm drmrpc
+ capabilities SYS_NICE
ioprio rt 4
task_profiles ProcessCapacityHigh
diff --git a/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc b/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc
index 0721dc3..9fca8fd 100644
--- a/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc
+++ b/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc
@@ -6,5 +6,6 @@
class hal
user media
group mediadrm drmrpc
+ capabilities SYS_NICE
ioprio rt 4
task_profiles ProcessCapacityHigh
diff --git a/cas/1.1/default/android.hardware.cas@1.1-service.rc b/cas/1.1/default/android.hardware.cas@1.1-service.rc
index 132d943..19fd031 100644
--- a/cas/1.1/default/android.hardware.cas@1.1-service.rc
+++ b/cas/1.1/default/android.hardware.cas@1.1-service.rc
@@ -2,5 +2,6 @@
class hal
user media
group mediadrm drmrpc
+ capabilities SYS_NICE
ioprio rt 4
task_profiles ProcessCapacityHigh
diff --git a/cas/1.2/default/android.hardware.cas@1.2-service-lazy.rc b/cas/1.2/default/android.hardware.cas@1.2-service-lazy.rc
index d91fdce..8c2a894 100644
--- a/cas/1.2/default/android.hardware.cas@1.2-service-lazy.rc
+++ b/cas/1.2/default/android.hardware.cas@1.2-service-lazy.rc
@@ -7,5 +7,6 @@
class hal
user media
group mediadrm drmrpc
+ capabilities SYS_NICE
ioprio rt 4
task_profiles ProcessCapacityHigh
diff --git a/cas/1.2/default/android.hardware.cas@1.2-service.rc b/cas/1.2/default/android.hardware.cas@1.2-service.rc
index b22971a..4b638bc 100644
--- a/cas/1.2/default/android.hardware.cas@1.2-service.rc
+++ b/cas/1.2/default/android.hardware.cas@1.2-service.rc
@@ -2,5 +2,6 @@
class hal
user media
group mediadrm drmrpc
+ capabilities SYS_NICE
ioprio rt 4
task_profiles ProcessCapacityHigh
diff --git a/cas/aidl/default/Android.bp b/cas/aidl/default/Android.bp
index 6ce5681..576016e 100644
--- a/cas/aidl/default/Android.bp
+++ b/cas/aidl/default/Android.bp
@@ -21,6 +21,7 @@
shared_libs: [
"android.hardware.cas-V1-ndk",
+ "libbase",
"libbinder_ndk",
"liblog",
"libutils",
@@ -48,6 +49,7 @@
],
shared_libs: [
"android.hardware.cas-V1-ndk",
+ "libbase",
"libbinder_ndk",
"liblog",
"libutils",
diff --git a/cas/aidl/default/FactoryLoader.h b/cas/aidl/default/FactoryLoader.h
index 6a562f6..443ea1f 100644
--- a/cas/aidl/default/FactoryLoader.h
+++ b/cas/aidl/default/FactoryLoader.h
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <android-base/strings.h>
#include <dirent.h>
#include <dlfcn.h>
#include <media/cas/CasAPI.h>
@@ -96,7 +97,7 @@
struct dirent* pEntry;
while ((pEntry = readdir(pDir))) {
String8 pluginPath = dirPath + "/" + pEntry->d_name;
- if (pluginPath.getPathExtension() == ".so") {
+ if (base::EndsWith(pluginPath.c_str(), ".so")) {
if (loadFactoryForSchemeFromPath(pluginPath, CA_system_id, library, factory)) {
mCASystemIdToLibraryPathMap.add(CA_system_id, pluginPath);
closedir(pDir);
@@ -135,7 +136,7 @@
struct dirent* pEntry;
while ((pEntry = readdir(pDir))) {
String8 pluginPath = dirPath + "/" + pEntry->d_name;
- if (pluginPath.getPathExtension() == ".so") {
+ if (base::EndsWith(pluginPath.c_str(), ".so")) {
queryPluginsFromPath(pluginPath, results);
}
}
diff --git a/cas/aidl/default/TypeConvert.cpp b/cas/aidl/default/TypeConvert.cpp
index 4f7005f..1f0a46d 100644
--- a/cas/aidl/default/TypeConvert.cpp
+++ b/cas/aidl/default/TypeConvert.cpp
@@ -98,7 +98,7 @@
for (auto it = sessionId.begin(); it != sessionId.end(); it++) {
result.appendFormat("%02x ", *it);
}
- if (result.isEmpty()) {
+ if (result.empty()) {
result.append("(null)");
}
return result;
diff --git a/cas/aidl/default/cas-default-lazy.rc b/cas/aidl/default/cas-default-lazy.rc
index 60b59ca..7321cf0 100644
--- a/cas/aidl/default/cas-default-lazy.rc
+++ b/cas/aidl/default/cas-default-lazy.rc
@@ -3,6 +3,7 @@
class hal
user media
group mediadrm drmrpc
+ capabilities SYS_NICE
ioprio rt 4
task_profiles ProcessCapacityHigh
oneshot
diff --git a/cas/aidl/default/cas-default.rc b/cas/aidl/default/cas-default.rc
index e00b9c5..5a60368 100644
--- a/cas/aidl/default/cas-default.rc
+++ b/cas/aidl/default/cas-default.rc
@@ -3,5 +3,6 @@
class hal
user media
group mediadrm drmrpc
+ capabilities SYS_NICE
ioprio rt 4
task_profiles ProcessCapacityHigh
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index a82a421..f1dd956 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -103,9 +103,15 @@
framework_compatibility_matrix.6.xml \
framework_compatibility_matrix.7.xml \
framework_compatibility_matrix.8.xml \
- framework_compatibility_matrix.9.xml \
framework_compatibility_matrix.device.xml \
+# Only allow the use of the unreleased compatibility matrix when we can use unfrozen
+# interfaces (in the `next` release configuration).
+ifeq ($(RELEASE_AIDL_USE_UNFROZEN),true)
+my_system_matrix_deps += \
+ framework_compatibility_matrix.9.xml
+endif
+
my_framework_matrix_deps += \
$(my_system_matrix_deps)
diff --git a/compatibility_matrices/compatibility_matrix.7.xml b/compatibility_matrices/compatibility_matrix.7.xml
index 33c3148..14c330e 100644
--- a/compatibility_matrices/compatibility_matrix.7.xml
+++ b/compatibility_matrices/compatibility_matrix.7.xml
@@ -43,6 +43,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.automotive.audiocontrol</name>
+ <version>1-2</version>
<interface>
<name>IAudioControl</name>
<instance>default</instance>
@@ -262,22 +263,6 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
- <name>android.hardware.gnss.visibility_control</name>
- <version>1</version>
- <interface>
- <name>IGnssVisibilityControl</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="aidl" optional="true">
- <name>android.hardware.gnss.measurement_corrections</name>
- <version>1</version>
- <interface>
- <name>IMeasurementCorrectionsInterface</name>
- <instance>default</instance>
- </interface>
- </hal>
<hal format="hidl" optional="true">
<name>android.hardware.graphics.allocator</name>
<!-- New, non-Go devices should use 4.0 or the AIDL hal. -->
diff --git a/compatibility_matrices/compatibility_matrix.8.xml b/compatibility_matrices/compatibility_matrix.8.xml
index 04a4674..40bd600 100644
--- a/compatibility_matrices/compatibility_matrix.8.xml
+++ b/compatibility_matrices/compatibility_matrix.8.xml
@@ -52,7 +52,7 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.authsecret</name>
<version>1</version>
<interface>
@@ -122,7 +122,7 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.biometrics.fingerprint</name>
<version>3</version>
<interface>
@@ -231,22 +231,6 @@
</interface>
</hal>
<hal format="aidl" optional="true">
- <name>android.hardware.gnss.visibility_control</name>
- <version>1</version>
- <interface>
- <name>IGnssVisibilityControl</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="aidl" optional="true">
- <name>android.hardware.gnss.measurement_corrections</name>
- <version>1</version>
- <interface>
- <name>IMeasurementCorrectionsInterface</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="aidl" optional="true">
<name>android.hardware.graphics.allocator</name>
<version>1-2</version>
<interface>
@@ -329,7 +313,7 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.security.keymint</name>
<version>1-3</version>
<interface>
@@ -338,7 +322,7 @@
<instance>strongbox</instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.security.keymint</name>
<version>1-3</version>
<interface>
@@ -391,7 +375,7 @@
<regex-instance>.*</regex-instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.nfc</name>
<interface>
<name>INfc</name>
@@ -535,7 +519,7 @@
<regex-instance>SIM[1-9][0-9]*</regex-instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.security.secureclock</name>
<version>1</version>
<interface>
@@ -543,7 +527,7 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.security.sharedsecret</name>
<version>1</version>
<interface>
@@ -695,7 +679,7 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.uwb</name>
<version>1</version>
<interface>
diff --git a/compatibility_matrices/compatibility_matrix.9.xml b/compatibility_matrices/compatibility_matrix.9.xml
index 5bcb349..eb3f74d 100644
--- a/compatibility_matrices/compatibility_matrix.9.xml
+++ b/compatibility_matrices/compatibility_matrix.9.xml
@@ -52,7 +52,7 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.authsecret</name>
<version>1</version>
<interface>
@@ -94,7 +94,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.automotive.vehicle</name>
- <version>1-2</version>
+ <version>1-3</version>
<interface>
<name>IVehicle</name>
<instance>default</instance>
@@ -223,22 +223,6 @@
</interface>
</hal>
<hal format="aidl" optional="true">
- <name>android.hardware.gnss.visibility_control</name>
- <version>1</version>
- <interface>
- <name>IGnssVisibilityControl</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="aidl" optional="true">
- <name>android.hardware.gnss.measurement_corrections</name>
- <version>1</version>
- <interface>
- <name>IMeasurementCorrectionsInterface</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="aidl" optional="true">
<name>android.hardware.graphics.allocator</name>
<version>1-2</version>
<interface>
@@ -318,7 +302,7 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.security.keymint</name>
<version>1-3</version>
<interface>
@@ -327,7 +311,7 @@
<instance>strongbox</instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.security.keymint</name>
<version>1-3</version>
<interface>
@@ -388,7 +372,7 @@
<regex-instance>.*</regex-instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.nfc</name>
<interface>
<name>INfc</name>
@@ -397,7 +381,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.power</name>
- <version>4</version>
+ <version>5</version>
<interface>
<name>IPower</name>
<instance>default</instance>
@@ -534,7 +518,7 @@
<regex-instance>SIM[1-9][0-9]*</regex-instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.security.secureclock</name>
<version>1</version>
<interface>
@@ -542,7 +526,7 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.security.sharedsecret</name>
<version>1</version>
<interface>
@@ -670,7 +654,7 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.uwb</name>
<version>1</version>
<interface>
@@ -702,7 +686,7 @@
<regex-instance>.*</regex-instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.threadnetwork</name>
<version>1</version>
<interface>
diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
index fc3a8b3..d92c0b9 100644
--- a/compatibility_matrices/exclude/fcm_exclude.cpp
+++ b/compatibility_matrices/exclude/fcm_exclude.cpp
@@ -24,9 +24,7 @@
namespace android::vintf::details {
// The predicate to VintfObject::checkMissingHalsInMatrices.
-bool ShouldCheckMissingHalsInFcm(const std::string& package) {
- using std::placeholders::_1;
-
+bool ShouldCheckMissingHidlHalsInFcm(const std::string& packageAndVersion) {
static std::vector<std::string> included_prefixes{
// Other AOSP HALs (e.g. android.frameworks.*) are not added because only framework
// matrix is checked.
@@ -51,29 +49,11 @@
"android.hardware.media.bufferpool@1.0",
"android.hardware.media.bufferpool@2.0",
"android.hardware.radio.config@1.2",
- // AIDL
- "android.hardware.audio.common",
- "android.hardware.audio.core.sounddose",
- "android.hardware.biometrics.common",
- "android.hardware.camera.metadata",
- "android.hardware.camera.device",
- "android.hardware.camera.common",
- "android.hardware.common",
- "android.hardware.common.fmq",
- "android.hardware.graphics.common",
- "android.hardware.input.common",
- "android.hardware.keymaster",
- "android.hardware.media.bufferpool2",
- "android.hardware.radio",
- "android.hardware.threadnetwork",
- "android.hardware.uwb.fira_android",
// Fastboot HAL is only used by recovery. Recovery is owned by OEM. Framework
// does not depend on this HAL, hence it is not declared in any manifests or matrices.
"android.hardware.fastboot@1.0",
"android.hardware.fastboot@1.1",
- // Fastboot AIDL
- "android.hardware.fastboot",
// Deprecated HALs.
// HIDL
@@ -107,7 +87,7 @@
};
auto package_has_prefix = [&](const std::string& prefix) {
- return android::base::StartsWith(package, prefix);
+ return android::base::StartsWith(packageAndVersion, prefix);
};
// Only check packageAndVersions that are in the include list and not in the exclude list.
@@ -115,7 +95,69 @@
return false;
}
- if (std::find(excluded_exact.begin(), excluded_exact.end(), package) != excluded_exact.end()) {
+ if (std::find(excluded_exact.begin(), excluded_exact.end(), packageAndVersion) !=
+ excluded_exact.end()) {
+ return false;
+ }
+
+ return !std::any_of(excluded_prefixes.begin(), excluded_prefixes.end(), package_has_prefix);
+}
+
+// The predicate to VintfObject::checkMissingHalsInMatrices.
+bool ShouldCheckMissingAidlHalsInFcm(const std::string& packageAndVersion) {
+ static std::vector<std::string> included_prefixes{
+ // Other AOSP HALs (e.g. android.frameworks.*) are not added because only framework
+ // matrix is checked.
+ "android.hardware.",
+ };
+
+ static std::vector<std::string> excluded_prefixes{
+ // Packages without top level interfaces (including types-only packages) are exempted.
+ "android.hardware.audio.common@",
+ "android.hardware.biometrics.common@",
+ "android.hardware.camera.metadata@",
+ "android.hardware.camera.device@",
+ "android.hardware.camera.common@",
+ "android.hardware.common@",
+ "android.hardware.common.fmq@",
+ "android.hardware.gnss.measurement_corrections@",
+ "android.hardware.gnss.visibility_control@",
+ "android.hardware.graphics.common@",
+ "android.hardware.input.common@",
+ "android.hardware.keymaster@",
+ "android.hardware.media.bufferpool2@",
+ "android.hardware.radio@",
+ "android.hardware.uwb.fira_android@",
+
+ // Test packages are exempted.
+ "android.hardware.tests.",
+
+ // Fastboot HAL is only used by recovery. Recovery is owned by OEM. Framework
+ // does not depend on this HAL, hence it is not declared in any manifests or matrices.
+ "android.hardware.fastboot@",
+ };
+
+ static std::vector<std::string> excluded_exact{
+ // Packages without top level interfaces (including types-only packages) are exempted.
+
+ // AIDL
+ "android.hardware.audio.core.sounddose@1",
+
+ // Deprecated HALs.
+ "android.hardware.bluetooth.audio@1",
+ };
+
+ auto package_has_prefix = [&](const std::string& prefix) {
+ return android::base::StartsWith(packageAndVersion, prefix);
+ };
+
+ // Only check packageAndVersions that are in the include list and not in the exclude list.
+ if (!std::any_of(included_prefixes.begin(), included_prefixes.end(), package_has_prefix)) {
+ return false;
+ }
+
+ if (std::find(excluded_exact.begin(), excluded_exact.end(), packageAndVersion) !=
+ excluded_exact.end()) {
return false;
}
diff --git a/compatibility_matrices/exclude/include/vintf/fcm_exclude.h b/compatibility_matrices/exclude/include/vintf/fcm_exclude.h
index f74c217..e7ef4a0 100644
--- a/compatibility_matrices/exclude/include/vintf/fcm_exclude.h
+++ b/compatibility_matrices/exclude/include/vintf/fcm_exclude.h
@@ -24,7 +24,8 @@
// Determine whether VINTF checks |package| is missing from FCMs.
// |package| can be a HIDL package and version like
// "android.hardware.foo@1.0", or an AIDL package name like
-// "android.hardware.foo".
-bool ShouldCheckMissingHalsInFcm(const std::string& package);
+// "android.hardware.foo@1".
+bool ShouldCheckMissingHidlHalsInFcm(const std::string& packageAndVersion);
+bool ShouldCheckMissingAidlHalsInFcm(const std::string& packageAndVersion);
} // namespace android::vintf::details
diff --git a/drm/1.0/default/Android.bp b/drm/1.0/default/Android.bp
index cbdab4f..45aba7b 100644
--- a/drm/1.0/default/Android.bp
+++ b/drm/1.0/default/Android.bp
@@ -134,6 +134,7 @@
shared_libs: [
"android.hardware.drm@1.0",
"android.hidl.memory@1.0",
+ "libbase",
"libcutils",
"libhidlbase",
"libhidlmemory",
diff --git a/drm/1.0/default/DrmPlugin.cpp b/drm/1.0/default/DrmPlugin.cpp
index 809f694..dfa5d22 100644
--- a/drm/1.0/default/DrmPlugin.cpp
+++ b/drm/1.0/default/DrmPlugin.cpp
@@ -98,8 +98,7 @@
break;
}
}
- _hidl_cb(toStatus(status), toHidlVec(legacyRequest), requestType,
- defaultUrl.string());
+ _hidl_cb(toStatus(status), toHidlVec(legacyRequest), requestType, defaultUrl.c_str());
return Void();
}
@@ -219,7 +218,7 @@
String8 legacyValue;
status_t status = mLegacyPlugin->getPropertyString(
String8(propertyName.c_str()), legacyValue);
- _hidl_cb(toStatus(status), legacyValue.string());
+ _hidl_cb(toStatus(status), legacyValue.c_str());
return Void();
}
diff --git a/drm/1.0/default/SharedLibrary.cpp b/drm/1.0/default/SharedLibrary.cpp
index 0a942cd..c9b5389 100644
--- a/drm/1.0/default/SharedLibrary.cpp
+++ b/drm/1.0/default/SharedLibrary.cpp
@@ -26,7 +26,7 @@
namespace helper {
SharedLibrary::SharedLibrary(const String8& path) {
- mLibHandle = dlopen(path.string(), RTLD_NOW);
+ mLibHandle = dlopen(path.c_str(), RTLD_NOW);
}
SharedLibrary::~SharedLibrary() {
diff --git a/drm/1.0/default/include/PluginLoader.h b/drm/1.0/default/include/PluginLoader.h
index 0c45fb3..5130b16 100644
--- a/drm/1.0/default/include/PluginLoader.h
+++ b/drm/1.0/default/include/PluginLoader.h
@@ -18,6 +18,8 @@
#define PLUGIN_LOADER_H_
#include "SharedLibrary.h"
+
+#include <android-base/strings.h>
#include <utils/Log.h>
#include <utils/String8.h>
#include <utils/Vector.h>
@@ -39,14 +41,14 @@
*/
String8 pluginDir(dir);
- DIR* pDir = opendir(pluginDir.string());
+ DIR* pDir = opendir(pluginDir.c_str());
if (pDir == NULL) {
- ALOGE("Failed to find plugin directory %s", pluginDir.string());
+ ALOGE("Failed to find plugin directory %s", pluginDir.c_str());
} else {
struct dirent* pEntry;
while ((pEntry = readdir(pDir))) {
String8 file(pEntry->d_name);
- if (file.getPathExtension() == ".so") {
+ if (base::EndsWith(file.c_str(), ".so")) {
String8 path = pluginDir + "/" + pEntry->d_name;
T *plugin = loadOne(path, entry);
if (plugin) {
diff --git a/gatekeeper/aidl/vts/functional/VtsHalGatekeeperTargetTest.cpp b/gatekeeper/aidl/vts/functional/VtsHalGatekeeperTargetTest.cpp
index c89243b..032f7e2 100644
--- a/gatekeeper/aidl/vts/functional/VtsHalGatekeeperTargetTest.cpp
+++ b/gatekeeper/aidl/vts/functional/VtsHalGatekeeperTargetTest.cpp
@@ -221,6 +221,47 @@
}
/**
+ * Ensure that passwords containing a NUL byte aren't truncated
+ */
+TEST_P(GatekeeperAidlTest, PasswordIsBinaryData) {
+ GatekeeperEnrollResponse enrollRsp;
+ GatekeeperVerifyResponse verifyRsp;
+ std::vector<uint8_t> rightPassword = {'A', 'B', 'C', '\0', 'D', 'E', 'F'};
+ std::vector<uint8_t> wrongPassword = {'A', 'B', 'C', '\0', '\0', '\0', '\0'};
+
+ ALOGI("Testing Enroll+Verify of password with embedded NUL (expected success)");
+ enrollNewPassword(rightPassword, enrollRsp, true);
+ verifyPassword(rightPassword, enrollRsp.data, 1, verifyRsp, true);
+
+ ALOGI("Testing Verify of wrong password (expected failure)");
+ verifyPassword(wrongPassword, enrollRsp.data, 1, verifyRsp, false);
+
+ ALOGI("PasswordIsBinaryData test done");
+}
+
+/**
+ * Ensure that long passwords aren't truncated
+ */
+TEST_P(GatekeeperAidlTest, LongPassword) {
+ GatekeeperEnrollResponse enrollRsp;
+ GatekeeperVerifyResponse verifyRsp;
+ std::vector<uint8_t> password;
+
+ password.resize(64); // maximum length used by Android
+ memset(password.data(), 'A', password.size());
+
+ ALOGI("Testing Enroll+Verify of long password (expected success)");
+ enrollNewPassword(password, enrollRsp, true);
+ verifyPassword(password, enrollRsp.data, 1, verifyRsp, true);
+
+ ALOGI("Testing Verify of wrong password (expected failure)");
+ password[password.size() - 1] ^= 1;
+ verifyPassword(password, enrollRsp.data, 1, verifyRsp, false);
+
+ ALOGI("LongPassword test done");
+}
+
+/**
* Ensure we can securely update password (keep the same
* secure user_id) if we prove we know old password
*/
diff --git a/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl b/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl
index 3ff0a65..4b6613e 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl
@@ -23,11 +23,26 @@
/**
* Default-assumption data space, when not explicitly specified.
*
- * It is safest to assume the buffer is an image with sRGB primaries and
- * encoding ranges, but the consumer and/or the producer of the data may
- * simply be using defaults. No automatic gamma transform should be
- * expected, except for a possible display gamma transform when drawn to a
- * screen.
+ * IAllocator implementations must not assume a particular dataspace interpretation when
+ * allocating a buffer. That is, the dataspace stored on a buffer's metadata must
+ * explicitly be UNKNOWN at the time of allocation. All other vendor implementations (for
+ * example, IComposer) are suggested to assume that the buffer is an image that conforms
+ * to the recommendations outlined by STANDARD_UNSPECIFIED, TRANSFER_UNSPECIFIED, and
+ * RANGE_UNSPECIFIED in order to avoid obviously-broken behavior.
+ *
+ * This means:
+ * - RGB buffers may be assumed to follow sRGB (IEC 61966-2.1)
+ * - YCbCr buffers smaller than 720p may be assumed to follow BT. 601-7
+ * - YCbCr buffers at least 720p may be assumed to follow BT. 709-6
+ * - Y buffers are full range with an undefined transfer and primaries
+ * - All other buffer formats may be treated in an implementation-defined manner
+ *
+ * It is the framework's - and application's - responsibility to communicate
+ * an accurate dataspace for any buffers throughout the system to guarantee
+ * well-defined behavior. For the framework, this means translating UNKNOWN
+ * dataspaces to a chosen default, and setting gralloc metadata on the buffer
+ * accordingly. For the application, this means signaling a defined dataspace
+ * to any framework apis.
*/
UNKNOWN = 0x0,
diff --git a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
index 62974f8..6960d06 100644
--- a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
+++ b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
@@ -71,7 +71,7 @@
auto texture = std::make_shared<renderengine::impl::ExternalTexture>(
mGraphicBuffer, *mRenderEngine, renderengine::impl::ExternalTexture::Usage::WRITEABLE);
auto result = mRenderEngine
- ->drawLayers(mDisplaySettings, compositionLayers, texture, true,
+ ->drawLayers(mDisplaySettings, compositionLayers, texture,
std::move(bufferFence))
.get();
if (result.ok()) {
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
index fa1d588..74d2f03 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
@@ -82,13 +82,13 @@
ASSERT_NO_FATAL_FAILURE(
mTestRenderEngine = std::unique_ptr<TestRenderEngine>(new TestRenderEngine(
renderengine::RenderEngineCreationArgs::Builder()
- .setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
- .setImageCacheSize(TestRenderEngine::sMaxFrameBufferAcquireBuffers)
- .setUseColorManagerment(true)
- .setEnableProtectedContext(false)
- .setPrecacheToneMapperShaderOnly(false)
- .setContextPriority(renderengine::RenderEngine::ContextPriority::HIGH)
- .build())));
+ .setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
+ .setImageCacheSize(TestRenderEngine::sMaxFrameBufferAcquireBuffers)
+ .setEnableProtectedContext(false)
+ .setPrecacheToneMapperShaderOnly(false)
+ .setContextPriority(
+ renderengine::RenderEngine::ContextPriority::HIGH)
+ .build())));
renderengine::DisplaySettings clientCompositionDisplay;
clientCompositionDisplay.physicalDisplay = Rect(mDisplayWidth, mDisplayHeight);
diff --git a/graphics/composer/aidl/Android.bp b/graphics/composer/aidl/Android.bp
index 88abb73..c105ad4 100644
--- a/graphics/composer/aidl/Android.bp
+++ b/graphics/composer/aidl/Android.bp
@@ -54,6 +54,9 @@
enabled: true,
},
},
+ rust: {
+ enabled: true,
+ },
},
versions_with_info: [
{
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
index a60c93d..bc27cc7 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -42,6 +42,9 @@
int getActiveConfig(long display);
android.hardware.graphics.composer3.ColorMode[] getColorModes(long display);
float[] getDataspaceSaturationMatrix(android.hardware.graphics.common.Dataspace dataspace);
+ /**
+ * @deprecated use getDisplayConfigurations instead. Returns a display attribute value for a particular display configuration. For legacy support getDisplayAttribute should return valid values for any requested DisplayAttribute, and for all of the configs obtained either through getDisplayConfigs or getDisplayConfigurations.
+ */
int getDisplayAttribute(long display, int config, android.hardware.graphics.composer3.DisplayAttribute attribute);
android.hardware.graphics.composer3.DisplayCapability[] getDisplayCapabilities(long display);
/**
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayConfiguration.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayConfiguration.aidl
index 791078d..09c42dc 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayConfiguration.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayConfiguration.aidl
@@ -31,7 +31,7 @@
int height;
/**
- * Dots per thousand inches.
+ * Dots per inch.
* If the DPI for a configuration is unavailable or is
* considered unreliable, the device may set null instead.
*/
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
index c57f94e..725c947 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -236,9 +236,18 @@
float[] getDataspaceSaturationMatrix(android.hardware.graphics.common.Dataspace dataspace);
/**
+ * @deprecated use getDisplayConfigurations instead.
+ *
* Returns a display attribute value for a particular display
* configuration.
*
+ * For legacy support getDisplayAttribute should return valid values for any requested
+ * DisplayAttribute, and for all of the configs obtained either through getDisplayConfigs
+ * or getDisplayConfigurations.
+ *
+ * @see getDisplayConfigurations
+ * @see getDisplayConfigs
+ *
* @param display is the display to query.
* @param config is the display configuration for which to return
* attribute values.
diff --git a/graphics/composer/aidl/vts/RenderEngineVts.cpp b/graphics/composer/aidl/vts/RenderEngineVts.cpp
index 19e8a9b..d1f89d0 100644
--- a/graphics/composer/aidl/vts/RenderEngineVts.cpp
+++ b/graphics/composer/aidl/vts/RenderEngineVts.cpp
@@ -66,7 +66,7 @@
mGraphicBuffer, *mRenderEngine,
::android::renderengine::impl::ExternalTexture::Usage::WRITEABLE);
auto result = mRenderEngine
- ->drawLayers(mDisplaySettings, compositionLayers, texture, true,
+ ->drawLayers(mDisplaySettings, compositionLayers, texture,
std::move(bufferFence))
.get();
if (result.ok()) {
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
index 269abd1..a83b833 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
@@ -70,7 +70,6 @@
::android::renderengine::RenderEngineCreationArgs::Builder()
.setPixelFormat(static_cast<int>(common::PixelFormat::RGBA_8888))
.setImageCacheSize(TestRenderEngine::sMaxFrameBufferAcquireBuffers)
- .setUseColorManagerment(true)
.setEnableProtectedContext(false)
.setPrecacheToneMapperShaderOnly(false)
.setContextPriority(::android::renderengine::RenderEngine::
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index 03d9041..bae362f 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -2223,11 +2223,14 @@
// Keep optional metadata types below and populate the encoded metadata vec
// with some arbitrary different metadata because the common gralloc4::decode*()
// functions do not distinguish between an empty vec and bad value.
- ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(Dataspace::SRGB_LINEAR, &vec));
- ASSERT_EQ(Error::UNSUPPORTED,
- mGralloc->set(bufferHandle, gralloc4::MetadataType_Smpte2086, vec));
- ASSERT_EQ(Error::UNSUPPORTED,
- mGralloc->set(bufferHandle, gralloc4::MetadataType_Cta861_3, vec));
+ if (base::GetIntProperty("ro.vendor.api_level", __ANDROID_API_FUTURE__) >= __ANDROID_API_T__) {
+ // Some old grallocs shipped with broken validation.
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(Dataspace::SRGB_LINEAR, &vec));
+ ASSERT_EQ(Error::UNSUPPORTED,
+ mGralloc->set(bufferHandle, gralloc4::MetadataType_Smpte2086, vec));
+ ASSERT_EQ(Error::UNSUPPORTED,
+ mGralloc->set(bufferHandle, gralloc4::MetadataType_Cta861_3, vec));
+ }
}
/**
diff --git a/input/common/aidl/Android.bp b/input/common/aidl/Android.bp
index 95a14b2..f23f270 100644
--- a/input/common/aidl/Android.bp
+++ b/input/common/aidl/Android.bp
@@ -20,6 +20,9 @@
java: {
enabled: false,
},
+ rust: {
+ enabled: true,
+ },
},
versions_with_info: [
{
diff --git a/nfc/aidl/Android.bp b/nfc/aidl/Android.bp
index 09a45d1..08ec5fe 100644
--- a/nfc/aidl/Android.bp
+++ b/nfc/aidl/Android.bp
@@ -34,6 +34,9 @@
sdk_version: "module_current",
enabled: false,
},
+ rust: {
+ enabled: true,
+ },
},
versions_with_info: [
{
diff --git a/power/aidl/Android.bp b/power/aidl/Android.bp
index 082572d..7643926 100644
--- a/power/aidl/Android.bp
+++ b/power/aidl/Android.bp
@@ -55,6 +55,44 @@
},
],
- frozen: true,
+ frozen: false,
}
+
+cc_defaults {
+ name: "android.hardware.power-ndk_shared",
+ shared_libs: [
+ "android.hardware.power-V5-ndk",
+ ],
+}
+
+cc_defaults {
+ name: "android.hardware.power-ndk_export_shared",
+ shared_libs: [
+ "android.hardware.power-V5-ndk",
+ ],
+ export_shared_lib_headers: [
+ "android.hardware.power-V5-ndk",
+ ],
+}
+
+cc_defaults {
+ name: "android.hardware.power-ndk_static",
+ static_libs: [
+ "android.hardware.power-V5-ndk",
+ ],
+}
+
+java_defaults {
+ name: "android.hardware.power-java_shared",
+ libs: [
+ "android.hardware.power-V5-java",
+ ],
+}
+
+java_defaults {
+ name: "android.hardware.power-java_static",
+ static_libs: [
+ "android.hardware.power-V5-java",
+ ],
+}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Boost.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Boost.aidl
index c792d4e..8ee15ef 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Boost.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Boost.aidl
@@ -34,10 +34,10 @@
package android.hardware.power;
@Backing(type="int") @VintfStability
enum Boost {
- INTERACTION = 0,
- DISPLAY_UPDATE_IMMINENT = 1,
- ML_ACC = 2,
- AUDIO_LAUNCH = 3,
- CAMERA_LAUNCH = 4,
- CAMERA_SHOT = 5,
+ INTERACTION,
+ DISPLAY_UPDATE_IMMINENT,
+ ML_ACC,
+ AUDIO_LAUNCH,
+ CAMERA_LAUNCH,
+ CAMERA_SHOT,
}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl
index e6809da..6bc663e 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl
@@ -41,4 +41,5 @@
oneway void close();
oneway void sendHint(android.hardware.power.SessionHint hint);
void setThreads(in int[] threadIds);
+ oneway void setMode(android.hardware.power.SessionMode type, boolean enabled);
}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl
index f38426b..efbb300 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl
@@ -34,21 +34,21 @@
package android.hardware.power;
@Backing(type="int") @VintfStability
enum Mode {
- DOUBLE_TAP_TO_WAKE = 0,
- LOW_POWER = 1,
- SUSTAINED_PERFORMANCE = 2,
- FIXED_PERFORMANCE = 3,
- VR = 4,
- LAUNCH = 5,
- EXPENSIVE_RENDERING = 6,
- INTERACTIVE = 7,
- DEVICE_IDLE = 8,
- DISPLAY_INACTIVE = 9,
- AUDIO_STREAMING_LOW_LATENCY = 10,
- CAMERA_STREAMING_SECURE = 11,
- CAMERA_STREAMING_LOW = 12,
- CAMERA_STREAMING_MID = 13,
- CAMERA_STREAMING_HIGH = 14,
- GAME = 15,
- GAME_LOADING = 16,
+ DOUBLE_TAP_TO_WAKE,
+ LOW_POWER,
+ SUSTAINED_PERFORMANCE,
+ FIXED_PERFORMANCE,
+ VR,
+ LAUNCH,
+ EXPENSIVE_RENDERING,
+ INTERACTIVE,
+ DEVICE_IDLE,
+ DISPLAY_INACTIVE,
+ AUDIO_STREAMING_LOW_LATENCY,
+ CAMERA_STREAMING_SECURE,
+ CAMERA_STREAMING_LOW,
+ CAMERA_STREAMING_MID,
+ CAMERA_STREAMING_HIGH,
+ GAME,
+ GAME_LOADING,
}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionMode.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionMode.aidl
new file mode 100644
index 0000000..d0ae0ba
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionMode.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.power;
+@Backing(type="int") @VintfStability
+enum SessionMode {
+ POWER_EFFICIENCY,
+}
diff --git a/power/aidl/android/hardware/power/IPowerHintSession.aidl b/power/aidl/android/hardware/power/IPowerHintSession.aidl
index 7db0ea1..62263c8 100644
--- a/power/aidl/android/hardware/power/IPowerHintSession.aidl
+++ b/power/aidl/android/hardware/power/IPowerHintSession.aidl
@@ -17,6 +17,7 @@
package android.hardware.power;
import android.hardware.power.SessionHint;
+import android.hardware.power.SessionMode;
import android.hardware.power.WorkDuration;
@VintfStability
@@ -81,4 +82,13 @@
* must be thrown.
*/
void setThreads(in int[] threadIds);
+
+ /**
+ * Called to enable or disable special modes for the hint session, which may
+ * adjust the power or performance of the session.
+ *
+ * @param type The mode being set
+ * @param enabled True to enable the mode, false to disable it
+ */
+ oneway void setMode(SessionMode type, boolean enabled);
}
diff --git a/power/aidl/android/hardware/power/SessionMode.aidl b/power/aidl/android/hardware/power/SessionMode.aidl
new file mode 100644
index 0000000..f1ee64e
--- /dev/null
+++ b/power/aidl/android/hardware/power/SessionMode.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.power;
+
+@VintfStability
+@Backing(type="int")
+enum SessionMode {
+ /**
+ * This mode indicates that the work of this hint session is not
+ * critical to perceived performance, despite its CPU intensity,
+ * and can be safely scheduled to prefer power efficiency.
+ */
+ POWER_EFFICIENCY,
+}
diff --git a/power/aidl/default/Android.bp b/power/aidl/default/Android.bp
index da91ee6..c0bfbe8 100644
--- a/power/aidl/default/Android.bp
+++ b/power/aidl/default/Android.bp
@@ -23,6 +23,7 @@
cc_binary {
name: "android.hardware.power-service.example",
+ defaults: ["android.hardware.power-ndk_shared"],
relative_install_path: "hw",
init_rc: [":android.hardware.power.rc"],
vintf_fragments: [":android.hardware.power.xml"],
@@ -30,7 +31,6 @@
shared_libs: [
"libbase",
"libbinder_ndk",
- "android.hardware.power-V4-ndk",
],
srcs: [
"main.cpp",
diff --git a/power/aidl/default/PowerHintSession.cpp b/power/aidl/default/PowerHintSession.cpp
index f395800..452e435 100644
--- a/power/aidl/default/PowerHintSession.cpp
+++ b/power/aidl/default/PowerHintSession.cpp
@@ -59,4 +59,8 @@
return ScopedAStatus::ok();
}
+ScopedAStatus PowerHintSession::setMode(SessionMode /* mode */, bool /* enabled */) {
+ return ScopedAStatus::ok();
+}
+
} // namespace aidl::android::hardware::power::impl::example
diff --git a/power/aidl/default/PowerHintSession.h b/power/aidl/default/PowerHintSession.h
index 1d74716..b488bf1 100644
--- a/power/aidl/default/PowerHintSession.h
+++ b/power/aidl/default/PowerHintSession.h
@@ -18,6 +18,7 @@
#include <aidl/android/hardware/power/BnPowerHintSession.h>
#include <aidl/android/hardware/power/SessionHint.h>
+#include <aidl/android/hardware/power/SessionMode.h>
#include <aidl/android/hardware/power/WorkDuration.h>
namespace aidl::android::hardware::power::impl::example {
@@ -33,6 +34,7 @@
ndk::ScopedAStatus close() override;
ndk::ScopedAStatus sendHint(SessionHint hint) override;
ndk::ScopedAStatus setThreads(const std::vector<int32_t>& threadIds) override;
+ ndk::ScopedAStatus setMode(SessionMode mode, bool enabled) override;
};
} // namespace aidl::android::hardware::power::impl::example
diff --git a/power/aidl/default/power-default.xml b/power/aidl/default/power-default.xml
index f5dd6b9..418fb83 100644
--- a/power/aidl/default/power-default.xml
+++ b/power/aidl/default/power-default.xml
@@ -1,7 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.power</name>
- <version>4</version>
+ <version>5</version>
<fqname>IPower/default</fqname>
</hal>
</manifest>
diff --git a/power/aidl/vts/Android.bp b/power/aidl/vts/Android.bp
index 56c98bd..eb98b8b 100644
--- a/power/aidl/vts/Android.bp
+++ b/power/aidl/vts/Android.bp
@@ -26,14 +26,12 @@
defaults: [
"VtsHalTargetTestDefaults",
"use_libaidlvintf_gtest_helper_static",
+ "android.hardware.power-ndk_static",
],
srcs: ["VtsHalPowerTargetTest.cpp"],
shared_libs: [
"libbinder_ndk",
],
- static_libs: [
- "android.hardware.power-V4-ndk",
- ],
test_suites: [
"general-tests",
"vts",
diff --git a/power/aidl/vts/VtsHalPowerTargetTest.cpp b/power/aidl/vts/VtsHalPowerTargetTest.cpp
index c2216f8..96995a0 100644
--- a/power/aidl/vts/VtsHalPowerTargetTest.cpp
+++ b/power/aidl/vts/VtsHalPowerTargetTest.cpp
@@ -29,12 +29,12 @@
namespace aidl::android::hardware::power {
namespace {
-using ::android::base::GetUintProperty;
using android::hardware::power::Boost;
using android::hardware::power::IPower;
using android::hardware::power::IPowerHintSession;
using android::hardware::power::Mode;
using android::hardware::power::SessionHint;
+using android::hardware::power::SessionMode;
using android::hardware::power::WorkDuration;
const std::vector<Boost> kBoosts{ndk::enum_range<Boost>().begin(), ndk::enum_range<Boost>().end()};
@@ -44,6 +44,9 @@
const std::vector<SessionHint> kSessionHints{ndk::enum_range<SessionHint>().begin(),
ndk::enum_range<SessionHint>().end()};
+const std::vector<SessionMode> kSessionModes{ndk::enum_range<SessionMode>().begin(),
+ ndk::enum_range<SessionMode>().end()};
+
const std::vector<Boost> kInvalidBoosts = {
static_cast<Boost>(static_cast<int32_t>(kBoosts.front()) - 1),
static_cast<Boost>(static_cast<int32_t>(kBoosts.back()) + 1),
@@ -59,6 +62,11 @@
static_cast<SessionHint>(static_cast<int32_t>(kSessionHints.back()) + 1),
};
+const std::vector<SessionMode> kInvalidSessionModes = {
+ static_cast<SessionMode>(static_cast<int32_t>(kSessionModes.front()) - 1),
+ static_cast<SessionMode>(static_cast<int32_t>(kSessionModes.back()) + 1),
+};
+
class DurationWrapper : public WorkDuration {
public:
DurationWrapper(int64_t dur, int64_t time) {
@@ -92,36 +100,33 @@
DurationWrapper(1000000000L, 4L),
};
-// DEVICEs launching with Android 11 MUST meet the requirements for the
-// target-level=5 compatibility_matrix file.
-const uint64_t kCompatibilityMatrix5ApiLevel = 30;
-
-// DEVICEs launching with Android 13 MUST meet the requirements for the
-// target-level=7 compatibility_matrix file.
-const uint64_t kCompatibilityMatrix7ApiLevel = 33;
-
-// DEVICEs launching with Android 14 MUST meet the requirements for the
-// target-level=8 compatibility_matrix file.
-const uint64_t kCompatibilityMatrix8ApiLevel = 34;
-
-inline bool isUnknownOrUnsupported(const ndk::ScopedAStatus& status) {
- return status.getStatus() == STATUS_UNKNOWN_TRANSACTION ||
- status.getExceptionCode() == EX_UNSUPPORTED_OPERATION;
-}
-
class PowerAidl : public testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
AIBinder* binder = AServiceManager_waitForService(GetParam().c_str());
ASSERT_NE(binder, nullptr);
power = IPower::fromBinder(ndk::SpAIBinder(binder));
-
- mApiLevel = GetUintProperty<uint64_t>("ro.vendor.api_level", 0);
- ASSERT_NE(mApiLevel, 0);
+ auto status = power->getInterfaceVersion(&mServiceVersion);
+ ASSERT_TRUE(status.isOk());
}
std::shared_ptr<IPower> power;
- uint64_t mApiLevel;
+ int32_t mServiceVersion;
+};
+
+class HintSessionAidl : public PowerAidl {
+ public:
+ virtual void SetUp() override {
+ PowerAidl::SetUp();
+ if (mServiceVersion < 2) {
+ GTEST_SKIP() << "DEVICE not launching with Power V2 and beyond.";
+ }
+
+ auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &mSession);
+ ASSERT_TRUE(status.isOk());
+ ASSERT_NE(nullptr, mSession);
+ }
+ std::shared_ptr<IPowerHintSession> mSession;
};
TEST_P(PowerAidl, setMode) {
@@ -175,113 +180,95 @@
}
TEST_P(PowerAidl, getHintSessionPreferredRate) {
- int64_t rate = -1;
- auto status = power->getHintSessionPreferredRate(&rate);
- if (mApiLevel < kCompatibilityMatrix7ApiLevel && !status.isOk()) {
- EXPECT_TRUE(isUnknownOrUnsupported(status));
- GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
+ if (mServiceVersion < 2) {
+ GTEST_SKIP() << "DEVICE not launching with Power V2 and beyond.";
}
- ASSERT_TRUE(status.isOk());
+
+ int64_t rate = -1;
+ ASSERT_TRUE(power->getHintSessionPreferredRate(&rate).isOk());
// At least 1ms rate limit from HAL
ASSERT_GE(rate, 1000000);
}
-TEST_P(PowerAidl, createAndCloseHintSession) {
- std::shared_ptr<IPowerHintSession> session;
- auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &session);
- if (mApiLevel < kCompatibilityMatrix7ApiLevel && !status.isOk()) {
- EXPECT_TRUE(isUnknownOrUnsupported(status));
- GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
- }
- ASSERT_TRUE(status.isOk());
- ASSERT_NE(nullptr, session);
- ASSERT_TRUE(session->pause().isOk());
- ASSERT_TRUE(session->resume().isOk());
+TEST_P(HintSessionAidl, createAndCloseHintSession) {
+ ASSERT_TRUE(mSession->pause().isOk());
+ ASSERT_TRUE(mSession->resume().isOk());
// Test normal destroy operation
- ASSERT_TRUE(session->close().isOk());
- session.reset();
+ ASSERT_TRUE(mSession->close().isOk());
+ mSession.reset();
}
-TEST_P(PowerAidl, createHintSessionFailed) {
+TEST_P(HintSessionAidl, createHintSessionFailed) {
std::shared_ptr<IPowerHintSession> session;
auto status = power->createHintSession(getpid(), getuid(), kEmptyTids, 16666666L, &session);
// Regardless of whether V2 and beyond is supported, the status is always not STATUS_OK.
ASSERT_FALSE(status.isOk());
-
- // If device not launching with Android 13 and beyond, check whether it's supported,
- // if not, skip the test.
- if (mApiLevel < kCompatibilityMatrix7ApiLevel && isUnknownOrUnsupported(status)) {
- GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
- }
ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
}
-TEST_P(PowerAidl, updateAndReportDurations) {
- std::shared_ptr<IPowerHintSession> session;
- auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &session);
- if (mApiLevel < kCompatibilityMatrix7ApiLevel && !status.isOk()) {
- EXPECT_TRUE(isUnknownOrUnsupported(status));
- GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
- }
- ASSERT_TRUE(status.isOk());
- ASSERT_NE(nullptr, session);
-
- ASSERT_TRUE(session->updateTargetWorkDuration(16666667LL).isOk());
- ASSERT_TRUE(session->reportActualWorkDuration(kDurations).isOk());
+TEST_P(HintSessionAidl, updateAndReportDurations) {
+ ASSERT_TRUE(mSession->updateTargetWorkDuration(16666667LL).isOk());
+ ASSERT_TRUE(mSession->reportActualWorkDuration(kDurations).isOk());
}
-TEST_P(PowerAidl, sendSessionHint) {
- std::shared_ptr<IPowerHintSession> session;
- auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &session);
- if (!status.isOk()) {
- EXPECT_TRUE(isUnknownOrUnsupported(status));
- return;
+TEST_P(HintSessionAidl, sendSessionHint) {
+ if (mServiceVersion < 4) {
+ GTEST_SKIP() << "DEVICE not launching with Power V4 and beyond.";
}
+
for (const auto& sessionHint : kSessionHints) {
- ASSERT_TRUE(session->sendHint(sessionHint).isOk());
+ ASSERT_TRUE(mSession->sendHint(sessionHint).isOk());
}
for (const auto& sessionHint : kInvalidSessionHints) {
- ASSERT_TRUE(session->sendHint(sessionHint).isOk());
+ ASSERT_TRUE(mSession->sendHint(sessionHint).isOk());
}
}
-TEST_P(PowerAidl, setThreads) {
- std::shared_ptr<IPowerHintSession> session;
- auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &session);
- if (mApiLevel < kCompatibilityMatrix7ApiLevel && !status.isOk()) {
- EXPECT_TRUE(isUnknownOrUnsupported(status));
- GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
+TEST_P(HintSessionAidl, setThreads) {
+ if (mServiceVersion < 4) {
+ GTEST_SKIP() << "DEVICE not launching with Power V4 and beyond.";
}
- ASSERT_TRUE(status.isOk());
- status = session->setThreads(kEmptyTids);
- if (mApiLevel < kCompatibilityMatrix8ApiLevel && isUnknownOrUnsupported(status)) {
- GTEST_SKIP() << "DEVICE not launching with Android 14 and beyond.";
- }
+ auto status = mSession->setThreads(kEmptyTids);
ASSERT_FALSE(status.isOk());
ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
- status = session->setThreads(kSelfTids);
- ASSERT_TRUE(status.isOk());
+ ASSERT_TRUE(mSession->setThreads(kSelfTids).isOk());
+}
+
+TEST_P(HintSessionAidl, setSessionMode) {
+ if (mServiceVersion < 5) {
+ GTEST_SKIP() << "DEVICE not launching with Power V5 and beyond.";
+ }
+
+ for (const auto& sessionMode : kSessionModes) {
+ ASSERT_TRUE(mSession->setMode(sessionMode, true).isOk());
+ ASSERT_TRUE(mSession->setMode(sessionMode, false).isOk());
+ }
+ for (const auto& sessionMode : kInvalidSessionModes) {
+ ASSERT_TRUE(mSession->setMode(sessionMode, true).isOk());
+ ASSERT_TRUE(mSession->setMode(sessionMode, false).isOk());
+ }
}
// FIXED_PERFORMANCE mode is required for all devices which ship on Android 11
// or later
TEST_P(PowerAidl, hasFixedPerformance) {
- if (mApiLevel < kCompatibilityMatrix5ApiLevel) {
- GTEST_SKIP() << "FIXED_PERFORMANCE mode is only required for all devices launching Android "
- "11 or later.";
- }
bool supported;
ASSERT_TRUE(power->isModeSupported(Mode::FIXED_PERFORMANCE, &supported).isOk());
ASSERT_TRUE(supported);
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PowerAidl);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HintSessionAidl);
+
INSTANTIATE_TEST_SUITE_P(Power, PowerAidl,
testing::ValuesIn(::android::getAidlHalInstanceNames(IPower::descriptor)),
::android::PrintInstanceNameToString);
+INSTANTIATE_TEST_SUITE_P(Power, HintSessionAidl,
+ testing::ValuesIn(::android::getAidlHalInstanceNames(IPower::descriptor)),
+ ::android::PrintInstanceNameToString);
} // namespace
} // namespace aidl::android::hardware::power
diff --git a/radio/1.2/vts/functional/AndroidTest.xml b/radio/1.2/vts/functional/AndroidTest.xml
index e25249b..4a0be56 100644
--- a/radio/1.2/vts/functional/AndroidTest.xml
+++ b/radio/1.2/vts/functional/AndroidTest.xml
@@ -30,6 +30,7 @@
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="native-test-timeout" value="300000" /> <!-- 5 min -->
<option name="module-name" value="VtsHalRadioV1_2TargetTest" />
</test>
</configuration>
diff --git a/radio/1.3/vts/functional/AndroidTest.xml b/radio/1.3/vts/functional/AndroidTest.xml
index 44b7419..a2cd791 100644
--- a/radio/1.3/vts/functional/AndroidTest.xml
+++ b/radio/1.3/vts/functional/AndroidTest.xml
@@ -30,6 +30,7 @@
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="native-test-timeout" value="300000" /> <!-- 5 min -->
<option name="module-name" value="VtsHalRadioV1_3TargetTest" />
</test>
</configuration>
diff --git a/radio/1.4/vts/functional/AndroidTest.xml b/radio/1.4/vts/functional/AndroidTest.xml
index d0843e6..54051ed 100644
--- a/radio/1.4/vts/functional/AndroidTest.xml
+++ b/radio/1.4/vts/functional/AndroidTest.xml
@@ -30,6 +30,7 @@
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="native-test-timeout" value="300000" /> <!-- 5 min -->
<option name="module-name" value="VtsHalRadioV1_4TargetTest" />
</test>
</configuration>
diff --git a/radio/1.5/vts/functional/AndroidTest.xml b/radio/1.5/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..d3617c8
--- /dev/null
+++ b/radio/1.5/vts/functional/AndroidTest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+<configuration description="Runs VtsHalRadioV1_5TargetTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+ <option name="config-descriptor:metadata" key="token" value="SIM_CARD" />
+
+ <!-- TODO: b/154638140, b/152655658: bad interactions -->
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+ <target_preparer class="com.android.tradefed.targetprep.MultiSimPreparer" />
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="VtsHalRadioV1_5TargetTest->/data/local/tmp/VtsHalRadioV1_5TargetTest" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="native-test-timeout" value="300000" /> <!-- 5 min -->
+ <option name="module-name" value="VtsHalRadioV1_5TargetTest" />
+ </test>
+</configuration>
diff --git a/radio/1.6/vts/functional/AndroidTest.xml b/radio/1.6/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..c3ecdb0
--- /dev/null
+++ b/radio/1.6/vts/functional/AndroidTest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+<configuration description="Runs VtsHalRadioV1_6TargetTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+ <option name="config-descriptor:metadata" key="token" value="SIM_CARD" />
+
+ <!-- TODO: b/154638140, b/152655658: bad interactions -->
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+ <target_preparer class="com.android.tradefed.targetprep.MultiSimPreparer" />
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="VtsHalRadioV1_6TargetTest->/data/local/tmp/VtsHalRadioV1_6TargetTest" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="native-test-timeout" value="300000" /> <!-- 5 min -->
+ <option name="module-name" value="VtsHalRadioV1_6TargetTest" />
+ </test>
+</configuration>
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
index d1a831b..cbc1e30 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
@@ -82,5 +82,4 @@
oneway void isNullCipherAndIntegrityEnabled(in int serial);
oneway void isN1ModeEnabled(in int serial);
oneway void setN1ModeEnabled(in int serial, boolean enable);
- oneway void setSatellitePlmn(in int serial, in List<String> plmnList);
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
index bf43d7c..c86bebc 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -81,5 +81,4 @@
oneway void isNullCipherAndIntegrityEnabledResponse(in android.hardware.radio.RadioResponseInfo info, in boolean isEnabled);
oneway void isN1ModeEnabledResponse(in android.hardware.radio.RadioResponseInfo info, boolean isEnabled);
oneway void setN1ModeEnabledResponse(in android.hardware.radio.RadioResponseInfo info);
- oneway void setSatellitePlmnResponse(in android.hardware.radio.RadioResponseInfo info);
}
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
index 2f40bd6..e4c3856 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
@@ -556,18 +556,4 @@
* Response function is IRadioNetworkResponse.setN1ModeEnabledResponse()
*/
void setN1ModeEnabled(in int serial, boolean enable);
-
- /**
- * Set the non-terrestrial PLMN with lower priority than terrestrial networks.
- * MCC/MNC broadcast by the non-terrestrial networks may not be included in OPLMNwACT file on
- * SIM profile. Acquisition of satellite based system is lower priority to terrestrial
- * networks. UE shall make all attempts to acquire terrestrial service prior to camping on
- * satellite LTE service.
- *
- * @param serial Serial number of request.
- * @param plmnList The list of roaming PLMN used for connecting to satellite networks.
- *
- * Response function is IRadioNetworkResponse.setSatellitePlmnResponse()
- */
- void setSatellitePlmn(in int serial, in List<String> plmnList);
}
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
index 9798944..db37a0e 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -668,21 +668,4 @@
* RadioError:INVALID_STATE
*/
void setN1ModeEnabledResponse(in RadioResponseInfo info);
-
- /**
- * Response of setSatellitePlmn.
- * This is an optional API.
- *
- * @param info Response info struct containing response type, serial no. and error.
- *
- * Valid errors returned:
- * RadioError:NONE
- * RadioError:INVALID_ARGUMENTS
- * RadioError:INVALID_MODEM_STATE
- * RadioError:MODEM_ERR
- * RadioError:NO_RESOURCES
- * RadioError:RADIO_NOT_AVAILABLE
- * RadioError:REQUEST_NOT_SUPPORTED
- */
- void setSatellitePlmnResponse(in RadioResponseInfo info);
}
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
index ff3f10d..d57c83d 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
@@ -108,9 +108,6 @@
::ndk::ScopedAStatus setNullCipherAndIntegrityEnabled(int32_t serial, bool enabled) override;
::ndk::ScopedAStatus isNullCipherAndIntegrityEnabled(int32_t serial) override;
- ::ndk::ScopedAStatus setSatellitePlmn(int32_t serial,
- const std::vector<std::string>& plmnList) override;
-
protected:
std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkResponse> respond();
diff --git a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
index 1aa7c29..a379eec 100644
--- a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
+++ b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
@@ -372,12 +372,4 @@
respond()->setN1ModeEnabledResponse(notSupported(serial));
return ok();
}
-
-ScopedAStatus RadioNetwork::setSatellitePlmn(int32_t serial,
- const std::vector<std::string>& /*plmnList*/) {
- LOG_CALL << serial;
- LOG(ERROR) << " setSatellitePlmn is unsupported by HIDL HALs";
- respond()->setSatellitePlmnResponse(notSupported(serial));
- return ok();
-}
} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/vts/radio_network_response.cpp b/radio/aidl/vts/radio_network_response.cpp
index eab9fac..25d45a5 100644
--- a/radio/aidl/vts/radio_network_response.cpp
+++ b/radio/aidl/vts/radio_network_response.cpp
@@ -320,9 +320,3 @@
parent_network.notify(info.serial);
return ndk::ScopedAStatus::ok();
}
-
-ndk::ScopedAStatus RadioNetworkResponse::setSatellitePlmnResponse(const RadioResponseInfo& info) {
- rspInfo = info;
- parent_network.notify(info.serial);
- return ndk::ScopedAStatus::ok();
-}
diff --git a/radio/aidl/vts/radio_network_test.cpp b/radio/aidl/vts/radio_network_test.cpp
index 9af2494..253ef82 100644
--- a/radio/aidl/vts/radio_network_test.cpp
+++ b/radio/aidl/vts/radio_network_test.cpp
@@ -106,7 +106,7 @@
RadioError::REQUEST_NOT_SUPPORTED, RadioError::NO_RESOURCES}));
if (radioRsp_network->rspInfo.error == RadioError::NONE) {
// verify we get the value we set
- ASSERT_EQ(radioRsp_network->networkTypeBitmapResponse, allowedNetworkTypesBitmap);
+ EXPECT_EQ(radioRsp_network->networkTypeBitmapResponse, allowedNetworkTypesBitmap);
}
}
@@ -2076,37 +2076,3 @@
{RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
RadioError::MODEM_ERR, RadioError::REQUEST_NOT_SUPPORTED}));
}
-
-/**
- * Test IRadioNetwork.setSatellitePlmn() for the response returned.
- */
-TEST_P(RadioNetworkTest, setSatellitePlmn) {
- int32_t aidl_version;
- std::vector<std::string> plmnList = {"00101", "00102", "00103"};
- ndk::ScopedAStatus aidl_status = radio_network->getInterfaceVersion(&aidl_version);
- ASSERT_OK(aidl_status);
- if (aidl_version < 3) {
- ALOGI("Skipped the test since setSatellitePlmn is not supported on version < 3.");
- GTEST_SKIP();
- }
-
- serial = GetRandomSerialNumber();
-
- ndk::ScopedAStatus res = radio_network->setSatellitePlmn(serial, plmnList);
- ASSERT_OK(res);
-
- EXPECT_EQ(std::cv_status::no_timeout, wait());
- EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
- EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
-
- ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
- {
- RadioError::NONE,
- RadioError::INVALID_ARGUMENTS,
- RadioError::INVALID_MODEM_STATE,
- RadioError::MODEM_ERR,
- RadioError::NO_RESOURCES,
- RadioError::RADIO_NOT_AVAILABLE,
- RadioError::REQUEST_NOT_SUPPORTED,
- }));
-}
diff --git a/radio/aidl/vts/radio_network_utils.h b/radio/aidl/vts/radio_network_utils.h
index c2466ac..8f8f6b0 100644
--- a/radio/aidl/vts/radio_network_utils.h
+++ b/radio/aidl/vts/radio_network_utils.h
@@ -169,8 +169,6 @@
const RadioResponseInfo& info, bool isEnabled) override;
virtual ndk::ScopedAStatus setN1ModeEnabledResponse(const RadioResponseInfo& info) override;
-
- virtual ndk::ScopedAStatus setSatellitePlmnResponse(const RadioResponseInfo& info) override;
};
/* Callback class for radio network indication */
diff --git a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
index 8a8eaa4..4c46719 100644
--- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
@@ -98,17 +98,17 @@
TypedTag<TagType::BYTES, tag> tag_type, const char* prop) {
::android::String8 prop_name =
::android::String8::format("ro.product.%s_for_attestation", prop);
- std::string prop_value = ::android::base::GetProperty(prop_name.string(), /* default= */ "");
+ std::string prop_value = ::android::base::GetProperty(prop_name.c_str(), /* default= */ "");
if (!prop_value.empty()) {
- add_tag_from_prop(attestation_id_tags, tag_type, prop_name.string());
+ add_tag_from_prop(attestation_id_tags, tag_type, prop_name.c_str());
} else {
prop_name = ::android::String8::format("ro.product.vendor.%s", prop);
- prop_value = ::android::base::GetProperty(prop_name.string(), /* default= */ "");
+ prop_value = ::android::base::GetProperty(prop_name.c_str(), /* default= */ "");
if (!prop_value.empty()) {
- add_tag_from_prop(attestation_id_tags, tag_type, prop_name.string());
+ add_tag_from_prop(attestation_id_tags, tag_type, prop_name.c_str());
} else {
prop_name = ::android::String8::format("ro.product.%s", prop);
- add_tag_from_prop(attestation_id_tags, tag_type, prop_name.string());
+ add_tag_from_prop(attestation_id_tags, tag_type, prop_name.c_str());
}
}
}
@@ -156,7 +156,7 @@
vector<uint8_t> attested_key_blob;
vector<KeyCharacteristics> attested_key_characteristics;
vector<Certificate> attested_key_cert_chain;
- EXPECT_EQ(ErrorCode::OK,
+ ASSERT_EQ(ErrorCode::OK,
GenerateKey(AuthorizationSetBuilder()
.RsaSigningKey(2048, 65537)
.Authorization(TAG_NO_AUTH_REQUIRED)
@@ -167,9 +167,11 @@
&attested_key_cert_chain));
KeyBlobDeleter attested_deleter(keymint_, attested_key_blob);
+ ASSERT_GT(attested_key_cert_chain.size(), 0);
+
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
- EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+ ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
SecLevel(),
attested_key_cert_chain[0].encodedCertificate));
@@ -186,7 +188,7 @@
*/
attested_key_characteristics.resize(0);
attested_key_cert_chain.resize(0);
- EXPECT_EQ(ErrorCode::OK,
+ ASSERT_EQ(ErrorCode::OK,
GenerateKey(AuthorizationSetBuilder()
.RsaEncryptionKey(2048, 65537)
.Digest(Digest::NONE)
@@ -199,9 +201,11 @@
&attested_key_cert_chain));
KeyBlobDeleter attested_deleter2(keymint_, attested_key_blob);
+ ASSERT_GT(attested_key_cert_chain.size(), 0);
+
hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
- EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo2", "bar2", sw_enforced,
+ ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo2", "bar2", sw_enforced,
hw_enforced, SecLevel(),
attested_key_cert_chain[0].encodedCertificate));
@@ -219,7 +223,7 @@
attested_key_characteristics.resize(0);
attested_key_cert_chain.resize(0);
uint64_t timestamp = 1619621648000;
- EXPECT_EQ(ErrorCode::OK,
+ ASSERT_EQ(ErrorCode::OK,
GenerateKey(AuthorizationSetBuilder()
.EcdsaSigningKey(EcCurve::P_256)
.Authorization(TAG_NO_AUTH_REQUIRED)
@@ -231,6 +235,8 @@
&attested_key_cert_chain));
KeyBlobDeleter attested_deleter3(keymint_, attested_key_blob);
+ ASSERT_GT(attested_key_cert_chain.size(), 0);
+
// The returned key characteristics will include CREATION_DATETIME (checked below)
// in SecurityLevel::KEYSTORE; this will be stripped out in the CheckCharacteristics()
// call below, to match what getKeyCharacteristics() returns (which doesn't include
@@ -246,7 +252,7 @@
EXPECT_TRUE(sw_enforced.Contains(TAG_CREATION_DATETIME, timestamp))
<< "expected CREATION_TIMESTAMP in sw_enforced:" << sw_enforced
<< " not in hw_enforced:" << hw_enforced;
- EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+ ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
SecLevel(),
attested_key_cert_chain[0].encodedCertificate));
@@ -336,7 +342,7 @@
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attest_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attest_key_characteristics);
- EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, //
+ ASSERT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, //
sw_enforced, hw_enforced, SecLevel(),
attest_key_cert_chain[0].encodedCertificate));
@@ -354,7 +360,7 @@
uint64_t serial_int2 = 255;
vector<uint8_t> serial_blob2(build_serial_blob(serial_int2));
- EXPECT_EQ(ErrorCode::OK,
+ ASSERT_EQ(ErrorCode::OK,
GenerateKey(AuthorizationSetBuilder()
.RsaSigningKey(2048, 65537)
.Authorization(TAG_NO_AUTH_REQUIRED)
@@ -367,9 +373,11 @@
&attested_key_cert_chain));
KeyBlobDeleter attested_deleter(keymint_, attested_key_blob);
+ ASSERT_GT(attested_key_cert_chain.size(), 0);
+
AuthorizationSet hw_enforced2 = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced2 = SwEnforcedAuthorizations(attested_key_characteristics);
- EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced2, hw_enforced2,
+ ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced2, hw_enforced2,
SecLevel(),
attested_key_cert_chain[0].encodedCertificate));
@@ -437,7 +445,7 @@
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
ASSERT_GT(cert_chain_list[i].size(), 0);
- EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+ ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
SecLevel(),
cert_chain_list[i][0].encodedCertificate));
@@ -512,7 +520,7 @@
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
ASSERT_GT(cert_chain_list[i].size(), 0);
- EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+ ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
SecLevel(),
cert_chain_list[i][0].encodedCertificate));
@@ -628,7 +636,7 @@
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
ASSERT_GT(cert_chain_list[i].size(), 0);
- EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+ ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
SecLevel(),
cert_chain_list[i][0].encodedCertificate));
@@ -678,7 +686,7 @@
vector<uint8_t> attested_key_blob;
vector<KeyCharacteristics> attested_key_characteristics;
vector<Certificate> attested_key_cert_chain;
- EXPECT_EQ(ErrorCode::ATTESTATION_CHALLENGE_MISSING,
+ ASSERT_EQ(ErrorCode::ATTESTATION_CHALLENGE_MISSING,
GenerateKey(AuthorizationSetBuilder()
.RsaSigningKey(2048, 65537)
.Authorization(TAG_NO_AUTH_REQUIRED)
@@ -687,7 +695,7 @@
attest_key, &attested_key_blob, &attested_key_characteristics,
&attested_key_cert_chain));
- EXPECT_EQ(ErrorCode::ATTESTATION_CHALLENGE_MISSING,
+ ASSERT_EQ(ErrorCode::ATTESTATION_CHALLENGE_MISSING,
GenerateKey(AuthorizationSetBuilder()
.EcdsaSigningKey(EcCurve::P_256)
.Authorization(TAG_NO_AUTH_REQUIRED)
@@ -725,7 +733,7 @@
vector<uint8_t> attested_key_blob;
vector<KeyCharacteristics> attested_key_characteristics;
vector<Certificate> attested_key_cert_chain;
- EXPECT_EQ(ErrorCode::OK,
+ ASSERT_EQ(ErrorCode::OK,
GenerateKey(AuthorizationSetBuilder()
.RsaSigningKey(2048, 65537)
.Authorization(TAG_NO_AUTH_REQUIRED)
@@ -740,7 +748,7 @@
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
- EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+ ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
SecLevel(),
attested_key_cert_chain[0].encodedCertificate));
@@ -756,7 +764,7 @@
/*
* Use attestation key to sign EC key
*/
- EXPECT_EQ(ErrorCode::OK,
+ ASSERT_EQ(ErrorCode::OK,
GenerateKey(AuthorizationSetBuilder()
.EcdsaSigningKey(EcCurve::P_256)
.Authorization(TAG_NO_AUTH_REQUIRED)
@@ -771,7 +779,7 @@
hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
- EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+ ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
SecLevel(),
attested_key_cert_chain[0].encodedCertificate));
@@ -809,7 +817,7 @@
vector<uint8_t> attested_key_blob;
vector<KeyCharacteristics> attested_key_characteristics;
vector<Certificate> attested_key_cert_chain;
- EXPECT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE,
+ ASSERT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE,
GenerateKey(AuthorizationSetBuilder()
.EcdsaSigningKey(EcCurve::P_256)
.Authorization(TAG_NO_AUTH_REQUIRED)
@@ -872,6 +880,7 @@
}
ASSERT_EQ(result, ErrorCode::OK);
+ ASSERT_GT(attested_key_cert_chain.size(), 0);
KeyBlobDeleter attested_deleter(keymint_, attested_key_blob);
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
@@ -882,7 +891,7 @@
// attestation extension should contain them, so make sure the extra tag is added.
hw_enforced.push_back(tag);
- EXPECT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
+ ASSERT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
hw_enforced, SecLevel(),
attested_key_cert_chain[0].encodedCertificate));
}
@@ -919,7 +928,9 @@
.Authorization(TAG_ATTESTATION_ID_MODEL, "malicious-model");
if (isSecondImeiIdAttestationRequired()) {
- attestation_id_tags.Authorization(TAG_ATTESTATION_ID_SECOND_IMEI, "invalid-second-imei");
+ // Note: the invalid value here is < 16 bytes long to avoid triggering any implementation
+ // checks on valid IMEI lengths.
+ attestation_id_tags.Authorization(TAG_ATTESTATION_ID_SECOND_IMEI, "invalid-imei2");
}
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
@@ -996,6 +1007,7 @@
}
ASSERT_EQ(result, ErrorCode::OK);
+ ASSERT_GT(attested_key_cert_chain.size(), 0);
KeyBlobDeleter attested_deleter(keymint_, attested_key_blob);
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
@@ -1008,7 +1020,7 @@
KeyParameter imei_tag = Authorization(TAG_ATTESTATION_ID_SECOND_IMEI, imei_blob);
hw_enforced.push_back(imei_tag);
- EXPECT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
+ ASSERT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
hw_enforced, SecLevel(),
attested_key_cert_chain[0].encodedCertificate));
}
@@ -1067,6 +1079,7 @@
}
ASSERT_EQ(result, ErrorCode::OK);
+ ASSERT_GT(attested_key_cert_chain.size(), 0);
KeyBlobDeleter attested_deleter(keymint_, attested_key_blob);
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
@@ -1082,7 +1095,7 @@
KeyParameter sec_imei_tag = Authorization(TAG_ATTESTATION_ID_SECOND_IMEI, sec_imei_blob);
hw_enforced.push_back(sec_imei_tag);
- EXPECT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
+ ASSERT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
hw_enforced, SecLevel(),
attested_key_cert_chain[0].encodedCertificate));
}
diff --git a/security/keymint/aidl/vts/functional/AuthTest.cpp b/security/keymint/aidl/vts/functional/AuthTest.cpp
index 290e8fc..d5c6d2a 100644
--- a/security/keymint/aidl/vts/functional/AuthTest.cpp
+++ b/security/keymint/aidl/vts/functional/AuthTest.cpp
@@ -453,8 +453,18 @@
vector<uint8_t> keyblob;
vector<KeyCharacteristics> key_characteristics;
vector<Certificate> cert_chain;
- ASSERT_EQ(ErrorCode::OK,
- GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain));
+ auto result = GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain);
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) {
+ result = GenerateKeyWithSelfSignedAttestKey(AuthorizationSetBuilder()
+ .EcdsaKey(EcCurve::P_256)
+ .AttestKey()
+ .SetDefaultValidity(),
+ builder, &keyblob, &key_characteristics,
+ &cert_chain);
+ }
+ }
+ ASSERT_EQ(ErrorCode::OK, result);
// Verify first user to get a HAT that should work.
const uint64_t challenge = 42;
@@ -535,7 +545,7 @@
ASSERT_GT(dodgy_hat->mac.size(), 0);
dodgy_hat->mac[0] ^= 0x01;
EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
- Finish(message, {} /* signature */, &ciphertext, hat.value()));
+ Finish(message, {} /* signature */, &ciphertext, dodgy_hat.value()));
}
// Test use of a key that requires an auth token for each action on the operation, with
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 9f8593c..5f8ec0e 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -1300,15 +1300,12 @@
}
bool KeyMintAidlTestBase::IsRkpSupportRequired() const {
- if (get_vsr_api_level() >= __ANDROID_API_T__) {
- return true;
- }
-
- if (get_vsr_api_level() >= __ANDROID_API_S__) {
- return SecLevel() != SecurityLevel::STRONGBOX;
- }
-
- return false;
+ // This is technically not a match to the requirements for S chipsets,
+ // however when S shipped there was a bug in the test that skipped the
+ // tests if KeyMint 2 was not on the system. So we allowed many chipests
+ // to ship without RKP support. In T we hardened the requirements around
+ // support for RKP, so relax the test to match.
+ return get_vsr_api_level() >= __ANDROID_API_T__;
}
vector<uint32_t> KeyMintAidlTestBase::ValidKeySizes(Algorithm algorithm) {
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 1e61a18..022dd3f 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -2565,22 +2565,24 @@
* NewKeyGenerationTest.EcdsaDefaultSize
*
* Verifies that failing to specify a curve for EC key generation returns
- * UNSUPPORTED_KEY_SIZE.
+ * UNSUPPORTED_KEY_SIZE or UNSUPPORTED_EC_CURVE.
*/
TEST_P(NewKeyGenerationTest, EcdsaDefaultSize) {
- ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
- GenerateKey(AuthorizationSetBuilder()
- .Authorization(TAG_ALGORITHM, Algorithm::EC)
- .SigningKey()
- .Digest(Digest::NONE)
- .SetDefaultValidity()));
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_ALGORITHM, Algorithm::EC)
+ .SigningKey()
+ .Digest(Digest::NONE)
+ .SetDefaultValidity());
+ ASSERT_TRUE(result == ErrorCode::UNSUPPORTED_KEY_SIZE ||
+ result == ErrorCode::UNSUPPORTED_EC_CURVE)
+ << "unexpected result " << result;
}
/*
* NewKeyGenerationTest.EcdsaInvalidCurve
*
* Verifies that specifying an invalid curve for EC key generation returns
- * UNSUPPORTED_KEY_SIZE.
+ * UNSUPPORTED_KEY_SIZE or UNSUPPORTED_EC_CURVE.
*/
TEST_P(NewKeyGenerationTest, EcdsaInvalidCurve) {
for (auto curve : InvalidCurves()) {
@@ -2593,7 +2595,8 @@
.SetDefaultValidity(),
&key_blob, &key_characteristics);
ASSERT_TRUE(result == ErrorCode::UNSUPPORTED_KEY_SIZE ||
- result == ErrorCode::UNSUPPORTED_EC_CURVE);
+ result == ErrorCode::UNSUPPORTED_EC_CURVE)
+ << "unexpected result " << result;
}
ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
@@ -8755,6 +8758,7 @@
using VsrRequirementTest = KeyMintAidlTestBase;
+// @VsrTest = VSR-3.10-008
TEST_P(VsrRequirementTest, Vsr13Test) {
int vsr_api_level = get_vsr_api_level();
if (vsr_api_level < __ANDROID_API_T__) {
@@ -8763,6 +8767,7 @@
EXPECT_GE(AidlVersion(), 2) << "VSR 13+ requires KeyMint version 2";
}
+// @VsrTest = VSR-3.10-013.001
TEST_P(VsrRequirementTest, Vsr14Test) {
int vsr_api_level = get_vsr_api_level();
if (vsr_api_level < __ANDROID_API_U__) {
diff --git a/security/rkp/README.md b/security/rkp/README.md
index 8cd1582..15ea817 100644
--- a/security/rkp/README.md
+++ b/security/rkp/README.md
@@ -42,7 +42,9 @@
sign certificate requests. Instead, UDS\_pub is just the first public key in a
chain of public keys that end the KeyMint public key. All keys in the chain are
transitively derived from the UDS and joined in a certificate chain following
-the specification of the [Android Profile for DICE](#android-profile-for-dice).
+the specification of the [Android Profile for DICE](android-profile-for-dice).
+
+[android-profile-for-dice]: https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/android.md
### Phases
@@ -53,7 +55,7 @@
certificate requests; a single self-signed certificate signifies this phase.
* DICE (Phase 2): A hardware root of trust key pair is only accessible to ROM
or ROM extension code; the boot process follows the [Android Profile for
- DICE](#android-profile-for-dice).
+ DICE](android-profile-for-dice).
* SoC vendor certified DICE (Phase 3): This is identical to Phase 2, except the
SoC vendor also does the UDS\_pub extraction or certification in their
facilities, along with the OEM doing it in the factory. This tightens up the
@@ -163,67 +165,6 @@
* **KeyMint** is the secure area component that manages cryptographic keys and
performs attestations (or perhaps some other secure area component).
-### Android Profile for DICE
-
-The Android Profile for DICE is based on the [Open Profile for
-DICE](https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/specification.md),
-with additional constraints for details that the Open Profile for DICE leaves
-intentionally underspecified. This section describes the differences from the
-Open Profile for DICE.
-
-#### Algorithms
-
-The choice of algorithm must remain consistent with a given certificate e.g. if
-SHA-256 is used for the code hash then the authority hash, config hash, etc.
-must also use SHA-256.
-
-* UDS and CDI key pairs:
- * Ed25519 / P-256 / P-384
-* Hash algorithms (digests can be encoded with their natural size and do not
- need to be the 64-bytes specified by the Open Profile for DICE):
- * SHA-256 / SHA-384 / SHA-512
-* HKDF with a supported message digest for all key derivation
-
-#### Mode
-
-A certificate must only set the mode to `normal` when all of the following
-conditions are met when loading and verifying the software component that is
-being described by the certificate:
-
-* verified boot with anti-rollback protection is enabled
-* only the verified boot authorities for production images are enabled
-* debug ports, fuses, or other debug facilities are disabled
-* device booted software from the normal primary source e.g. internal flash
-
-The mode should never be `not configured`.
-
-Every certificate in the DICE chain will need to be have the `normal` mode in
-order to be provisioned with production certificates by RKP.
-
-#### Configuration descriptor
-
-The configuration descriptor is a CBOR map with the following optional fields.
-If no fields are relevant, an empty map should be encoded. The key value range
-\[-70000, -70999\] is reserved for the Android Profile for DICE.
-Implementation-specific fields may be added using key values outside of the
-reserved range.
-
-```
-| Name | Key | Value type | Meaning |
-| ----------------- | ------ | ---------- | ----------------------------------|
-| Component name | -70002 | tstr | Name of firmware component / boot |
-: : : : stage :
-| Component version | -70003 | int / tstr | Version of firmware component / |
-: : : : boot stage :
-| Resettable | -70004 | null | If present, key changes on factory|
-: : : : reset :
-| Security version | -70005 | uint | Machine-comparable, monotonically |
-: : : : increasing version of the firmware:
-: : : : component / boot stage where a :
-: : : : greater value indicates a newer :
-: : : : version :
-```
-
### HAL
The remote provisioning HAL provides a simple interface that can be implemented
diff --git a/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
index b231dae..f8a5540 100644
--- a/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
+++ b/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
@@ -414,7 +414,7 @@
* 1 : tstr, ; Issuer
* 2 : tstr, ; Subject
* -4670552 : bstr .cbor PubKeyEd25519 /
- * bstr .cbor PubKeyECDSA256,
+ * bstr .cbor PubKeyECDSA256 /
* bstr .cbor PubKeyECDSA384, ; Subject Public Key
* -4670553 : bstr ; Key Usage
*
diff --git a/sensors/common/default/2.X/Sensor.cpp b/sensors/common/default/2.X/Sensor.cpp
index 2c1cdfb..f8c857b 100644
--- a/sensors/common/default/2.X/Sensor.cpp
+++ b/sensors/common/default/2.X/Sensor.cpp
@@ -40,6 +40,7 @@
: mIsEnabled(false),
mSamplingPeriodNs(0),
mLastSampleTimeNs(0),
+ mStopThread(false),
mCallback(callback),
mMode(OperationMode::NORMAL) {
mRunThread = std::thread(startThread, this);
diff --git a/sensors/common/vts/utils/GrallocWrapper.cpp b/sensors/common/vts/utils/GrallocWrapper.cpp
index e6e0888..a15e7fe 100644
--- a/sensors/common/vts/utils/GrallocWrapper.cpp
+++ b/sensors/common/vts/utils/GrallocWrapper.cpp
@@ -124,7 +124,8 @@
private:
static constexpr uint64_t kBufferUsage =
- static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::CPU_READ_OFTEN);
+ static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::CPU_READ_OFTEN |
+ BufferUsage::CPU_WRITE_RARELY);
AllocatorWrapperT<AllocatorT> mAllocator;
sp<MapperT> mMapper;
diff --git a/threadnetwork/aidl/default/Android.bp b/threadnetwork/aidl/default/Android.bp
index bcd5704..62c8c9e 100644
--- a/threadnetwork/aidl/default/Android.bp
+++ b/threadnetwork/aidl/default/Android.bp
@@ -9,22 +9,21 @@
// in whole or in part, without the express written permission of
// Google LLC.
-cc_defaults {
- name: "threadnetwork_service_default",
- vintf_fragments: ["threadnetwork-default.xml"],
+cc_binary {
+ name: "android.hardware.threadnetwork-service",
vendor: true,
relative_install_path: "hw",
shared_libs: [
- "android.hardware.threadnetwork-V1-ndk",
- "libbase",
"libbinder_ndk",
- "libcutils",
"liblog",
- "libutils",
],
static_libs: [
+ "android.hardware.threadnetwork-V1-ndk",
+ "libbase",
+ "libcutils",
+ "libutils",
"openthread-common",
"openthread-hdlc",
"openthread-platform",
@@ -33,6 +32,8 @@
"openthread-url",
],
+ stl: "c++_static",
+
srcs: [
"main.cpp",
"service.cpp",
@@ -41,22 +42,10 @@
],
}
-cc_binary {
- name: "android.hardware.threadnetwork-service.sim",
- defaults: ["threadnetwork_service_default"],
- init_rc: ["android.hardware.threadnetwork-service.sim.rc"],
- required: ["ot-rcp"],
-}
-
-cc_binary {
- name: "android.hardware.threadnetwork-service",
- defaults: ["threadnetwork_service_default"],
-}
-
cc_fuzz {
name: "android.hardware.threadnetwork-service.fuzzer",
- defaults:["service_fuzzer_defaults"],
+ defaults: ["service_fuzzer_defaults"],
shared_libs: [
"libbinder_ndk",
],
@@ -85,3 +74,36 @@
],
},
}
+
+prebuilt_etc {
+ name: "threadnetwork-default.xml",
+ src: "threadnetwork-default.xml",
+ sub_dir: "vintf",
+ installable: false,
+}
+
+prebuilt_etc {
+ name: "threadnetwork-service-sim.rc",
+ src: "threadnetwork-service-sim.rc",
+ installable: false,
+}
+
+apex {
+ name: "com.android.hardware.threadnetwork",
+ manifest: "manifest.json",
+ file_contexts: "file_contexts",
+ key: "com.android.hardware.key",
+ certificate: ":com.android.hardware.certificate",
+ updatable: false,
+ vendor: true,
+
+ binaries: [
+ "android.hardware.threadnetwork-service",
+ "ot-rcp",
+ ],
+ prebuilts: [
+ "threadnetwork-default.xml", // vintf_fragment
+ "threadnetwork-service-sim.rc", // init_rc
+ "android.hardware.thread_network.prebuilt.xml", // permission
+ ],
+}
diff --git a/threadnetwork/aidl/default/android.hardware.threadnetwork-service.sim.rc b/threadnetwork/aidl/default/android.hardware.threadnetwork-service.sim.rc
deleted file mode 100644
index 2fb409c..0000000
--- a/threadnetwork/aidl/default/android.hardware.threadnetwork-service.sim.rc
+++ /dev/null
@@ -1,3 +0,0 @@
-service vendor.threadnetwork_hal /vendor/bin/hw/android.hardware.threadnetwork-service.sim spinel+hdlc+forkpty:///vendor/bin/ot-rcp?forkpty-arg=1
- class hal
- user thread_network
diff --git a/threadnetwork/aidl/default/file_contexts b/threadnetwork/aidl/default/file_contexts
new file mode 100644
index 0000000..39ba3b5
--- /dev/null
+++ b/threadnetwork/aidl/default/file_contexts
@@ -0,0 +1,4 @@
+(/.*)? u:object_r:vendor_file:s0
+/etc(/.*)? u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.threadnetwork-service u:object_r:hal_threadnetwork_default_exec:s0
+/bin/ot-rcp u:object_r:ot_rcp_exec:s0
diff --git a/threadnetwork/aidl/default/manifest.json b/threadnetwork/aidl/default/manifest.json
new file mode 100644
index 0000000..61e6dc1
--- /dev/null
+++ b/threadnetwork/aidl/default/manifest.json
@@ -0,0 +1,4 @@
+{
+ "name": "com.android.hardware.threadnetwork",
+ "version": 1
+}
diff --git a/threadnetwork/aidl/default/thread_chip.cpp b/threadnetwork/aidl/default/thread_chip.cpp
index 3d38cb8..9358eba 100644
--- a/threadnetwork/aidl/default/thread_chip.cpp
+++ b/threadnetwork/aidl/default/thread_chip.cpp
@@ -59,10 +59,6 @@
AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(), ThreadChip::onBinderUnlinkedJump);
}
-ThreadChip::~ThreadChip() {
- AIBinder_DeathRecipient_delete(mDeathRecipient.get());
-}
-
void ThreadChip::onBinderDiedJump(void* context) {
reinterpret_cast<ThreadChip*>(context)->onBinderDied();
}
diff --git a/threadnetwork/aidl/default/thread_chip.hpp b/threadnetwork/aidl/default/thread_chip.hpp
index 1ab6d54..680580a 100644
--- a/threadnetwork/aidl/default/thread_chip.hpp
+++ b/threadnetwork/aidl/default/thread_chip.hpp
@@ -34,7 +34,7 @@
class ThreadChip : public BnThreadChip, ot::Posix::Mainloop::Source {
public:
ThreadChip(char* url);
- ~ThreadChip();
+ ~ThreadChip() {}
ndk::ScopedAStatus open(const std::shared_ptr<IThreadChipCallback>& in_callback) override;
ndk::ScopedAStatus close() override;
diff --git a/threadnetwork/aidl/default/threadnetwork-service-sim.rc b/threadnetwork/aidl/default/threadnetwork-service-sim.rc
new file mode 100644
index 0000000..3b889eb
--- /dev/null
+++ b/threadnetwork/aidl/default/threadnetwork-service-sim.rc
@@ -0,0 +1,3 @@
+service vendor.threadnetwork_hal /apex/com.android.hardware.threadnetwork/bin/hw/android.hardware.threadnetwork-service spinel+hdlc+forkpty:///apex/com.android.hardware.threadnetwork/bin/ot-rcp?forkpty-arg=1
+ class hal
+ user thread_network
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
index ff9c247..21951b6 100644
--- a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
@@ -45,6 +45,7 @@
CCC_SUPPORTED_RAN_MULTIPLIER = 0xA7,
CCC_SUPPORTED_MAX_RANGING_SESSION_NUMBER = 0xA8,
CCC_SUPPORTED_MIN_UWB_INITIATION_TIME_MS = 0xA9,
+ CCC_PRIORITIZED_CHANNEL_LIST = 0xAA,
RADAR_SUPPORT = 0xB0,
SUPPORTED_AOA_RESULT_REQ_ANTENNA_INTERLEAVING = 0xE3,
SUPPORTED_MIN_RANGING_INTERVAL_MS = 0xE4,
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
index ceef1be..2141b5a 100644
--- a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
+++ b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
@@ -149,6 +149,11 @@
*/
CCC_SUPPORTED_MIN_UWB_INITIATION_TIME_MS = 0xA9,
+ /**
+ * Byte array of channels supported by the device, ordered by priority from highest to lowest.
+ */
+ CCC_PRIORITIZED_CHANNEL_LIST = 0xAA,
+
/*********************************************
* RADAR specific
********************************************/
diff --git a/uwb/aidl/default/Android.bp b/uwb/aidl/default/Android.bp
index 9621f2c..c6d1a52 100644
--- a/uwb/aidl/default/Android.bp
+++ b/uwb/aidl/default/Android.bp
@@ -11,8 +11,8 @@
name: "android.hardware.uwb-service",
crate_name: "uwb_default_hal",
relative_install_path: "hw",
- vintf_fragments: ["uwb-service.xml"],
vendor: true,
+ prefer_rlib: true,
rustlibs: [
"android.hardware.uwb-V1-rust",
"liblogger",
@@ -30,3 +30,47 @@
"src/service.rs",
],
}
+
+prebuilt_etc {
+ name: "uwb-service.rc",
+ src: "uwb-service.rc",
+ vendor: true,
+ installable: false,
+}
+
+prebuilt_etc {
+ name: "uwb-service.xml",
+ src: "uwb-service.xml",
+ sub_dir: "vintf",
+ vendor: true,
+ installable: false,
+}
+
+apex_key {
+ name: "com.android.hardware.uwb.key",
+ public_key: "com.android.hardware.uwb.avbpubkey",
+ private_key: "com.android.hardware.uwb.pem",
+}
+
+android_app_certificate {
+ name: "com.android.hardware.uwb.certificate",
+ certificate: "com.android.hardware.uwb",
+}
+
+apex {
+ name: "com.android.hardware.uwb",
+ manifest: "manifest.json",
+ file_contexts: "file_contexts",
+ key: "com.android.hardware.uwb.key",
+ certificate: ":com.android.hardware.uwb.certificate",
+ updatable: false,
+ vendor: true,
+
+ binaries: [
+ "android.hardware.uwb-service",
+ ],
+ prebuilts: [
+ "uwb-service.rc", // init_rc
+ "uwb-service.xml", // vintf_fragments
+ ],
+}
diff --git a/uwb/aidl/default/com.android.hardware.uwb.avbpubkey b/uwb/aidl/default/com.android.hardware.uwb.avbpubkey
new file mode 100644
index 0000000..7a7fce8
--- /dev/null
+++ b/uwb/aidl/default/com.android.hardware.uwb.avbpubkey
Binary files differ
diff --git a/uwb/aidl/default/com.android.hardware.uwb.pem b/uwb/aidl/default/com.android.hardware.uwb.pem
new file mode 100644
index 0000000..cd38ef8
--- /dev/null
+++ b/uwb/aidl/default/com.android.hardware.uwb.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQChE5EVDbSAKAru
+myK22LP72i2ivpJGi8DqRjgA5r6Zz3OKwtvrtSBaTtACv3j6ZALLndA2sgxbt64B
+ik1vU1tpnrGnaqcdlgDio6QIfpavWEcZ9rOHuGXvLlv3Tzc2gyr1UKsaGtce+os8
+jbfyEl4keN59oI2D8Nj1VVKYRKS+mrp4+hnvt3itGbvIKLCgGBYlcSxIiWKDfJXy
+jQEpb5pZy3wCdn2CCrTb64oclkmYbGcfoYuSBV6+PBrGa2b0b5aWm40YFbgZ5h+j
+Hlkb7sX7Vz499DK1lbm8rRt+EkHZ/9IFS1DBSj6MK3LKyGspj7BzJ25UQI23B3pM
+iaNsjBR1gGwqJxWpjuuZm9qdNPMSUUSxs/EB0GX96jnC5HFjh3sLOWKqqP6SRCZW
+xYRzjAno1L1jjPXdDqM9n2aJHu35+YVG/sFn20eIBSxH9u1hSnOw8ccc0Zo774cc
+oTJHKlL9GUO5SEGLkz3XTMEe6e55yujChymMe5jz8jkkCaXqsNDB0AMUtQ6g0Kzu
+FNUdTS2DAr/Xo7qxJ6VoDwOx/OQeDQSjSuojt/JMHEp6QMir+/axVWuxIaegjElH
+Kmx7Ie6ZGZscaTxKFEYEkWaIeJKTml0NxEitrJAibc58itj93zBMP2EDve46ghWJ
+SlmeeVmn0CuYeE8EHwZSB4I7EaHP1QIDAQABAoICADQESZnu7xdj1wPu/Wrm2FjA
+wHQJ7trxTr9ZJcTEv1CUec+Z1cNsnqILSYlZpAvYOD7hG9hN70e/LWY573+//4lA
+Qka6XnVjd625AsPrfWXqsCtmS9vMZL60zeYzorTr7veBsX+go0/RwR0w9vIplFVa
+4x7Wtlyhbq7retzJbhpPhWCEA9Qx/7qG0Ol2mnNY0+4Lei2CkFm95f6KIpHrBIFz
+AP0anrVcF8PdcKCCuAmNGFBSruvc6Beu+UaScJEHaC4C1bGtceKLOjRHHKe0mCLu
+rZ78OVQCohSYIoS4CKQJxR0IkW+aNlC1x0BNMK4fRPArD6oNnrY4p/oHiMsJAaHc
+tLWeUqvlSAdK0C5ejUzdjTiZW7rzI2gluy+BBKY1nByQsVWK7saG6hEON63idfl+
+GwPPb253n49UIk3UlUy1PxVb/othlw0dlD7p4wAlOJoRlOuJnqAifwWckS2rpNHO
+9wR1tak8hLi2LMDJqu/GlHoSqkb+JdAV5yujLQ8k1So/y/4bvNY2pRpXPydxkOew
+FY/BOoslS6RD5/XHfSJsK/Oq53Y+d04qdV7jwgrp4lqFEqMwJgzVEoC5cMvJVeK9
+/wjUdWw9hg0DSk8LVmNbIWZjZs4C39uQljmt8s+exSmzm5MSQU3K11vGRGKOsPlA
+5ZzRRaV81lBYKhATE8aRAoIBAQDfPgJ3l/38RPyoNrJuhOPH4UJj0rDX0+5ezqla
+iAXDxec55lM8qbPDW3jl/MWE3LePVokKN8DBxwZxi9Po4UEQ4hG4+zIyPcT1AQlH
++kHGG0TBtJox8J+DkG5oW79wXCn6tyl8ZLwWNa6T/3vIi3BNadnoe3AFqgcHVwHz
+e/tl0z6Tz56r/eNN6dl01+D31rirqiYRbe3982ZiX3JfS3t+AIQoxcU4suU+DC37
+G5h0zbzjgXP+ZrpPfh6O7JwH7Ac83nJAYBsVcHU4P/ZstkIWjuzleEQcDcsj3sHu
+NO2/wbReo/8Yvk0q2vUQm9IkWlU83H2KLPzIa1VuzTfPql0bAoIBAQC4tlP393ly
+krhmRLs6msAjXp5oZzoyHnrYvn+5LlKoPul98EqAW9GczLSlgjYO3w2DqnimBhU/
+YorWvkhcSJsrjiEn7CZ3UXuXoLciRiyHk/3xSDP4CLZ8tvUcEGs34LITXMPlrIk1
+WfYseSukE1TB6GDEj4MsxFILKhwnxGWeD9x9+ejOPj7+Jk3oTiZPVc67LR0MDgDz
+hRZW/8VOsequ+B/TF9LiwUHI3Ps3Geh3kKMR6DQaxXW08HDk1NGsZmKXq+O+JWFT
+3ZwCNnXqUCpm9YsD6QXTHILtBHVS5cxE65BFs08WEAqcgDhr3Yczz8L/UN/qR+FH
+RSOcymVFHQXPAoIBAQDK8Lsbbw+UGj64yGhysdnD5dINnwXmXiHPC/3Gb+sVqr3l
+060Nc5QYXvpL0PraKi+wXVFc+YwAXGZOKHfut38H0wubZreeFqsKsvN1/Fl4t2dM
+1FpsVbscxdqogedJRG9hHMrY61ZUtl5K6jDkAWaI6VYP0s7mR0f2czEx4B6M1XmI
+s3AiGD5foNtvLaS0iPz+CUJsC8wTVQZZHT2CxcKwq9V4nzkHrxFY04elQ9PXMwSo
+qRECTu7FvvgWo5/AT9/QhMPGI9fbKI1XIkZpU1JG4Y0XmboI6r0lkaYoXvNWo8fN
+VTZcjvrln4CypYRmSbw9BJAXYYg2xeQ3QtWesdfLAoIBAQCM9ifyjpvSQgITmdRA
+jySeWXEOP+j7oqMhkY+rZJyT5R8Pizdv6aJ3xQj/XfWfN736gzf7i5zfeHZ4F1Ll
+iktQ2/CVpPReDoMBXhckQuVsuhYL8owmd4+8cWtw9V69j+6WNC8Tsa4sVvE1U2to
+lZATQyHGH7d9jH0IJCTEfG8IRxZ/1R5DduFf1x+Rb0JxPQy9b1pBftZfAWvhDOQo
+gEKXMKgo0n+PqOhpP6s/i7gKtwibe9d3rsV7RhsBpyA0LxaCpRzyWViDRhXu4lzu
+aitR04U5gLV/PLz14Hcgwlo3JoY9iu+J6MgQUxG7z52EfsNTUQbwpdZYK31YBGVw
+bwulAoIBAQClsNAtbbwmExh3P0rjkgQOVy7FMQXgOyldR/LYTRI6Zbt47Jb4eO6M
+vfKK4C67/RoD1PEWgdboY8axPNj3dR1RdAuyTOOJfhJYVCW2eRS2fjSjYmUnLoFB
+N2ABYE8yKmmcPIlcJzXs3Jzeb+URxtDrvuEWPBHm8Ia1u29t42W7pg4AZHitilTl
+Su1Xi+Ic2n0NVzqZzLVUb6dKr2NFAjynthOCFXbbwD6awFeTxFIXVGT9TPTaiIlA
+Ssnh+yii4NHRoZjivUCsrfEfn+NiCzOgrfXTtUiRDvhZHdpqAIqQ6lpju7naCCwG
+vApJsLERxjCi0eqDwVx/e6xbeOVUZc/m
+-----END PRIVATE KEY-----
diff --git a/uwb/aidl/default/com.android.hardware.uwb.pk8 b/uwb/aidl/default/com.android.hardware.uwb.pk8
new file mode 100644
index 0000000..8855197
--- /dev/null
+++ b/uwb/aidl/default/com.android.hardware.uwb.pk8
Binary files differ
diff --git a/uwb/aidl/default/com.android.hardware.uwb.x509.pem b/uwb/aidl/default/com.android.hardware.uwb.x509.pem
new file mode 100644
index 0000000..762ad88
--- /dev/null
+++ b/uwb/aidl/default/com.android.hardware.uwb.x509.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF1TCCA70CFEagTJLwbnblSQu8MjFHXcEDFQ1MMA0GCSqGSIb3DQEBCwUAMIGl
+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
+bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
+MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEhMB8GA1UEAwwYY29t
+LmFuZHJvaWQuaGFyZHdhcmUudXdiMCAXDTIzMDgyMTA0MTE0M1oYDzQ3NjEwNzE3
+MDQxMTQzWjCBpTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAU
+BgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB0FuZHJvaWQxEDAOBgNVBAsM
+B0FuZHJvaWQxIjAgBgkqhkiG9w0BCQEWE2FuZHJvaWRAYW5kcm9pZC5jb20xITAf
+BgNVBAMMGGNvbS5hbmRyb2lkLmhhcmR3YXJlLnV3YjCCAiIwDQYJKoZIhvcNAQEB
+BQADggIPADCCAgoCggIBAJpvvE7i50v4hE5VmlFTiOsQ+zOYWF+MjzEMXcqLQDzs
+26XBYJV7O3TwgrQNp1XV8KCPTAF8APEyGb237rlZO/3KvS9zYa3zFfEMPg5pnFmR
+QLWSfqrXm7ttKIQHNVAjqrLnlt8pjvKS/t/UXLAWgHiXnd2ZX62tQjyDouszLEwP
+59zJbkgX9o6fwEssdRTpuyoRoyPylfK3Thk22RBSTt+pS6pwqeUj4vttrPr7k7YU
+S5CeB7XVBRPRzXFrpasgzQqp2deOpqxC44H90+pl7QmBHFrnGk+90lcOPYgqF2Ah
+DfCBxAHzn8ioSsAJ0U34yqoNbWIUX3ZHgq1ru1uctdLwGMrKmqsw4uvfXLV+sjoi
+qUFW+9uEOHAVnmZEO2T7LAlUIoAGgdd58EJ+hdXP2yvNpGVPestrwWttAaMJoEJN
+qEWt67+iEjdEpVn0lUFo+up42mYEXGUAOpoc6t5WJinrQTY4JK/OIGJPUiOjbUTI
+T/hQTddr0HNGsKP2zRv0d49VtVht6wR0HlO1srCFZAGxRIdBtjjenu1l7ALMWlHw
+4YXLSpQoeYfavV8C3j5bzz6KaDj6HcKvRbyHRX8+JL9kFDgpOD1yI/jaaPepRAe6
+qek5jEJMEFj0tFifB8e0CZbURreXa1tErWybfuDkaNBDtAHL333/IQGI0vV7zr0x
+AgMBAAEwDQYJKoZIhvcNAQELBQADggIBAFqnBngYd7rXHwIXHYKZuRMf+NLQxNFN
+f0m6ioFYgNnMwoMQidBHdRsJ2qTb9zfyt5O1/5Wel8Ix9aUCRbJejyX2lYXNIJNC
+ykahkoP+3CEA8QtPkmtWzNraDJRh2eYn6V5DJOWyvkz02DsHA4mxatYkF7dUfqLx
+f/y1y3cbnTyAraotTRb3W/F/zEYbcCzwlFZDT/IASVM89WRDE76+rp7/wDNJ0aEJ
+l6cQaUWDPbrvDWZaptRWfnebPtg81v03qKauwrBADddxu+/Nqs0iczBdsP1tdXr/
+Hxs47D7+fZnytVQglldBG4yky9YceL22yft/bCNDe5d7nF1/iUpJNbRIcrZxD86Z
+wwPpo0VMJ+r6VuD6UGQTS6Zyi94QD3GYYkGrPPwyrLKpp1EU6dV32bWCNp5eQojY
+FyTse/lfAJ9/Xu3klHYuR9xOaJiH+2MmtJTwKdjvK5h+EIiVbyrDJJHBd9sWav3a
+Emo+wKaIxQzXEUjWxUwy7eAAwq5WzawLMMQ97P0zIgasNIlUHW2cvBzVsQlM1tN7
+2t+7UPs5RifK5hadK6Ge1oqkG0xC1t65E7yGwrPMzKuz9aPgg7j1YAaETcKuFOHG
+rZr/0kALZc6VKNSZ8eM2P5ObrelLOe4ED9Ha1ZhmnCDXN9BP2gwqmCekwfNJ3cPA
+GObJiF81f9ZM
+-----END CERTIFICATE-----
diff --git a/uwb/aidl/default/file_contexts b/uwb/aidl/default/file_contexts
new file mode 100644
index 0000000..6ec53ed
--- /dev/null
+++ b/uwb/aidl/default/file_contexts
@@ -0,0 +1,3 @@
+(/.*)? u:object_r:vendor_file:s0
+/etc(/.*)? u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.uwb-service u:object_r:hal_uwb_default_exec:s0
\ No newline at end of file
diff --git a/uwb/aidl/default/manifest.json b/uwb/aidl/default/manifest.json
new file mode 100644
index 0000000..3f2f911
--- /dev/null
+++ b/uwb/aidl/default/manifest.json
@@ -0,0 +1,4 @@
+{
+ "name": "com.android.hardware.uwb",
+ "version": 1
+}
diff --git a/uwb/aidl/default/src/uwb_chip.rs b/uwb/aidl/default/src/uwb_chip.rs
index cf32694..9587efb 100644
--- a/uwb/aidl/default/src/uwb_chip.rs
+++ b/uwb/aidl/default/src/uwb_chip.rs
@@ -6,8 +6,8 @@
use async_trait::async_trait;
use binder::{Result, Strong};
-use tokio::fs::{self, File};
-use tokio::io::AsyncReadExt;
+use tokio::fs::{File, OpenOptions};
+use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::sync::Mutex;
use std::os::fd::AsRawFd;
@@ -22,6 +22,7 @@
callbacks: Strong<dyn IUwbClientCallback>,
#[allow(dead_code)]
tasks: tokio::task::JoinSet<()>,
+ serial: File,
},
}
@@ -64,7 +65,11 @@
async fn open(&self, callbacks: &Strong<dyn IUwbClientCallback>) -> Result<()> {
log::debug!("open: {:?}", &self.path);
- let mut serial = File::open(&self.path)
+ let serial = OpenOptions::new()
+ .read(true)
+ .write(true)
+ .create(false)
+ .open(&self.path)
.await
.and_then(makeraw)
.map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
@@ -75,13 +80,17 @@
let client_callbacks = callbacks.clone();
let mut tasks = tokio::task::JoinSet::new();
+ let mut reader = serial
+ .try_clone()
+ .await
+ .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
tasks.spawn(async move {
loop {
const UWB_HEADER_SIZE: usize = 4;
let mut buffer = vec![0; UWB_HEADER_SIZE];
- serial
+ reader
.read_exact(&mut buffer[0..UWB_HEADER_SIZE])
.await
.unwrap();
@@ -89,7 +98,7 @@
let length = buffer[3] as usize + UWB_HEADER_SIZE;
buffer.resize(length, 0);
- serial
+ reader
.read_exact(&mut buffer[UWB_HEADER_SIZE..length])
.await
.unwrap();
@@ -103,6 +112,7 @@
*state = State::Opened {
callbacks: callbacks.clone(),
tasks,
+ serial,
};
Ok(())
@@ -149,10 +159,11 @@
async fn sendUciMessage(&self, data: &[u8]) -> Result<i32> {
log::debug!("sendUciMessage");
- if let State::Opened { .. } = &mut *self.state.lock().await {
- fs::write(&self.path, data)
+ if let State::Opened { ref mut serial, .. } = &mut *self.state.lock().await {
+ serial
+ .write(data)
.await
- .map(|_| data.len() as i32)
+ .map(|written| written as i32)
.map_err(|_| binder::StatusCode::UNKNOWN_ERROR.into())
} else {
Err(binder::ExceptionCode::ILLEGAL_STATE.into())
diff --git a/uwb/aidl/default/uwb-service.rc b/uwb/aidl/default/uwb-service.rc
new file mode 100644
index 0000000..d6a8eda
--- /dev/null
+++ b/uwb/aidl/default/uwb-service.rc
@@ -0,0 +1,3 @@
+service vendor.uwb_hal /apex/com.android.hardware.uwb/bin/hw/android.hardware.uwb-service ${ro.vendor.uwb.dev}
+ class hal
+ user uwb
diff --git a/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp b/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp
index 049ec73..00943fd 100644
--- a/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp
+++ b/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp
@@ -18,7 +18,6 @@
#include <android-base/logging.h>
#include <android/hardware/vr/1.0/IVr.h>
#include <gtest/gtest.h>
-#include <hardware/vr.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
#include <log/log.h>
diff --git a/wifi/aidl/default/aidl_struct_util.cpp b/wifi/aidl/default/aidl_struct_util.cpp
index 7bc2eeb..83e1193 100644
--- a/wifi/aidl/default/aidl_struct_util.cpp
+++ b/wifi/aidl/default/aidl_struct_util.cpp
@@ -887,6 +887,15 @@
return true;
}
+StaLinkLayerLinkStats::StaLinkState convertLegacyMlLinkStateToAidl(wifi_link_state state) {
+ if (state == wifi_link_state::WIFI_LINK_STATE_NOT_IN_USE) {
+ return StaLinkLayerLinkStats::StaLinkState::NOT_IN_USE;
+ } else if (state == wifi_link_state::WIFI_LINK_STATE_IN_USE) {
+ return StaLinkLayerLinkStats::StaLinkState::IN_USE;
+ }
+ return StaLinkLayerLinkStats::StaLinkState::UNKNOWN;
+}
+
bool convertLegacyLinkLayerMlStatsToAidl(const legacy_hal::LinkLayerMlStats& legacy_ml_stats,
StaLinkLayerStats* aidl_stats) {
if (!aidl_stats) {
@@ -898,6 +907,7 @@
for (const auto& link : legacy_ml_stats.links) {
StaLinkLayerLinkStats linkStats = {};
linkStats.linkId = link.stat.link_id;
+ linkStats.state = convertLegacyMlLinkStateToAidl(link.stat.state);
linkStats.radioId = link.stat.radio;
linkStats.frequencyMhz = link.stat.frequency;
linkStats.beaconRx = link.stat.beacon_rx;
diff --git a/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp b/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp
index 5c334f8..995a13d 100644
--- a/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp
+++ b/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp
@@ -123,6 +123,9 @@
// Add two radio stats
legacy_ml_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{});
legacy_ml_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{});
+ wifi_link_state states[sizeof(wifi_link_state)] = {wifi_link_state::WIFI_LINK_STATE_UNKNOWN,
+ wifi_link_state::WIFI_LINK_STATE_NOT_IN_USE,
+ wifi_link_state::WIFI_LINK_STATE_IN_USE};
// Add two links.
legacy_ml_stats.links.push_back(legacy_hal::LinkStats{});
legacy_ml_stats.links.push_back(legacy_hal::LinkStats{});
@@ -133,6 +136,7 @@
link.stat.beacon_rx = rand();
// MLO link id: 0 - 15
link.stat.link_id = rand() % 16;
+ link.stat.state = states[rand() % sizeof(states)];
// Maximum number of radios is limited to 3 for testing.
link.stat.radio = rand() % 4;
link.stat.frequency = rand();
@@ -241,6 +245,18 @@
int l = 0;
for (legacy_hal::LinkStats& link : legacy_ml_stats.links) {
EXPECT_EQ(link.stat.link_id, (uint8_t)converted.iface.links[l].linkId);
+ StaLinkLayerLinkStats::StaLinkState expectedState;
+ switch (link.stat.state) {
+ case wifi_link_state::WIFI_LINK_STATE_NOT_IN_USE:
+ expectedState = StaLinkLayerLinkStats::StaLinkState::NOT_IN_USE;
+ break;
+ case wifi_link_state::WIFI_LINK_STATE_IN_USE:
+ expectedState = StaLinkLayerLinkStats::StaLinkState::IN_USE;
+ break;
+ default:
+ expectedState = StaLinkLayerLinkStats::StaLinkState::UNKNOWN;
+ }
+ EXPECT_EQ(expectedState, converted.iface.links[l].state);
EXPECT_EQ(link.stat.radio, converted.iface.links[l].radioId);
EXPECT_EQ(link.stat.frequency, (uint32_t)converted.iface.links[l].frequencyMhz);
EXPECT_EQ(link.stat.beacon_rx, (uint32_t)converted.iface.links[l].beaconRx);