1aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy/*
2aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * Copyright (C) 2011 The Android Open Source Project
3aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy *
4aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * Licensed under the Apache License, Version 2.0 (the "License");
5aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * you may not use this file except in compliance with the License.
6aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * You may obtain a copy of the License at
7aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy *
8aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy *      http://www.apache.org/licenses/LICENSE-2.0
9aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy *
10aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * Unless required by applicable law or agreed to in writing, software
11aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * distributed under the License is distributed on an "AS IS" BASIS,
12aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * See the License for the specific language governing permissions and
14aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * limitations under the License.
15aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy */
16aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy
17aa6c24c21c727a196451332448d4e3b11a80be69Romain Guypackage com.android.test.hwui;
18aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy
19aa6c24c21c727a196451332448d4e3b11a80be69Romain Guyimport android.app.Activity;
20a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guyimport android.graphics.Bitmap;
21302a9df1d50373c82923bb84ff665dfce584fb22Romain Guyimport android.graphics.Matrix;
22aa6c24c21c727a196451332448d4e3b11a80be69Romain Guyimport android.graphics.SurfaceTexture;
23aa6c24c21c727a196451332448d4e3b11a80be69Romain Guyimport android.hardware.Camera;
24aa6c24c21c727a196451332448d4e3b11a80be69Romain Guyimport android.os.Bundle;
25a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guyimport android.os.Environment;
26aa6c24c21c727a196451332448d4e3b11a80be69Romain Guyimport android.view.Gravity;
27a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guyimport android.view.Surface;
28aa6c24c21c727a196451332448d4e3b11a80be69Romain Guyimport android.view.TextureView;
29aa6c24c21c727a196451332448d4e3b11a80be69Romain Guyimport android.view.View;
30451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guyimport android.widget.Button;
31aa6c24c21c727a196451332448d4e3b11a80be69Romain Guyimport android.widget.FrameLayout;
32aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy
33a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guyimport java.io.BufferedOutputStream;
34a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guyimport java.io.File;
35a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guyimport java.io.FileNotFoundException;
36a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guyimport java.io.FileOutputStream;
37aa6c24c21c727a196451332448d4e3b11a80be69Romain Guyimport java.io.IOException;
38aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy
39aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy@SuppressWarnings({"UnusedDeclaration"})
40aa6c24c21c727a196451332448d4e3b11a80be69Romain Guypublic class TextureViewActivity extends Activity implements TextureView.SurfaceTextureListener {
41aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy    private Camera mCamera;
42aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy    private TextureView mTextureView;
43451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy    private FrameLayout mContent;
44302a9df1d50373c82923bb84ff665dfce584fb22Romain Guy    private Matrix mMatrix = new Matrix();
45aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy
46aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy    @Override
47aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy    protected void onCreate(Bundle savedInstanceState) {
48aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy        super.onCreate(savedInstanceState);
49aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy
50451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy        mContent = new FrameLayout(this);
51451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy
52aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy        mTextureView = new TextureView(this);
53aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy        mTextureView.setSurfaceTextureListener(this);
54a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy        mTextureView.setOnClickListener(new View.OnClickListener() {
55a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy            @Override
56a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy            public void onClick(View v) {
57a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy                Bitmap b = mTextureView.getBitmap(800, 800);
58a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy                BufferedOutputStream out = null;
59a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy                try {
60a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy                    File dump = new File(Environment.getExternalStorageDirectory(), "out.png");
61a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy                    out = new BufferedOutputStream(new FileOutputStream(dump));
62a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy                    b.compress(Bitmap.CompressFormat.PNG, 100, out);
63a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy                } catch (FileNotFoundException e) {
64a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy                    e.printStackTrace();
65a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy                } finally {
66a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy                    if (out != null) try {
67a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy                        out.close();
68a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy                    } catch (IOException e) {
69a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy                        e.printStackTrace();
70a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy                    }
71a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy                }
72a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy            }
73a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy        });
74aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy
75451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy        Button button = new Button(this);
76451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy        button.setText("Remove/Add");
77451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy        button.setOnClickListener(new View.OnClickListener() {
78451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy            private boolean mAdded = true;
79aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy
80451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy            @Override
81451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy            public void onClick(View v) {
82451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy                if (mAdded) {
83451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy                    mContent.removeView(mTextureView);
84451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy                } else {
85451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy                    mContent.addView(mTextureView);
86451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy                }
87451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy                mAdded = !mAdded;
88451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy            }
89451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy        });
90aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy
919ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy        mContent.addView(mTextureView, new FrameLayout.LayoutParams(
929ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy                FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT,
939ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy                Gravity.CENTER));
94451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy        mContent.addView(button, new FrameLayout.LayoutParams(
95451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy                FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT,
96451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy                Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM));
97451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy        setContentView(mContent);
98aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy    }
99aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy
100aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy    @Override
101451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
102aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy        mCamera = Camera.open();
103a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy        mCamera.setDisplayOrientation(getCameraOrientation());
104a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy
1059ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy        Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
1069ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy        mTextureView.setLayoutParams(new FrameLayout.LayoutParams(
1079ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy                previewSize.width, previewSize.height, Gravity.CENTER));
108aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy
109aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy        try {
110aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy            mCamera.setPreviewTexture(surface);
111aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy        } catch (IOException t) {
112aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy            android.util.Log.e("TextureView", "Cannot set preview texture target!", t);
113aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy        }
114aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy
115aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy        mCamera.startPreview();
116aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy    }
1178f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
118a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy    private int getCameraOrientation() {
119a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy        Camera.CameraInfo info = new Camera.CameraInfo();
120a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy        for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
121a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy            Camera.getCameraInfo(i, info);
122a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy            if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) break;
123a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy        }
124a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy
125a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy        int rotation = getWindowManager().getDefaultDisplay().getRotation();
126a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy        int degrees = 0;
127a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy
128a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy        switch (rotation) {
129a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy            case Surface.ROTATION_0:
130a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy                degrees = 0;
131a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy                break;
132a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy            case Surface.ROTATION_90:
133a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy                degrees = 90;
134a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy                break;
135a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy            case Surface.ROTATION_180:
136a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy                degrees = 180;
137a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy                break;
138a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy            case Surface.ROTATION_270:
139a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy                degrees = 270;
140a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy                break;
141a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy        }
142a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy
143a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy        return (info.orientation - degrees + 360) % 360;
144a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy    }
145a9dc86b21defc26db0d71f276aff5c3af0b62ff5Romain Guy
1468f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy    @Override
1478f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
1488f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        // Ignored, the Camera does all the work for us
1498f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy    }
150451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy
151451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy    @Override
152402f05530352f34d5320c2d23be43c274d97c4e2Grace Kloba    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
153451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy        mCamera.stopPreview();
154451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy        mCamera.release();
155402f05530352f34d5320c2d23be43c274d97c4e2Grace Kloba        return true;
156451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy    }
157cf559377b750271472aa0a717bf3b7d34abc0b39Grace Kloba
158cf559377b750271472aa0a717bf3b7d34abc0b39Grace Kloba    @Override
159cf559377b750271472aa0a717bf3b7d34abc0b39Grace Kloba    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
160cf559377b750271472aa0a717bf3b7d34abc0b39Grace Kloba        // Ignored
161cf559377b750271472aa0a717bf3b7d34abc0b39Grace Kloba    }
162aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy}
163