本文修改的源码是 Android 10 mt6580平台,由于解决的项目没有传感器,所以是强制横屏
相当于 getContext().getResources().getConfiguration().orientation == 2
以下是修改过程
**Camera2源码位置:**vendor/mediatek/proprietary/packages/apps/Camera2
1.vendor/mediatek/proprietary/packages/apps/Camera2/host/AndroidManifest.xml
或者在CameraActivity中添加setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
屏蔽横竖切换代码(UI强制横屏)
1.vendor/mediatek/proprietary/packages/apps/Camera2/host/src/com/mediatek/camera/CameraActivity.java
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
//add start
/*RotateLayout root = (RotateLayout) findViewById(R.id.app_ui);
LogHelper.d(TAG, "onConfigurationChanged orientation = " + newConfig.orientation);
if (root != null) {
if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
root.setOrientation(0, false);
} else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
root.setOrientation(90, false);
}
mCameraAppUI.onConfigurationChanged(newConfig);
}*/
//add end
}
2.vendor/mediatek/proprietary/packages/apps/Camera2/host/src/com/mediatek/camera/ui/CameraAppUI.java
public void onCreate() {
ViewGroup rootView = (ViewGroup) mApp.getActivity()
.findViewById(R.id.app_ui_root);
ViewGroup parentView = (ViewGroup) mApp.getActivity().getLayoutInflater()
.inflate(R.layout.camera_ui_root, rootView, true);
View appUI = parentView.findViewById(R.id.camera_ui_root);
if (CameraUtil.isHasNavigationBar(mApp.getActivity())) {
//get navigation bar height.
int navigationBarHeight = CameraUtil.getNavigationBarHeight(mApp.getActivity());
//set root view bottom margin to let the UI above the navigation bar.
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) appUI.getLayoutParams();
if (CameraUtil.isTablet()) {
int displayRotation = CameraUtil.getDisplayRotation(mApp.getActivity());
LogHelper.d(TAG, " onCreate displayRotation " + displayRotation);
if (displayRotation == 90 || displayRotation == 270) {
params.leftMargin += navigationBarHeight;
appUI.setLayoutParams(params);
} else {
params.bottomMargin += navigationBarHeight;
appUI.setLayoutParams(params);
}
} else {
//add start
//params.bottomMargin += navigationBarHeight;
params.rightMargin += navigationBarHeight;
appUI.setLayoutParams(params);
//add end
}
}
........
}
/**
* Called when activity's onResume() is invoked.
*/
public void onResume() {
///M: add start
/*RotateLayout root = (RotateLayout) mApp.getActivity().findViewById(R.id.app_ui);
Configuration newConfig = mApp.getActivity().getResources().getConfiguration();
hideAlertDialog();
LogHelper.d(TAG, "onResume orientation = " + newConfig.orientation);
if (root != null) {
if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
root.setOrientation(0, false);
} else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
root.setOrientation(90, false);
}
}*/
///M: add end
...............
}
1.拍照录像不能滑动处理(源码Camera2点击preview对焦也是这里实现)
vendor/mediatek/proprietary/packages/apps/Camera2/host/src/com/mediatek/camera/ui/CameraAppUI.java
private class OnTouchListenerImpl implements View.OnTouchListener {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (mGestureManager != null) {
//M:add start
/*Rect rect = new Rect();
getShutterRootView().getHitRect(rect);
Configuration config = mApp.getActivity().getResources().getConfiguration();
f (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
if (motionEvent.getRawY() > rect.top) {
//If the touch point is below shutter, ignore it.
return true;
} else if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
if (motionEvent.getRawX() > rect.top) {
//If the touch point is below shutter, ignore it.
return true;
}
}
if (motionEvent.getRawX() > rect.top) {
//If the touch point is below shutter, ignore it.
return true;
}*/
///M: add end
mGestureManager.getOnTouchListener().onTouch(view, motionEvent);
}
return true;
}
}
vendor/mediatek/proprietary/packages/apps/Camera2/host/src/com/mediatek/camera/ui/shutter/ShutterRootLayout.java
/**
* Gesture listener implementer.
*/
private class GestureListenerImpl implements IAppUiListener.OnGestureListener {
private float mTransitionX;
private float mTransitionY;
private boolean mIsScale;
@Override
public boolean onDown(MotionEvent event) {
mTransitionX = 0;
mTransitionY = 0;
return false;
}
@Override
public boolean onUp(MotionEvent event) {
mTransitionX = 0;
mTransitionY = 0;
return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float dx, float dy) {
if (e2.getPointerCount() > 1) {
return false;
}
if (getChildCount() < 2) {
return false;
}
if (mIsScale) {
return false;
}
if (mScroller.isFinished() && isEnabled() && mResumed) {
mTransitionX += dx;
mTransitionY += dy;
///M: add start
/*Configuration config = getResources().getConfiguration();
if (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
if (Math.abs(mTransitionX) > MINI_SCROLL_LENGTH
&& Math.abs(mTransitionY) < Math.abs(mTransitionX)) {
if (mTransitionX > 0 && mCurrentIndex < (getChildCount() - 1)) {
if (getVisibility() != VISIBLE) {
return false;
}
if (getChildAt(mCurrentIndex + 1).getVisibility() != VISIBLE) {
return false;
}
snapTOShutter(mCurrentIndex + 1, ANIM_DURATION_MS);
} else if (mTransitionX < 0 && mCurrentIndex > 0) {
if (getVisibility() != VISIBLE) {
return false;
}
if (getChildAt(mCurrentIndex - 1).getVisibility() != VISIBLE) {
return false;
}
snapTOShutter(mCurrentIndex - 1, ANIM_DURATION_MS);
}
return true;
} else if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
if (Math.abs(mTransitionY) > MINI_SCROLL_LENGTH
&& Math.abs(mTransitionX) < Math.abs(mTransitionY)) {
if (mTransitionY < 0 && mCurrentIndex < (getChildCount() - 1)) {
if (getChildAt(mCurrentIndex + 1).getVisibility() != VISIBLE) {
return false;
}
snapTOShutter(mCurrentIndex + 1, ANIM_DURATION_MS);
} else if (mTransitionY > 0 && mCurrentIndex > 0) {
if (getChildAt(mCurrentIndex - 1).getVisibility() != VISIBLE) {
return false;
}
snapTOShutter(mCurrentIndex - 1, ANIM_DURATION_MS);
}
}
}*/
if (Math.abs(mTransitionX) > MINI_SCROLL_LENGTH &&
Math.abs(mTransitionY) < Math.abs(mTransitionX)) {
if (mTransitionX > 0 && mCurrentIndex < (getChildCount() - 1)) {
if (getVisibility() != VISIBLE) {
return false;
}
if (getChildAt(mCurrentIndex + 1).getVisibility() != VISIBLE) {
return false;
}
snapTOShutter(mCurrentIndex + 1, ANIM_DURATION_MS);
} else if (mTransitionX < 0 && mCurrentIndex > 0) {
if (getVisibility() != VISIBLE) {
return false;
}
if (getChildAt(mCurrentIndex - 1).getVisibility() != VISIBLE) {
return false;
}
snapTOShutter(mCurrentIndex - 1, ANIM_DURATION_MS);
}
return true;
}
///M: add end
return false;
} else {
return true;
}
}
......................
}
以上解决了拍照和录像滑动切换问题
vendor/mediatek/proprietary/packages/apps/Camera2/common/src/com/mediatek/camera/common/mode/photo/device/PhotoDevice2Controller.java
private Builder doCreateAndConfigRequest(int templateType) throws CameraAccessException {
LogHelper.i(TAG, "[doCreateAndConfigRequest] mCamera2Proxy =" + mCamera2Proxy);
CaptureRequest.Builder builder = null;
if (mCamera2Proxy != null) {
builder = mCamera2Proxy.createCaptureRequest(templateType);
if (builder == null) {
LogHelper.d(TAG, "Builder is null, ignore this configuration");
return null;
}
mSettingDevice2Configurator.configCaptureRequest(builder);
ThumbnailHelper.configPostViewRequest(builder);
configureQuickPreview(builder);
configureBGService(builder);
configurePdafImgo(builder);
if (Camera2Proxy.TEMPLATE_PREVIEW == templateType) {
builder.addTarget(mPreviewSurface);
} else if (Camera2Proxy.TEMPLATE_STILL_CAPTURE == templateType) {
builder.addTarget(mCaptureSurface.getSurface());
if ("off".equalsIgnoreCase(mZsdStatus)) {
builder.addTarget(mPreviewSurface);
}
if (ThumbnailHelper.isPostViewOverrideSupported()) {
builder.addTarget(mThumbnailSurface.getSurface());
}
ThumbnailHelper.setDefaultJpegThumbnailSize(builder);
P2DoneInfo.enableP2Done(builder);
CameraUtil.enable4CellRequest(mCameraCharacteristics, builder);
int rotation = CameraUtil.getJpegRotationFromDeviceSpec(
Integer.parseInt(mCurrentCameraId), mJpegRotation, mActivity);
HeifHelper.orientation = rotation;
///M:add start
//builder.set(CaptureRequest.JPEG_ORIENTATION, rotation);
builder.set(CaptureRequest.JPEG_ORIENTATION, 0);
///M:add end
if (mICameraContext.getLocation() != null) {
if (!CameraUtil.is3rdPartyIntentWithoutLocationPermission(mActivity)) {
builder.set(CaptureRequest.JPEG_GPS_LOCATION,
mICameraContext.getLocation());
}
}
}
}
return builder;
}
录像旋转
vendor/mediatek/proprietary/packages/apps/Camera2/common/src/com/mediatek/camera/common/mode/video/recorder/NormalRecorder.java
@Override
public void init(RecorderSpec spec) {
..........
///M:Solve the problem of landscape recorder rotation
//mMediaRecorder.setOrientationHint(spec.orientationHint);
mMediaRecorder.setOrientationHint(0);
..........
}
MTK Camera2处理预览大小都是已经计算好的,获取当前的PictureSize,算出PreviewSize
vendor/mediatek/proprietary/packages/apps/Camera2/common/src/com/mediatek/camera/common/mode/photo/device/PhotoDevice2Controller.java
private void updatePreviewSize() {
//1.获取PictureSize
ISettingManager.SettingController controller = mSettingManager.getSettingController();
String pictureSize = controller.queryValue(KEY_PICTURE_SIZE);
LogHelper.i(TAG, "[updatePreviewSize] :" + pictureSize);
if (pictureSize != null) {
String[] pictureSizes = pictureSize.split("x");
int width = Integer.parseInt(pictureSizes[0]);
int height = Integer.parseInt(pictureSizes[1]);
double ratio = (double) width / height;
//算出PreviewSize
getTargetPreviewSize(ratio);//ratio:一般情况4:3(1.33333333333333)
或16:9(1.7777777777)
}
}
更新SurfaceView或TextureView大小
@Override
public void doCameraOpened(@Nonnull Camera2Proxy camera2proxy) {
LogHelper.i(TAG, "[onOpened] camera2proxy = " + camera2proxy + " preview surface = "
+ mPreviewSurface + " mCameraState = " + mCameraState + "camera2Proxy id = "
+ camera2proxy.getId() + " mCameraId = " + mCurrentCameraId);
try {
if (CameraState.CAMERA_OPENING == getCameraState()
&& camera2proxy != null && camera2proxy.getId().equals(mCurrentCameraId)) {
mCamera2Proxy = camera2proxy;
mFirstFrameArrived = false;
CameraSysTrace.onEventSystrace("donCameraOpened.onCameraOpened", true, true);
if (mModeDeviceCallback != null) {
mModeDeviceCallback.onCameraOpened(mCurrentCameraId);
}
CameraSysTrace.onEventSystrace("donCameraOpened.onCameraOpened", false, true);
updateCameraState(CameraState.CAMERA_OPENED);
ThumbnailHelper.setCameraCharacteristics(mCameraCharacteristics,
mActivity.getApplicationContext(), Integer.parseInt(mCurrentCameraId));
CameraSysTrace.onEventSystrace("donCameraOpened.setCameraCharacteristics", true, true);
mSettingDevice2Configurator.setCameraCharacteristics(mCameraCharacteristics);
CameraSysTrace.onEventSystrace("donCameraOpened.setCameraCharacteristics", false, true);
CameraSysTrace.onEventSystrace("donCameraOpened.updatePreviewPictureSize", true, true);
updatePreviewSize();//设置默认的preview大小
updatePictureSize();//设置照片大小
if (mPreviewSizeCallback != null) {//通过回调来更新SurfaceView)
mPreviewSizeCallback.onPreviewSizeReady(new Size(mPreviewWidth,
mPreviewHeight));
}
........
}
vendor/mediatek/proprietary/packages/apps/Camera2/host/src/com/mediatek/camera/ui/preview/PreviewManager.java
public PreviewManager(IApp app) {
mApp = app;
mPreviewAreaChangedListeners = new CopyOnWriteArrayList<>();
mPreviewFrameLayout =(PreviewFrameLayout) mApp.getActivity()
.findViewById(R.id.preview_layout_container);
int enabledValue = SystemProperties.getInt("vendor.debug.surface.enabled",
DEFAULT_SURFACEVIEW_VALUE);
int appVersion = SystemProperties.getInt("ro.vendor.mtk_camera_app_version",
DEFAULT_APP_VERSION);
LogHelper.i(TAG, "enabledValue = " + enabledValue + " appVersion " + appVersion);
//判断使用SurfaceView还是TextureView(这里使用的SurfaceView,
//如果你当前使用的是TextureView,处理流程也是一样的)
//如果你使用的是别的TextureView,建议使用Google提供的旋转预览的方法
if (enabledValue == SURFACEVIEW_ENABLED_VALUE || appVersion == DEFAULT_APP_VERSION) {
mPreviewController = new SurfaceViewController(app);
} else {
mPreviewController = new TextureViewController(app);
}
.....
}
vendor/mediatek/proprietary/packages/apps/Camera2/host/src/com/mediatek/camera/ui/preview/SurfaceViewController.java
private void attachSurfaceView(ISurfaceStatusListener listener) {
ViewGroup container = (ViewGroup) mApp.getActivity().getLayoutInflater().inflate(
R.layout.surfacepreview_layout, null);
PreviewSurfaceView surfaceView =
(PreviewSurfaceView) container.findViewById(R.id.preview_surface);
surfaceView.setVisibility(View.GONE);
if (mLastPreviewContainer != null) {
SurfaceView surface =
(SurfaceView) mLastPreviewContainer.findViewById(R.id.preview_surface);
surface.removeOnLayoutChangeListener(mOnLayoutChangeListener);
surface.getHolder().removeCallback(mSurfaceChangeCallback);
if (mSurfaceChangeCallback != null) {
mSurfaceChangeCallback.surfaceDestroyed(surface.getHolder());
}
mLastPreviewContainer.bringToFront();
if (!mFrameLayoutQueue.contains(mLastPreviewContainer)) {
mFrameLayoutQueue.add(mLastPreviewContainer);
}
}
SurfaceHolder surfaceHolder = surfaceView.getHolder();
mSurfaceChangeCallback = new SurfaceChangeCallback(listener);
surfaceHolder.addCallback(mSurfaceChangeCallback);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceView.addOnLayoutChangeListener(mOnLayoutChangeListener);
surfaceView.setOnTouchListener(mOnTouchListener);
mPreviewRoot.addView(container, 0);
mPreviewContainer = container;
mSurfaceView = surfaceView;
mSurfaceView.setVisibility(View.VISIBLE);
}
//通过PreviewSizeCallback的回调来更新大小( PhotoMode.java中转调用)
@Override
public void updatePreviewSize(int width, int height, ISurfaceStatusListener listener) {
LogHelper.i(TAG, "updatePreviewSize: new size (" + width + " , " + height + " )"
+ " current size (" + mPreviewWidth + " , " + mPreviewHeight + " )" + "," +
"mIsSurfaceCreated = " + mIsSurfaceCreated +
" listener = " + listener);
if (mPreviewWidth == width && mPreviewHeight == height) {
//If preview size is same, just call back surface available.
ISurfaceStatusListener l = mSurfaceChangeCallback.getBindStatusListener();
if (listener != null && listener != l) {
mSurfaceView.getHolder().removeCallback(mSurfaceChangeCallback);
mSurfaceChangeCallback = new SurfaceChangeCallback(listener);
mSurfaceView.getHolder().addCallback(mSurfaceChangeCallback);
}
if (mIsSurfaceCreated) {
if (listener != null) {
listener.surfaceAvailable(mSurfaceView.getHolder(),
mPreviewWidth, mPreviewHeight);
}
}
return;
}
if (mPreviewAspectRatio != 0) {
mLastPreviewContainer = mPreviewContainer;
mSurfaceView = null;
} else {
double ratio = (double) Math.max(width, height)
/ Math.min(width, height);
if (mSurfaceView != null && !mSurfaceView.isFullScreenPreview(ratio)) {
mLastPreviewContainer = mPreviewContainer;
mSurfaceView = null;
}
}
mPreviewWidth = width;
mPreviewHeight = height;
mPreviewAspectRatio = (double) Math.max(width, height)
/ Math.min(width, height);
//onCreate加载
//其他的代码都是onPause状态加载
attachSurfaceView(listener);
} else {
mSurfaceView.getHolder().removeCallback(mSurfaceChangeCallback);
mSurfaceChangeCallback = new SurfaceChangeCallback(listener);
mSurfaceView.getHolder().addCallback(mSurfaceChangeCallback);
}
mSurfaceView.getHolder().setFixedSize(mPreviewWidth, mPreviewHeight);
mSurfaceView.setAspectRatio(mPreviewAspectRatio);
vendor/mediatek/proprietary/packages/apps/Camera2/host/src/com/mediatek/camera/ui/preview/PreviewSurfaceView.java
更新ui
public void setAspectRatio(double aspectRatio) {
if (mAspectRatio != aspectRatio) {
mAspectRatio = aspectRatio;
requestLayout();
}
}
制定大小
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int previewWidth = MeasureSpec.getSize(widthMeasureSpec);
int previewHeight = MeasureSpec.getSize(heightMeasureSpec);
boolean widthLonger = previewWidth > previewHeight;
int longSide = (widthLonger ? previewWidth : previewHeight);
int shortSide = (widthLonger ? previewHeight : previewWidth);
if (mAspectRatio > 0) {
double fullScreenRatio = findFullscreenRatio(getContext());
if (Math.abs((mAspectRatio - fullScreenRatio)) <= ASPECT_TOLERANCE) {
// full screen preview case
if (longSide < shortSide * mAspectRatio) {
longSide = Math.round((float) (shortSide * mAspectRatio) / 2) * 2;
} else {
shortSide = Math.round((float) (longSide / mAspectRatio) / 2) * 2;
}
} else {
// standard (4:3) preview case
if (longSide > shortSide * mAspectRatio) {
longSide = Math.round((float) (shortSide * mAspectRatio) / 2) * 2;
} else {
shortSide = Math.round((float) (longSide / mAspectRatio) / 2) * 2;
}
}
}
if (widthLonger) {
previewWidth = longSide;
previewHeight = shortSide;
} else {
previewWidth = shortSide;
previewHeight = longSide;
}
setMeasuredDimension(previewWidth, previewHeight);
}
以上就是Camera2 Preview大小更新的流程,源码已经进行了处理,我们只需要将Camera 驱动进行旋转
vendor/mediatek/proprietary/custom/平台(我这边是mt6580)/hal/imgsensor_metadata/common/config_static_metadata_common.h
//------------------------------------------------------------------------------
// android.sensor
//------------------------------------------------------------------------------
//==========================================================================
switch (rInfo.getDeviceId())
{
case 0://后置摄像头
//======================================================================
CONFIG_METADATA_BEGIN(MTK_SENSOR_INFO_ORIENTATION)
//CONFIG_ENTRY_VALUE(90, MINT32)
CONFIG_ENTRY_VALUE(0, MINT32)//这里改成0
CONFIG_METADATA_END()
//======================================================================
CONFIG_METADATA_BEGIN(MTK_SENSOR_ORIENTATION)
//CONFIG_ENTRY_VALUE(90, MINT32)
CONFIG_ENTRY_VALUE(0, MINT32)//这里改成0
CONFIG_METADATA_END()
//======================================================================
CONFIG_METADATA_BEGIN(MTK_SENSOR_INFO_WANTED_ORIENTATION)
//CONFIG_ENTRY_VALUE(90, MINT32)//这里改成0
CONFIG_ENTRY_VALUE(0, MINT32)
CONFIG_METADATA_END()
//======================================================================
CONFIG_METADATA_BEGIN(MTK_SENSOR_INFO_FACING)
CONFIG_ENTRY_VALUE(MTK_LENS_FACING_BACK, MUINT8)
CONFIG_METADATA_END()
//======================================================================
CONFIG_METADATA_BEGIN(MTK_HAL_VERSION)
CONFIG_ENTRY_VALUE(MTK_HAL_VERSION_1_0, MINT32)
CONFIG_METADATA_END()
//======================================================================
CONFIG_METADATA_BEGIN(MTK_FLASH_INFO_AVAILABLE)
CONFIG_ENTRY_VALUE(MTK_FLASH_INFO_AVAILABLE_TRUE, MUINT8)
CONFIG_METADATA_END()
//======================================================================
break;
case 1://前置摄像头
//======================================================================
CONFIG_METADATA_BEGIN(MTK_SENSOR_INFO_ORIENTATION)
CONFIG_ENTRY_VALUE(270, MINT32)
CONFIG_METADATA_END()
//======================================================================
CONFIG_METADATA_BEGIN(MTK_SENSOR_INFO_WANTED_ORIENTATION)
CONFIG_ENTRY_VALUE(270, MINT32)
CONFIG_METADATA_END()
//======================================================================
CONFIG_METADATA_BEGIN(MTK_SENSOR_INFO_FACING)
CONFIG_ENTRY_VALUE(MTK_LENS_FACING_FRONT, MUINT8)
CONFIG_METADATA_END()
//======================================================================
CONFIG_METADATA_BEGIN(MTK_HAL_VERSION)
CONFIG_ENTRY_VALUE(MTK_HAL_VERSION_1_0, MINT32)
CONFIG_METADATA_END()
//======================================================================
CONFIG_METADATA_BEGIN(MTK_FLASH_INFO_AVAILABLE)
CONFIG_ENTRY_VALUE(MTK_FLASH_INFO_AVAILABLE_FALSE, MUINT8)
CONFIG_METADATA_END()
//======================================================================
CONFIG_METADATA_BEGIN(MTK_SENSOR_ORIENTATION)
CONFIG_ENTRY_VALUE(270, MINT32)
CONFIG_METADATA_END()
//======================================================================
break;
..........
}
以上就是Camera2横屏方案了,还有对焦框和人脸识别框 在这里有相关的处理 https://blog.csdn.net/u012932409/article/details/103243162#commentBox