From e48aedd17221940b03b4087aefdb559fcb16b76d Mon Sep 17 00:00:00 2001 From: Matthew Date: Wed, 7 Aug 2024 11:14:45 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=B3=BB=E7=BB=9Fcamera?= =?UTF-8?q?=E7=9A=84=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 5 + app/src/main/cpp/camera2/ndkcamera.cpp | 26 ++--- .../com/xypower/mpapp/MicroPhotoService.java | 60 ++++++++++ .../java/com/xypower/mpapp/adb/CameraAdb.java | 103 ++++++++++++++++++ .../java/com/xypower/common/FilesUtils.java | 2 + 5 files changed, 183 insertions(+), 13 deletions(-) create mode 100644 app/src/main/java/com/xypower/mpapp/adb/CameraAdb.java diff --git a/app/build.gradle b/app/build.gradle index e6adc7fc..ac966552 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -110,6 +110,9 @@ android { exclude 'META-INF/INDEX.LIST' exclude 'META-INF/io.netty.versions.properties' exclude 'META-INF/DEPENDENCIES' + exclude 'META-INF/LICENSE-notice.md' + exclude 'META-INF/LICENSE.md' + } } @@ -136,6 +139,8 @@ dependencies { releaseImplementation files('libs/rtmp-client.aar') implementation project(':gpuv') + implementation 'dev.mobile:dadb:1.2.7' + // implementation group: 'io.netty', name: 'netty-all', version: '4.1.96.Final' // implementation 'io.netty:netty-all:4.1.23.Final' // implementation 'org.apache.logging.log4j:log4j-api:2.14.0' diff --git a/app/src/main/cpp/camera2/ndkcamera.cpp b/app/src/main/cpp/camera2/ndkcamera.cpp index d99e6481..7560618d 100644 --- a/app/src/main/cpp/camera2/ndkcamera.cpp +++ b/app/src/main/cpp/camera2/ndkcamera.cpp @@ -590,21 +590,22 @@ int NdkCamera::open(const std::string& cameraId) { templateId = (ACameraDevice_request_template)m_params.requestTemplate; status = ACameraDevice_createCaptureRequest(camera_device, templateId, &capture_request); - int32_t fpsRange[2] = {1,10}; + int32_t fpsRange[2] = {1, 5}; status = ACaptureRequest_setEntry_i32(capture_request, ACAMERA_CONTROL_AE_TARGET_FPS_RANGE,2,fpsRange); } - uint8_t ctrlMode = sceneModeSupported ? ACAMERA_CONTROL_MODE_USE_SCENE_MODE : ACAMERA_CONTROL_MODE_AUTO; + // uint8_t ctrlMode = sceneModeSupported ? ACAMERA_CONTROL_MODE_USE_SCENE_MODE : ACAMERA_CONTROL_MODE_AUTO; + uint8_t ctrlMode = ACAMERA_CONTROL_MODE_AUTO; status = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_MODE, 1, &ctrlMode); uint8_t flashMode = ACAMERA_FLASH_MODE_OFF; - status = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_FLASH_MODE, 1, &flashMode); + // status = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_FLASH_MODE, 1, &flashMode); uint8_t nrMode = ACAMERA_NOISE_REDUCTION_MODE_FAST; - status = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_NOISE_REDUCTION_MODE, 1, &nrMode); + // status = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_NOISE_REDUCTION_MODE, 1, &nrMode); uint8_t edgeMode = ACAMERA_EDGE_MODE_FAST; - status = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_EDGE_MODE, 1, &edgeMode); + // status = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_EDGE_MODE, 1, &edgeMode); if (afSupported && m_params.autoFocus) { @@ -742,7 +743,7 @@ int NdkCamera::open(const std::string& cameraId) { } int64_t frameDuration = maxFrameDuration / 2; - status = ACaptureRequest_setEntry_i64(capture_request, ACAMERA_SENSOR_FRAME_DURATION, 1, &frameDuration); + // status = ACaptureRequest_setEntry_i64(capture_request, ACAMERA_SENSOR_FRAME_DURATION, 1, &frameDuration); } // TODO: @@ -960,17 +961,16 @@ void NdkCamera::onImageAvailable(AImageReader* reader) } #endif - if (m_imagesCaptured == ~0 || m_imagesCaptured >= 1) + if (m_imagesCaptured == ~0 || m_imagesCaptured != 1) { // XYLOG(XYLOG_SEVERITY_DEBUG, "m_imagesCaptured=%u wait for next image", m_imagesCaptured); // Not Ready Or Taken AImage_delete(image); - /* if (m_imagesCaptured != ~0) + if (m_imagesCaptured != ~0) { XYLOG(XYLOG_SEVERITY_DEBUG, "Skip Image index=%u", m_imagesCaptured); m_imagesCaptured++; } - */ return; } @@ -1315,11 +1315,11 @@ void NdkCamera::onCaptureCompleted(ACameraCaptureSession* session, ACaptureReque if (mResult.aeState == ACAMERA_CONTROL_AE_STATE_PRECAPTURE) { uint8_t aePrecatureTrigger = ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL; - // status = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER, 1, &aePrecatureTrigger); + status = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER, 1, &aePrecatureTrigger); aePrecatureTrigger = ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER_START; - // status = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER, 1, &aePrecatureTrigger); - // XYLOG(XYLOG_SEVERITY_DEBUG, "Trigger PRECAPTURE status=%d AES=%u", (int)status, (unsigned int)mResult.aeState); + status = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_AE_PRECAPTURE_TRIGGER, 1, &aePrecatureTrigger); + XYLOG(XYLOG_SEVERITY_DEBUG, "Trigger PRECAPTURE status=%d AES=%u", (int)status, (unsigned int)mResult.aeState); numberOfPrecaptures = 0; m_precaptureStartTime = ts; @@ -1440,7 +1440,7 @@ void NdkCamera::onCaptureCompleted(ACameraCaptureSession* session, ACaptureReque if (m_imagesCaptured != 0 || camera_facing == 2) { - return; + // return; } val = { 0 }; diff --git a/app/src/main/java/com/xypower/mpapp/MicroPhotoService.java b/app/src/main/java/com/xypower/mpapp/MicroPhotoService.java index 73ae4699..d7b36981 100644 --- a/app/src/main/java/com/xypower/mpapp/MicroPhotoService.java +++ b/app/src/main/java/com/xypower/mpapp/MicroPhotoService.java @@ -50,18 +50,23 @@ import android.widget.Toast; import com.dev.devapi.api.SysApi; import com.xypower.common.FileDownloader; +import com.xypower.common.FilesUtils; import com.xypower.common.NetworkUtils; import com.xypower.common.MicroPhotoContext; +import com.xypower.mpapp.adb.CameraAdb; import com.xypower.mpapp.v2.Camera2VideoActivity; import java.io.File; +import java.io.IOException; import java.lang.reflect.Method; import java.net.InetAddress; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; public class MicroPhotoService extends Service { public static final String TAG = "MPLOG"; @@ -332,6 +337,61 @@ public class MicroPhotoService extends Service { Log.i(TAG, "PhotoTimer Fired: CH=" + channel + " PR=" + preset); mService.notifyToTakePhoto(mService.mNativeHandle, channel, preset, ts, photoOrVideo); + + if (channel == 2) { + final String appPath = MicroPhotoContext.buildMpAppDir(context); + + new Thread(new Runnable() { + @Override + public void run() { + + try { + Thread.sleep(20000); + } catch (Exception ex) { + ex.printStackTrace(); + } + + final long requestTime = System.currentTimeMillis() / 1000; + + CameraAdb cameraAdb = new CameraAdb(context, appPath); + cameraAdb.takePhoto(); + + mService.mHander.postDelayed(new Runnable() { + @Override + public void run() { + long takingTime = System.currentTimeMillis() / 1000; + String photoPath = appPath + "photos/"; + String photoFile = "IMG_" + Long.toHexString(requestTime).toUpperCase() + "_2_FF_0_" + Long.toHexString(requestTime).toUpperCase() + "_" + Long.toHexString(takingTime).toUpperCase() + ".jpg"; + + File cameraPath = new File("/sdcard/DCIM/Camera/"); + + Optional opFile = Arrays.stream(cameraPath.listFiles(File::isFile)) + .max((f1, f2) -> Long.compare(f1.lastModified(), f2.lastModified())); + + boolean res = false; + if (opFile.isPresent()) { + File targetFile = new File(new File(photoPath), photoFile); + try { + File srcFile = opFile.get(); + // FilesUtils.copyFile(srcFile, targetFile); + res = srcFile.renameTo(targetFile); + + SysApi.forceStopApp(context, "com.mediatek.camera"); + + restartApp(context, MicroPhotoContext.PACKAGE_NAME_MPAPP); + } catch (Exception e) { + e.printStackTrace(); + } + if (!res) { + Log.e(TAG, "Failed to copy photo from Camera"); + } + } + } + }, 4000); + } + }).start(); + + } } } diff --git a/app/src/main/java/com/xypower/mpapp/adb/CameraAdb.java b/app/src/main/java/com/xypower/mpapp/adb/CameraAdb.java new file mode 100644 index 00000000..90b246d5 --- /dev/null +++ b/app/src/main/java/com/xypower/mpapp/adb/CameraAdb.java @@ -0,0 +1,103 @@ +package com.xypower.mpapp.adb; + +import android.content.Context; +import android.content.Intent; +import android.util.Log; + +import com.xypower.common.FilesUtils; +import com.xypower.mpapp.v2.Camera2VideoActivity; + +import java.io.File; + +import dadb.AdbKeyPair; +import dadb.AdbShellResponse; +import dadb.Dadb; + +public class CameraAdb { + private final String TAG = "CameraAdb"; + + private Context mContext; + private String mAppPath; + private AdbKeyPair mAdbKeyPair; + private String mDeviceIp = "127.0.0.1"; + + public CameraAdb(Context context, String appPath) { + + mContext = context; + mAppPath = appPath; + + File file = new File( new File(appPath), "data/.keypair"); + if (!file.exists()) { + file.mkdirs(); + } + + final File pubKeyFile = new File(file, "pub.key"); + final File priKeyFile = new File(file, "pri.key"); + if (!priKeyFile.exists() || !pubKeyFile.exists()) { + AdbKeyPair.generate(priKeyFile, pubKeyFile); + } + + mAdbKeyPair = AdbKeyPair.read(priKeyFile, pubKeyFile); + } + + public void takePhoto() { + (new Thread(new Runnable() { + @Override + public void run() { + + try { + runImpl(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + private void runImpl() { + Dadb adb = Dadb.discover(mDeviceIp, mAdbKeyPair); + + if (adb == null) { + return; + } + + Log.d(TAG, mDeviceIp + " Connected"); + boolean res = false; + + String[] cmds = { + "am force-stop com.mediatek.camera", + "setprop mtk.camera.app.keycode.enable 1", + "setprop mtk.camera.switch.camera.debug 1", + "setprop mtk.camera.switch.id.debug back-1", + "am start -a android.media.action.STILL_IMAGE_CAMERA --ez com.google.assistant.extra.USE_FRONT_CAMERA true -f " + Integer.toString(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP), + "wait", + "input keyevent 27"}; + + AdbShellResponse adbShellResponse = null; + for (String cmd : cmds) { + if (cmd.equals("wait")) { + try { + Thread.sleep(3000); + } catch (Exception ex) { + ex.printStackTrace(); + } + continue; + } + try { + adbShellResponse = adb.shell(cmd); + } catch (Exception ex) { + ex.printStackTrace(); + } + + Log.i(TAG, "CMD: " + cmd); + if (adbShellResponse.getExitCode() == 0) { + String[] lines = FilesUtils.splitLines(adbShellResponse.getAllOutput()); + for (String line : lines) { + Log.i(TAG, line); + } + } + + + } + } + })).start(); + } +} diff --git a/common/src/main/java/com/xypower/common/FilesUtils.java b/common/src/main/java/com/xypower/common/FilesUtils.java index 892db452..24645db2 100644 --- a/common/src/main/java/com/xypower/common/FilesUtils.java +++ b/common/src/main/java/com/xypower/common/FilesUtils.java @@ -31,6 +31,8 @@ public class FilesUtils { while ((bytesRead = input.read(buf)) > 0) { output.write(buf, 0, bytesRead); } + } catch (Exception ex) { + ex.printStackTrace(); } finally { try { if (input != null) input.close();