44 Commits

Author SHA1 Message Date
Konsta
941fb0f0c1 sepolicy: add hwc3 hal
* Fixes 3fba3e61e5.
* Fixes https://github.com/raspberry-vanilla/android_local_manifest/issues/158.
2024-12-12 17:55:12 +02:00
Konsta
3fba3e61e5 graphics: switch to hwc3
* Support for HWC3 was implemented in upstream drm_hwcomposer.
2024-12-09 14:25:10 +02:00
Konsta
441c2cde9f graphics: add libgbm_mesa to mesa packages
* This gets built as a dependency to minigbm gbm_mesa_driver's
  libgbm_mesa_wrapper but add it here for completeness.
* Move Mesa gbm libraries under separate section.
2024-12-05 19:59:21 +02:00
Konsta
be7c3b6462 sepolicy: update mesa libraries
* Adapt to changes in Mesa 24.2/24.3.
2024-12-05 19:59:21 +02:00
Konsta
c86505857d sepolicy: add bluetooth hal
* Fixes fe5a39b067.
2024-12-05 19:59:14 +02:00
Konsta
fe5a39b067 bluetooth: switch to aidl hal 2024-11-23 15:53:34 +02:00
Konsta
75efcfcbb4 bluetooth: adjust rfkill
* Switch to android.hardware.bluetooth@1.1-service.btlinux rfkill
  implementation that uses /sys/class/rfkill/rfkill*/state.
2024-11-23 15:53:34 +02:00
Konsta
be98ffc92d bluetooth: remove serial implementation
* Remove serial bluetooth implementation that is used on cuttlefish
  as we're only using the HCI socket implementation on Raspberry Pi.
2024-11-23 15:53:34 +02:00
Konsta
21a6d545b2 bluetooth: rename aidl hal for rpi 2024-11-23 15:53:34 +02:00
Konsta
01569e8eec bluetooth: add aidl hal
* Copy from hardware/interfaces/bluetooth/aidl/default
  at 488942f82bd1bc9ad1cb65a02c71421dc3a6a3d6.
2024-11-23 15:53:34 +02:00
Konsta
f9f7db29e1 usb: convert gadget hal to aidl
* Based on hardware/interfaces/usb/gadget/aidl/default.
2024-11-22 15:53:36 +02:00
Konsta
6119d30d95 usb: add gadget lib
* Copy from hardware/interfaces/usb/gadget/1.2/default.
2024-11-22 15:53:33 +02:00
Konsta
ce6b4687fa graphics: add dri_gbm to mesa packages
* Needed with Mesa 24.3.
  15bea329d7
  514df444eb
2024-11-22 13:03:10 +02:00
Konsta
2bcf780b91 Revert "seccomp_policy: v4l2_codec2: allow mkdirat"
* No longer needed with 8a5dd4d00a.

This reverts commit 9f0b78612e.
2024-11-22 13:02:50 +02:00
Konsta
aebb08edae Revert "seccomp_policy: mediaswcodec: allow mkdirat"
* No longer needed with 8a5dd4d00a.

This reverts commit a152d68eac.
2024-11-22 13:02:31 +02:00
Oleg Lyovin
fb83928d5a CEC: fix use-after-free in hdmicec_close
Fields of 'ctx' are accessed just after it is freed.

Test: manual
Change-Id: I7c3786db9ae618d84149874c72662e4d105765b4
Signed-off-by: Oleg Lyovin <ovlevin@salutedevices.com>
2024-11-22 13:02:20 +02:00
Oleg Lyovin
9fdacb0960 CEC: do not join NULL thread
'hdmicec_close' may be called after exit_fd initialized,
but before ctx->thread created.

This patch checks it for NULL before join.

Test: manual
Change-Id: I1c57be56f2cd9956044d9a48fea914b1c1fd0132
Signed-off-by: Oleg Lyovin <ovlevin@salutedevices.com>
2024-11-22 13:02:11 +02:00
Konsta
2785f1c5fd audio: minor code readability and formatting fixes
* Fixes 0205059ddb.
2024-11-22 13:02:03 +02:00
Konsta
c94112be0b libcamera: add configuration for ai camera module 2024-10-16 11:46:26 +03:00
Konsta
0113344e01 graphics: bump opengles/vulkan deqp levels 2024-10-16 11:46:18 +03:00
Konsta
741b658768 car: enable A2DP source bluetooth profile
* 61473cb0eb
2024-09-07 13:27:05 +03:00
Konsta
c0ecc79bbb car: show instrument cluster on secondary display
* Fixes https://github.com/raspberry-vanilla/android_local_manifest/issues/43
2024-09-07 13:26:57 +03:00
Konsta
e107fc556c car: build can bus hal and debug tools 2024-09-07 13:26:49 +03:00
Konsta
85a8359c38 car: build occupant awareness hal 2024-09-07 13:26:41 +03:00
Konsta
31279e096f car: build audio control hal 2024-09-07 13:26:34 +03:00
Konsta
c2217592d2 car: switch to aidl vehicle hal 2024-09-07 13:26:26 +03:00
Konsta
ef8706e703 car: move automotive related configs to separate directory 2024-09-07 13:26:17 +03:00
Konsta
3ed5d0e615 keylayout: update for Android 15
* Changes from frameworks/base/data/keyboards/Generic.kl
2024-09-05 16:36:13 +03:00
Konsta
33e503a632 readme: mkimg: Raspberry Vanilla Ice Cream AOSP 15 2024-09-05 16:35:44 +03:00
Konsta
a152d68eac seccomp_policy: mediaswcodec: allow mkdirat 2024-09-04 20:09:01 +03:00
Konsta
9f0b78612e seccomp_policy: v4l2_codec2: allow mkdirat 2024-08-15 16:38:40 +03:00
Konsta
7e5f70d8a8 vulkan: bump to 1.3
* Missing patches to expose V3DV Vulkan 1.3 level have been backported
  to Raspberry Vanilla's Mesa 24.2.
2024-08-15 10:37:09 +03:00
Konsta
7f899c9b64 storage: disable stable uris for for external primary
* MediaProvider changes in AOSP 14 QPR3 cause a crash if external USB
  storage device is connected on the first boot.
* D MediaProvider: Backup is present for external_primary
  E FuseDaemon: Leveldb setup is missing for: external_primary
  I FuseDaemon: ReadFilePathsFromLevelDb: Missing leveldb connection, attempting setup.
  E FuseDaemon: Leveldb setup is missing for: internal
  E FuseDaemon: Leveldb connection failed for :internal with error:IO error: /storage/emulated/0/.transforms/recovery/leveldb-internal/LOCK: Permission denied
  E FuseDaemon: Leveldb setup is missing for: external_primary
  E FuseDaemon: Leveldb connection failed for :external_primary with error:IO error: /storage/emulated/0/.transforms/recovery/leveldb-external_primary/LOCK: Permission denied
  E FuseDaemon: Leveldb setup is missing for: ownership
  E FuseDaemon: Leveldb connection failed for :ownership with error:IO error: /storage/emulated/0/.transforms/recovery/leveldb-ownership/LOCK: Permission denied
  F libc    : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 in tid 12344 (fg), pid 12323 (rs.media.module)
2024-06-20 15:00:54 +03:00
Konsta
3856f29874 overlay: add safety center to default qs tiles
* Otherwise QS tile changes in AOSP 14 QPR3 cause a crash.
* E DatabaseUtils: java.lang.IllegalArgumentException: The value of your setting [sysui_qs_tiles] is too long. The max length allowed for the string is 32768.
2024-06-20 15:00:19 +03:00
Konsta
2790cd7abd keylayout: update for Android 14 QPR2
* Changes from frameworks/base/data/keyboards/Generic.kl
2024-05-03 21:50:03 +03:00
Konsta
881295d1f0 thermal: switch to apex
* e1ba194595
2024-05-03 21:50:03 +03:00
Konsta
0424549bf0 ramdisk: remove vold.post_fs_data_done
* This was used by FDE which was removed in Android 13.
  0803ba0985
* Fixes 3ca55b2c31.
2024-05-03 21:50:03 +03:00
Konsta
4a80053345 audio: reduce id name size
* Fixes 0205059ddb.
2024-05-03 21:49:47 +03:00
Konsta
ca3c59bc6e seccomp_policy: v4l2_codec2: whitelist missing syscalls
* Needed for H.264 hardware encoder.
* Fixes 7276df653b.
2024-04-30 12:55:10 +03:00
Konsta
34e6ccbc75 use generic cpu variant
* AOSP14 QPR2 (android-14.0.0_r29) introduced some (bionic?) changes that
  fail to boot on rpi4 with cortex-a72 CPU variant.
* Neither cortex-a72/cortex-a72 nor cortex-a53/generic TARGET_CPU_VARIANT/
  TARGET_2ND_CPU_VARIANT combinations seem to work. Use generic CPU variant.
* Fixes https://github.com/raspberry-vanilla/android_local_manifest/issues/70.
2024-04-25 17:56:19 +03:00
Konsta
ec52be7fcf window extensions: enable large screen optimization
* Feature was disabled by default in Android 14 QPR2
  f18920bc5e
2024-04-08 11:23:36 +03:00
Konsta
cfb419c398 health: update aidl to v3
* c33734ade7
2024-04-08 11:23:28 +03:00
Konsta
7276df653b v4l2_codec2: bump hidl hal to 1.2 2024-04-08 11:22:13 +03:00
Greg Kaiser
b1e605a615 Fix lunch choices for git_main
We add "trunk_staging-" for all COMMON_LUNCH_CHOICES so they are
valid in the trunk stable setup.

Bug: 307738446
Test: lunch
2024-04-08 11:21:58 +03:00
43 changed files with 1780 additions and 282 deletions

View File

@@ -10,6 +10,6 @@ PRODUCT_MAKEFILES := \
$(LOCAL_DIR)/aosp_rpi4_tv.mk
COMMON_LUNCH_CHOICES := \
aosp_rpi4-userdebug \
aosp_rpi4_car-userdebug \
aosp_rpi4_tv-userdebug
aosp_rpi4-trunk_staging-userdebug \
aosp_rpi4_car-trunk_staging-userdebug \
aosp_rpi4_tv-trunk_staging-userdebug

View File

@@ -16,13 +16,13 @@ TARGET_ARCH := arm64
TARGET_ARCH_VARIANT := armv8-a
TARGET_CPU_ABI := arm64-v8a
TARGET_CPU_ABI2 :=
TARGET_CPU_VARIANT := cortex-a72
TARGET_CPU_VARIANT := generic
TARGET_2ND_ARCH := arm
TARGET_2ND_ARCH_VARIANT := armv7-a-neon
TARGET_2ND_CPU_ABI := armeabi-v7a
TARGET_2ND_CPU_ABI2 := armeabi
TARGET_2ND_CPU_VARIANT := cortex-a72
TARGET_2ND_CPU_VARIANT := generic
# Bluetooth
BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR := $(DEVICE_PATH)/bluetooth

View File

@@ -1 +1 @@
Raspberry Vanilla AOSP 14 device configuration for Raspberry Pi 4.
Raspberry Vanilla AOSP 15 device configuration for Raspberry Pi 4.

View File

@@ -7,16 +7,24 @@
# Inherit device configuration
$(call inherit-product, device/brcm/rpi4/device.mk)
DEVICE_CAR_PATH := device/brcm/rpi4/car
PRODUCT_AAPT_CONFIG := normal mdpi hdpi
PRODUCT_AAPT_PREF_CONFIG := hdpi
PRODUCT_CHARACTERISTICS := automotive,nosdcard
$(call inherit-product, $(SRC_TARGET_DIR)/product/full_base.mk)
$(call inherit-product, packages/services/Car/car_product/build/car.mk)
# Audio
PRODUCT_PACKAGES += \
android.hardware.automotive.audiocontrol-service.example
PRODUCT_COPY_FILES += \
$(DEVICE_CAR_PATH)/car_audio_configuration.xml:$(TARGET_COPY_OUT_VENDOR)/etc/car_audio_configuration.xml
# Bluetooth
PRODUCT_VENDOR_PROPERTIES += \
bluetooth.device.class_of_device=38,4,8 \
bluetooth.profile.a2dp.source.enabled=false \
bluetooth.profile.asha.central.enabled=false \
bluetooth.profile.bap.broadcast.assist.enabled=false \
bluetooth.profile.bap.unicast.client.enabled=false \
@@ -45,6 +53,19 @@ PRODUCT_COPY_FILES += \
# Camera
ENABLE_CAMERA_SERVICE := true
# CAN
PRODUCT_PACKAGES += \
android.hardware.automotive.can-service
PRODUCT_PACKAGES += \
canhalctrl \
canhaldump \
canhalsend
# Display
PRODUCT_COPY_FILES += \
$(DEVICE_CAR_PATH)/display_settings.xml:$(TARGET_COPY_OUT_VENDOR)/etc/display_settings.xml
# EVS
ENABLE_CAREVSSERVICE_SAMPLE := true
ENABLE_EVS_SAMPLE := true
@@ -52,7 +73,13 @@ ENABLE_EVS_SERVICE := true
ENABLE_REAR_VIEW_CAMERA_SAMPLE := true
PRODUCT_COPY_FILES += \
device/brcm/rpi4/camera/evs_config_override.json:${TARGET_COPY_OUT_VENDOR}/etc/automotive/evs/config_override.json
$(DEVICE_CAR_PATH)/evs_config_override.json:${TARGET_COPY_OUT_VENDOR}/etc/automotive/evs/config_override.json
# Occupant awareness
PRODUCT_PACKAGES += \
android.hardware.automotive.occupant_awareness@1.0-service
include packages/services/Car/car_product/occupant_awareness/OccupantAwareness.mk
# Overlays
PRODUCT_PACKAGES += \
@@ -68,7 +95,7 @@ PRODUCT_COPY_FILES += \
# Vehicle
PRODUCT_PACKAGES += \
android.hardware.automotive.vehicle@2.0-default-service
android.hardware.automotive.vehicle@V3-default-service
# Device identifier. This must come after all inclusions.
PRODUCT_DEVICE := rpi4

