call: use TextureView for camera preview
Change-Id: I764078009b604a012c73e8eeff2f18a77b955d04
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.java
index 797b8cf..cc1e54e 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.java
@@ -20,6 +20,7 @@
*/
package cx.ring.fragments;
+import android.app.Activity;
import android.app.PendingIntent;
import android.app.PictureInPictureParams;
import android.app.RemoteAction;
@@ -27,8 +28,11 @@
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
+import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.SurfaceTexture;
import android.graphics.drawable.Icon;
import android.os.Build;
import android.os.Bundle;
@@ -44,10 +48,13 @@
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
+import android.view.Surface;
import android.view.SurfaceHolder;
+import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
+import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import com.rodolfonavalon.shaperipplelibrary.model.Circle;
@@ -100,6 +107,7 @@
private boolean restartVideo = false;
private PowerManager.WakeLock mScreenWakeLock;
private int mCurrentOrientation = Configuration.ORIENTATION_UNDEFINED;
+ private int mPreviewWidth = 720, mPreviewHeight = 1280;
private final CompositeDisposable mCompositeDisposable = new CompositeDisposable();
@@ -241,6 +249,29 @@
return binding.getRoot();
}
+
+ private TextureView.SurfaceTextureListener listener = new TextureView.SurfaceTextureListener() {
+ @Override
+ public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+ configureTransform(width, height);
+ presenter.previewVideoSurfaceCreated(binding.previewSurface);
+ }
+
+ @Override
+ public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+ configureTransform(width, height);
+ }
+
+ @Override
+ public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+ presenter.previewVideoSurfaceDestroyed();
+ return true;
+ }
+
+ @Override
+ public void onSurfaceTextureUpdated(SurfaceTexture surface) {}
+ };
+
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
setHasOptionsMenu(true);
@@ -271,31 +302,14 @@
presenter.videoSurfaceDestroyed();
}
});
- view.addOnLayoutChangeListener((parent, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> presenter.layoutChanged());
view.setOnSystemUiVisibilityChangeListener(visibility -> {
boolean ui = (visibility & (View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN)) == 0;
presenter.uiVisibilityChanged(ui);
});
- binding.previewSurface.getHolder().addCallback(new SurfaceHolder.Callback() {
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- presenter.previewVideoSurfaceCreated(holder);
- }
-
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
-
- }
-
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- presenter.previewVideoSurfaceDestroyed();
- }
- });
- binding.previewSurface.setZOrderMediaOverlay(true);
binding.shapeRipple.setRippleShape(new Circle());
binding.callSpeakerBtn.setChecked(presenter.isSpeakerphoneOn());
+ binding.previewSurface.setSurfaceTextureListener(listener);
binding.dialpadEditText.addTextChangedListener(new TextWatcher() {
@Override
@@ -389,8 +403,9 @@
@Override
public void displayVideoSurface(final boolean display) {
+ Log.w(TAG, "displayVideoSurface " + display);
binding.videoSurface.setVisibility(display ? View.VISIBLE : View.GONE);
- binding.previewSurface.setVisibility(display ? View.VISIBLE : View.GONE);
+ //binding.previewSurface.setVisibility(display ? View.VISIBLE : View.GONE);
updateMenu();
}
@@ -398,10 +413,10 @@
public void displayPreviewSurface(final boolean display) {
if (display) {
binding.videoSurface.setZOrderOnTop(false);
- binding.previewSurface.setZOrderMediaOverlay(true);
+ //binding.previewSurface.setZOrderMediaOverlay(true);
binding.videoSurface.setZOrderMediaOverlay(false);
} else {
- binding.previewSurface.setZOrderMediaOverlay(false);
+ //binding.previewSurface.setZOrderMediaOverlay(false);
binding.videoSurface.setZOrderMediaOverlay(true);
binding.videoSurface.setZOrderOnTop(true);
}
@@ -570,45 +585,36 @@
if (previewWidth == -1 && previewHeight == -1)
return;
+ mPreviewWidth = previewWidth;
+ mPreviewHeight = previewHeight;
Log.w(TAG, "resetVideoSize preview: " + previewWidth + "x" + previewHeight);
- ViewGroup.LayoutParams paramsPreview = binding.previewSurface.getLayoutParams();
- DisplayMetrics metrics = getResources().getDisplayMetrics();
+ }
- oldW = paramsPreview.width;
- oldH = paramsPreview.height;
- double previewMaxDim = Math.max(previewWidth, previewHeight);
- double previewRatio = metrics.density * 160. / previewMaxDim;
- paramsPreview.width = (int) (previewWidth * previewRatio);
- paramsPreview.height = (int) (previewHeight * previewRatio);
-
- if (oldW != paramsPreview.width || oldH != paramsPreview.height) {
- Log.w(TAG, "mVideoPreview.setLayoutParams: " + paramsPreview.width + "x" + paramsPreview.height + " was: " + oldW + "x"+oldH);
- binding.previewSurface.setLayoutParams(paramsPreview);
+ private void configureTransform(int viewWidth, int viewHeight) {
+ Activity activity = getActivity();
+ if (null == binding.previewSurface|| null == activity) {
+ return;
}
-
- /*final int mPreviewWidth;
- final int mPreviewHeight;
-
- if (mCurrentOrientation == Configuration.ORIENTATION_PORTRAIT) {
- mPreviewWidth = HardwareServiceImpl.VIDEO_HEIGHT;
- mPreviewHeight = HardwareServiceImpl.VIDEO_WIDTH;
- } else {
- mPreviewWidth = HardwareServiceImpl.VIDEO_WIDTH;
- mPreviewHeight = HardwareServiceImpl.VIDEO_HEIGHT;
+ int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
+ boolean rot = Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation;
+ Log.w(TAG, "configureTransform " + viewWidth + "x" + viewHeight + " rot="+rot + " mPreviewWidth="+mPreviewWidth + " mPreviewHeight="+mPreviewHeight);
+ Matrix matrix = new Matrix();
+ RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
+ float centerX = viewRect.centerX();
+ float centerY = viewRect.centerY();
+ if (rot) {
+ RectF bufferRect = new RectF(0, 0, mPreviewHeight, mPreviewWidth);
+ bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
+ matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
+ float scale = Math.max(
+ (float) viewHeight / mPreviewHeight,
+ (float) viewWidth / mPreviewWidth);
+ matrix.postScale(scale, scale, centerX, centerY);
+ matrix.postRotate(90 * (rotation - 2), centerX, centerY);
+ } else if (Surface.ROTATION_180 == rotation) {
+ matrix.postRotate(180, centerX, centerY);
}
-
- DisplayMetrics metrics = getResources().getDisplayMetrics();
- RelativeLayout.LayoutParams paramsPreview = (RelativeLayout.LayoutParams) mVideoPreview.getLayoutParams();
- oldW = paramsPreview.width;
- oldH = paramsPreview.height;
- double previewMaxDim = Math.max(mPreviewWidth, mPreviewHeight);
- double previewRatio = metrics.density * 160. / previewMaxDim;
- paramsPreview.width = (int) (mPreviewWidth * previewRatio);
- paramsPreview.height = (int) (mPreviewHeight * previewRatio);
-
- if (oldW != paramsPreview.width || oldH != paramsPreview.height) {
- mVideoPreview.setLayoutParams(paramsPreview);
- }*/
+ binding.previewSurface.setTransform(matrix);
}
@Override
diff --git a/ring-android/app/src/main/java/cx/ring/services/CameraService.java b/ring-android/app/src/main/java/cx/ring/services/CameraService.java
index 6b8c672..4e0a63b 100644
--- a/ring-android/app/src/main/java/cx/ring/services/CameraService.java
+++ b/ring-android/app/src/main/java/cx/ring/services/CameraService.java
@@ -183,7 +183,7 @@
void onError();
}
- abstract void openCamera(Context c, VideoParams videoParams, SurfaceHolder surface, CameraListener listener);
+ abstract void openCamera(Context c, VideoParams videoParams, Object surface, CameraListener listener);
abstract void closeCamera();
diff --git a/ring-android/app/src/main/java/cx/ring/services/CameraServiceCamera2.java b/ring-android/app/src/main/java/cx/ring/services/CameraServiceCamera2.java
index fa56b23..ceccee0 100644
--- a/ring-android/app/src/main/java/cx/ring/services/CameraServiceCamera2.java
+++ b/ring-android/app/src/main/java/cx/ring/services/CameraServiceCamera2.java
@@ -20,8 +20,10 @@
package cx.ring.services;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.ImageFormat;
import android.graphics.Point;
+import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
@@ -48,6 +50,8 @@
import android.view.SurfaceHolder;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import androidx.annotation.NonNull;
@@ -56,6 +60,7 @@
import cx.ring.daemon.RingserviceJNI;
import cx.ring.daemon.UintVect;
import cx.ring.utils.Log;
+import cx.ring.views.AutoFitTextureView;
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
class CameraServiceCamera2 extends CameraService {
@@ -200,10 +205,55 @@
return new Pair<>(codec, encoderInput);
}
- @Override
- public void openCamera(Context context, VideoParams videoParams, SurfaceHolder surface, CameraListener listener) {
- Log.e(TAG, "openCamera " + videoParams.width + "x" + videoParams.height);
+ /**
+ * Compares two {@code Size}s based on their areas.
+ */
+ static class CompareSizesByArea implements Comparator<Size> {
+ @Override
+ public int compare(Size lhs, Size rhs) {
+ // We cast here to ensure the multiplications won't overflow
+ return Long.signum((long) lhs.getWidth() * lhs.getHeight() -
+ (long) rhs.getWidth() * rhs.getHeight());
+ }
+
+ }
+
+ private static Size chooseOptimalSize(Size[] choices, int textureViewWidth,
+ int textureViewHeight, int maxWidth, int maxHeight, Size aspectRatio) {
+
+ // Collect the supported resolutions that are at least as big as the preview Surface
+ List<Size> bigEnough = new ArrayList<>();
+ // Collect the supported resolutions that are smaller than the preview Surface
+ List<Size> notBigEnough = new ArrayList<>();
+ int w = aspectRatio.getWidth();
+ int h = aspectRatio.getHeight();
+ for (Size option : choices) {
+ if (option.getWidth() <= maxWidth && option.getHeight() <= maxHeight &&
+ option.getHeight() == option.getWidth() * h / w) {
+ if (option.getWidth() >= textureViewWidth &&
+ option.getHeight() >= textureViewHeight) {
+ bigEnough.add(option);
+ } else {
+ notBigEnough.add(option);
+ }
+ }
+ }
+
+ // Pick the smallest of those big enough. If there is no one big enough, pick the
+ // largest of those not big enough.
+ if (bigEnough.size() > 0) {
+ return Collections.min(bigEnough, new CompareSizesByArea());
+ } else if (notBigEnough.size() > 0) {
+ return Collections.max(notBigEnough, new CompareSizesByArea());
+ } else {
+ android.util.Log.e(TAG, "Couldn't find any suitable preview size");
+ return choices[0];
+ }
+ }
+
+ @Override
+ public void openCamera(Context context, VideoParams videoParams, Object surface, CameraListener listener) {
CameraDevice camera = previewCamera;
if (camera != null) {
camera.close();
@@ -220,14 +270,41 @@
Size[] sizes = streamConfigs.getOutputSizes(SurfaceHolder.class);
for (Size s : sizes)
Log.w(TAG, "supportedSize: " + s);
-
+ AutoFitTextureView view = (AutoFitTextureView) surface;
+ //view.getSurfaceTexture().
boolean flip = videoParams.rotation % 180 != 0;
- surface.setFixedSize(flip ? videoParams.height : videoParams.width, flip ? videoParams.width : videoParams.height);
- Surface s = surface.getSurface();
+
+ Size previewSize = chooseOptimalSize(sizes,
+ flip ? view.getHeight() : view.getWidth(), flip ? view.getWidth() : view.getHeight(),
+ videoParams.width, videoParams.height,
+ new Size(videoParams.width, videoParams.height));
+
+ //videoParams.
+ Log.e(TAG, "openCamera " + videoParams.width + "x" + videoParams.height + " flip:" + flip);
+ Log.e(TAG, "openCamera " + videoParams.rotWidth + "x" + videoParams.rotHeight);
+ Log.e(TAG, "openCamera view " + view.getWidth() + "x" + view.getHeight());
+ Log.e(TAG, "openCamera previewSize " + previewSize.getWidth() + "x" + previewSize.getHeight());
+
+ //view.setAspectRatio(flip ? videoParams.height : videoParams.width, flip ? videoParams.width : videoParams.height);
+ //view.setAspectRatio(videoParams.height, videoParams.width);
+ int orientation = context.getResources().getConfiguration().orientation;
+ if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ view.setAspectRatio(
+ previewSize.getWidth(), previewSize.getHeight());
+ } else {
+ view.setAspectRatio(
+ previewSize.getHeight(), previewSize.getWidth());
+ }
+
+ SurfaceTexture texture = view.getSurfaceTexture();
+ //texture.setDefaultBufferSize(flip ? previewSize.getHeight() : previewSize.getWidth(), flip ? previewSize.getWidth() : previewSize.getHeight());
+
+ Surface s = new Surface(texture);
+ //s.setFixedSize(flip ? videoParams.height : videoParams.width, flip ? videoParams.width : videoParams.height);
Pair<MediaCodec, Surface> codec = USE_HARDWARE_ENCODER ? openCameraWithEncoder(videoParams, MediaFormat.MIMETYPE_VIDEO_VP8) : null;
- List<Surface> targets = new ArrayList<>(2);
+ final List<Surface> targets = new ArrayList<>(2);
targets.add(s);
ImageReader tmpReader = null;
if (codec != null && codec.second != null) {
@@ -249,6 +326,7 @@
try {
Log.w(TAG, "onOpened");
previewCamera = camera;
+ texture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
CaptureRequest.Builder builder = camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
builder.addTarget(s);
if (codec != null && codec.second != null) {
@@ -259,6 +337,7 @@
builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO);
builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
builder.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_AUTO);
+ //builder.set(CaptureRequest.);
final CaptureRequest request = builder.build();
camera.createCaptureSession(targets, new CameraCaptureSession.StateCallback() {
diff --git a/ring-android/app/src/main/java/cx/ring/services/CameraServiceKitKat.java b/ring-android/app/src/main/java/cx/ring/services/CameraServiceKitKat.java
index 48b8ffa..522324e 100644
--- a/ring-android/app/src/main/java/cx/ring/services/CameraServiceKitKat.java
+++ b/ring-android/app/src/main/java/cx/ring/services/CameraServiceKitKat.java
@@ -66,7 +66,7 @@
}
@Override
- public void openCamera(Context c, VideoParams videoParams, SurfaceHolder surface, CameraListener listener) {
+ public void openCamera(Context c, VideoParams videoParams, Object surface, CameraListener listener) {
final Camera preview;
try {
if (previewCamera != null) {
@@ -82,7 +82,7 @@
}
try {
- preview.setPreviewDisplay(surface);
+ preview.setPreviewDisplay((SurfaceHolder) surface);
} catch (IOException e) {
Log.e(TAG, "setPreviewDisplay: " + e.getMessage());
return;
diff --git a/ring-android/app/src/main/java/cx/ring/services/HardwareServiceImpl.java b/ring-android/app/src/main/java/cx/ring/services/HardwareServiceImpl.java
index ffe125d..61adc3a 100644
--- a/ring-android/app/src/main/java/cx/ring/services/HardwareServiceImpl.java
+++ b/ring-android/app/src/main/java/cx/ring/services/HardwareServiceImpl.java
@@ -33,6 +33,7 @@
import androidx.annotation.Nullable;
+import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.WindowManager;
@@ -64,7 +65,7 @@
public static final int VIDEO_HEIGHT = 480;
private static final String TAG = HardwareServiceImpl.class.getName();
- private static WeakReference<SurfaceHolder> mCameraPreviewSurface = new WeakReference<>(null);
+ private static WeakReference<Object> mCameraPreviewSurface = new WeakReference<>(null);
private static final Map<String, WeakReference<SurfaceHolder>> videoSurfaces = Collections.synchronizedMap(new HashMap<String, WeakReference<SurfaceHolder>>());
private final Map<String, Shm> videoInputs = new HashMap<>();
private final Context mContext;
@@ -380,7 +381,7 @@
Log.w(TAG, "startCapture: no video parameters ");
return;
}
- final SurfaceHolder surface = mCameraPreviewSurface.get();
+ final Object surface = mCameraPreviewSurface.get();
if (surface == null) {
Log.w(TAG, "Can't start capture: no surface registered.");
cameraService.setPreviewParams(videoParams);
@@ -413,7 +414,6 @@
event.w = s ? videoParams.height : videoParams.width;
event.h = s ? videoParams.width : videoParams.height;
videoEvents.onNext(event);
-
}
@Override
@@ -471,14 +471,15 @@
@Override
public void addPreviewVideoSurface(Object oholder) {
- if (!(oholder instanceof SurfaceHolder)) {
+ /*if (!(oholder instanceof SurfaceHolder)) {
return;
}
- SurfaceHolder holder = (SurfaceHolder)oholder;
- Log.w(TAG, "addPreviewVideoSurface " + holder.hashCode() + " mCapturingId " + mCapturingId);
- if (mCameraPreviewSurface.get() == holder)
+ SurfaceHolder holder = (SurfaceHolder)oholder;*/
+ //Surface holder = (Surface) oholder;
+ Log.w(TAG, "addPreviewVideoSurface " + oholder.hashCode() + " mCapturingId " + mCapturingId);
+ if (mCameraPreviewSurface.get() == oholder)
return;
- mCameraPreviewSurface = new WeakReference<>(holder);
+ mCameraPreviewSurface = new WeakReference<>(oholder);
if (mShouldCapture && !mIsCapturing) {
startCapture(mCapturingId);
}
diff --git a/ring-android/app/src/main/java/cx/ring/views/AutoFitTextureView.java b/ring-android/app/src/main/java/cx/ring/views/AutoFitTextureView.java
new file mode 100644
index 0000000..cc17996
--- /dev/null
+++ b/ring-android/app/src/main/java/cx/ring/views/AutoFitTextureView.java
@@ -0,0 +1,105 @@
+package cx.ring.views;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.TextureView;
+
+/**
+ * A {@link TextureView} that can be adjusted to a specified aspect ratio.
+ */
+public class AutoFitTextureView extends TextureView {
+
+ private int mRatioWidth = 720;
+ private int mRatioHeight = 1280;
+ private final int mSize;
+
+ public AutoFitTextureView(Context context) {
+ this(context, null);
+ }
+
+ public AutoFitTextureView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public AutoFitTextureView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ mSize = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 192, context.getResources().getDisplayMetrics()));
+ }
+
+ /**
+ * Sets the aspect ratio for this view. The size of the view will be measured based on the ratio
+ * calculated from the parameters. Note that the actual sizes of parameters don't matter, that
+ * is, calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the same result.
+ *
+ * @param width Relative horizontal size
+ * @param height Relative vertical size
+ */
+ public void setAspectRatio(int width, int height) {
+ if (width < 0 || height < 0) {
+ throw new IllegalArgumentException("Size cannot be negative.");
+ }
+ Log.w("AutoFitTextureView", "setAspectRatio " + width + "x" + height);
+ mRatioWidth = width;
+ mRatioHeight = height;
+ requestLayout();
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ Log.w("AutoFitTextureView", "onMeasure " + widthMeasureSpec + " " + heightMeasureSpec);
+ //int width = MeasureSpec.getSize(widthMeasureSpec);
+ //int height = MeasureSpec.getSize(heightMeasureSpec);
+ int width = Math.min(MeasureSpec.getSize(widthMeasureSpec), mSize);
+ int height = Math.min(MeasureSpec.getSize(heightMeasureSpec), mSize);
+ //MeasureSpec.getMode(widthMeasureSpec);
+ if (0 == mRatioWidth || 0 == mRatioHeight) {
+ setMeasuredDimension(width, height);
+ } else {
+ /*int maxDim = Math.min(Math.max(width, height), mSize);
+ if (width > height) {
+ setMeasuredDimension(maxDim, maxDim * mRatioHeight / mRatioWidth);
+ } else {
+ setMeasuredDimension(maxDim * mRatioWidth / mRatioHeight, maxDim);
+ }*/
+ if (width < height * mRatioWidth / mRatioHeight) {
+ setMeasuredDimension(width, width * mRatioHeight / mRatioWidth);
+ } else {
+ setMeasuredDimension(height * mRatioWidth / mRatioHeight, height);
+ }
+ }
+ }
+ /*@Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+ Log.w("AutoFitTextureView", "onMeasure " + width + "x" + height);
+ //width = Math.min(width, mSize);
+ //height = Math.min(height, mSize);
+ if (0 != mRatioWidth && 0 != mRatioHeight) {
+ int wrh = width * mRatioHeight;
+ int hrw = height * mRatioWidth;
+ //if (wrh == hrw) {
+ // setMeasuredDimension(width, height);
+ // return;
+ //}
+ float w, h;
+ if (wrh < hrw) {
+ w = width;
+ h = wrh / (float)mRatioWidth;
+ } else {
+ w = hrw / (float)mRatioHeight;
+ h = height;
+ }
+ //width = Math.round(w);
+ //height = Math.round(h);
+ Log.w("AutoFitTextureView", "setMeasuredDimension " + width + "x" + height + " ratio: " + (width > height ? height/(float)width : width/(float)height));
+ setMeasuredDimension((int)w, (int)h);
+ } else {
+ setMeasuredDimension(0, 0);
+ }
+ }*/
+}
diff --git a/ring-android/app/src/main/res/layout-land/frag_call.xml b/ring-android/app/src/main/res/layout-land/frag_call.xml
index bda5f2c..701e04f 100644
--- a/ring-android/app/src/main/res/layout-land/frag_call.xml
+++ b/ring-android/app/src/main/res/layout-land/frag_call.xml
@@ -46,15 +46,23 @@
android:visibility="gone"
tools:visibility="visible" />
- <SurfaceView
- android:id="@+id/preview_surface"
- android:layout_width="160dp"
- android:layout_height="120dp"
+ <androidx.cardview.widget.CardView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_margin="12dp"
- android:visibility="gone"
- tools:visibility="visible" />
+ app:cardCornerRadius="16dp"
+ app:cardPreventCornerOverlap="false">
+
+ <cx.ring.views.AutoFitTextureView
+ android:id="@+id/preview_surface"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="visible"
+ tools:visibility="visible" />
+ </androidx.cardview.widget.CardView>
+
</RelativeLayout>
<RelativeLayout
@@ -216,7 +224,7 @@
android:layout_height="wrap_content"
android:layout_margin="12dp"
android:background="@drawable/call_button_background"
- android:contentDescription="Mute microphone"
+ android:contentDescription="@string/action_call_mic_mute"
android:onClick="@{() -> presenter.micClicked()}"
android:padding="16dp"
android:tint="@color/white"
diff --git a/ring-android/app/src/main/res/layout-w720dp-land/tv_frag_call.xml b/ring-android/app/src/main/res/layout-w720dp-land/tv_frag_call.xml
index 1f5ba41..db2cec6 100644
--- a/ring-android/app/src/main/res/layout-w720dp-land/tv_frag_call.xml
+++ b/ring-android/app/src/main/res/layout-w720dp-land/tv_frag_call.xml
@@ -35,15 +35,22 @@
android:visibility="gone"
tools:visibility="visible" />
- <SurfaceView
- android:id="@+id/preview_surface"
- android:layout_width="160dp"
- android:layout_height="120dp"
- android:layout_alignParentBottom="true"
+ <androidx.cardview.widget.CardView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
- android:layout_margin="8dp"
- android:visibility="gone"
- tools:visibility="visible" />
+ android:layout_alignParentBottom="true"
+ android:layout_margin="12dp"
+ app:cardCornerRadius="16dp"
+ app:cardPreventCornerOverlap="false">
+
+ <cx.ring.views.AutoFitTextureView
+ android:id="@+id/preview_surface"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="visible"
+ tools:visibility="visible" />
+ </androidx.cardview.widget.CardView>
<LinearLayout
android:id="@+id/contact_bubble_layout"
diff --git a/ring-android/app/src/main/res/layout/frag_call.xml b/ring-android/app/src/main/res/layout/frag_call.xml
index fc7ea624..beebdd0 100644
--- a/ring-android/app/src/main/res/layout/frag_call.xml
+++ b/ring-android/app/src/main/res/layout/frag_call.xml
@@ -46,15 +46,23 @@
android:visibility="gone"
tools:visibility="visible" />
- <SurfaceView
- android:id="@+id/preview_surface"
- android:layout_width="160dp"
- android:layout_height="120dp"
+ <androidx.cardview.widget.CardView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_margin="12dp"
- android:visibility="gone"
- tools:visibility="visible" />
+ app:cardCornerRadius="16dp"
+ app:cardPreventCornerOverlap="false">
+
+ <cx.ring.views.AutoFitTextureView
+ android:id="@+id/preview_surface"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="visible"
+ tools:visibility="visible" />
+ </androidx.cardview.widget.CardView>
+
</RelativeLayout>
<RelativeLayout
@@ -206,7 +214,7 @@
android:layout_height="wrap_content"
android:layout_margin="12dp"
android:background="@drawable/call_button_background"
- android:contentDescription="Mute microphone"
+ android:contentDescription="@string/action_call_mic_mute"
android:onClick="@{() -> presenter.micClicked()}"
android:padding="16dp"
android:tint="@color/white"
@@ -243,13 +251,13 @@
android:layout_centerHorizontal="true"
android:layout_marginBottom="4dp"
android:contentDescription="@string/action_call_hangup"
+ android:onClick="@{() -> presenter.hangUpClicked()}"
app:backgroundTint="@color/error_red"
app:elevation="6dp"
app:fabSize="normal"
app:pressedTranslationZ="12dp"
app:rippleColor="@android:color/white"
app:srcCompat="@drawable/ic_call_end_white"
- android:onClick="@{() -> presenter.hangUpClicked()}"
app:useCompatPadding="true" />
</RelativeLayout>
diff --git a/ring-android/app/src/main/res/layout/tv_frag_call.xml b/ring-android/app/src/main/res/layout/tv_frag_call.xml
index 1f5ba41..db2cec6 100644
--- a/ring-android/app/src/main/res/layout/tv_frag_call.xml
+++ b/ring-android/app/src/main/res/layout/tv_frag_call.xml
@@ -35,15 +35,22 @@
android:visibility="gone"
tools:visibility="visible" />
- <SurfaceView
- android:id="@+id/preview_surface"
- android:layout_width="160dp"
- android:layout_height="120dp"
- android:layout_alignParentBottom="true"
+ <androidx.cardview.widget.CardView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
- android:layout_margin="8dp"
- android:visibility="gone"
- tools:visibility="visible" />
+ android:layout_alignParentBottom="true"
+ android:layout_margin="12dp"
+ app:cardCornerRadius="16dp"
+ app:cardPreventCornerOverlap="false">
+
+ <cx.ring.views.AutoFitTextureView
+ android:id="@+id/preview_surface"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="visible"
+ tools:visibility="visible" />
+ </androidx.cardview.widget.CardView>
<LinearLayout
android:id="@+id/contact_bubble_layout"
diff --git a/ring-android/app/src/main/res/values/strings.xml b/ring-android/app/src/main/res/values/strings.xml
index e2dcf24..89e6177 100644
--- a/ring-android/app/src/main/res/values/strings.xml
+++ b/ring-android/app/src/main/res/values/strings.xml
@@ -130,6 +130,7 @@
<string name="start_error_mic_required">Ring requires the microphone permission to work.</string>
<string name="action_call_accept">Take call</string>
<string name="action_call_decline">Decline</string>
+ <string name="action_call_mic_mute">Mute microphone</string>
<string name="ab_action_speakerphone">Enable speaker</string>
<string name="ab_action_contact_add">Add to contacts</string>
<string name="ab_action_contact_add_question">Add to contacts?</string>
diff --git a/ring-android/libringclient/src/main/java/cx/ring/call/CallPresenter.java b/ring-android/libringclient/src/main/java/cx/ring/call/CallPresenter.java
index c68aa4a..7dab460 100644
--- a/ring-android/libringclient/src/main/java/cx/ring/call/CallPresenter.java
+++ b/ring-android/libringclient/src/main/java/cx/ring/call/CallPresenter.java
@@ -163,6 +163,9 @@
}
public void screenRotationClick() {
+ //getView().resetVideoSize(videoWidth, videoHeight, previewHeight, previewWidth);
+ mHardwareService.stopCapture();
+
getView().changeScreenRotation();
}
@@ -229,7 +232,7 @@
}
public void layoutChanged() {
- getView().resetVideoSize(videoWidth, videoHeight, previewWidth, previewHeight);
+ //getView().resetVideoSize(videoWidth, videoHeight, previewWidth, previewHeight);
}
public void uiVisibilityChanged(boolean displayed) {
@@ -321,7 +324,9 @@
previewHeight = event.h;
}
}
- getView().resetVideoSize(videoWidth, videoHeight, previewWidth, previewHeight);
+ if (event.started || event.start) {
+ getView().resetVideoSize(videoWidth, videoHeight, previewWidth, previewHeight);
+ }
}
public void positiveButtonClicked() {