diff --git a/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml b/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
new file mode 100644
index 00000000000..0c938f82ede
--- /dev/null
+++ b/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
index a864f511e93..ab38ac106a0 100644
--- a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
+++ b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
@@ -32,7 +32,7 @@
android:layout_width="320dp"
android:layout_height="426dp"
android:layout_gravity="center"/>
- {
- getActivity().setResult(Activity.RESULT_CANCELED);
- getActivity().finish();});
+ getActivity().setResult(Activity.RESULT_CANCELED);
+ getActivity().finish();
+ });
+ }
+
+ @Override
+ 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);
+
+ mDecorateView = (QrDecorateView) view.findViewById(R.id.decorate_view);
+ }
+
+ @Override
+ public void surfaceCreated(final SurfaceHolder holder) {
+ initCamera(holder);
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ destroyCamera();
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ // Do nothing
+ }
+
+ @Override
+ public Size getViewSize() {
+ return new Size(mSurfaceView.getWidth(), mSurfaceView.getHeight());
+ }
+
+ @Override
+ public Rect getFramePosition(Size previewSize, int cameraOrientation) {
+ return new Rect(0, 0, previewSize.getHeight(), previewSize.getHeight());
+ }
+
+ @Override
+ public void handleSuccessfulResult(String qrCode) {
+ destroyCamera();
+ mDecorateView.setFocused(true);
+ // TODO(b/120243131): Add a network by Wi-Fi Network config shared via QR code.
+ }
+
+ @Override
+ public void handleCameraFailure() {
+ destroyCamera();
+ }
+
+ private void initCamera(SurfaceHolder holder) {
+ // Check if the camera has already created.
+ if (mCamera == null) {
+ mCamera = new QrCamera(getContext(), this);
+ mCamera.start(holder);
+ }
+ }
+
+ private void destroyCamera() {
+ if (mCamera != null) {
+ mCamera.stop();
+ mCamera = null;
+ }
}
}
diff --git a/src/com/android/settings/wifi/qrcode/QrCamera.java b/src/com/android/settings/wifi/qrcode/QrCamera.java
index c29236c2da4..dc650b9e067 100644
--- a/src/com/android/settings/wifi/qrcode/QrCamera.java
+++ b/src/com/android/settings/wifi/qrcode/QrCamera.java
@@ -43,6 +43,7 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import androidx.annotation.VisibleForTesting;
@@ -85,14 +86,26 @@ public class QrCamera extends Handler {
mReader.setHints(HINTS);
}
- void start(SurfaceHolder surfaceHolder) {
+ /**
+ * 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.
+ */
+ public void start(SurfaceHolder surfaceHolder) {
if (mDecodeTask == null) {
mDecodeTask = new DecodingTask(surfaceHolder);
- mDecodeTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ // Execute in the separate thread pool to prevent block other AsyncTask.
+ mDecodeTask.executeOnExecutor(Executors.newSingleThreadExecutor());
}
}
- void stop() {
+ /**
+ * The function stop camera preview and background decode task. Caller call this function when
+ * the surface is being destroyed.
+ */
+ public void stop() {
removeMessages(MSG_AUTO_FOCUS);
if (mDecodeTask != null) {
mDecodeTask.cancel(true);
@@ -104,7 +117,7 @@ public class QrCamera extends Handler {
}
/** The scanner which includes this QrCamera class should implement this */
- interface ScannerCallback {
+ public interface ScannerCallback {
/**
* The function used to handle the decoding result of the QR code.
diff --git a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java
index 0f4bfd9e6b4..c46db2c78fa 100644
--- a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java
+++ b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java
@@ -24,6 +24,7 @@ import static com.google.common.truth.Truth.assertThat;
import android.app.Activity;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
@@ -53,4 +54,12 @@ public class WifiDppQrCodeScannerFragmentTest {
assertThat(mActivityRule.getActivityResult().getResultCode()).
isEqualTo(Activity.RESULT_CANCELED);
}
+
+ @Test
+ public void rotateScreen_shouldNotCrash() {
+ mActivityRule.getActivity().setRequestedOrientation(
+ ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ mActivityRule.getActivity().setRequestedOrientation(
+ ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ }
}