View File

@@ -86,14 +86,14 @@ struct alsa_stream_out {
static int probe_pcm_out_card() {
FILE *fp;
char card_node[] = "/proc/asound/card0/id";
char card_id[64];
char card_node[32];
char card_id[16];
char card_prop[PROPERTY_VALUE_MAX];
property_get("persist.audio.device", card_prop, "");
for (int i = 0; i < 5; i++) {
card_node[17] = i + '0';
snprintf(card_node, sizeof(card_node), "/proc/asound/card%d/id", i);
if ((fp = fopen(card_node, "r")) != NULL) {
fgets(card_id, sizeof(card_id), fp);
ALOGV("%s: %s", card_node, card_id);
@@ -346,17 +346,17 @@ static int out_get_presentation_position(const struct audio_stream_out *stream,
struct alsa_stream_out *out = (struct alsa_stream_out *)stream;
int ret = -1;
if (out->pcm) {
unsigned int avail;
if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
int64_t signed_frames = out->written - kernel_buffer_size + avail;
if (signed_frames >= 0) {
*frames = signed_frames;
ret = 0;
}
if (out->pcm) {
unsigned int avail;
if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
int64_t signed_frames = out->written - kernel_buffer_size + avail;
if (signed_frames >= 0) {
*frames = signed_frames;
ret = 0;
}
}
}
return ret;
}

33
bluetooth/Android.bp Normal file
View File

@@ -0,0 +1,33 @@
// Copyright (C) 2020 The Android Open Source Project
// Copyright (C) 2024 KonstaKANG
//
// SPDX-License-Identifier: Apache-2.0
cc_binary {
name: "android.hardware.bluetooth-service.rpi",
relative_install_path: "hw",
init_rc: ["bluetooth-service-rpi.rc"],
vintf_fragments: ["bluetooth-service-rpi.xml"],
vendor: true,
cflags: [
"-Wall",
"-Wextra",
],
srcs: [
"BluetoothHci.cpp",
"net_bluetooth_mgmt.cpp",
"service.cpp",
],
shared_libs: [
"android.hardware.bluetooth-V1-ndk",
"libbase",
"libbinder_ndk",
"libhidlbase",
"liblog",
"libutils",
],
static_libs: [
"android.hardware.bluetooth.async",
"android.hardware.bluetooth.hci",
],
}

227
bluetooth/BluetoothHci.cpp Normal file
View File

@@ -0,0 +1,227 @@
/*
* Copyright (C) 2022 The Android Open Source Project
* Copyright (C) 2024 KonstaKANG
*
* 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 "android.hardware.bluetooth.service.rpi"
#include "BluetoothHci.h"
#include "log/log.h"
using namespace ::android::hardware::bluetooth::hci;
using namespace ::android::hardware::bluetooth::async;
using aidl::android::hardware::bluetooth::Status;
namespace aidl::android::hardware::bluetooth::impl {
void OnDeath(void* cookie);
class BluetoothDeathRecipient {
public:
BluetoothDeathRecipient(BluetoothHci* hci) : mHci(hci) {}
void LinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
mCb = cb;
clientDeathRecipient_ = AIBinder_DeathRecipient_new(OnDeath);
auto linkToDeathReturnStatus = AIBinder_linkToDeath(
mCb->asBinder().get(), clientDeathRecipient_, this /* cookie */);
LOG_ALWAYS_FATAL_IF(linkToDeathReturnStatus != STATUS_OK,
"Unable to link to death recipient");
}
void UnlinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
LOG_ALWAYS_FATAL_IF(cb != mCb, "Unable to unlink mismatched pointers");
}
void serviceDied() {
if (mCb != nullptr && !AIBinder_isAlive(mCb->asBinder().get())) {
ALOGE("Bluetooth remote service has died");
} else {
ALOGE("BluetoothDeathRecipient::serviceDied called but service not dead");
return;
}
{
std::lock_guard<std::mutex> guard(mHasDiedMutex);
has_died_ = true;
}
mHci->close();
}
BluetoothHci* mHci;
std::shared_ptr<IBluetoothHciCallbacks> mCb;
AIBinder_DeathRecipient* clientDeathRecipient_;
bool getHasDied() {
std::lock_guard<std::mutex> guard(mHasDiedMutex);
return has_died_;
}
private:
std::mutex mHasDiedMutex;
bool has_died_{false};
};
void OnDeath(void* cookie) {
auto* death_recipient = static_cast<BluetoothDeathRecipient*>(cookie);
death_recipient->serviceDied();
}
BluetoothHci::BluetoothHci() {
mDeathRecipient = std::make_shared<BluetoothDeathRecipient>(this);
}
ndk::ScopedAStatus BluetoothHci::initialize(
const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
ALOGI(__func__);
if (cb == nullptr) {
ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)");
return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
}
HalState old_state = HalState::READY;
{
std::lock_guard<std::mutex> guard(mStateMutex);
if (mState != HalState::READY) {
old_state = mState;
} else {
mState = HalState::INITIALIZING;
}
}
if (old_state != HalState::READY) {
ALOGE("initialize: Unexpected State %d", static_cast<int>(old_state));
close();
cb->initializationComplete(Status::ALREADY_INITIALIZED);
return ndk::ScopedAStatus::ok();
}
mCb = cb;
management_.reset(new NetBluetoothMgmt);
mFd = management_->openHci();
if (mFd < 0) {
management_.reset();
ALOGI("Unable to open Linux interface.");
mState = HalState::READY;
cb->initializationComplete(Status::UNABLE_TO_OPEN_INTERFACE);
return ndk::ScopedAStatus::ok();
}
mDeathRecipient->LinkToDeath(mCb);
mH4 = std::make_shared<H4Protocol>(
mFd,
[](const std::vector<uint8_t>& /* raw_command */) {
LOG_ALWAYS_FATAL("Unexpected command!");
},
[this](const std::vector<uint8_t>& raw_acl) {
mCb->aclDataReceived(raw_acl);
},
[this](const std::vector<uint8_t>& raw_sco) {
mCb->scoDataReceived(raw_sco);
},
[this](const std::vector<uint8_t>& raw_event) {
mCb->hciEventReceived(raw_event);
},
[this](const std::vector<uint8_t>& raw_iso) {
mCb->isoDataReceived(raw_iso);
},
[this]() {
ALOGI("HCI socket device disconnected");
mFdWatcher.StopWatchingFileDescriptors();
});
mFdWatcher.WatchFdForNonBlockingReads(mFd,
[this](int) { mH4->OnDataReady(); });
{
std::lock_guard<std::mutex> guard(mStateMutex);
mState = HalState::ONE_CLIENT;
}
ALOGI("initialization complete");
auto status = mCb->initializationComplete(Status::SUCCESS);
if (!status.isOk()) {
if (!mDeathRecipient->getHasDied()) {
ALOGE("Error sending init callback, but no death notification");
}
close();
return ndk::ScopedAStatus::fromServiceSpecificError(
STATUS_FAILED_TRANSACTION);
}
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus BluetoothHci::close() {
ALOGI(__func__);
{
std::lock_guard<std::mutex> guard(mStateMutex);
if (mState != HalState::ONE_CLIENT) {
LOG_ALWAYS_FATAL_IF(mState == HalState::INITIALIZING,
"mState is INITIALIZING");
ALOGI("Already closed");
return ndk::ScopedAStatus::ok();
}
mState = HalState::CLOSING;
}
mFdWatcher.StopWatchingFileDescriptors();
management_->closeHci();
{
std::lock_guard<std::mutex> guard(mStateMutex);
mState = HalState::READY;
mH4 = nullptr;
}
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus BluetoothHci::sendHciCommand(
const std::vector<uint8_t>& packet) {
return send(PacketType::COMMAND, packet);
}
ndk::ScopedAStatus BluetoothHci::sendAclData(
const std::vector<uint8_t>& packet) {
return send(PacketType::ACL_DATA, packet);
}
ndk::ScopedAStatus BluetoothHci::sendScoData(
const std::vector<uint8_t>& packet) {
return send(PacketType::SCO_DATA, packet);
}
ndk::ScopedAStatus BluetoothHci::sendIsoData(
const std::vector<uint8_t>& packet) {
return send(PacketType::ISO_DATA, packet);
}
ndk::ScopedAStatus BluetoothHci::send(PacketType type,
const std::vector<uint8_t>& v) {
if (v.empty()) {
ALOGE("Packet is empty, no data was found to be sent");
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
std::lock_guard<std::mutex> guard(mStateMutex);
if (mH4 == nullptr) {
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
mH4->Send(type, v);
return ndk::ScopedAStatus::ok();
}
} // namespace aidl::android::hardware::bluetooth::impl

75
bluetooth/BluetoothHci.h Normal file
View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2022 The Android Open Source Project
* Copyright (C) 2024 KonstaKANG
*
* 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/hardware/bluetooth/BnBluetoothHci.h>
#include <aidl/android/hardware/bluetooth/IBluetoothHciCallbacks.h>
#include "async_fd_watcher.h"
#include "h4_protocol.h"
#include "net_bluetooth_mgmt.h"
namespace aidl::android::hardware::bluetooth::impl {
class BluetoothDeathRecipient;
// This Bluetooth HAL implementation connects with a serial port at dev_path_.
class BluetoothHci : public BnBluetoothHci {
public:
BluetoothHci();
ndk::ScopedAStatus initialize(
const std::shared_ptr<IBluetoothHciCallbacks>& cb) override;
ndk::ScopedAStatus sendHciCommand(
const std::vector<uint8_t>& packet) override;
ndk::ScopedAStatus sendAclData(const std::vector<uint8_t>& packet) override;
ndk::ScopedAStatus sendScoData(const std::vector<uint8_t>& packet) override;
ndk::ScopedAStatus sendIsoData(const std::vector<uint8_t>& packet) override;
ndk::ScopedAStatus close() override;
private:
int mFd{-1};
std::shared_ptr<IBluetoothHciCallbacks> mCb = nullptr;
std::shared_ptr<::android::hardware::bluetooth::hci::H4Protocol> mH4;
std::shared_ptr<BluetoothDeathRecipient> mDeathRecipient;
::android::hardware::bluetooth::async::AsyncFdWatcher mFdWatcher;
[[nodiscard]] ndk::ScopedAStatus send(
::android::hardware::bluetooth::hci::PacketType type,
const std::vector<uint8_t>& packet);
std::unique_ptr<NetBluetoothMgmt> management_{};
// Don't close twice or open before close is complete
std::mutex mStateMutex;
enum class HalState {
READY,
INITIALIZING,
ONE_CLIENT,
CLOSING,
} mState{HalState::READY};
};
} // namespace aidl::android::hardware::bluetooth::impl

View File

@@ -0,0 +1,6 @@
service vendor.bluetooth-default /vendor/bin/hw/android.hardware.bluetooth-service.rpi
class hal
capabilities BLOCK_SUSPEND NET_ADMIN SYS_NICE
user bluetooth
group bluetooth
task_profiles HighPerformance

View File

@@ -0,0 +1,6 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.bluetooth</name>
<fqname>IBluetoothHci/default</fqname>
</hal>
</manifest>

View File

@@ -0,0 +1,278 @@
/*
* Copyright (C) 2022 The Android Open Source Project
* Copyright (C) 2024 KonstaKANG
*
* 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 "android.hardware.bluetooth.service.rpi"
#include "net_bluetooth_mgmt.h"
#include <fcntl.h>
#include <log/log.h>
#include <poll.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cerrno>
#include <cstdint>
#include <cstdlib>
#include <cstring>
// Definitions imported from <linux/net/bluetooth/bluetooth.h>
#define BTPROTO_HCI 1
// Definitions imported from <linux/net/bluetooth/hci_sock.h>
#define HCI_CHANNEL_USER 1
#define HCI_CHANNEL_CONTROL 3
#define HCI_DEV_NONE 0xffff
struct sockaddr_hci {
sa_family_t hci_family;
unsigned short hci_dev;
unsigned short hci_channel;
};
// Definitions imported from <linux/net/bluetooth/mgmt.h>
#define MGMT_OP_READ_INDEX_LIST 0x0003
#define MGMT_EV_INDEX_ADDED 0x0004
#define MGMT_EV_CMD_COMPLETE 0x0001
#define MGMT_PKT_SIZE_MAX 1024
#define MGMT_INDEX_NONE 0xFFFF
#define WRITE_NO_INTR(fn) \
do { \
} while ((fn) == -1 && errno == EINTR)
struct mgmt_pkt {
uint16_t opcode;
uint16_t index;
uint16_t len;
uint8_t data[MGMT_PKT_SIZE_MAX];
} __attribute__((packed));
struct mgmt_ev_read_index_list {
uint16_t opcode;
uint8_t status;
uint16_t num_controllers;
uint16_t index[];
} __attribute__((packed));
namespace aidl::android::hardware::bluetooth::impl {
// Wait indefinitely for the selected HCI interface to be enabled in the
// bluetooth driver.
int NetBluetoothMgmt::waitHciDev(int hci_interface) {
ALOGI("waiting for hci interface %d", hci_interface);
int ret = -1;
struct mgmt_pkt cmd;
struct pollfd pollfd;
struct sockaddr_hci hci_addr = {
.hci_family = AF_BLUETOOTH,
.hci_dev = HCI_DEV_NONE,
.hci_channel = HCI_CHANNEL_CONTROL,
};
// Open and bind a socket to the bluetooth control interface in the
// kernel driver, used to send control commands and receive control
// events.
int fd = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
if (fd < 0) {
ALOGE("unable to open raw bluetooth socket: %s", strerror(errno));
return -1;
}
if (bind(fd, (struct sockaddr*)&hci_addr, sizeof(hci_addr)) < 0) {
ALOGE("unable to bind bluetooth control channel: %s", strerror(errno));
goto end;
}
// Send the control command [Read Index List].
cmd = {
.opcode = MGMT_OP_READ_INDEX_LIST,
.index = MGMT_INDEX_NONE,
.len = 0,
};
if (write(fd, &cmd, 6) != 6) {
ALOGE("error writing mgmt command: %s", strerror(errno));
goto end;
}
// Poll the control socket waiting for the command response,
// and subsequent [Index Added] events. The loops continue without
// timeout until the selected hci interface is detected.
pollfd = {.fd = fd, .events = POLLIN};
for (;;) {
ret = poll(&pollfd, 1, -1);
// Poll interrupted, try again.
if (ret == -1 && (errno == EINTR || errno == EAGAIN)) {
continue;
}
// Poll failure, abandon.
if (ret == -1) {
ALOGE("poll error: %s", strerror(errno));
break;
}
// Spurious wakeup, try again.
if (ret == 0 || (pollfd.revents & POLLIN) == 0) {
continue;
}
// Read the next control event.
struct mgmt_pkt ev {};
ret = read(fd, &ev, sizeof(ev));
if (ret < 0) {
ALOGE("error reading mgmt event: %s", strerror(errno));
goto end;
}
// Received [Read Index List] command response.
if (ev.opcode == MGMT_EV_CMD_COMPLETE) {
struct mgmt_ev_read_index_list* data =
(struct mgmt_ev_read_index_list*)ev.data;
// Prefer the exact hci_interface
for (int i = 0; i < data->num_controllers; i++) {
if (data->index[i] == hci_interface) {
ALOGI("hci interface %d found", data->index[i]);
ret = data->index[i];
goto end;
}
}
// Accept a larger one if we can't find the exact one
for (int i = 0; i < data->num_controllers; i++) {
if (data->index[i] >= hci_interface) {
ALOGI("hci interface %d found", data->index[i]);
ret = data->index[i];
goto end;
}
}
}
// Received [Index Added] event.
if (ev.opcode == MGMT_EV_INDEX_ADDED && ev.index == hci_interface) {
ALOGI("hci interface %d added", hci_interface);
ret = hci_interface;
goto end;
}
}
end:
::close(fd);
return ret;
}
int NetBluetoothMgmt::findRfKill() {
char rfkill_type[64];
char type[16];
int fd, size, i;
for(i = 0; rfkill_state_ == NULL; i++)
{
snprintf(rfkill_type, sizeof(rfkill_type), "/sys/class/rfkill/rfkill%d/type", i);
if ((fd = open(rfkill_type, O_RDONLY)) < 0)
{
ALOGE("open(%s) failed: %s (%d)\n", rfkill_type, strerror(errno), errno);
return -1;
}
size = read(fd, &type, sizeof(type));
::close(fd);
if ((size >= 9) && !memcmp(type, "bluetooth", 9))
{
::asprintf(&rfkill_state_, "/sys/class/rfkill/rfkill%d/state", i);
break;
}
}
return 0;
}
int NetBluetoothMgmt::rfKill(int block) {
int fd;
char on = (block)?'1':'0';
if (findRfKill() != 0) return 0;
fd = open(rfkill_state_, O_WRONLY);
if (fd < 0) {
ALOGE( "Unable to open /dev/rfkill");
return -1;
}
ssize_t len;
WRITE_NO_INTR(len = write(fd, &on, 1));
if (len < 0) {
ALOGE( "Failed to change rfkill state");
::close(fd);
return -1;
}
::close(fd);
return 0;
}
int NetBluetoothMgmt::openHci(int hci_interface) {
ALOGI("opening hci interface %d", hci_interface);
// Block Bluetooth.
rfkill_state_ = NULL;
rfKill(1);
// Wait for the HCI interface to complete initialization or to come online.
int hci = waitHciDev(hci_interface);
if (hci < 0) {
ALOGE("hci interface %d not found", hci_interface);
return -1;
}
// Open the raw HCI socket.
int fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
if (fd < 0) {
ALOGE("unable to open raw bluetooth socket: %s", strerror(errno));
return -1;
}
struct sockaddr_hci hci_addr = {
.hci_family = AF_BLUETOOTH,
.hci_dev = static_cast<uint16_t>(hci),
.hci_channel = HCI_CHANNEL_USER,
};
// Bind the socket to the selected interface.
if (bind(fd, (struct sockaddr*)&hci_addr, sizeof(hci_addr)) < 0) {
ALOGE("unable to bind bluetooth user channel: %s", strerror(errno));
::close(fd);
return -1;
}
ALOGI("hci interface %d ready", hci);
bt_fd_ = fd;
return fd;
}
void NetBluetoothMgmt::closeHci() {
if (bt_fd_ != -1) {
::close(bt_fd_);
bt_fd_ = -1;
}
// Unblock Bluetooth.
rfKill(0);
free(rfkill_state_);
}
} // namespace aidl::android::hardware::bluetooth::impl

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2022 The Android Open Source Project
* Copyright (C) 2024 KonstaKANG
*
* 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 <unistd.h>
namespace aidl::android::hardware::bluetooth::impl {
class NetBluetoothMgmt {
public:
NetBluetoothMgmt() {}
~NetBluetoothMgmt() {
::close(bt_fd_);
}
int openHci(int hci_interface = 0);
void closeHci();
private:
int waitHciDev(int hci_interface);
int findRfKill();
int rfKill(int block);
char *rfkill_state_;
// File descriptor opened to the bluetooth user channel.
int bt_fd_{-1};
};
} // namespace aidl::android::hardware::bluetooth::impl

50
bluetooth/service.cpp Normal file
View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2022 The Android Open Source Project
* Copyright (C) 2024 KonstaKANG
*
* 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 "aidl.android.hardware.bluetooth.service.rpi"
#include <aidl/android/hardware/bluetooth/IBluetoothHci.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <hidl/HidlSupport.h>
#include <hidl/HidlTransportSupport.h>
#include "BluetoothHci.h"
using ::aidl::android::hardware::bluetooth::impl::BluetoothHci;
using ::android::hardware::configureRpcThreadpool;
using ::android::hardware::joinRpcThreadpool;
int main(int /* argc */, char** /* argv */) {
ALOGI("Bluetooth HAL starting");
if (!ABinderProcess_setThreadPoolMaxThreadCount(0)) {
ALOGI("failed to set thread pool max thread count");
return 1;
}
std::shared_ptr<BluetoothHci> service =
ndk::SharedRefBase::make<BluetoothHci>();
std::string instance = std::string() + BluetoothHci::descriptor + "/default";
auto result =
AServiceManager_addService(service->asBinder().get(), instance.c_str());
if (result == STATUS_OK) {
ABinderProcess_joinThreadPool();
} else {
ALOGE("Could not register as a service!");
}
return 0;
}

View File

@@ -8,6 +8,9 @@ cameras:
"/base/soc/i2c0mux/i2c@1/imx477@1a":
location: back
rotation: 0
"/base/soc/i2c0mux/i2c@1/imx500@1a":
location: back
rotation: 0
"/base/soc/i2c0mux/i2c@1/imx708@1a":
location: back
rotation: 0

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 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.
-->
<!--
Defines the audio configuration in a car, including
- Audio zones
- Zone configurations (in each audio zone)
- Volume groups (in each zone configuration)
- Context to audio bus mappings (in each volume group)
in the car environment.
-->
<carAudioConfiguration version="3">
<zones>
<zone name="Primary zone" isPrimary="true" occupantZoneId="0">
<zoneConfigs>
<zoneConfig name="Config 0" isDefault="true">
<volumeGroups>
<group>
<device address="Speaker">
<context context="music"/>
<context context="navigation"/>
<context context="voice_command"/>
<context context="call_ring"/>
<context context="call"/>
<context context="alarm"/>
<context context="notification"/>
<context context="system_sound"/>
<context context="emergency"/>
<context context="safety"/>
<context context="vehicle_status"/>
<context context="announcement"/>
</device>
</group>
</volumeGroups>
</zoneConfig>
</zoneConfigs>
</zone>
</zones>
</carAudioConfiguration>

8
car/display_settings.xml Normal file
View File

@@ -0,0 +1,8 @@
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<display-settings>
<!-- Use physical port number instead of local id -->
<config identifier="1" />
<!-- Display settings for cluster -->
<display name="port:1" dontMoveToTop="true" />
</display-settings>

View File

@@ -462,7 +462,8 @@ static int hdmicec_close(struct hdmi_cec_device *dev)
if (ctx->exit_fd > 0) {
write(ctx->exit_fd, &tmp, sizeof(tmp));
pthread_join(ctx->thread, NULL);
if (ctx->thread)
pthread_join(ctx->thread, NULL);
}
if (ctx->cec_fd > 0)
@@ -470,9 +471,6 @@ static int hdmicec_close(struct hdmi_cec_device *dev)
if (ctx->exit_fd > 0)
close(ctx->exit_fd);
free(ctx);
ctx->cec_enabled = false;
ctx->cec_control_enabled = false;
return 0;
}

