Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 80236336 authored by Johnson Lu's avatar Johnson Lu Committed by Android (Google) Code Review
Browse files

Merge "Adjust camera preview area to square"

parents fa00f329 ebbb0bc5
Loading
Loading
Loading
Loading
+9 −10
Original line number Diff line number Diff line
@@ -24,20 +24,19 @@

    <include layout="@layout/wifi_dpp_fragment_header"/>

    <FrameLayout
    <com.android.settings.wifi.qrcode.QrPreviewLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <SurfaceView
        android:layout_height="match_parent"
        android:layout_gravity="center">
        <TextureView
            android:id="@+id/preview_view"
            android:layout_width="426dp"
            android:layout_height="320dp"
            android:layout_gravity="center"/>
            android:layout_width="wrap_content"
            android:layout_height="match_parent"/>
        <com.android.settings.wifi.qrcode.QrDecorateView
            android:id="@+id/decorate_view"
            android:layout_width="426dp"
            android:layout_height="320dp"
            android:layout_gravity="center"/>
    </FrameLayout>
            android:layout_width="wrap_content"
            android:layout_height="match_parent"/>
    </com.android.settings.wifi.qrcode.QrPreviewLayout>

    <TextView android:id="@+id/error_message"
        android:layout_width="wrap_content"
+8 −8
Original line number Diff line number Diff line
@@ -24,20 +24,20 @@

    <include layout="@layout/wifi_dpp_fragment_header"/>

    <FrameLayout
    <com.android.settings.wifi.qrcode.QrPreviewLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <SurfaceView
        android:layout_height="match_parent">
        <TextureView
            android:id="@+id/preview_view"
            android:layout_width="320dp"
            android:layout_height="426dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"/>
        <com.android.settings.wifi.qrcode.QrDecorateView
            android:id="@+id/decorate_view"
            android:layout_width="320dp"
            android:layout_height="426dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"/>
    </FrameLayout>
    </com.android.settings.wifi.qrcode.QrPreviewLayout>

    <TextView android:id="@+id/error_message"
        android:layout_width="wrap_content"
+0 −13
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package com.android.settings.wifi.dpp;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
@@ -30,7 +29,6 @@ import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto;

import com.android.settings.core.InstrumentedFragment;
import com.android.settings.wifi.qrcode.QrDecorateView;
import com.android.settings.R;

/**
@@ -50,14 +48,8 @@ public abstract class WifiDppQrCodeBaseFragment extends InstrumentedFragment {
    private TextView mTitle;
    private TextView mDescription;

    private SurfaceView mPreviewView;       //optional, for WifiDppQrCodeScannerFragment
    private QrDecorateView mDecorateViiew;  //optional, for WifiDppQrCodeScannerFragment
    private TextView mErrorMessage;         //optional, for WifiDppQrCodeScannerFragment

    private ImageView mBarcodeView;         //optional, for WifiDppQrCodeGeneratorFragment

    private ListView mSavedWifiNetworkList; //optional, for WifiDppChooseSavedWifiNetworkFragment

    private ProgressBar mProgressBar;       //optional, for WifiDppAddDeviceFragment
    private ImageView mWifiApPictureView;   //optional, for WifiDppAddDeviceFragment
    private TextView mChooseDifferentNetwork;//optional, for WifiDppAddDeviceFragment
@@ -91,13 +83,8 @@ public abstract class WifiDppQrCodeBaseFragment extends InstrumentedFragment {
    private void initView(View view) {
        mTitle = view.findViewById(R.id.title);
        mDescription = view.findViewById(R.id.description);

        mPreviewView = view.findViewById(R.id.preview_view);
        mDecorateViiew = view.findViewById(R.id.decorate_view);
        mErrorMessage = view.findViewById(R.id.error_message);

        mBarcodeView = view.findViewById(R.id.barcode_view);

        mSavedWifiNetworkList = view.findViewById(R.id.saved_wifi_network_list);

        mProgressBar = view.findViewById(R.id.progress_bar);
+26 −23
Original line number Diff line number Diff line
@@ -21,14 +21,16 @@ import android.app.ActionBar;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Size;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.TextureView.SurfaceTextureListener;
import android.view.View;

import com.android.settings.R;
@@ -36,10 +38,10 @@ import com.android.settings.wifi.qrcode.QrCamera;
import com.android.settings.wifi.qrcode.QrDecorateView;

public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment implements
        SurfaceHolder.Callback,
        SurfaceTextureListener,
        QrCamera.ScannerCallback {
    private QrCamera mCamera;
    private SurfaceView mSurfaceView;
    private TextureView mTextureView;
    private QrDecorateView mDecorateView;

    /** true if the fragment working for configurator, false enrollee*/
