当前位置:网站首页>Camera 手电筒修改
Camera 手电筒修改
2022-07-23 10:42:00 【虫师魁拔】
文档内容:修改原生接口,使用节点控制的方式替换原生调用hal层接口。
一、应用设置API
应用设置手电筒代码,调用系统接口 setTorchMode
private final CameraManager mCameraManager;
private final Context mContext;
public FlashlightControllerImpl(Context context) {
mContext = context;
mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
}
public void setFlashlight(String cameraId, boolean enabled) {
synchronized (this) {
try {
mCameraManager.setTorchMode(cameraId, enabled);
} catch (CameraAccessException e) {
Log.e(TAG, "Couldn't set torch mode", e);
}
}
}这里CameraManager调用会直接到 libcameraservice 的 CameraService.cpp 中,这点不同于一般XXXManager 之类的实现代码在 framework 中 services.jar 模块之中。
二、关键函数
CameraService.cpp 中执行几个重要函数
setTorchMode 操作闪光灯
Status CameraService::setTorchMode(const String16& cameraId, bool enabled,
const sp<IBinder>& clientBinder) {
Mutex::Autolock lock(mServiceLock);
ATRACE_CALL();
if (enabled && clientBinder == nullptr) {
ALOGE("%s: torch client binder is NULL", __FUNCTION__);
return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT,
"Torch client Binder is null");
}
String8 id = String8(cameraId.string());
//ADD 写节点打开手电筒代码块
std::string idStr = std::string(id);
char value[PROPERTY_VALUE_MAX];
memset(value, 0, sizeof(value));
property_get("sys.torch.rw_dev", value, "0");
int32_t serviceStatus = ICameraServiceListener::TORCH_STATUS_NOT_AVAILABLE;
if (0 == strcmp(value, "1") && idStr.compare("0") == 0) {
if (enabled) {
FILE *fp = NULL;
fp = fopen("/sys/class/leds/led:torch_0/brightness", "w");
fprintf(fp, "250");
fclose(fp);
fp = fopen("/sys/class/leds/led:switch_0/brightness", "w");
fprintf(fp, "1");
fclose(fp);
serviceStatus = ICameraServiceListener::TORCH_STATUS_AVAILABLE_ON;
} else {
FILE *fp = NULL;
fp = fopen("/sys/class/leds/led:switch_0/brightness", "w");
fprintf(fp, "0");
fclose(fp);
serviceStatus = ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF;
}
// 通知手电筒状态变化
for (auto& i : mListenerList) {
i->getListener()->onTorchStatusChanged(serviceStatus, String16{cameraId});
}
return Status::ok();
}
//ADD
... ...
// 判断是否设置为系统相机
int uid = CameraThreadState::getCallingUid();
if (shouldRejectSystemCameraConnection(id)) {
return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "Unable to set torch mode"
" for system only device %s: ", id.string());
}
... ...
// 原生check闪光灯是否可用
StatusInternal cameraStatus = state->getStatus();
... ...
// 原生操作闪光灯地方
status_t err = mFlashlight->setTorchMode(id, enabled);
... ...
return Status::ok();
}
onTorchStatusChangedLocked 手电筒状态回调函数
即使改成写节点的方式操作手电筒,开启关闭camera后也会执行此函数通知状态
void CameraService::onTorchStatusChangedLocked(const String8& cameraId,
TorchModeStatus newStatus, SystemCameraKind systemCameraKind) {
ALOGI("%s: Torch status changed for cameraId=%s, mHCameraIdStr=%s, newStatus=%d",
__FUNCTION__, cameraId.string(), mHCameraIdStr.string(), newStatus);
TorchModeStatus status;
status_t res = getTorchStatusLocked(cameraId, &status);
if (res) {
ALOGE("%s: cannot get torch status of camera %s: %s (%d)",
__FUNCTION__, cameraId.string(), strerror(-res), res);
return;
}
if (status == newStatus) {
return;
}
// 增加判断,对于后摄(后摄有闪光灯)打开时,关闭手电筒
char value[PROPERTY_VALUE_MAX];
memset(value, 0, sizeof(value));
property_get("sys.torch.rw_dev", value, "0");
std::string idStr = std::string(cameraId);
if (0 == strcmp(value, "1") && newStatus != TorchModeStatus::AVAILABLE_ON) {
if (idStr.compare("0") == 0) {
FILE *fp = NULL;
fp = fopen("/sys/class/leds/led:switch_0/brightness", "w");
fprintf(fp, "0");
fclose(fp);
}
}
// 原生的Torch回调事件,通知应用手电筒状态的
res = setTorchStatusLocked(cameraId, newStatus);
... ...
broadcastTorchModeStatus(cameraId, newStatus, systemCameraKind);
}开启关闭Camera执行如下函数
// closeCamera时会执行disconnect步骤
binder::Status CameraService::BasicClient::disconnect() {
binder::Status res = Status::ok();
if (mDisconnected) {
return res;
}
... ...
}
// openCamera时会执行connect步骤
template<class CALLBACK, class CLIENT>
Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
int api1CameraId, int halVersion, const String16& clientPackageName,
const std::unique_ptr<String16>& clientFeatureId, int clientUid, int clientPid,
apiLevel effectiveApiLevel, bool shimUpdateOnly,
/*out*/sp<CLIENT>& device) {
binder::Status ret = binder::Status::ok();
String8 clientName8(clientPackageName);
... ...
}边栏推荐
猜你喜欢

The official redis visualization tool is coming. The needle doesn't poke

Matlab simulation of depth information extraction and target ranging based on binocular camera images

Live classroom system 01 database table design

Kettle implements shared database connection and insert update component instances

Use of RSA encryption

AVX指令集加速矩阵乘法

基于双目相机拍摄图像的深度信息提取和目标测距matlab仿真

Live classroom system 03 model class and entity

Simulink simulation of ESP three-phase SVPWM controller

VSCode 更新後與tab相關快捷鍵無法使用
随机推荐
Live classroom system 02 build project environment
【Pygame实战】打扑克牌嘛?赢了输了?这款打牌游戏,竟让我废寝忘食。
The problem of double type precision loss and its solution
NVIDIA vid2vid paper reproduction
uniapp路由跳转的六种方式
Kettle實現共享數據庫連接及插入更新組件實例
supervisord安装使用
PostgreSQL has no NVL solution. PostgreSQL queries all tables
查找论文源代码
颜值爆表 Redis官方可视化工具来啦,针不戳
Les raccourcis clavier liés à l'onglet ne peuvent pas être utilisés après la mise à jour du vscode
The official redis visualization tool is coming. The needle doesn't poke
c语言:深度刨析const关键字
Unreal中通过FMonitoredProcess启动其他独立程序
MySQL执行顺序
Solve the problem that kotlin writes the Android project compilation report execution failed for task ': app:kaptdebugkotlin'. Exception
多线程一定能优化程序性能吗?
uniapp实现横向点击滑动菜单
ERP管理系统在装备制造企业管理中的应用
Blazor快速实现扫雷(MineSweeper)