View File

@@ -74,7 +74,7 @@ PRODUCT_COPY_FILES += \
# Bluetooth
PRODUCT_PACKAGES += \
android.hardware.bluetooth@1.1-service.btlinux
android.hardware.bluetooth-service.rpi
PRODUCT_COPY_FILES += \
frameworks/native/data/etc/android.hardware.bluetooth.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.bluetooth.xml \
@@ -115,6 +115,7 @@ PRODUCT_COPY_FILES += \
external/libcamera/src/ipa/rpi/vc4/data/imx477.json:$(TARGET_COPY_OUT_VENDOR)/etc/libcamera/ipa/rpi/vc4/imx477.json \
external/libcamera/src/ipa/rpi/vc4/data/imx477_noir.json:$(TARGET_COPY_OUT_VENDOR)/etc/libcamera/ipa/rpi/vc4/imx477_noir.json \
external/libcamera/src/ipa/rpi/vc4/data/imx477_scientific.json:$(TARGET_COPY_OUT_VENDOR)/etc/libcamera/ipa/rpi/vc4/imx477_scientific.json \
external/libcamera/src/ipa/rpi/vc4/data/imx500.json:$(TARGET_COPY_OUT_VENDOR)/etc/libcamera/ipa/rpi/vc4/imx500.json \
external/libcamera/src/ipa/rpi/vc4/data/imx708.json:$(TARGET_COPY_OUT_VENDOR)/etc/libcamera/ipa/rpi/vc4/imx708.json \
external/libcamera/src/ipa/rpi/vc4/data/imx708_noir.json:$(TARGET_COPY_OUT_VENDOR)/etc/libcamera/ipa/rpi/vc4/imx708_noir.json \
external/libcamera/src/ipa/rpi/vc4/data/imx708_wide.json:$(TARGET_COPY_OUT_VENDOR)/etc/libcamera/ipa/rpi/vc4/imx708_wide.json \
@@ -172,8 +173,7 @@ PRODUCT_PACKAGES += \
libgbm_mesa_wrapper
PRODUCT_PACKAGES += \
android.hardware.graphics.composer@2.4-service \
hwcomposer.drm
android.hardware.composer.hwc3-service.drm
PRODUCT_PACKAGES += \
libEGL_mesa \
@@ -182,16 +182,20 @@ PRODUCT_PACKAGES += \
libgallium_dri \
libglapi
PRODUCT_PACKAGES += \
dri_gbm \
libgbm_mesa
PRODUCT_COPY_FILES += \
frameworks/native/data/etc/android.software.opengles.deqp.level-2023-03-01.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.opengles.deqp.level.xml
frameworks/native/data/etc/android.software.opengles.deqp.level-2024-03-01.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.opengles.deqp.level.xml
PRODUCT_PACKAGES += \
vulkan.broadcom
PRODUCT_COPY_FILES += \
$(DEVICE_PATH)/vulkan/android.hardware.vulkan.version-1_2.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.version.xml \
frameworks/native/data/etc/android.hardware.vulkan.level-0.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.level.xml \
frameworks/native/data/etc/android.software.vulkan.deqp.level-2023-03-01.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.vulkan.deqp.level.xml
frameworks/native/data/etc/android.hardware.vulkan.version-1_3.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.version.xml \
frameworks/native/data/etc/android.software.vulkan.deqp.level-2024-03-01.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.vulkan.deqp.level.xml
# Health
PRODUCT_PACKAGES += \
@@ -234,7 +238,7 @@ PRODUCT_COPY_FILES += \
# Seccomp
PRODUCT_COPY_FILES += \
$(DEVICE_PATH)/seccomp_policy/codec2.vendor.ext.policy:$(TARGET_COPY_OUT_VENDOR)/etc/seccomp_policy/codec2.vendor.ext.policy \
$(DEVICE_PATH)/seccomp_policy/android.hardware.media.c2-extended-seccomp_policy:$(TARGET_COPY_OUT_VENDOR)/etc/seccomp_policy/android.hardware.media.c2-extended-seccomp_policy \
$(DEVICE_PATH)/seccomp_policy/mediacodec.policy:$(TARGET_COPY_OUT_VENDOR)/etc/seccomp_policy/mediacodec.policy \
$(DEVICE_PATH)/seccomp_policy/mediaswcodec.policy:$(TARGET_COPY_OUT_VENDOR)/etc/seccomp_policy/mediaswcodec.policy
@@ -247,12 +251,12 @@ PRODUCT_PACKAGES += \
# Thermal
PRODUCT_PACKAGES += \
android.hardware.thermal-service.example
com.android.hardware.thermal
# USB
PRODUCT_PACKAGES += \
android.hardware.usb-service.example \
android.hardware.usb.gadget@1.2-service.rpi
android.hardware.usb.gadget-service.rpi
PRODUCT_COPY_FILES += \
frameworks/native/data/etc/android.hardware.usb.accessory.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.usb.accessory.xml \
@@ -263,7 +267,7 @@ PRODUCT_COPY_FILES += \
PRODUCT_SOONG_NAMESPACES += external/v4l2_codec2
PRODUCT_PACKAGES += \
android.hardware.media.c2@1.0-service-v4l2 \
android.hardware.media.c2@1.2-service-v4l2 \
libc2plugin_store
PRODUCT_COPY_FILES += \

