TestingCamera.java revision abe36163445fb3fe458252fd8d21c3e1ac14ed6d
148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala/*
248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala * Copyright (C) 2012 The Android Open Source Project
348f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala *
448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala * Licensed under the Apache License, Version 2.0 (the "License");
548f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala * you may not use this file except in compliance with the License.
648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala * You may obtain a copy of the License at
748f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala *
848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala *      http://www.apache.org/licenses/LICENSE-2.0
948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala *
1048f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala * Unless required by applicable law or agreed to in writing, software
1148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala * distributed under the License is distributed on an "AS IS" BASIS,
1248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1348f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala * See the License for the specific language governing permissions and
1448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala * limitations under the License.
1548f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala */
1648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
1748f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalapackage com.android.testingcamera;
1848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
1948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport android.app.Activity;
2048f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport android.app.Dialog;
21bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvalaimport android.app.FragmentManager;
2248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport android.graphics.Bitmap;
2348f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport android.graphics.BitmapFactory;
2448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport android.hardware.Camera;
25abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvalaimport android.hardware.Camera.Parameters;
26bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvalaimport android.media.CamcorderProfile;
27abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvalaimport android.media.MediaRecorder;
2848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport android.os.Bundle;
29abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvalaimport android.os.Environment;
3048f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport android.view.View;
3148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport android.view.SurfaceHolder;
3248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport android.view.SurfaceView;
33bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvalaimport android.view.View.OnClickListener;
3448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport android.widget.AdapterView;
35abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvalaimport android.widget.AdapterView.OnItemSelectedListener;
3648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport android.widget.ArrayAdapter;
3748f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport android.widget.Button;
3848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport android.widget.ImageView;
3948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport android.widget.LinearLayout.LayoutParams;
4048f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport android.widget.Spinner;
4148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport android.widget.CompoundButton;
4248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport android.widget.TextView;
4348f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport android.widget.ToggleButton;
44abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvalaimport android.text.Layout;
45abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvalaimport android.text.method.ScrollingMovementMethod;
4648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport android.util.Log;
4748f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
48abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvalaimport java.io.File;
49abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvalaimport java.io.FileDescriptor;
5048f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport java.io.IOException;
51abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvalaimport java.io.PrintWriter;
52abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvalaimport java.io.StringWriter;
53abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvalaimport java.text.FieldPosition;
54abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvalaimport java.text.SimpleDateFormat;
5548f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport java.util.ArrayList;
5648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport java.util.Comparator;
57abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvalaimport java.util.Date;
58abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvalaimport java.util.HashSet;
5948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport java.util.List;
60abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvalaimport java.util.Set;
6148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvalaimport java.util.TreeSet;
6248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
6348f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala/**
6448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala * A simple test application for the camera API.
6594d24977868e0713cf03f7cec4d6de051f411dcaEino-Ville Talvala *
6694d24977868e0713cf03f7cec4d6de051f411dcaEino-Ville Talvala * The goal of this application is to allow all camera API features to be
67abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala * exercised, and all information provided by the API to be shown.
6848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala */
69b28605e5d09a08c915183772819cb1c7c53cdb34Eino-Ville Talvalapublic class TestingCamera extends Activity implements SurfaceHolder.Callback {
7048f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
7148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    /** UI elements */
7248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private SurfaceView mPreviewView;
7348f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private SurfaceHolder mPreviewHolder;
7448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
7548f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private Spinner mCameraSpinner;
76bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala    private Button mInfoButton;
7748f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private Spinner mPreviewSizeSpinner;
7848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private ToggleButton mPreviewToggle;
79abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private Spinner mAutofocusModeSpinner;
80abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private Button mAutofocusButton;
81abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private Button mCancelAutofocusButton;
82bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala    private Spinner mSnapshotSizeSpinner;
8348f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private Button  mTakePictureButton;
84bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala    private Spinner mCamcorderProfileSpinner;
85bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala    private ToggleButton mRecordToggle;
8648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
87abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private TextView mLogView;
88abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
89abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private Set<View> mPreviewOnlyControls = new HashSet<View>();
90abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
9148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    /** Camera state */
9248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private int mCameraId = 0;
9348f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private Camera mCamera;
9448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private Camera.Parameters mParams;
9548f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private List<Camera.Size> mPreviewSizes;
9648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private int mPreviewSize = 0;
97abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private List<String> mAfModes;
98abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private int mAfMode = 0;
99bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala    private List<Camera.Size> mSnapshotSizes;
100bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala    private int mSnapshotSize = 0;
101bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala    private List<CamcorderProfile> mCamcorderProfiles;
102bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala    private int mCamcorderProfile = 0;
10348f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
104abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private MediaRecorder mRecorder;
105abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
10648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private static final int CAMERA_UNINITIALIZED = 0;
10748f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private static final int CAMERA_OPEN = 1;
10848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private static final int CAMERA_PREVIEW = 2;
10948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private static final int CAMERA_TAKE_PICTURE = 3;
110abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private static final int CAMERA_RECORD = 4;
11148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private int mState = CAMERA_UNINITIALIZED;
11248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
11348f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    /** Misc variables */
11448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
11548f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private static final String TAG = "TestingCamera";
11648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
117abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    /** Activity lifecycle */
118abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
11948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    @Override
12048f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    public void onCreate(Bundle savedInstanceState) {
12148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        super.onCreate(savedInstanceState);
12248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
12348f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        setContentView(R.layout.main);
12448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
12548f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        mPreviewView = (SurfaceView)findViewById(R.id.preview);
12648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        mPreviewView.getHolder().addCallback(this);
12748f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
12848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        mCameraSpinner = (Spinner) findViewById(R.id.camera_spinner);
12948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        mCameraSpinner.setOnItemSelectedListener(mCameraSpinnerListener);
13048f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
131bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        mInfoButton = (Button) findViewById(R.id.info_button);
132bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        mInfoButton.setOnClickListener(mInfoButtonListener);
133bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
13448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        mPreviewSizeSpinner = (Spinner) findViewById(R.id.preview_size_spinner);
13548f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        mPreviewSizeSpinner.setOnItemSelectedListener(mPreviewSizeListener);
13648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
13748f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        mPreviewToggle = (ToggleButton) findViewById(R.id.start_preview);
13848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        mPreviewToggle.setOnClickListener(mPreviewToggleListener);
13948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
140abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mAutofocusModeSpinner = (Spinner) findViewById(R.id.af_mode_spinner);
141abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mAutofocusModeSpinner.setOnItemSelectedListener(mAutofocusModeListener);
142abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
143abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mAutofocusButton = (Button) findViewById(R.id.af_button);
144abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mAutofocusButton.setOnClickListener(mAutofocusButtonListener);
145abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mPreviewOnlyControls.add(mAutofocusButton);
146abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
147abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mCancelAutofocusButton = (Button) findViewById(R.id.af_cancel_button);
148abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mCancelAutofocusButton.setOnClickListener(mCancelAutofocusButtonListener);
149abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mPreviewOnlyControls.add(mCancelAutofocusButton);
150abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
151bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        mSnapshotSizeSpinner = (Spinner) findViewById(R.id.snapshot_size_spinner);
152bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        mSnapshotSizeSpinner.setOnItemSelectedListener(mSnapshotSizeListener);
153bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
15448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        mTakePictureButton = (Button) findViewById(R.id.take_picture);
15548f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        mTakePictureButton.setOnClickListener(mTakePictureListener);
156abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mPreviewOnlyControls.add(mTakePictureButton);
15748f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
158bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        mCamcorderProfileSpinner = (Spinner) findViewById(R.id.camcorder_profile_spinner);
159bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        mCamcorderProfileSpinner.setOnItemSelectedListener(mCamcorderProfileListener);
160bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
161bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        mRecordToggle = (ToggleButton) findViewById(R.id.start_record);
162bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        mRecordToggle.setOnClickListener(mRecordToggleListener);
163abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mPreviewOnlyControls.add(mRecordToggle);
164bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
165abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mLogView = (TextView) findViewById(R.id.log);
166abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mLogView.setMovementMethod(new ScrollingMovementMethod());
167bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
16848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        int numCameras = Camera.getNumberOfCameras();
16948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        String[] cameraNames = new String[numCameras];
17048f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        for (int i = 0; i < numCameras; i++) {
17148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala            cameraNames[i] = "Camera " + i;
17248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        }
17348f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
17448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        mCameraSpinner.setAdapter(
17548f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala                new ArrayAdapter<String>(this,
17648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala                        R.layout.spinner_item, cameraNames));
17748f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    }
17848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
17948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    @Override
18048f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    public void onResume() {
18148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        super.onResume();
182abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        log("onResume: Setting up camera");
18348f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        mPreviewHolder = null;
18448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        setUpCamera();
18548f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    }
18648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
18748f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    @Override
18848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    public void onPause() {
18948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        super.onPause();
190abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        log("onPause: Releasing camera");
19148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        mCamera.release();
19248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        mState = CAMERA_UNINITIALIZED;
19348f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    }
19448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
195abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    /** SurfaceHolder.Callback methods */
19648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    public void surfaceChanged(SurfaceHolder holder,
19748f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala            int format,
19848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala            int width,
19948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala            int height) {
20048f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        if (mPreviewHolder != null) return;
20148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
202abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        log("Surface holder available: " + width + " x " + height);
20348f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        mPreviewHolder = holder;
20448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        try {
20548f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala            mCamera.setPreviewDisplay(holder);
20648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        } catch (IOException e) {
207abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            logE("Unable to set up preview!");
20848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        }
20948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    }
21048f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
21148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    public void surfaceCreated(SurfaceHolder holder) {
21248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
21348f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    }
21448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
21548f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    public void surfaceDestroyed(SurfaceHolder holder) {
216abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mPreviewHolder = null;
217abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    }
21848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
219abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    /** UI controls enable/disable */
220abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private void enablePreviewOnlyControls(boolean enabled) {
221abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        for (View v : mPreviewOnlyControls) {
222abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                v.setEnabled(enabled);
223abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        }
22448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    }
22548f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
226abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    /** UI listeners */
22748f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
22848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private AdapterView.OnItemSelectedListener mCameraSpinnerListener =
229bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala                new AdapterView.OnItemSelectedListener() {
230bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        public void onItemSelected(AdapterView<?> parent,
23148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala                        View view, int pos, long id) {
232bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            if (mCameraId != pos) {
233bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala                mCameraId = pos;
234bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala                setUpCamera();
235bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            }
236bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        }
23748f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
238abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        public void onNothingSelected(AdapterView<?> parent) {
2394ae1a87883045d820ffd6e1b8a95c13b1919e00aEino-Ville Talvala
240bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        }
241bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala    };
242bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
243bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala    private OnClickListener mInfoButtonListener = new OnClickListener() {
244bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        public void onClick(View v) {
245bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            FragmentManager fm = getFragmentManager();
246bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            InfoDialogFragment infoDialog = new InfoDialogFragment();
247bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            infoDialog.updateInfo(mCameraId, mCamera);
248bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            infoDialog.show(fm, "info_dialog_fragment");
249bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        }
250bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala    };
25148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
25248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private AdapterView.OnItemSelectedListener mPreviewSizeListener =
253bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        new AdapterView.OnItemSelectedListener() {
254bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        public void onItemSelected(AdapterView<?> parent,
255bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala                View view, int pos, long id) {
256bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            if (pos == mPreviewSize) return;
257bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            if (mState == CAMERA_PREVIEW) {
258abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                log("Stopping preview to switch resolutions");
259bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala                mCamera.stopPreview();
260bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            }
26148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
262bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            mPreviewSize = pos;
263bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            int width = mPreviewSizes.get(mPreviewSize).width;
264bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            int height = mPreviewSizes.get(mPreviewSize).height;
265bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            mParams.setPreviewSize(width, height);
26648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
267abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            log("Setting preview size to " + width + "x" + height);
268abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
269bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            mCamera.setParameters(mParams);
27048f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
271bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            if (mState == CAMERA_PREVIEW) {
272abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                log("Restarting preview");
273abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                resizePreview(width, height);
274bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala                mCamera.startPreview();
275bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            }
276bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        }
27748f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
278abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        public void onNothingSelected(AdapterView<?> parent) {
27948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
280bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        }
281bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala    };
28248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
28348f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private View.OnClickListener mPreviewToggleListener =
28448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala            new View.OnClickListener() {
28548f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        public void onClick(View v) {
28648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala            if (mState == CAMERA_TAKE_PICTURE) {
287abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                logE("Can't change preview state while taking picture!");
28848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala                return;
28948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala            }
29048f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala            if (mPreviewToggle.isChecked()) {
291abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                log("Starting preview");
292abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                resizePreview(mPreviewSizes.get(mPreviewSize).width,
293abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                        mPreviewSizes.get(mPreviewSize).height);
29448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala                mCamera.startPreview();
29548f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala                mState = CAMERA_PREVIEW;
296abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                enablePreviewOnlyControls(true);
29748f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala            } else {
298abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                log("Stopping preview");
29948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala                mCamera.stopPreview();
30048f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala                mState = CAMERA_OPEN;
30148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
302abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                enablePreviewOnlyControls(false);
30348f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala            }
30448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        }
30548f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    };
30648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
307abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private OnItemSelectedListener mAutofocusModeListener =
308abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                new OnItemSelectedListener() {
309abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        public void onItemSelected(AdapterView<?> parent,
310abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                        View view, int pos, long id) {
311abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            if (pos == mAfMode) return;
312abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
313abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            mAfMode = pos;
314abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            String focusMode = mAfModes.get(mAfMode);
315abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            log("Setting focus mode to " + focusMode);
316abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            mParams.setFocusMode(focusMode);
317abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
318abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            mCamera.setParameters(mParams);
319abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        }
320abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
321abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        public void onNothingSelected(AdapterView<?> arg0) {
322abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
323abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        }
324abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    };
325abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
326abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private OnClickListener mAutofocusButtonListener =
327abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            new View.OnClickListener() {
328abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        public void onClick(View v) {
329abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            log("Triggering autofocus");
330abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            mCamera.autoFocus(mAutofocusCallback);
331abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        }
332abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    };
333abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
334abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private OnClickListener mCancelAutofocusButtonListener =
335abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            new View.OnClickListener() {
336abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        public void onClick(View v) {
337abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            log("Cancelling autofocus");
338abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            mCamera.cancelAutoFocus();
339abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        }
340abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    };
341abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
342abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private Camera.AutoFocusCallback mAutofocusCallback =
343abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            new Camera.AutoFocusCallback() {
344abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        public void onAutoFocus(boolean success, Camera camera) {
345abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            log("Autofocus completed: " + (success ? "success" : "failure") );
346abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        }
347abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    };
348abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
349abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private Camera.AutoFocusMoveCallback mAutofocusMoveCallback =
350abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            new Camera.AutoFocusMoveCallback() {
351abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        public void onAutoFocusMoving(boolean start, Camera camera) {
352abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            log("Autofocus movement: " + (start ? "starting" : "stopped") );
353abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        }
354abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    };
355abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
356bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala    private AdapterView.OnItemSelectedListener mSnapshotSizeListener =
357abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            new AdapterView.OnItemSelectedListener() {
358bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        public void onItemSelected(AdapterView<?> parent,
359bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala                View view, int pos, long id) {
360bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            if (pos == mSnapshotSize) return;
361bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
362bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            mSnapshotSize = pos;
363bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            int width = mSnapshotSizes.get(mSnapshotSize).width;
364bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            int height = mSnapshotSizes.get(mSnapshotSize).height;
365abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            log("Setting snapshot size to " + width + " x " + height);
366abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
367bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            mParams.setPictureSize(width, height);
368bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
369bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            mCamera.setParameters(mParams);
370bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        }
371bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
372abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        public void onNothingSelected(AdapterView<?> parent) {
373bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
374bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        }
375bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala    };
376bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
37748f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private View.OnClickListener mTakePictureListener =
37848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala            new View.OnClickListener() {
37948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        public void onClick(View v) {
380abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            log("Taking picture");
38148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala            if (mState == CAMERA_PREVIEW) {
38248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala                mState = CAMERA_TAKE_PICTURE;
383abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                enablePreviewOnlyControls(false);
38448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala                mPreviewToggle.setChecked(false);
38548f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
38648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala                mCamera.takePicture(mShutterCb, mRawCb, mPostviewCb, mJpegCb);
38748f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala            } else {
388abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                logE("Can't take picture while not running preview!");
38948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala            }
39048f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        }
39148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    };
39248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
393bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala    private AdapterView.OnItemSelectedListener mCamcorderProfileListener =
394bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala                new AdapterView.OnItemSelectedListener() {
395bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        public void onItemSelected(AdapterView<?> parent,
396bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala                        View view, int pos, long id) {
397abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            if (pos == mCamcorderProfile) return;
398abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
399abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            log("Setting camcorder profile to " + ((TextView)view).getText());
400abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            mCamcorderProfile = pos;
401bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        }
402bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
403abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        public void onNothingSelected(AdapterView<?> parent) {
404bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
405bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        }
406bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala    };
407bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
408bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala    private View.OnClickListener mRecordToggleListener =
409abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            new View.OnClickListener() {
410bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        public void onClick(View v) {
411abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            mPreviewToggle.setEnabled(false);
412abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            if (mState == CAMERA_PREVIEW) {
413abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                startRecording();
414abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            } else if (mState == CAMERA_RECORD) {
415abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                stopRecording();
416abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            } else {
417abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                logE("Can't toggle recording in current state!");
418abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            }
419abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            mPreviewToggle.setEnabled(true);
420bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        }
421bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala    };
422bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
42348f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private Camera.ShutterCallback mShutterCb = new Camera.ShutterCallback() {
42448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        public void onShutter() {
425abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            log("Shutter callback received");
42648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        }
42748f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    };
42848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
42948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private Camera.PictureCallback mRawCb = new Camera.PictureCallback() {
43048f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        public void onPictureTaken(byte[] data, Camera camera) {
431abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            log("Raw callback received");
43248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        }
43348f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    };
43448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
43548f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private Camera.PictureCallback mPostviewCb = new Camera.PictureCallback() {
43648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        public void onPictureTaken(byte[] data, Camera camera) {
437abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            log("Postview callback received");
43848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        }
43948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    };
44048f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
44148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    private Camera.PictureCallback mJpegCb = new Camera.PictureCallback() {
44248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        public void onPictureTaken(byte[] data, Camera camera) {
443abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            log("JPEG picture callback received");
444bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            FragmentManager fm = getFragmentManager();
445bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            SnapshotDialogFragment snapshotDialog = new SnapshotDialogFragment();
44648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
44748f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala            Bitmap img = BitmapFactory.decodeByteArray(data, 0, data.length);
448bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            snapshotDialog.updateImage(img);
449bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            snapshotDialog.show(fm, "snapshot_dialog_fragment");
45048f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
45148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala            mPreviewToggle.setEnabled(true);
45248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
45348f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala            mState = CAMERA_OPEN;
45448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        }
45548f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    };
45648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
45748f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    // Internal methods
45848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
45948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    void setUpCamera() {
460abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        log("Setting up camera " + mCameraId);
461abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        logIndent(1);
46248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        if (mState >= CAMERA_OPEN) {
463abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            log("Closing old camera");
46448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala            mCamera.release();
46548f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala            mState = CAMERA_UNINITIALIZED;
46648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        }
467abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        log("Opening camera " + mCameraId);
46848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        mCamera = Camera.open(mCameraId);
46948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        mState = CAMERA_OPEN;
47048f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
47148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        mParams = mCamera.getParameters();
472bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
473bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        // Set up preview size selection
474abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
475abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        log("Configuring camera");
476abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        logIndent(1);
477abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
478abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        updatePreviewSizes(mParams);
479abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        updateAfModes(mParams);
480abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        updateSnapshotSizes(mParams);
481abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        updateCamcorderProfile(mCameraId);
482abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
483abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        // Update parameters based on above updates
484abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mCamera.setParameters(mParams);
485abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
486abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mCamera.setAutoFocusMoveCallback(mAutofocusMoveCallback);
487abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
488abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        if (mPreviewHolder != null) {
489abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            log("Setting preview display");
490abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            try {
491abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                mCamera.setPreviewDisplay(mPreviewHolder);
492abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            } catch(IOException e) {
493abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                Log.e(TAG, "Unable to set up preview!");
494abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            }
495abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        }
496abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
497abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        logIndent(-1);
498abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
499abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mPreviewToggle.setEnabled(true);
500abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mPreviewToggle.setChecked(false);
501abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        enablePreviewOnlyControls(false);
502abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
503abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        int width = mPreviewSizes.get(mPreviewSize).width;
504abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        int height = mPreviewSizes.get(mPreviewSize).height;
505abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        resizePreview(width, height);
506abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        if (mPreviewToggle.isChecked()) {
507abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            log("Starting preview" );
508abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            mCamera.startPreview();
509abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            mState = CAMERA_PREVIEW;
510abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        }
511abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        logIndent(-1);
512abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    }
513abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
514abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private void updateAfModes(Parameters params) {
515abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mAfModes = params.getSupportedFocusModes();
516abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
517abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mAutofocusModeSpinner.setAdapter(
518abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                new ArrayAdapter<String>(this, R.layout.spinner_item,
519abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                        mAfModes.toArray(new String[0])));
520abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
521abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mAfMode = 0;
522abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
523abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        params.setFocusMode(mAfModes.get(mAfMode));
524abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
525abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        log("Setting AF mode to " + mAfModes.get(mAfMode));
526abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    }
527abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
528abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private void updatePreviewSizes(Camera.Parameters params) {
529abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mPreviewSizes = params.getSupportedPreviewSizes();
53048f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
53148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        String[] availableSizeNames = new String[mPreviewSizes.size()];
532bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        int i = 0;
533bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        for (Camera.Size previewSize: mPreviewSizes) {
534bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            availableSizeNames[i++] =
535abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                Integer.toString(previewSize.width) + " x " +
536abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                Integer.toString(previewSize.height);
53748f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        }
53848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        mPreviewSizeSpinner.setAdapter(
539abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                new ArrayAdapter<String>(
540abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                        this, R.layout.spinner_item, availableSizeNames));
54148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
54248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        mPreviewSize = 0;
54348f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
54448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        int width = mPreviewSizes.get(mPreviewSize).width;
54548f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        int height = mPreviewSizes.get(mPreviewSize).height;
546abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        params.setPreviewSize(width, height);
547abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        log("Setting preview size to " + width + " x " + height);
548abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    }
549bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
550abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private void updateSnapshotSizes(Camera.Parameters params) {
551abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        String[] availableSizeNames;
552abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mSnapshotSizes = params.getSupportedPictureSizes();
553bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
554bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        availableSizeNames = new String[mSnapshotSizes.size()];
555abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        int i = 0;
556bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        for (Camera.Size snapshotSize : mSnapshotSizes) {
557bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala            availableSizeNames[i++] =
558abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                Integer.toString(snapshotSize.width) + " x " +
559abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                Integer.toString(snapshotSize.height);
560bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        }
561bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        mSnapshotSizeSpinner.setAdapter(
562abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                new ArrayAdapter<String>(
563abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                        this, R.layout.spinner_item, availableSizeNames));
564bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
565bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        mSnapshotSize = 0;
566bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
567abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        int snapshotWidth = mSnapshotSizes.get(mSnapshotSize).width;
568abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        int snapshotHeight = mSnapshotSizes.get(mSnapshotSize).height;
569abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        params.setPictureSize(snapshotWidth, snapshotHeight);
570abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        log("Setting snapshot size to " + snapshotWidth + " x " + snapshotHeight);
57148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    }
57248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
573bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala    private void updateCamcorderProfile(int cameraId) {
574bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        // Have to query all of these individually,
575bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        final int PROFILES[] = new int[] {
576abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            CamcorderProfile.QUALITY_1080P,
577abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            CamcorderProfile.QUALITY_480P,
578abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            CamcorderProfile.QUALITY_720P,
579abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            CamcorderProfile.QUALITY_CIF,
580abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            CamcorderProfile.QUALITY_HIGH,
581abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            CamcorderProfile.QUALITY_LOW,
582abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            CamcorderProfile.QUALITY_QCIF,
583abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            CamcorderProfile.QUALITY_QVGA,
584abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            CamcorderProfile.QUALITY_TIME_LAPSE_1080P,
585abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            CamcorderProfile.QUALITY_TIME_LAPSE_480P,
586abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            CamcorderProfile.QUALITY_TIME_LAPSE_720P,
587abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            CamcorderProfile.QUALITY_TIME_LAPSE_CIF,
588abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            CamcorderProfile.QUALITY_TIME_LAPSE_HIGH,
589abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            CamcorderProfile.QUALITY_TIME_LAPSE_LOW,
590abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            CamcorderProfile.QUALITY_TIME_LAPSE_QCIF,
591abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            CamcorderProfile.QUALITY_TIME_LAPSE_QVGA
592bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        };
593bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
594bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        final String PROFILE_NAMES[] = new String[] {
595abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            "1080P",
596abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            "480P",
597abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            "720P",
598abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            "CIF",
599abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            "HIGH",
600abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            "LOW",
601abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            "QCIF",
602abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            "QVGA",
603abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            "TIME_LAPSE_1080P",
604abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            "TIME_LAPSE_480P",
605abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            "TIME_LAPSE_720P",
606abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            "TIME_LAPSE_CIF",
607abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            "TIME_LAPSE_HIGH",
608abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            "TIME_LAPSE_LOW",
609abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            "TIME_LAPSE_QCIF",
610abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            "TIME_LAPSE_QVGA"
611bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        };
612bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
613bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        List<String> availableCamcorderProfileNames = new ArrayList<String>();
614bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        mCamcorderProfiles = new ArrayList<CamcorderProfile>();
615bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
616bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        for (int i = 0; i < PROFILES.length; i++) {
617abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            if (CamcorderProfile.hasProfile(cameraId, PROFILES[i])) {
618abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                availableCamcorderProfileNames.add(PROFILE_NAMES[i]);
619abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                mCamcorderProfiles.add(CamcorderProfile.get(cameraId, PROFILES[i]));
620abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            }
621bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        }
622bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        String[] nameArray = (String[])availableCamcorderProfileNames.toArray(new String[0]);
623bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala        mCamcorderProfileSpinner.setAdapter(
624abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                new ArrayAdapter<String>(
625abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                        this, R.layout.spinner_item, nameArray));
626abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
627abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mCamcorderProfile = 0;
628abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        log("Setting camcorder profile to " + nameArray[mCamcorderProfile]);
629abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
630bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala    }
631bc88c6ed6508927ad72eefba3f6f63c6436f06d3Eino-Ville Talvala
63248f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    void resizePreview(int width, int height) {
63348f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        if (mPreviewHolder != null) {
63448f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala            int viewHeight = mPreviewView.getHeight();
63548f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala            int viewWidth = (int)(((double)width)/height * viewHeight);
63648f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
63748f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala            mPreviewView.setLayoutParams(
63848f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala                new LayoutParams(viewWidth, viewHeight));
63948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala        }
64048f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala
64148f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala    }
642abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
643abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    static final int MEDIA_TYPE_IMAGE = 0;
644abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    static final int MEDIA_TYPE_VIDEO = 1;
645abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private File getOutputMediaFile(int type){
646abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        // To be safe, you should check that the SDCard is mounted
647abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        // using Environment.getExternalStorageState() before doing this.
648abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
649abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        String state = Environment.getExternalStorageState();
650abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        if (!Environment.MEDIA_MOUNTED.equals(state)) {
651abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                return null;
652abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        }
653abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
654abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
655abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                  Environment.DIRECTORY_PICTURES), "TestingCamera");
656abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        // This location works best if you want the created images to be shared
657abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        // between applications and persist after your app has been uninstalled.
658abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
659abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        // Create the storage directory if it does not exist
660abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        if (! mediaStorageDir.exists()){
661abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            if (! mediaStorageDir.mkdirs()){
662abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                logE("Failed to create directory for pictures/video");
663abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                return null;
664abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            }
665abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        }
666abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
667abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        // Create a media file name
668abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
669abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        File mediaFile;
670abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        if (type == MEDIA_TYPE_IMAGE){
671abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            mediaFile = new File(mediaStorageDir.getPath() + File.separator +
672abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            "IMG_"+ timeStamp + ".jpg");
673abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        } else if(type == MEDIA_TYPE_VIDEO) {
674abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            mediaFile = new File(mediaStorageDir.getPath() + File.separator +
675abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            "VID_"+ timeStamp + ".mp4");
676abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        } else {
677abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            return null;
678abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        }
679abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
680abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        return mediaFile;
681abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    }
682abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
683abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private void startRecording() {
684abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        log("Starting recording");
685abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        logIndent(1);
686abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        log("Configuring MediaRecoder");
687abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mCamera.unlock();
688abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mRecorder = new MediaRecorder();
689abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mRecorder.setOnErrorListener(mRecordingErrorListener);
690abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mRecorder.setOnInfoListener(mRecordingInfoListener);
691abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mRecorder.setCamera(mCamera);
692abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
693abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
694abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mRecorder.setProfile(mCamcorderProfiles.get(mCamcorderProfile));
695abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        File outputFile = getOutputMediaFile(MEDIA_TYPE_VIDEO);
696abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        log("File name:" + outputFile.toString());
697abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mRecorder.setOutputFile(outputFile.toString());
698abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
699abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        boolean ready = false;
700abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        log("Preparing MediaRecorder");
701abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        try {
702abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            mRecorder.prepare();
703abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            ready = true;
704abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        } catch (Exception e) {
705abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            StringWriter writer = new StringWriter();
706abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            e.printStackTrace(new PrintWriter(writer));
707abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            logE("Exception preparing MediaRecorder:\n" + writer.toString());
708abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        }
709abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
710abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        if (ready) {
711abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            try {
712abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                log("Starting MediaRecorder");
713abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                mRecorder.start();
714abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                mState = CAMERA_RECORD;
715abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                log("Recording active");
716abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            } catch (Exception e) {
717abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                StringWriter writer = new StringWriter();
718abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                e.printStackTrace(new PrintWriter(writer));
719abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                logE("Exception starting MediaRecorder:\n" + writer.toString());
720abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            }
721abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        } else {
722abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            mPreviewToggle.setChecked(false);
723abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        }
724abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        logIndent(-1);
725abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    }
726abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
727abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private MediaRecorder.OnErrorListener mRecordingErrorListener =
728abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            new MediaRecorder.OnErrorListener() {
729abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        public void onError(MediaRecorder mr, int what, int extra) {
730abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            logE("MediaRecorder reports error: " + what + ", extra "
731abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                    + extra);
732abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            if (mState == CAMERA_RECORD) {
733abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                stopRecording();
734abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            }
735abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        }
736abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    };
737abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
738abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private MediaRecorder.OnInfoListener mRecordingInfoListener =
739abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            new MediaRecorder.OnInfoListener() {
740abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        public void onInfo(MediaRecorder mr, int what, int extra) {
741abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            log("MediaRecorder reports info: " + what + ", extra "
742abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                    + extra);
743abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        }
744abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    };
745abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
746abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private void stopRecording() {
747abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        log("Stopping recording");
748abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        if (mRecorder != null) {
749abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            mRecorder.stop();
750abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            mCamera.lock();
751abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            mState = CAMERA_PREVIEW;
752abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            mRecorder.release();
753abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            mRecorder = null;
754abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        } else {
755abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            logE("Recorder is unexpectedly null!");
756abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        }
757abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    }
758abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
759abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private int mLogIndentLevel = 0;
760abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private String mLogIndent = "\t";
761abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    /** Increment or decrement log indentation level */
762abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private void logIndent(int delta) {
763abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mLogIndentLevel += delta;
764abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        if (mLogIndentLevel < 0) mLogIndentLevel = 0;
765abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        char[] mLogIndentArray = new char[mLogIndentLevel + 1];
766abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        for (int i = -1; i < mLogIndentLevel; i++) {
767abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            mLogIndentArray[i + 1] = '\t';
768abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        }
769abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mLogIndent = new String(mLogIndentArray);
770abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    }
771abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
772abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    SimpleDateFormat mDateFormatter = new SimpleDateFormat("HH:mm:ss.SSS");
773abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    /** Log both to log text view and to device logcat */
774abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private void log(String logLine) {
775abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        Log.d(TAG, logLine);
776abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        logAndScrollToBottom(logLine, mLogIndent);
777abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    }
778abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
779abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private void logE(String logLine) {
780abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        Log.e(TAG, logLine);
781abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        logAndScrollToBottom(logLine, mLogIndent + "!!! ");
782abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    }
783abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
784abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    private void logAndScrollToBottom(String logLine, String logIndent) {
785abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        StringBuffer logEntry = new StringBuffer(32);
786abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        logEntry.append("\n").append(mDateFormatter.format(new Date())).append(logIndent);
787abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        logEntry.append(logLine);
788abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        mLogView.append(logEntry);
789abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        final Layout layout = mLogView.getLayout();
790abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        if (layout != null){
791abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            int scrollDelta = layout.getLineBottom(mLogView.getLineCount() - 1)
792abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                - mLogView.getScrollY() - mLogView.getHeight();
793abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            if(scrollDelta > 0) {
794abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala                mLogView.scrollBy(0, scrollDelta);
795abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala            }
796abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala        }
797abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala    }
798abe36163445fb3fe458252fd8d21c3e1ac14ed6dEino-Ville Talvala
79948f2556e12eeaa8932947fe6c8083e64bb5eb804Eino-Ville Talvala}