@@ -109,22 +111,12 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        mSurfaceView = (SurfaceView) view.findViewById(R.id.preview_view);
        final SurfaceHolder surfaceHolder = mSurfaceView.getHolder();
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        surfaceHolder.addCallback(this);
        mTextureView = (TextureView) view.findViewById(R.id.preview_view);
        mTextureView.setSurfaceTextureListener(this);

        mDecorateView = (QrDecorateView) view.findViewById(R.id.decorate_view);
    }

    @Override
    public void onDestroyView() {
        SurfaceHolder surfaceHolder = mSurfaceView.getHolder();
        surfaceHolder.removeCallback(this);

        super.onDestroyView();
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        menu.removeItem(Menu.FIRST);
@@ -133,23 +125,29 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
    }

    @Override
    public void surfaceCreated(final SurfaceHolder holder) {
        initCamera(holder);
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        initCamera(surface);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
        // Do nothing
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        destroyCamera();
        return true;
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
        // Do nothing
    }

    @Override
    public Size getViewSize() {
        return new Size(mSurfaceView.getWidth(), mSurfaceView.getHeight());
        return new Size(mTextureView.getWidth(), mTextureView.getHeight());
    }

    @Override
@@ -157,6 +155,11 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
        return new Rect(0, 0, previewSize.getHeight(), previewSize.getHeight());
    }

    @Override
    public void setTransform(Matrix transform) {
        mTextureView.setTransform(transform);
    }

    @Override
    public void handleSuccessfulResult(String qrCode) {
        destroyCamera();
@@ -169,11 +172,11 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
        destroyCamera();
    }

    private void initCamera(SurfaceHolder holder) {
    private void initCamera(SurfaceTexture surface) {
        // Check if the camera has already created.
        if (mCamera == null) {
            mCamera = new QrCamera(getContext(), this);
            mCamera.start(holder);
            mCamera.start(surface);
        }
    }

+51 −12
Original line number Diff line number Diff line
@@ -17,7 +17,10 @@
package com.android.settings.wifi.qrcode;

import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Parameters;
@@ -29,7 +32,6 @@ import android.util.ArrayMap;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.WindowManager;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
@@ -50,7 +52,7 @@ import androidx.annotation.VisibleForTesting;

/**
 * Manage the camera for the QR scanner and help the decoder to get the image inside the scanning
 * frame. Caller prepares a {@link SurfaceHolder} then call {@link #start(SurfaceHolder)} to
 * frame. Caller prepares a {@link SurfaceTexture} then call {@link #start(SurfaceTexture)} to
 * start QR Code scanning. The scanning result will return by ScannerCallback interface. Caller
 * can also call {@link #stop()} to halt QR Code scanning before the result returned.
 */
@@ -90,12 +92,11 @@ public class QrCamera extends Handler {
     * The function start camera preview and capture pictures to decode QR code continuously in a
     * background task.
     *
     * @param surfaceHolder the Surface to be used for live preview, must already contain a surface
     *                      when this method is called.
     * @param surface The surface to be used for live preview.
     */
    public void start(SurfaceHolder surfaceHolder) {
    public void start(SurfaceTexture surface) {
        if (mDecodeTask == null) {
            mDecodeTask = new DecodingTask(surfaceHolder);
            mDecodeTask = new DecodingTask(surface);
            // Execute in the separate thread pool to prevent block other AsyncTask.
            mDecodeTask.executeOnExecutor(Executors.newSingleThreadExecutor());
        }
@@ -144,6 +145,13 @@ public class QrCamera extends Handler {
         * @return The rectangle would like to crop from the camera preview shot.
         */
        Rect getFramePosition(Size previewSize, int cameraOrientation);

        /**
         * Sets the transform to associate with preview area.
         *
         * @param transform The transform to apply to the content of preview
         */
        void setTransform(Matrix transform);
    }

    private void setCameraParameter() {
@@ -200,15 +208,15 @@ public class QrCamera extends Handler {

    private class DecodingTask extends AsyncTask<Void, Void, String> {
        private QrYuvLuminanceSource mImage;
        private SurfaceHolder mSurfaceHolder;
        private SurfaceTexture mSurface;

        private DecodingTask(SurfaceHolder surfaceHolder) {
            mSurfaceHolder = surfaceHolder;
        private DecodingTask(SurfaceTexture surface) {
            mSurface = surface;
        }

        @Override
        protected String doInBackground(Void... tmp) {
            if (!initCamera(mSurfaceHolder)) {
            if (!initCamera(mSurface)) {
                return null;
            }

@@ -253,7 +261,7 @@ public class QrCamera extends Handler {
            }
        }

        private boolean initCamera(SurfaceHolder surfaceHolder) {
        private boolean initCamera(SurfaceTexture surface) {
            final int numberOfCameras = Camera.getNumberOfCameras();
            Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
            try {
@@ -261,7 +269,7 @@ public class QrCamera extends Handler {
                    Camera.getCameraInfo(i, cameraInfo);
                    if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
                        mCamera = Camera.open(i);
                        mCamera.setPreviewDisplay(surfaceHolder);
                        mCamera.setPreviewTexture(surface);
                        mCameraOrientation = cameraInfo.orientation;
                        break;
                    }
@@ -272,6 +280,7 @@ public class QrCamera extends Handler {
                    return false;
                }
                setCameraParameter();
                setTransformationMatrix(mScannerCallback.getViewSize());
                if (!startPreview()) {
                    Log.e(TAG, "Error to init Camera");
                    mCamera = null;
@@ -288,6 +297,36 @@ public class QrCamera extends Handler {
        }
    }

    /** Set transfom matrix to crop and center the preview picture */
    private void setTransformationMatrix(Size viewSize) {
        // Check aspect ratio, can only handle square view.
        final int viewRatio = (int)getRatio(viewSize.getWidth(), viewSize.getHeight());
        if (viewRatio != 1) {
            throw new IllegalArgumentException("Preview area should be square");
        }

        final boolean isPortrait = mContext.get().getResources().getConfiguration().orientation
                == Configuration.ORIENTATION_PORTRAIT ? true : false;

        final int previewWidth = isPortrait ? mPreviewSize.getWidth() : mPreviewSize.getHeight();
        final int previewHeight = isPortrait ? mPreviewSize.getHeight() : mPreviewSize.getWidth();
        final float ratioPreview = (float) getRatio(previewWidth, previewHeight);

        // Calculate transformation matrix.
        float scaleX = 1.0f;
        float scaleY = 1.0f;
        if (previewWidth > previewHeight) {
            scaleY = scaleX / ratioPreview;
        } else {
            scaleX = scaleY / ratioPreview;
        }

        // Set the transform matrix.
        final Matrix matrix = new Matrix();
        matrix.setScale(scaleX, scaleY);
        mScannerCallback.setTransform(matrix);
    }

    private QrYuvLuminanceSource getFrameImage(byte[] imageData) {
        final Rect frame = mScannerCallback.getFramePosition(mPreviewSize, mCameraOrientation);
        final Camera.Size size = mParameters.getPictureSize();
Loading