View File

@@ -2,7 +2,7 @@
<hal format="hidl" optional="true">
<name>android.hardware.media.c2</name>
<transport>hwbinder</transport>
<version>1.0-2</version>
<version>1.2</version>
<interface>
<name>IComponentStore</name>
<instance>ffmpeg</instance>

View File

@@ -26,7 +26,7 @@ cc_binary {
"libhidlbase",
"liblog",
"libutils",
"android.hardware.health-V2-ndk",
"android.hardware.health-V3-ndk",
],
overrides: ["charger"],
}

View File

@@ -1,7 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.health</name>
<version>2</version>
<version>3</version>
<fqname>IHealth/default</fqname>
</hal>
</manifest>

View File

@@ -324,7 +324,7 @@ key 362 GUIDE
# key 365 "KEY_EPG"
key 366 DVR
# key 367 "KEY_MHP"
# key 368 "KEY_LANGUAGE"
key 368 LANGUAGE_SWITCH
# key 369 "KEY_TITLE"
key 370 CAPTIONS
# key 371 "KEY_ANGLE"
@@ -424,6 +424,7 @@ key 580 APP_SWITCH
key 582 VOICE_ASSIST
# Linux KEY_ASSISTANT
key 583 ASSIST
key 585 EMOJI_PICKER
key 656 MACRO_1
key 657 MACRO_2
key 658 MACRO_3
@@ -436,17 +437,24 @@ key 141 POWER
key 174 BACK
# Keys defined by HID usages
key usage 0x0c0067 WINDOW
key usage 0x0c006F BRIGHTNESS_UP
key usage 0x0c0070 BRIGHTNESS_DOWN
key usage 0x0c0079 KEYBOARD_BACKLIGHT_UP
key usage 0x0c007A KEYBOARD_BACKLIGHT_DOWN
key usage 0x0c007C KEYBOARD_BACKLIGHT_TOGGLE
key usage 0x0c0173 MEDIA_AUDIO_TRACK
key usage 0x0c019C PROFILE_SWITCH
key usage 0x0c01A2 ALL_APPS
key usage 0x0d0044 STYLUS_BUTTON_PRIMARY
key usage 0x0d005a STYLUS_BUTTON_SECONDARY
key usage 0x0c0065 SCREENSHOT FALLBACK_USAGE_MAPPING
key usage 0x0c0067 WINDOW FALLBACK_USAGE_MAPPING
key usage 0x0c006F BRIGHTNESS_UP FALLBACK_USAGE_MAPPING
key usage 0x0c0070 BRIGHTNESS_DOWN FALLBACK_USAGE_MAPPING
key usage 0x0c0079 KEYBOARD_BACKLIGHT_UP FALLBACK_USAGE_MAPPING
key usage 0x0c007A KEYBOARD_BACKLIGHT_DOWN FALLBACK_USAGE_MAPPING
key usage 0x0c007C KEYBOARD_BACKLIGHT_TOGGLE FALLBACK_USAGE_MAPPING
key usage 0x0c00D9 EMOJI_PICKER FALLBACK_USAGE_MAPPING
key usage 0x0c0173 MEDIA_AUDIO_TRACK FALLBACK_USAGE_MAPPING
key usage 0x0c019C PROFILE_SWITCH FALLBACK_USAGE_MAPPING
key usage 0x0c019F SETTINGS FALLBACK_USAGE_MAPPING
key usage 0x0c01A2 ALL_APPS FALLBACK_USAGE_MAPPING
key usage 0x0c0227 REFRESH FALLBACK_USAGE_MAPPING
key usage 0x0c029D LANGUAGE_SWITCH FALLBACK_USAGE_MAPPING
key usage 0x0c029F RECENT_APPS FALLBACK_USAGE_MAPPING
key usage 0x0c02A2 ALL_APPS FALLBACK_USAGE_MAPPING
key usage 0x0d0044 STYLUS_BUTTON_PRIMARY FALLBACK_USAGE_MAPPING
key usage 0x0d005a STYLUS_BUTTON_SECONDARY FALLBACK_USAGE_MAPPING
# Joystick and game controller axes.
# Axes that are not mapped will be assigned generic axis numbers by the input subsystem.

View File

@@ -17,15 +17,6 @@
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>android.hardware.bluetooth</name>
<transport>hwbinder</transport>
<version>1.1</version>
<interface>
<name>IBluetoothHci</name>
<instance>default</instance>
</interface>
</hal>
<hal format="aidl">
<name>android.hardware.camera.provider</name>
<version>1</version>
@@ -43,15 +34,6 @@
<instance>legacy/0</instance>
</interface>
</hal>
<hal format="hidl">
<name>android.hardware.graphics.composer</name>
<transport>hwbinder</transport>
<version>2.4</version>
<interface>
<name>IComposer</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>android.hardware.tv.cec</name>
<transport>hwbinder</transport>

View File

@@ -6,7 +6,7 @@
# SPDX-License-Identifier: Apache-2.0
#
VERSION=RaspberryVanillaAOSP14
VERSION=RaspberryVanillaAOSP15
DATE=$(date +%Y%m%d)
IMGNAME=${VERSION}-${DATE}-rpi4.img
IMGSIZE=7

View File

@@ -18,6 +18,39 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!--
Specifies configuration of displays in system telling its usage / type and assigned
occupant. DEFAULT_DISPLAY, if assigned here, should be always assigned to the DRIVER zone.
Some examples are:
<item>displayPort=0,displayType=MAIN,occupantZoneId=0,inputTypes=DPAD_KEYS|
NAVIGATE_KEYS|ROTARY_NAVIGATION</item>
<item>displayPort=1,displayType=INSTRUMENT_CLUSTER,occupantZoneId=0,
inputTypes=DPAD_KEYS</item>
<item>displayPort=2,displayType=MAIN,occupantZoneId=1,
inputTypes=TOUCH_SCREEN</item>
<item>displayPort=3,displayType=MAIN,occupantZoneId=2,
inputTypes=TOUCH_SCREEN</item>
<item>displayUniqueId=virtual:com.example:MainD,displayType=MAIN,occupantZoneId=3,
inputTypes=TOUCH_SCREEN</item>
NOTE: each item should have displayPort or displayUniqueId, if it has both, displayPort
will be used.
displayPort: Unique Port id for the physical display.
displayUniqueId: Unique Id for the display.
The unique id of the virtual display will be the form of 'virtual:<PACKAGE>:<ID>'.
displayType: Display type for the display. Use * part from
CarOccupantZoneManager.DISPLAY_TYPE_* like MAIN, INSTRUMENT_CLUSTER and
etc.
occupantZoneId: occupantZoneId specified from config_occupant_zones.
inputTypes: supported input types for the corresponding display.
-->
<string-array translatable="false" name="config_occupant_display_mapping">
<item>displayPort=0,displayType=MAIN,occupantZoneId=0,inputTypes=TOUCH_SCREEN|DPAD_KEYS|NAVIGATE_KEYS|ROTARY_NAVIGATION</item>
<item>displayPort=1,displayType=INSTRUMENT_CLUSTER,occupantZoneId=0,inputTypes=DPAD_KEYS</item>
</string-array>
<!-- Specifies notice UI that will be launched when user starts a car or do user
switching. It is recommended to use dialog with at least TYPE_APPLICATION_OVERLAY window
type to show the UI regardless of activity launches. Target package will be auto-granted

View File

@@ -20,7 +20,7 @@
<!-- The default tiles to display in QuickSettings -->
<string name="quick_settings_tiles_default" translatable="false">
internet,bt,airplane,hotspot,dark,screenrecord
internet,bt,airplane,hotspot,dark,screenrecord,custom(com.android.permissioncontroller/.permission.service.v33.SafetyCenterQsTileService)
</string>
</resources>

View File

@@ -12,9 +12,6 @@ on post-fs-data
mkdir /data/vendor/wifi/wpa 0770 wifi wifi
mkdir /data/vendor/wifi/wpa/sockets 0770 wifi wifi
# Set indication (checked by vold) that we have finished this action
setprop vold.post_fs_data_done 1
on property:sys.boot_completed=1
# Reinit lmkd to reconfigure lmkd properties
setprop lmkd.reinit 1

View File

@@ -9,7 +9,9 @@ fstatat64: 1
fstatfs64: 1
getcwd: 1
getdents64: 1
getegid32: 1
geteuid32: 1
getgid32: 1
getuid32: 1
mmap2: 1
open: 1

View File

