104571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee/*
204571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee * Copyright (C) 2014 The Android Open Source Project
304571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee *
404571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee * Licensed under the Apache License, Version 2.0 (the "License");
504571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee * you may not use this file except in compliance with the License.
604571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee * You may obtain a copy of the License at
704571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee *
804571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee *      http://www.apache.org/licenses/LICENSE-2.0
904571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee *
1004571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee * Unless required by applicable law or agreed to in writing, software
1104571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee * distributed under the License is distributed on an "AS IS" BASIS,
1204571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1304571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee * See the License for the specific language governing permissions and
1404571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee * limitations under the License
1504571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee */
1604571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee
177cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnpackage com.android.server.telecom.testapps;
1804571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee
19b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport com.android.ex.camera2.blocking.BlockingCameraManager;
20b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException;
219399ae6672196db82e491ddb425c48d6a3b67451Eino-Ville Talvalaimport com.android.ex.camera2.blocking.BlockingSessionCallback;
22945a82ea92bf4fcc8b505738760650f9fb74960bIhab Awadimport com.android.server.telecom.testapps.R;
23e09b47b2f8b96780fc5c921785d73082cd932828Yorke Leeimport com.android.server.telecom.testapps.TestConnectionService.TestConnection;
24b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn
25dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Leeimport android.content.Context;
26f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunnimport android.graphics.SurfaceTexture;
27b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport android.hardware.camera2.CameraAccessException;
28b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport android.hardware.camera2.CameraCaptureSession;
29f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunnimport android.hardware.camera2.CameraCharacteristics;
30b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport android.hardware.camera2.CameraDevice;
31b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport android.hardware.camera2.CameraManager;
32b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport android.hardware.camera2.CaptureFailure;
33b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport android.hardware.camera2.CaptureRequest;
34b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport android.hardware.camera2.TotalCaptureResult;
35f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunnimport android.hardware.camera2.params.StreamConfigurationMap;
36dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunnimport android.media.MediaPlayer;
3736004e70d54d4f8063733cc8b85150b1931e1c03Yorke Leeimport android.net.Uri;
38b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport android.os.Handler;
397cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.Connection;
407cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.VideoProfile;
410f215ce43e23f8c72b8caeb710946ae40dac07d3Yorke Leeimport android.telecom.VideoProfile.CameraCapabilities;
42b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport android.text.TextUtils;
4304571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Leeimport android.util.Log;
44f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunnimport android.util.Size;
450b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunnimport android.view.Surface;
4604571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee
47f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunnimport java.lang.IllegalArgumentException;
48f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunnimport java.lang.String;
49b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport java.util.ArrayList;
50b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunnimport java.util.List;
51dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Leeimport java.util.Random;
52dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee
5304571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee/**
543bcf935b25470e94c8c6855862434d15b785c54aAndrew Lee * Implements the VideoCallProvider.
5504571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee */
566fb37c87836b5245046bd3b14320823ab839a10cIhab Awadpublic class TestVideoProvider extends Connection.VideoProvider {
57e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee    private TestConnection mConnection;
586fb37c87836b5245046bd3b14320823ab839a10cIhab Awad    private CameraCapabilities mCameraCapabilities;
59dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee    private Random random;
60dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn    private Surface mDisplaySurface;
61dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn    private Surface mPreviewSurface;
62dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn    private Context mContext;
63dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn    /** Used to play incoming video during a call. */
64dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn    private MediaPlayer mIncomingMediaPlayer;
65b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn
66b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn    private CameraManager mCameraManager;
67b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn    private CameraDevice mCameraDevice;
68b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn    private CameraCaptureSession mCameraSession;
69b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn    private CameraThread mLooperThread;
70b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn
71e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee    private final Handler mHandler = new Handler();
72e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee
73b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn    private String mCameraId;
74b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn
75b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn    private static final long SESSION_TIMEOUT_MS = 2000;
76dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee
77e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee    public TestVideoProvider(Context context, TestConnection connection) {
78e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee        mConnection = connection;
79dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn        mContext = context;
80dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee        random = new Random();
81b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
82dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee    }
8304571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee
84b9e44bcf88078bcbcbf80b7df356bb0dfef229f3Andrew Lee    @Override
85b9e44bcf88078bcbcbf80b7df356bb0dfef229f3Andrew Lee    public void onSetCamera(String cameraId) {
8604571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee        log("Set camera to " + cameraId);
87b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        mCameraId = cameraId;
88f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn
89f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn        stopCamera();
90b19d23fd57cf17b7d0c66760131319a5fec930adTyler Gunn        // Get the capabilities of the camera
91f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn        setCameraCapabilities(mCameraId);
9204571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee    }
9304571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee
940b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn    @Override
95b9e44bcf88078bcbcbf80b7df356bb0dfef229f3Andrew Lee    public void onSetPreviewSurface(Surface surface) {
96dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn        log("Set preview surface " + (surface == null ? "unset" : "set"));
97f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn        if (mPreviewSurface != null) {
98b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            stopCamera();
99b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        }
100b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn
101f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn        mPreviewSurface = surface;
102f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn
103b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        if (!TextUtils.isEmpty(mCameraId) && mPreviewSurface != null) {
104b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            startCamera(mCameraId);
105dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn        }
1060b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn    }
1070b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn
1080b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn    @Override
109b9e44bcf88078bcbcbf80b7df356bb0dfef229f3Andrew Lee    public void onSetDisplaySurface(Surface surface) {
110dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn        log("Set display surface " + (surface == null ? "unset" : "set"));
111dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn        mDisplaySurface = surface;
112dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn
113dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn        if (mDisplaySurface != null) {
114dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn            if (mIncomingMediaPlayer == null) {
115f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn                // For a Rick-Rolling good time use R.raw.test_video
116f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn                mIncomingMediaPlayer = createMediaPlayer(mDisplaySurface, R.raw.test_pattern);
117dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn            }
118dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn            mIncomingMediaPlayer.setSurface(mDisplaySurface);
119dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn            if (!mIncomingMediaPlayer.isPlaying()) {
120dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn                mIncomingMediaPlayer.start();
121dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn            }
122dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn        } else {
123b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            if (mIncomingMediaPlayer != null) {
124b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn                mIncomingMediaPlayer.stop();
125b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn                mIncomingMediaPlayer.setSurface(null);
126b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            }
127dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn        }
1280b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn    }
1290b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn
1300b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn    @Override
131b9e44bcf88078bcbcbf80b7df356bb0dfef229f3Andrew Lee    public void onSetDeviceOrientation(int rotation) {
132f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn        log("Set device orientation " + rotation);
1330b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn    }
1340b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn
135dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee    /**
136dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee     * Sets the zoom value, creating a new CallCameraCapabalities object. If the zoom value is
137dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee     * non-positive, assume that zoom is not supported.
138dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee     */
1390b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn    @Override
140b9e44bcf88078bcbcbf80b7df356bb0dfef229f3Andrew Lee    public void onSetZoom(float value) {
141dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee        log("Set zoom to " + value);
1420b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn    }
1430b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn
144dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee    /**
145dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee     * "Sends" a request with a video call profile. Assumes that this response succeeds and sends
146dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee     * the response back via the CallVideoClient.
147dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee     */
1480b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn    @Override
1490bd4de37ac94b371a1f54891da0fe3df2da8fb6eTyler Gunn    public void onSendSessionModifyRequest(final VideoProfile fromProfile,
1500bd4de37ac94b371a1f54891da0fe3df2da8fb6eTyler Gunn            final VideoProfile requestProfile) {
151dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee        log("Sent session modify request");
152dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee
153e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee        mHandler.postDelayed(new Runnable() {
154e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee            @Override
155e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee            public void run() {
156e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee                final VideoProfile responseProfile = new VideoProfile(
157e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee                        requestProfile.getVideoState(), requestProfile.getQuality());
158e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee                mConnection.setVideoState(requestProfile.getVideoState());
159e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee
160e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee                receiveSessionModifyResponse(
161e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee                        SESSION_MODIFY_REQUEST_SUCCESS,
162e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee                        requestProfile,
163e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee                        responseProfile);
164e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee            }
165e09b47b2f8b96780fc5c921785d73082cd932828Yorke Lee        }, 2000);
1660b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn    }
1670b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn
1680b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn    @Override
1696fb37c87836b5245046bd3b14320823ab839a10cIhab Awad    public void onSendSessionModifyResponse(VideoProfile responseProfile) {
1700b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn
1710b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn    }
1720b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn
173dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee    /**
174dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee     * Returns a CallCameraCapabilities object without supporting zoom.
175dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee     */
1760b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn    @Override
177b9e44bcf88078bcbcbf80b7df356bb0dfef229f3Andrew Lee    public void onRequestCameraCapabilities() {
178dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee        log("Requested camera capabilities");
179f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn        changeCameraCapabilities(mCameraCapabilities);
1800b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn    }
1810b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn
182dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee    /**
183dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee     * Randomly reports data usage of value ranging from 10MB to 60MB.
184dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee     */
1850b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn    @Override
18607bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad    public void onRequestConnectionDataUsage() {
18707bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad        log("Requested connection data usage");
188d240fe8e16205623eb6cb73c3d42448554690033Rekha Kumar        long dataUsageKb = (10 *1024) + random.nextInt(50 * 1024);
1893bcf935b25470e94c8c6855862434d15b785c54aAndrew Lee        changeCallDataUsage(dataUsageKb);
1900b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn    }
1910b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn
192dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee    /**
193dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee     * We do not have a need to set a paused image.
194dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee     */
1950b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn    @Override
19636004e70d54d4f8063733cc8b85150b1931e1c03Yorke Lee    public void onSetPauseImage(Uri uri) {
197dfe7b6d0e323b511bf4046ae4d7ff77cd1634415Andrew Lee        // Not implemented.
1980b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn    }
1990b3f7ddea6c5bed145601977f979999a4039d66fTyler Gunn
200b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn    /**
201b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn     * Stop and cleanup the media players used for test video playback.
202b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn     */
203b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn    public void stopAndCleanupMedia() {
204b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        if (mIncomingMediaPlayer != null) {
205b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            mIncomingMediaPlayer.setSurface(null);
206b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            mIncomingMediaPlayer.stop();
207b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            mIncomingMediaPlayer.release();
208b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            mIncomingMediaPlayer = null;
209b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        }
210b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn    }
211b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn
21204571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee    private static void log(String msg) {
213905dfba7883666f45a0c6958d8bc6c19d68972d9Sailesh Nepal        Log.w("TestCallVideoProvider", "[TestCallServiceProvider] " + msg);
21404571e905b59d20e2b289bf152f7f1c9c0ae3633Andrew Lee    }
215dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn
216dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn    /**
217dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn     * Creates a media player to play a video resource on a surface.
218dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn     * @param surface The surface.
219dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn     * @param videoResource The video resource.
220dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn     * @return The {@code MediaPlayer}.
221dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn     */
222dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn    private MediaPlayer createMediaPlayer(Surface surface, int videoResource) {
223dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn        MediaPlayer mediaPlayer = MediaPlayer.create(mContext.getApplicationContext(),
224dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn                videoResource);
225dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn        mediaPlayer.setSurface(surface);
226dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn        mediaPlayer.setLooping(true);
227dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn        return mediaPlayer;
228dcdf5b0916d6f5cf1e172d030d7ec5c0b8b21827Tyler Gunn    }
229b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn
230b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn    /**
231b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn     * Starts displaying the camera image on the preview surface.
232b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn     *
233b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn     * @param cameraId
234b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn     */
235b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn    private void startCamera(String cameraId) {
236b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        stopCamera();
237b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn
238b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        if (mPreviewSurface == null) {
239b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            return;
240b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        }
241b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn
242b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        // Configure a looper thread.
243b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        mLooperThread = new CameraThread();
244b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        Handler mHandler;
245b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        try {
246b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            mHandler = mLooperThread.start();
247b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        } catch (Exception e) {
248b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            log("Exception: " + e);
249b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            return;
250b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        }
251b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn
252b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        // Get the camera device.
253b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        try {
254b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            BlockingCameraManager blockingCameraManager = new BlockingCameraManager(mCameraManager);
255b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            mCameraDevice = blockingCameraManager.openCamera(cameraId, null /* listener */,
256b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn                    mHandler);
257b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        } catch (CameraAccessException e) {
258b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            log("CameraAccessException: " + e);
259b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            return;
260b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        } catch (BlockingOpenException be) {
261b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            log("BlockingOpenException: " + be);
262b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            return;
263b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        }
264b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn
265b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        // Create a capture session to get the preview and display it on the surface.
266b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        List<Surface> surfaces = new ArrayList<Surface>();
267b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        surfaces.add(mPreviewSurface);
268b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        CaptureRequest.Builder mCaptureRequest = null;
269b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        try {
2709399ae6672196db82e491ddb425c48d6a3b67451Eino-Ville Talvala            BlockingSessionCallback blkSession = new BlockingSessionCallback();
271b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            mCameraDevice.createCaptureSession(surfaces, blkSession, mHandler);
272b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            mCaptureRequest = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
273b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            mCaptureRequest.addTarget(mPreviewSurface);
274b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            mCameraSession = blkSession.waitAndGetSession(SESSION_TIMEOUT_MS);
275b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        } catch (CameraAccessException e) {
276b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            log("CameraAccessException: " + e);
277b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            return;
278b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        }
279b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn
280b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        // Keep repeating
281b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        try {
2829399ae6672196db82e491ddb425c48d6a3b67451Eino-Ville Talvala            mCameraSession.setRepeatingRequest(mCaptureRequest.build(), new CameraCaptureCallback(),
283b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn                    mHandler);
284b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        } catch (CameraAccessException e) {
285b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            log("CameraAccessException: " + e);
286b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            return;
287b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        }
288b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn    }
289b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn
290b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn    /**
291b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn     * Stops the camera and looper thread.
292b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn     */
293b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn    public void stopCamera() {
294b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        try {
295b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            if (mCameraDevice != null) {
296b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn                mCameraDevice.close();
297b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn                mCameraDevice = null;
298b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            }
299b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            if (mLooperThread != null) {
300b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn                mLooperThread.close();
301b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn                mLooperThread = null;
302b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn            }
303b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        } catch (Exception e) {
304b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn           log("stopCamera Exception: "+e.toString());
305b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        }
306b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn    }
307b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn
308b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn    /**
309b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn     * Required listener for camera capture events.
310b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn     */
3119399ae6672196db82e491ddb425c48d6a3b67451Eino-Ville Talvala    private class CameraCaptureCallback extends CameraCaptureSession.CaptureCallback {
312b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        @Override
313b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        public void onCaptureCompleted(CameraCaptureSession camera, CaptureRequest request,
314b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn                TotalCaptureResult result) {
315b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        }
316b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn
317b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        @Override
318b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        public void onCaptureFailed(CameraCaptureSession camera, CaptureRequest request,
319b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn                CaptureFailure failure) {
320b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        }
321b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn    }
322f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn
323f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn    /**
324f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn     * Uses the camera manager to retrieve the camera capabilities for the chosen camera.
325f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn     *
326f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn     * @param cameraId The camera ID to get the capabilities for.
327f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn     */
328f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn    private void setCameraCapabilities(String cameraId) {
329f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn        CameraManager cameraManager = (CameraManager) mContext.getSystemService(
330f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn                Context.CAMERA_SERVICE);
331f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn
332f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn        CameraCharacteristics c = null;
333f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn        try {
334f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn            c = cameraManager.getCameraCharacteristics(cameraId);
335f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn        } catch (IllegalArgumentException | CameraAccessException e) {
336f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn            // Ignoring camera problems.
337f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn        }
338f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn        if (c != null) {
339f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn            // Get the video size for the camera
340f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn            StreamConfigurationMap map = c.get(
341f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn                    CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
342f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn            Size previewSize = map.getOutputSizes(SurfaceTexture.class)[0];
343f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn
34431d68d261288a19e9a402efa84b7afcf7cec9dd2Jay Shrauner            mCameraCapabilities = new CameraCapabilities(previewSize.getWidth(),
345f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn                    previewSize.getHeight());
346f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn        }
347f9b7f539fa9406d104ad8d098b8503a668faa26bTyler Gunn    }
348905dfba7883666f45a0c6958d8bc6c19d68972d9Sailesh Nepal}
349