@@ -1,5 +1,6 @@
# Bluetooth
/sys/class/rfkill/rfkill[0-9]/state u:object_r:sysfs_bluetooth_writable:s0
/vendor/bin/hw/android\.hardware\.bluetooth-service\.rpi u:object_r:hal_bluetooth_default_exec:s0
# CEC
/dev/cec0 u:object_r:cec_device:s0
@@ -20,11 +21,13 @@
/dev/dri/card0 u:object_r:gpu_device:s0
/dev/dri/card1 u:object_r:gpu_device:s0
/dev/dri/renderD128 u:object_r:gpu_device:s0
/vendor/bin/hw/android\.hardware\.composer\.hwc3-service\.drm u:object_r:hal_graphics_composer_default_exec:s0
/vendor/bin/hw/android\.hardware\.graphics\.allocator@4\.0-service\.minigbm_gbm_mesa u:object_r:hal_graphics_allocator_default_exec:s0
/vendor/lib(64)?/dri/libgallium_dri\.so u:object_r:same_process_hal_file:s0
/vendor/lib(64)?/hw/android\.hardware\.graphics.mapper@4\.0-impl\.minigbm_gbm_mesa\.so u:object_r:same_process_hal_file:s0
/vendor/lib(64)?/hw/vulkan\.broadcom\.so u:object_r:same_process_hal_file:s0
/vendor/lib(64)?/dri_gbm\.so u:object_r:same_process_hal_file:s0
/vendor/lib(64)?/libdrm\.so u:object_r:same_process_hal_file:s0
/vendor/lib(64)?/libgallium_dri\.so u:object_r:same_process_hal_file:s0
/vendor/lib(64)?/libgbm_mesa\.so u:object_r:same_process_hal_file:s0
/vendor/lib{64}?/libgbm_mesa_wrapper\.so u:object_r:same_process_hal_file:s0
/vendor/lib(64)?/libglapi\.so u:object_r:same_process_hal_file:s0
@@ -48,7 +51,7 @@
/vendor/bin/suspend_blocker_rpi u:object_r:suspend_blocker_exec:s0
# USB
/vendor/bin/hw/android\.hardware\.usb\.gadget@1\.2-service\.rpi u:object_r:hal_usb_gadget_default_exec:s0
/vendor/bin/hw/android\.hardware\.usb\.gadget-service\.rpi u:object_r:hal_usb_gadget_default_exec:s0
# V4L2
/vendor/bin/hw/android\.hardware\.media\.c2@1\.0-service-v4l2(.*)? u:object_r:mediacodec_exec:s0
/vendor/bin/hw/android\.hardware\.media\.c2@1\.2-service-v4l2(.*)? u:object_r:mediacodec_exec:s0

View File

@@ -1,23 +1,22 @@
// Copyright (C) 2020 The Android Open Source Project
// Copyright (C) 2023 KonstaKANG
// Copyright (C) 2024 KonstaKANG
//
// SPDX-License-Identifier: Apache-2.0
cc_binary {
name: "android.hardware.usb.gadget@1.2-service.rpi",
name: "android.hardware.usb.gadget-service.rpi",
defaults: ["hidl_defaults"],
relative_install_path: "hw",
init_rc: ["android.hardware.usb.gadget@1.2-service.rpi.rc"],
vintf_fragments: ["android.hardware.usb.gadget@1.2-service.rpi.xml"],
init_rc: ["android.hardware.usb.gadget-service.rpi.rc"],
vintf_fragments: ["android.hardware.usb.gadget-service.rpi.xml"],
vendor: true,
srcs: [
"service.cpp",
"UsbGadget.cpp",
],
shared_libs: [
"android.hardware.usb.gadget@1.0",
"android.hardware.usb.gadget@1.1",
"android.hardware.usb.gadget@1.2",
"android.hardware.usb.gadget-V1-ndk",
"libbinder_ndk",
"libbase",
"libcutils",
"libhardware",
@@ -25,5 +24,5 @@ cc_binary {
"liblog",
"libutils",
],
static_libs: ["libusbconfigfs-2"],
static_libs: ["libusbconfigfs-rpi"],
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2020 The Android Open Source Project
* Copyright (C) 2023 KonstaKANG
* Copyright (C) 2024 KonstaKANG
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
* limitations under the License.
*/
#define LOG_TAG "android.hardware.usb.gadget@1.2-service.rpi"
#define LOG_TAG "android.hardware.usb.gadget-service.rpi"
#include "UsbGadget.h"
#include <dirent.h>
@@ -27,12 +27,11 @@
#include <sys/types.h>
#include <unistd.h>
namespace aidl {
namespace android {
namespace hardware {
namespace usb {
namespace gadget {
namespace V1_2 {
namespace implementation {
UsbGadget::UsbGadget() {
if (access(OS_DESC_PATH, R_OK) != 0) {
@@ -46,16 +45,24 @@ void currentFunctionsAppliedCallback(bool functionsApplied, void* payload) {
gadget->mCurrentUsbFunctionsApplied = functionsApplied;
}
Return<void> UsbGadget::getCurrentUsbFunctions(const sp<V1_0::IUsbGadgetCallback>& callback) {
Return<void> ret = callback->getCurrentUsbFunctionsCb(
mCurrentUsbFunctions, mCurrentUsbFunctionsApplied ? Status::FUNCTIONS_APPLIED
: Status::FUNCTIONS_NOT_APPLIED);
if (!ret.isOk()) ALOGE("Call to getCurrentUsbFunctionsCb failed %s", ret.description().c_str());
ScopedAStatus UsbGadget::getCurrentUsbFunctions(const shared_ptr<IUsbGadgetCallback>& callback,
int64_t in_transactionId) {
if (callback == nullptr) {
return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
}
return Void();
ScopedAStatus ret = callback->getCurrentUsbFunctionsCb(
mCurrentUsbFunctions,
mCurrentUsbFunctionsApplied ? Status::FUNCTIONS_APPLIED : Status::FUNCTIONS_NOT_APPLIED,
in_transactionId);
if (!ret.isOk())
ALOGE("Call to getCurrentUsbFunctionsCb failed %s", ret.getDescription().c_str());
return ScopedAStatus::ok();
}
Return<void> UsbGadget::getUsbSpeed(const sp<V1_2::IUsbGadgetCallback>& callback) {
ScopedAStatus UsbGadget::getUsbSpeed(const shared_ptr<IUsbGadgetCallback> &callback,
int64_t in_transactionId) {
std::string current_speed;
if (ReadFileToString(SPEED_PATH, &current_speed)) {
current_speed = Trim(current_speed);
@@ -72,144 +79,150 @@ Return<void> UsbGadget::getUsbSpeed(const sp<V1_2::IUsbGadgetCallback>& callback
mUsbSpeed = UsbSpeed::SUPERSPEED_10Gb;
else if (current_speed == "UNKNOWN")
mUsbSpeed = UsbSpeed::UNKNOWN;
else {
/**
* This part is used for USB4 or reserved speed.
*
* If reserved speed is detected, it needs to convert to other speeds.
* For example:
* If the bandwidth of new speed is 7G, adding new if
* statement and set mUsbSpeed to SUPERSPEED.
* If the bandwidth of new speed is 80G, adding new if
* statement and set mUsbSpeed to USB4_GEN3_40Gb.
*/
mUsbSpeed = UsbSpeed::RESERVED_SPEED;
}
else
mUsbSpeed = UsbSpeed::UNKNOWN;
} else {
ALOGE("Fail to read current speed");
mUsbSpeed = UsbSpeed::UNKNOWN;
}
if (callback) {
Return<void> ret = callback->getUsbSpeedCb(mUsbSpeed);
ScopedAStatus ret = callback->getUsbSpeedCb(mUsbSpeed, in_transactionId);
if (!ret.isOk()) ALOGE("Call to getUsbSpeedCb failed %s", ret.description().c_str());
if (!ret.isOk())
ALOGE("Call to getUsbSpeedCb failed %s", ret.getDescription().c_str());
}
return Void();
return ScopedAStatus::ok();
}
V1_0::Status UsbGadget::tearDownGadget() {
if (resetGadget() != V1_0::Status::SUCCESS) return V1_0::Status::ERROR;
Status UsbGadget::tearDownGadget() {
if (resetGadget() != Status::SUCCESS) return Status::ERROR;
if (monitorFfs.isMonitorRunning()) {
monitorFfs.reset();
} else {
ALOGI("mMonitor not running");
}
return V1_0::Status::SUCCESS;
return Status::SUCCESS;
}
Return<Status> UsbGadget::reset() {
ScopedAStatus UsbGadget::reset(const shared_ptr<IUsbGadgetCallback> &callback,
int64_t in_transactionId) {
if (!WriteStringToFile("none", PULLUP_PATH)) {
ALOGI("Gadget cannot be pulled down");
return Status::ERROR;
if (callback)
callback->resetCb(Status::ERROR, in_transactionId);
return ScopedAStatus::fromServiceSpecificErrorWithMessage(
-1, "Error while calling resetCb");
}
usleep(kDisconnectWaitUs);
if (!WriteStringToFile(kGadgetName, PULLUP_PATH)) {
ALOGI("Gadget cannot be pulled up");
return Status::ERROR;
if (callback)
callback->resetCb(Status::ERROR, in_transactionId);
return ScopedAStatus::fromServiceSpecificErrorWithMessage(
-1, "Error while calling resetCb");
}
return Status::SUCCESS;
if (callback)
callback->resetCb(Status::SUCCESS, in_transactionId);
return ScopedAStatus::ok();
}
static V1_0::Status validateAndSetVidPid(uint64_t functions) {
V1_0::Status ret = V1_0::Status::SUCCESS;
static Status validateAndSetVidPid(uint64_t functions) {
Status ret = Status::SUCCESS;
switch (functions) {
case static_cast<uint64_t>(V1_2::GadgetFunction::MTP):
case GadgetFunction::MTP:
ret = setVidPid("0x18d1", "0x4ee1");
break;
case V1_2::GadgetFunction::ADB | V1_2::GadgetFunction::MTP:
case GadgetFunction::ADB | GadgetFunction::MTP:
ret = setVidPid("0x18d1", "0x4ee2");
break;
case static_cast<uint64_t>(V1_2::GadgetFunction::RNDIS):
case GadgetFunction::RNDIS:
ret = setVidPid("0x18d1", "0x4ee3");
break;
case V1_2::GadgetFunction::ADB | V1_2::GadgetFunction::RNDIS:
case GadgetFunction::ADB | GadgetFunction::RNDIS:
ret = setVidPid("0x18d1", "0x4ee4");
break;
case static_cast<uint64_t>(V1_2::GadgetFunction::PTP):
case GadgetFunction::PTP:
ret = setVidPid("0x18d1", "0x4ee5");
break;
case V1_2::GadgetFunction::ADB | V1_2::GadgetFunction::PTP:
case GadgetFunction::ADB | GadgetFunction::PTP:
ret = setVidPid("0x18d1", "0x4ee6");
break;
case static_cast<uint64_t>(V1_2::GadgetFunction::ADB):
case GadgetFunction::ADB:
ret = setVidPid("0x18d1", "0x4ee7");
break;
case static_cast<uint64_t>(V1_2::GadgetFunction::MIDI):
case GadgetFunction::MIDI:
ret = setVidPid("0x18d1", "0x4ee8");
break;
case V1_2::GadgetFunction::ADB | V1_2::GadgetFunction::MIDI:
case GadgetFunction::ADB | GadgetFunction::MIDI:
ret = setVidPid("0x18d1", "0x4ee9");
break;
case static_cast<uint64_t>(V1_2::GadgetFunction::NCM):
case GadgetFunction::NCM:
ret = setVidPid("0x18d1", "0x4eeb");
break;
case V1_2::GadgetFunction::ADB | V1_2::GadgetFunction::NCM:
case GadgetFunction::ADB | GadgetFunction::NCM:
ret = setVidPid("0x18d1", "0x4eec");
break;
case static_cast<uint64_t>(V1_2::GadgetFunction::ACCESSORY):
case GadgetFunction::ACCESSORY:
ret = setVidPid("0x18d1", "0x2d00");
break;
case V1_2::GadgetFunction::ADB | V1_2::GadgetFunction::ACCESSORY:
case GadgetFunction::ADB | GadgetFunction::ACCESSORY:
ret = setVidPid("0x18d1", "0x2d01");
break;
case static_cast<uint64_t>(V1_2::GadgetFunction::AUDIO_SOURCE):
case GadgetFunction::AUDIO_SOURCE:
ret = setVidPid("0x18d1", "0x2d02");
break;
case V1_2::GadgetFunction::ADB | V1_2::GadgetFunction::AUDIO_SOURCE:
case GadgetFunction::ADB | GadgetFunction::AUDIO_SOURCE:
ret = setVidPid("0x18d1", "0x2d03");
break;
case V1_2::GadgetFunction::ACCESSORY | V1_2::GadgetFunction::AUDIO_SOURCE:
case GadgetFunction::ACCESSORY | GadgetFunction::AUDIO_SOURCE:
ret = setVidPid("0x18d1", "0x2d04");
break;
case V1_2::GadgetFunction::ADB | V1_2::GadgetFunction::ACCESSORY |
V1_2::GadgetFunction::AUDIO_SOURCE:
case GadgetFunction::ADB | GadgetFunction::ACCESSORY |
GadgetFunction::AUDIO_SOURCE:
ret = setVidPid("0x18d1", "0x2d05");
break;
default:
ALOGE("Combination not supported");
ret = V1_0::Status::CONFIGURATION_NOT_SUPPORTED;
ret = Status::CONFIGURATION_NOT_SUPPORTED;
}
return ret;
}
V1_0::Status UsbGadget::setupFunctions(uint64_t functions,
const sp<V1_0::IUsbGadgetCallback>& callback,
uint64_t timeout) {
Status UsbGadget::setupFunctions(long functions,
const shared_ptr<IUsbGadgetCallback> &callback, uint64_t timeout,
int64_t in_transactionId) {
bool ffsEnabled = false;
int i = 0;
if (addGenericAndroidFunctions(&monitorFfs, functions, &ffsEnabled, &i) !=
V1_0::Status::SUCCESS)
return V1_0::Status::ERROR;
Status::SUCCESS)
return Status::ERROR;
if ((functions & V1_2::GadgetFunction::ADB) != 0) {
if ((functions & GadgetFunction::ADB) != 0) {
ffsEnabled = true;
if (addAdb(&monitorFfs, &i) != V1_0::Status::SUCCESS) return V1_0::Status::ERROR;
if (addAdb(&monitorFfs, &i) != Status::SUCCESS) return Status::ERROR;
}
// Pull up the gadget right away when there are no ffs functions.
if (!ffsEnabled) {
if (!WriteStringToFile(kGadgetName, PULLUP_PATH)) return V1_0::Status::ERROR;
if (!WriteStringToFile(kGadgetName, PULLUP_PATH))
return Status::ERROR;
mCurrentUsbFunctionsApplied = true;
if (callback) callback->setCurrentUsbFunctionsCb(functions, V1_0::Status::SUCCESS);
return V1_0::Status::SUCCESS;
if (callback)
callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS, in_transactionId);
return Status::SUCCESS;
}
monitorFfs.registerFunctionsAppliedCallback(&currentFunctionsAppliedCallback, this);
@@ -222,25 +235,28 @@ V1_0::Status UsbGadget::setupFunctions(uint64_t functions,
if (callback) {
bool pullup = monitorFfs.waitForPullUp(timeout);
Return<void> ret = callback->setCurrentUsbFunctionsCb(
functions, pullup ? V1_0::Status::SUCCESS : V1_0::Status::ERROR);
if (!ret.isOk()) ALOGE("setCurrentUsbFunctionsCb error %s", ret.description().c_str());
ScopedAStatus ret = callback->setCurrentUsbFunctionsCb(functions,
pullup ? Status::SUCCESS : Status::ERROR,
in_transactionId);
if (!ret.isOk())
ALOGE("setCurrentUsbFunctionsCb error %s", ret.getMessage());
}
return V1_0::Status::SUCCESS;
return Status::SUCCESS;
}
Return<void> UsbGadget::setCurrentUsbFunctions(uint64_t functions,
const sp<V1_0::IUsbGadgetCallback>& callback,
uint64_t timeout) {
ScopedAStatus UsbGadget::setCurrentUsbFunctions(int64_t functions,
const shared_ptr<IUsbGadgetCallback> &callback,
int64_t timeoutMs,
int64_t in_transactionId) {
std::unique_lock<std::mutex> lk(mLockSetCurrentFunction);
mCurrentUsbFunctions = functions;
mCurrentUsbFunctionsApplied = false;
// Unlink the gadget and stop the monitor if running.
V1_0::Status status = tearDownGadget();
if (status != V1_0::Status::SUCCESS) {
Status status = tearDownGadget();
if (status != Status::SUCCESS) {
goto error;
}
@@ -249,39 +265,45 @@ Return<void> UsbGadget::setCurrentUsbFunctions(uint64_t functions,
// Leave the gadget pulled down to give time for the host to sense disconnect.
usleep(kDisconnectWaitUs);
if (functions == static_cast<uint64_t>(V1_2::GadgetFunction::NONE)) {
if (callback == NULL) return Void();
Return<void> ret = callback->setCurrentUsbFunctionsCb(functions, V1_0::Status::SUCCESS);
if (functions == GadgetFunction::NONE) {
if (callback == NULL)
return ScopedAStatus::fromServiceSpecificErrorWithMessage(
-1, "callback == NULL");
ScopedAStatus ret = callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS, in_transactionId);
if (!ret.isOk())
ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.description().c_str());
return Void();
ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.getDescription().c_str());
return ScopedAStatus::fromServiceSpecificErrorWithMessage(
-1, "Error while calling setCurrentUsbFunctionsCb");
}
status = validateAndSetVidPid(functions);
if (status != V1_0::Status::SUCCESS) {
if (status != Status::SUCCESS) {
goto error;
}
status = setupFunctions(functions, callback, timeout);
if (status != V1_0::Status::SUCCESS) {
status = setupFunctions(functions, callback, timeoutMs, in_transactionId);
if (status != Status::SUCCESS) {
goto error;
}
ALOGI("Usb Gadget setcurrent functions called successfully");
return Void();
return ScopedAStatus::fromServiceSpecificErrorWithMessage(
-1, "Usb Gadget setcurrent functions called successfully");
error:
ALOGI("Usb Gadget setcurrent functions failed");
if (callback == NULL) return Void();
Return<void> ret = callback->setCurrentUsbFunctionsCb(functions, status);
if (callback == NULL)
return ScopedAStatus::fromServiceSpecificErrorWithMessage(
-1, "Usb Gadget setcurrent functions failed");
ScopedAStatus ret = callback->setCurrentUsbFunctionsCb(functions, status, in_transactionId);
if (!ret.isOk())
ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.description().c_str());
return Void();
ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.getDescription().c_str());
return ScopedAStatus::fromServiceSpecificErrorWithMessage(
-1, "Error while calling setCurrentUsbFunctionsCb");
}
} // namespace implementation
} // namespace V1_2
} // namespace gadget
} // namespace usb
} // namespace hardware
} // namespace android
} // aidl

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2020 The Android Open Source Project
* Copyright (C) 2023 KonstaKANG
* Copyright (C) 2024 KonstaKANG
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,18 +15,18 @@
* limitations under the License.
*/
#ifndef ANDROID_HARDWARE_USB_GADGET_V1_2_USBGADGET_H
#define ANDROID_HARDWARE_USB_GADGET_V1_2_USBGADGET_H
#pragma once
#include <UsbGadgetCommon.h>
#include <android-base/file.h>
#include <android-base/properties.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <android/hardware/usb/gadget/1.2/IUsbGadget.h>
#include <android/hardware/usb/gadget/1.2/types.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <android-base/strings.h>
#include <aidl/android/hardware/usb/gadget/BnUsbGadget.h>
#include <aidl/android/hardware/usb/gadget/BnUsbGadgetCallback.h>
#include <aidl/android/hardware/usb/gadget/GadgetFunction.h>
#include <aidl/android/hardware/usb/gadget/IUsbGadget.h>
#include <aidl/android/hardware/usb/gadget/IUsbGadgetCallback.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <utils/Log.h>
@@ -36,36 +36,25 @@
#include <string>
#include <thread>
namespace aidl {
namespace android {
namespace hardware {
namespace usb {
namespace gadget {
namespace V1_2 {
namespace implementation {
using ::android::sp;
using ::aidl::android::hardware::usb::gadget::GadgetFunction;
using ::aidl::android::hardware::usb::gadget::IUsbGadgetCallback;
using ::aidl::android::hardware::usb::gadget::IUsbGadget;
using ::aidl::android::hardware::usb::gadget::Status;
using ::aidl::android::hardware::usb::gadget::UsbSpeed;
using ::android::base::GetProperty;
using ::android::base::ReadFileToString;
using ::android::base::SetProperty;
using ::android::base::Trim;
using ::android::base::unique_fd;
using ::android::base::ReadFileToString;
using ::android::base::Trim;
using ::android::base::WriteStringToFile;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::usb::gadget::addAdb;
using ::android::hardware::usb::gadget::addEpollFd;
using ::android::hardware::usb::gadget::getVendorFunctions;
using ::android::hardware::usb::gadget::kDebug;
using ::android::hardware::usb::gadget::kDisconnectWaitUs;
using ::android::hardware::usb::gadget::linkFunction;
using ::android::hardware::usb::gadget::MonitorFfs;
using ::android::hardware::usb::gadget::resetGadget;
using ::android::hardware::usb::gadget::setVidPid;
using ::android::hardware::usb::gadget::unlinkFunctions;
using ::ndk::ScopedAStatus;
using ::std::shared_ptr;
using ::std::string;
constexpr char kGadgetName[] = "fe980000.usb";
@@ -74,36 +63,36 @@ static MonitorFfs monitorFfs(kGadgetName);
#define UDC_PATH "/sys/class/udc/fe980000.usb/"
#define SPEED_PATH UDC_PATH "current_speed"
struct UsbGadget : public IUsbGadget {
struct UsbGadget : public BnUsbGadget {
UsbGadget();
// Makes sure that only one request is processed at a time.
std::mutex mLockSetCurrentFunction;
uint64_t mCurrentUsbFunctions;
long mCurrentUsbFunctions;
bool mCurrentUsbFunctionsApplied;
UsbSpeed mUsbSpeed;
Return<void> setCurrentUsbFunctions(uint64_t functions,
const sp<V1_0::IUsbGadgetCallback>& callback,
uint64_t timeout) override;
ScopedAStatus setCurrentUsbFunctions(int64_t functions,
const shared_ptr<IUsbGadgetCallback> &callback,
int64_t timeoutMs, int64_t in_transactionId) override;
Return<void> getCurrentUsbFunctions(const sp<V1_0::IUsbGadgetCallback>& callback) override;
ScopedAStatus getCurrentUsbFunctions(const shared_ptr<IUsbGadgetCallback> &callback,
int64_t in_transactionId) override;
Return<Status> reset() override;
ScopedAStatus reset(const shared_ptr<IUsbGadgetCallback> &callback,
int64_t in_transactionId) override;
Return<void> getUsbSpeed(const sp<V1_2::IUsbGadgetCallback>& callback) override;
ScopedAStatus getUsbSpeed(const shared_ptr<IUsbGadgetCallback> &callback,
int64_t in_transactionId) override;
private:
V1_0::Status tearDownGadget();
V1_0::Status setupFunctions(uint64_t functions, const sp<V1_0::IUsbGadgetCallback>& callback,
uint64_t timeout);
Status tearDownGadget();
Status setupFunctions(long functions, const shared_ptr<IUsbGadgetCallback> &callback,
uint64_t timeout, int64_t in_transactionId);
};
} // namespace implementation
} // namespace V1_2
} // namespace gadget
} // namespace usb
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_USB_V1_2_USBGADGET_H
} // aidl

View File

@@ -0,0 +1,4 @@
service vendor.usb_gadget-default /vendor/bin/hw/android.hardware.usb.gadget-service.rpi
class hal
user system
group system shell mtp

View File

@@ -1,8 +1,7 @@
<manifest version="1.0" type="device">
<hal format="hidl">
<hal format="aidl">
<name>android.hardware.usb.gadget</name>
<transport>hwbinder</transport>
<version>1.2</version>
<version>1</version>
<interface>
<name>IUsbGadget</name>
<instance>default</instance>

View File

@@ -1,7 +0,0 @@
service vendor.usb-gadget-hal-1-2 /vendor/bin/hw/android.hardware.usb.gadget@1.2-service.rpi
interface android.hardware.usb.gadget@1.0::IUsbGadget default
interface android.hardware.usb.gadget@1.1::IUsbGadget default
interface android.hardware.usb.gadget@1.2::IUsbGadget default
class hal
user system
group system shell mtp

28
usb/lib/Android.bp Normal file
View File

@@ -0,0 +1,28 @@
// Copyright (C) 2020 The Android Open Source Project
// Copyright (C) 2024 KonstaKANG
//
// SPDX-License-Identifier: Apache-2.0
cc_library_static {
name: "libusbconfigfs-rpi",
vendor_available: true,
export_include_dirs: ["include"],
srcs: [
"UsbGadgetUtils.cpp",
"MonitorFfs.cpp",
],
cflags: [
"-Wall",
"-Werror",
],
shared_libs: [
"android.hardware.usb.gadget-V1-ndk",
"libbase",
"libcutils",
"libhidlbase",
"libutils",
],
}

272
usb/lib/MonitorFfs.cpp Normal file
View File

@@ -0,0 +1,272 @@
/*
* Copyright (C) 2020 The Android Open Source Project
* Copyright (C) 2024 KonstaKANG
*
* 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 "libusbconfigfs"
#include "include/UsbGadgetCommon.h"
namespace aidl {
namespace android {
namespace hardware {
namespace usb {
namespace gadget {
static volatile bool gadgetPullup;
MonitorFfs::MonitorFfs(const char* const gadget)
: mWatchFd(),
mEndpointList(),
mLock(),
mCv(),
mLockFd(),
mCurrentUsbFunctionsApplied(false),
mMonitor(),
mCallback(NULL),
mPayload(NULL),
mGadgetName(gadget),
mMonitorRunning(false) {
unique_fd eventFd(eventfd(0, 0));
if (eventFd == -1) {
ALOGE("mEventFd failed to create %d", errno);
abort();
}
unique_fd epollFd(epoll_create(2));
if (epollFd == -1) {
ALOGE("mEpollFd failed to create %d", errno);
abort();
}
unique_fd inotifyFd(inotify_init());
if (inotifyFd < 0) {
ALOGE("inotify init failed");
abort();
}
if (addEpollFd(epollFd, inotifyFd) == -1) abort();
if (addEpollFd(epollFd, eventFd) == -1) abort();
mEpollFd = std::move(epollFd);
mInotifyFd = std::move(inotifyFd);
mEventFd = std::move(eventFd);
gadgetPullup = false;
}
static void displayInotifyEvent(struct inotify_event* i) {
ALOGE(" wd =%2d; ", i->wd);
if (i->cookie > 0) ALOGE("cookie =%4d; ", i->cookie);
ALOGE("mask = ");
if (i->mask & IN_ACCESS) ALOGE("IN_ACCESS ");
if (i->mask & IN_ATTRIB) ALOGE("IN_ATTRIB ");
if (i->mask & IN_CLOSE_NOWRITE) ALOGE("IN_CLOSE_NOWRITE ");
if (i->mask & IN_CLOSE_WRITE) ALOGE("IN_CLOSE_WRITE ");
if (i->mask & IN_CREATE) ALOGE("IN_CREATE ");
if (i->mask & IN_DELETE) ALOGE("IN_DELETE ");
if (i->mask & IN_DELETE_SELF) ALOGE("IN_DELETE_SELF ");
if (i->mask & IN_IGNORED) ALOGE("IN_IGNORED ");
if (i->mask & IN_ISDIR) ALOGE("IN_ISDIR ");
if (i->mask & IN_MODIFY) ALOGE("IN_MODIFY ");
if (i->mask & IN_MOVE_SELF) ALOGE("IN_MOVE_SELF ");
if (i->mask & IN_MOVED_FROM) ALOGE("IN_MOVED_FROM ");
if (i->mask & IN_MOVED_TO) ALOGE("IN_MOVED_TO ");
if (i->mask & IN_OPEN) ALOGE("IN_OPEN ");
if (i->mask & IN_Q_OVERFLOW) ALOGE("IN_Q_OVERFLOW ");
if (i->mask & IN_UNMOUNT) ALOGE("IN_UNMOUNT ");
ALOGE("\n");
if (i->len > 0) ALOGE(" name = %s\n", i->name);
}
void* MonitorFfs::startMonitorFd(void* param) {
MonitorFfs* monitorFfs = (MonitorFfs*)param;
char buf[kBufferSize];
bool writeUdc = true, stopMonitor = false;
struct epoll_event events[kEpollEvents];
steady_clock::time_point disconnect;
bool descriptorWritten = true;
for (int i = 0; i < static_cast<int>(monitorFfs->mEndpointList.size()); i++) {
if (access(monitorFfs->mEndpointList.at(i).c_str(), R_OK)) {
descriptorWritten = false;
break;
}
}
// notify here if the endpoints are already present.
if (descriptorWritten) {
usleep(kPullUpDelay);
if (!!WriteStringToFile(monitorFfs->mGadgetName, PULLUP_PATH)) {
lock_guard<mutex> lock(monitorFfs->mLock);
monitorFfs->mCurrentUsbFunctionsApplied = true;
monitorFfs->mCallback(monitorFfs->mCurrentUsbFunctionsApplied, monitorFfs->mPayload);
gadgetPullup = true;
writeUdc = false;
ALOGI("GADGET pulled up");
monitorFfs->mCv.notify_all();
}
}
while (!stopMonitor) {
int nrEvents = epoll_wait(monitorFfs->mEpollFd, events, kEpollEvents, -1);
if (nrEvents <= 0) {
ALOGE("epoll wait did not return descriptor number");
continue;
}
for (int i = 0; i < nrEvents; i++) {
ALOGI("event=%u on fd=%d\n", events[i].events, events[i].data.fd);
if (events[i].data.fd == monitorFfs->mInotifyFd) {
// Process all of the events in buffer returned by read().
int numRead = read(monitorFfs->mInotifyFd, buf, kBufferSize);
for (char* p = buf; p < buf + numRead;) {
struct inotify_event* event = (struct inotify_event*)p;
if (kDebug) displayInotifyEvent(event);
p += sizeof(struct inotify_event) + event->len;
bool descriptorPresent = true;
for (int j = 0; j < static_cast<int>(monitorFfs->mEndpointList.size()); j++) {
if (access(monitorFfs->mEndpointList.at(j).c_str(), R_OK)) {
if (kDebug) ALOGI("%s absent", monitorFfs->mEndpointList.at(j).c_str());
descriptorPresent = false;
break;
}
}
if (!descriptorPresent && !writeUdc) {
if (kDebug) ALOGI("endpoints not up");
writeUdc = true;
disconnect = std::chrono::steady_clock::now();
} else if (descriptorPresent && writeUdc) {
steady_clock::time_point temp = steady_clock::now();
if (std::chrono::duration_cast<microseconds>(temp - disconnect).count() <
kPullUpDelay)
usleep(kPullUpDelay);
if (!!WriteStringToFile(monitorFfs->mGadgetName, PULLUP_PATH)) {
lock_guard<mutex> lock(monitorFfs->mLock);
monitorFfs->mCurrentUsbFunctionsApplied = true;
monitorFfs->mCallback(monitorFfs->mCurrentUsbFunctionsApplied,
monitorFfs->mPayload);
ALOGI("GADGET pulled up");
writeUdc = false;
gadgetPullup = true;
// notify the main thread to signal userspace.
monitorFfs->mCv.notify_all();
}
}
}
} else {
uint64_t flag;
read(monitorFfs->mEventFd, &flag, sizeof(flag));
if (flag == 100) {
stopMonitor = true;
break;
}
}
}
}
return NULL;
}
void MonitorFfs::reset() {
lock_guard<mutex> lock(mLockFd);
uint64_t flag = 100;
unsigned long ret;
if (mMonitorRunning) {
// Stop the monitor thread by writing into signal fd.
ret = TEMP_FAILURE_RETRY(write(mEventFd, &flag, sizeof(flag)));
if (ret < 0) ALOGE("Error writing eventfd errno=%d", errno);
ALOGI("mMonitor signalled to exit");
mMonitor->join();
ALOGI("mMonitor destroyed");
mMonitorRunning = false;
}
for (std::vector<int>::size_type i = 0; i != mWatchFd.size(); i++)
inotify_rm_watch(mInotifyFd, mWatchFd[i]);
mEndpointList.clear();
gadgetPullup = false;
mCallback = NULL;
mPayload = NULL;
}
bool MonitorFfs::startMonitor() {
mMonitor = unique_ptr<thread>(new thread(this->startMonitorFd, this));
mMonitorRunning = true;
return true;
}
bool MonitorFfs::isMonitorRunning() {
return mMonitorRunning;
}
bool MonitorFfs::waitForPullUp(int timeout_ms) {
std::unique_lock<std::mutex> lk(mLock);
if (gadgetPullup) return true;
if (mCv.wait_for(lk, timeout_ms * 1ms, [] { return gadgetPullup; })) {
ALOGI("monitorFfs signalled true");
return true;
} else {
ALOGI("monitorFfs signalled error");
// continue monitoring as the descriptors might be written at a later
// point.
return false;
}
}
bool MonitorFfs::addInotifyFd(string fd) {
lock_guard<mutex> lock(mLockFd);
int wfd;
wfd = inotify_add_watch(mInotifyFd, fd.c_str(), IN_ALL_EVENTS);
if (wfd == -1)
return false;
else
mWatchFd.push_back(wfd);
return true;
}
void MonitorFfs::addEndPoint(string ep) {
lock_guard<mutex> lock(mLockFd);
mEndpointList.push_back(ep);
}
void MonitorFfs::registerFunctionsAppliedCallback(void (*callback)(bool functionsApplied,
void* payload),
void* payload) {
mCallback = callback;
mPayload = payload;
}
} // namespace gadget
} // namespace usb
} // namespace hardware
} // namespace android
} // namespace aidl

210
usb/lib/UsbGadgetUtils.cpp Normal file
View File

@@ -0,0 +1,210 @@
/*
* Copyright (C) 2020 The Android Open Source Project
* Copyright (C) 2024 KonstaKANG
*
* 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 "libusbconfigfs"
#include "include/UsbGadgetCommon.h"
namespace aidl {
namespace android {
namespace hardware {
namespace usb {
namespace gadget {
int unlinkFunctions(const char* path) {
DIR* config = opendir(path);
struct dirent* function;
char filepath[kMaxFilePathLength];
int ret = 0;
if (config == NULL) return -1;
// d_type does not seems to be supported in /config
// so filtering by name.
while (((function = readdir(config)) != NULL)) {
if ((strstr(function->d_name, FUNCTION_NAME) == NULL)) continue;
// build the path for each file in the folder.
sprintf(filepath, "%s/%s", path, function->d_name);
ret = remove(filepath);
if (ret) {
ALOGE("Unable remove file %s errno:%d", filepath, errno);
break;
}
}
closedir(config);
return ret;
}
int addEpollFd(const unique_fd& epfd, const unique_fd& fd) {
struct epoll_event event;
int ret;
event.data.fd = fd;
event.events = EPOLLIN;
ret = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event);
if (ret) ALOGE("epoll_ctl error %d", errno);
return ret;
}
int linkFunction(const char* function, int index) {
char functionPath[kMaxFilePathLength];
char link[kMaxFilePathLength];
sprintf(functionPath, "%s%s", FUNCTIONS_PATH, function);
sprintf(link, "%s%d", FUNCTION_PATH, index);
if (symlink(functionPath, link)) {
ALOGE("Cannot create symlink %s -> %s errno:%d", link, functionPath, errno);
return -1;
}
return 0;
}
Status setVidPid(const char* vid, const char* pid) {
if (!WriteStringToFile(vid, VENDOR_ID_PATH)) return Status::ERROR;
if (!WriteStringToFile(pid, PRODUCT_ID_PATH)) return Status::ERROR;
return Status::SUCCESS;
}
std::string getVendorFunctions() {
if (GetProperty(kBuildType, "") == "user") return "user";
std::string bootMode = GetProperty(PERSISTENT_BOOT_MODE, "");
std::string persistVendorFunctions = GetProperty(kPersistentVendorConfig, "");
std::string vendorFunctions = GetProperty(kVendorConfig, "");
std::string ret = "";
if (vendorFunctions != "") {
ret = vendorFunctions;
} else if (bootMode == "usbradio" || bootMode == "factory" || bootMode == "ffbm-00" ||
bootMode == "ffbm-01") {
if (persistVendorFunctions != "")
ret = persistVendorFunctions;
else
ret = "diag";
// vendor.usb.config will reflect the current configured functions
SetProperty(kVendorConfig, ret);
}
return ret;
}
Status resetGadget() {
ALOGI("setCurrentUsbFunctions None");
if (!WriteStringToFile("none", PULLUP_PATH)) ALOGI("Gadget cannot be pulled down");
if (!WriteStringToFile("0", DEVICE_CLASS_PATH)) return Status::ERROR;
if (!WriteStringToFile("0", DEVICE_SUB_CLASS_PATH)) return Status::ERROR;
if (!WriteStringToFile("0", DEVICE_PROTOCOL_PATH)) return Status::ERROR;
if (!WriteStringToFile("0", DESC_USE_PATH)) return Status::ERROR;
if (unlinkFunctions(CONFIG_PATH)) return Status::ERROR;
return Status::SUCCESS;
}
Status addGenericAndroidFunctions(MonitorFfs* monitorFfs, uint64_t functions, bool* ffsEnabled,
int* functionCount) {
if (((functions & GadgetFunction::MTP) != 0)) {
*ffsEnabled = true;
ALOGI("setCurrentUsbFunctions mtp");
if (!WriteStringToFile("1", DESC_USE_PATH)) return Status::ERROR;
if (!monitorFfs->addInotifyFd("/dev/usb-ffs/mtp/")) return Status::ERROR;
if (linkFunction("ffs.mtp", (*functionCount)++)) return Status::ERROR;
// Add endpoints to be monitored.
monitorFfs->addEndPoint("/dev/usb-ffs/mtp/ep1");
monitorFfs->addEndPoint("/dev/usb-ffs/mtp/ep2");
monitorFfs->addEndPoint("/dev/usb-ffs/mtp/ep3");
} else if (((functions & GadgetFunction::PTP) != 0)) {
*ffsEnabled = true;
ALOGI("setCurrentUsbFunctions ptp");
if (!WriteStringToFile("1", DESC_USE_PATH)) return Status::ERROR;
if (!monitorFfs->addInotifyFd("/dev/usb-ffs/ptp/")) return Status::ERROR;
if (linkFunction("ffs.ptp", (*functionCount)++)) return Status::ERROR;
// Add endpoints to be monitored.
monitorFfs->addEndPoint("/dev/usb-ffs/ptp/ep1");
monitorFfs->addEndPoint("/dev/usb-ffs/ptp/ep2");
monitorFfs->addEndPoint("/dev/usb-ffs/ptp/ep3");
}
if ((functions & GadgetFunction::MIDI) != 0) {
ALOGI("setCurrentUsbFunctions MIDI");
if (linkFunction("midi.gs5", (*functionCount)++)) return Status::ERROR;
}
if ((functions & GadgetFunction::ACCESSORY) != 0) {
ALOGI("setCurrentUsbFunctions Accessory");
if (linkFunction("accessory.gs2", (*functionCount)++)) return Status::ERROR;
}
if ((functions & GadgetFunction::AUDIO_SOURCE) != 0) {
ALOGI("setCurrentUsbFunctions Audio Source");
if (linkFunction("audio_source.gs3", (*functionCount)++)) return Status::ERROR;
}
if ((functions & GadgetFunction::RNDIS) != 0) {
ALOGI("setCurrentUsbFunctions rndis");
std::string rndisFunction = GetProperty(kVendorRndisConfig, "");
if (rndisFunction != "") {
if (linkFunction(rndisFunction.c_str(), (*functionCount)++)) return Status::ERROR;
} else {
// link gsi.rndis for older pixel projects
if (linkFunction("gsi.rndis", (*functionCount)++)) return Status::ERROR;
}
}
if ((functions & GadgetFunction::NCM) != 0) {
ALOGI("setCurrentUsbFunctions ncm");
if (linkFunction("ncm.gs6", (*functionCount)++)) return Status::ERROR;
}
return Status::SUCCESS;
}
Status addAdb(MonitorFfs* monitorFfs, int* functionCount) {
ALOGI("setCurrentUsbFunctions Adb");
if (!WriteStringToFile("1", DESC_USE_PATH))
return Status::ERROR;
if (!monitorFfs->addInotifyFd("/dev/usb-ffs/adb/")) return Status::ERROR;
if (linkFunction("ffs.adb", (*functionCount)++)) return Status::ERROR;
monitorFfs->addEndPoint("/dev/usb-ffs/adb/ep1");
monitorFfs->addEndPoint("/dev/usb-ffs/adb/ep2");
ALOGI("Service started");
return Status::SUCCESS;
}
} // namespace gadget
} // namespace usb
} // namespace hardware
} // namespace android
} // namespace aidl

View File

@@ -0,0 +1,182 @@
/*
* Copyright (C) 2020 The Android Open Source Project
* Copyright (C) 2024 KonstaKANG
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef HARDWARE_USB_USBGADGETCOMMON_H
#define HARDWARE_USB_USBGADGETCOMMON_H
#include <android-base/file.h>
#include <android-base/properties.h>
#include <android-base/unique_fd.h>
#include <aidl/android/hardware/usb/gadget/IUsbGadget.h>
#include <aidl/android/hardware/usb/gadget/GadgetFunction.h>
#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <sys/inotify.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <utils/Log.h>
#include <chrono>
#include <condition_variable>
#include <mutex>
#include <string>
#include <thread>
namespace aidl {
namespace android {
namespace hardware {
namespace usb {
namespace gadget {
constexpr int kBufferSize = 512;
constexpr int kMaxFilePathLength = 256;
constexpr int kEpollEvents = 10;
constexpr bool kDebug = false;
constexpr int kDisconnectWaitUs = 100000;
constexpr int kPullUpDelay = 500000;
constexpr int kShutdownMonitor = 100;
constexpr char kBuildType[] = "ro.build.type";
constexpr char kPersistentVendorConfig[] = "persist.vendor.usb.usbradio.config";
constexpr char kVendorConfig[] = "vendor.usb.config";
constexpr char kVendorRndisConfig[] = "vendor.usb.rndis.config";
#define GADGET_PATH "/config/usb_gadget/g1/"
#define PULLUP_PATH GADGET_PATH "UDC"
#define PERSISTENT_BOOT_MODE "ro.bootmode"
#define VENDOR_ID_PATH GADGET_PATH "idVendor"
#define PRODUCT_ID_PATH GADGET_PATH "idProduct"
#define DEVICE_CLASS_PATH GADGET_PATH "bDeviceClass"
#define DEVICE_SUB_CLASS_PATH GADGET_PATH "bDeviceSubClass"
#define DEVICE_PROTOCOL_PATH GADGET_PATH "bDeviceProtocol"
#define DESC_USE_PATH GADGET_PATH "os_desc/use"
#define OS_DESC_PATH GADGET_PATH "os_desc/b.1"
#define CONFIG_PATH GADGET_PATH "configs/b.1/"
#define FUNCTIONS_PATH GADGET_PATH "functions/"
#define FUNCTION_NAME "function"
#define FUNCTION_PATH CONFIG_PATH FUNCTION_NAME
#define RNDIS_PATH FUNCTIONS_PATH "gsi.rndis"
using ::android::base::GetProperty;
using ::android::base::SetProperty;
using ::android::base::unique_fd;
using ::android::base::WriteStringToFile;
using ::aidl::android::hardware::usb::gadget::GadgetFunction;
using ::aidl::android::hardware::usb::gadget::Status;
using ::std::lock_guard;
using ::std::move;
using ::std::mutex;
using ::std::string;
using ::std::thread;
using ::std::unique_ptr;
using ::std::vector;
using ::std::chrono::microseconds;
using ::std::chrono::steady_clock;
using ::std::literals::chrono_literals::operator""ms;
// MonitorFfs automously manages gadget pullup by monitoring
// the ep file status. Restarts the usb gadget when the ep
// owner restarts.
class MonitorFfs {
private:
// Monitors the endpoints Inotify events.
unique_fd mInotifyFd;
// Control pipe for shutting down the mMonitor thread.
// mMonitor exits when SHUTDOWN_MONITOR is written into
// mEventFd/
unique_fd mEventFd;
// Pools on mInotifyFd and mEventFd.
unique_fd mEpollFd;
vector<int> mWatchFd;
// Maintains the list of Endpoints.
vector<string> mEndpointList;
// protects the CV.
std::mutex mLock;
std::condition_variable mCv;
// protects mInotifyFd, mEpollFd.
std::mutex mLockFd;
// Flag to maintain the current status of gadget pullup.
bool mCurrentUsbFunctionsApplied;
// Thread object that executes the ep monitoring logic.
unique_ptr<thread> mMonitor;
// Callback to be invoked when gadget is pulled up.
void (*mCallback)(bool functionsApplied, void* payload);
void* mPayload;
// Name of the USB gadget. Used for pullup.
const char* const mGadgetName;
// Monitor State
bool mMonitorRunning;
public:
MonitorFfs(const char* const gadget);
// Inits all the UniqueFds.
void reset();
// Starts monitoring endpoints and pullup the gadget when
// the descriptors are written.
bool startMonitor();
// Waits for timeout_ms for gadget pull up to happen.
// Returns immediately if the gadget is already pulled up.
bool waitForPullUp(int timeout_ms);
// Adds the given fd to the watch list.
bool addInotifyFd(string fd);
// Adds the given endpoint to the watch list.
void addEndPoint(string ep);
// Registers the async callback from the caller to notify the caller
// when the gadget pull up happens.
void registerFunctionsAppliedCallback(void (*callback)(bool functionsApplied, void*(payload)),
void* payload);
bool isMonitorRunning();
// Ep monitoring and the gadget pull up logic.
static void* startMonitorFd(void* param);
};
//**************** Helper functions ************************//
// Adds the given fd to the epollfd(epfd).
int addEpollFd(const unique_fd& epfd, const unique_fd& fd);
// Removes all the usb functions link in the specified path.
int unlinkFunctions(const char* path);
// Craetes a configfs link for the function.
int linkFunction(const char* function, int index);
// Sets the USB VID and PID.
Status setVidPid(const char* vid, const char* pid);
// Extracts vendor functions from the vendor init properties.
std::string getVendorFunctions();
// Adds Adb to the usb configuration.
Status addAdb(MonitorFfs* monitorFfs, int* functionCount);
// Adds all applicable generic android usb functions other than ADB.
Status addGenericAndroidFunctions(MonitorFfs* monitorFfs, uint64_t functions, bool* ffsEnabled,
int* functionCount);
// Pulls down USB gadget.
Status resetGadget();
} // namespace gadget
} // namespace usb
} // namespace hardware
} // namespace android
} // namespace aidl
#endif

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2020 The Android Open Source Project
* Copyright (C) 2023 KonstaKANG
* Copyright (C) 2022 The Android Open Source Project
* Copyright (C) 2024 KonstaKANG
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,39 +15,19 @@
* limitations under the License.
*/
#define LOG_TAG "android.hardware.usb.gadget@1.2-service.rpi"
#include <hidl/HidlTransportSupport.h>
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include "UsbGadget.h"
using android::sp;
// libhwbinder:
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
// Generated HIDL files
using android::hardware::usb::gadget::V1_2::IUsbGadget;
using android::hardware::usb::gadget::V1_2::implementation::UsbGadget;
using android::OK;
using android::status_t;
using ::aidl::android::hardware::usb::gadget::UsbGadget;
int main() {
configureRpcThreadpool(1, true /*callerWillJoin*/);
android::sp<IUsbGadget> service = new UsbGadget();
status_t status = service->registerAsService();
if (status != OK) {
ALOGE("Cannot register USB Gadget HAL service");
return 1;
}
ALOGI("USB Gadget HAL Ready.");
joinRpcThreadpool();
// Under noraml cases, execution will not reach this line.
ALOGI("USB Gadget HAL failed to join thread pool.");
return 1;
ABinderProcess_setThreadPoolMaxThreadCount(0);
std::shared_ptr<UsbGadget> usbgadget = ndk::SharedRefBase::make<UsbGadget>();
const std::string instance = std::string() + UsbGadget::descriptor + "/default";
binder_status_t status = AServiceManager_addService(usbgadget->asBinder().get(), instance.c_str());
CHECK(status == STATUS_OK);
ABinderProcess_joinThreadPool();
return -1;
}

View File

@@ -51,7 +51,6 @@ persist.ffmpeg_codec2.v4l2.h265=true
# Graphics
ro.hardware.egl=mesa
ro.hardware.hwcomposer=drm
ro.hardware.vulkan=broadcom
ro.opengles.version=196609
vendor.hwc.drm.ctm=DRM_OR_IGNORE
@@ -77,6 +76,9 @@ debug.stagefright.c2inputsurface=-1
# MGLRU
persist.device_config.mglru_native.lru_gen_config=core
# Storage
persist.sys.fuse.backup.external_volume_backup=false
# V4L2
debug.stagefright.c2-poolmask=0xf50000
persist.v4l2_codec2.rank.decoder=128
@@ -87,3 +89,6 @@ ro.vendor.v4l2_codec2.encode_concurrent_instances=8
# Wifi
wifi.interface=wlan0
# Window extensions
persist.settings.large_screen_opt.enabled=true

View File

@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2022 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- This is the standard feature indicating that the device has a Vulkan
driver that supports API version 1.2 (0x00402000) -->
<permissions>
<feature name="android.hardware.vulkan.version" version="4202496" />
</permissions>