/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.camera;
import com.android.camera.ui.FocusRectangle;
import com.android.camera.ui.IndicatorControl;
import com.android.camera.ui.RotateImageView;
import com.android.camera.ui.SharePopup;
import com.android.camera.ui.ZoomPicker;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences.Editor;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.hardware.Camera.Area;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.location.Location;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.media.AudioManager;
import android.media.CameraProfile;
import android.media.ToneGenerator;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
import android.os.SystemClock;
import android.provider.MediaStore;
import android.provider.Settings;
import android.util.Log;
import android.view.GestureDetector;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.MotionEvent;
import android.view.OrientationEventListener;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
/** The Camera activity which can preview and take pictures. */
public class Camera extends ActivityBase implements View.OnClickListener,
View.OnTouchListener, ShutterButton.OnShutterButtonListener,
SurfaceHolder.Callback, ModePicker.OnModeChangeListener {
private static final String TAG = "camera";
private static final String LAST_THUMB_FILENAME = "image_last_thumb";
private static final int CROP_MSG = 1;
private static final int FIRST_TIME_INIT = 2;
private static final int RESTART_PREVIEW = 3;
private static final int CLEAR_SCREEN_DELAY = 4;
private static final int SET_CAMERA_PARAMETERS_WHEN_IDLE = 5;
private static final int CHECK_DISPLAY_ROTATION = 6;
private static final int RESET_TOUCH_FOCUS = 7;
// The subset of parameters we need to update in setCameraParameters().
private static final int UPDATE_PARAM_INITIALIZE = 1;
private static final int UPDATE_PARAM_ZOOM = 2;
private static final int UPDATE_PARAM_PREFERENCE = 4;
private static final int UPDATE_PARAM_ALL = -1;
// When setCameraParametersWhenIdle() is called, we accumulate the subsets
// needed to be updated in mUpdateSet.
private int mUpdateSet;
// The brightness settings used when it is set to automatic in the system.
// The reason why it is set to 0.7 is just because 1.0 is too bright.
private static final float DEFAULT_CAMERA_BRIGHTNESS = 0.7f;
private static final int SCREEN_DELAY = 2 * 60 * 1000;
private static final int FOCUS_BEEP_VOLUME = 100;
private static final int ZOOM_STOPPED = 0;
private static final int ZOOM_START = 1;
private static final int ZOOM_STOPPING = 2;
private int mZoomState = ZOOM_STOPPED;
private boolean mSmoothZoomSupported = false;
private int mZoomValue; // The current zoom value.
private int mZoomMax;
private int mTargetZoomValue;
private ZoomPicker mZoomPicker;
private Parameters mParameters;
private Parameters mInitialParams;
private MyOrientationEventListener mOrientationListener;
// The degrees of the device rotated clockwise from its natural orientation.
private int mOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
// The orientation compensation for icons and thumbnails. Ex: if the value
// is 90, the UI components should be rotated 90 degrees counter-clockwise.
private int mOrientationCompensation = 0;
private ComboPreferences mPreferences;
private static final String sTempCropFilename = "crop-temp";
private android.hardware.Camera mCameraDevice;
private ContentProviderClient mMediaProviderClient;
private SurfaceHolder mSurfaceHolder = null;
private ShutterButton mShutterButton;
private ToneGenerator mFocusToneGenerator;
private GestureDetector mPopupGestureDetector;
private boolean mOpenCameraFail = false;
private boolean mCameraDisabled = false;
private View mPreviewFrame; // Preview frame area.
private View mPreviewBorder;
private FocusRectangle mFocusRectangle;
private List mFocusArea; // focus area in driver format
private static final int RESET_TOUCH_FOCUS_DELAY = 3000;
// A popup window that contains a bigger thumbnail and a list of apps to share.
private SharePopup mSharePopup;
// The bitmap of the last captured picture thumbnail and the URI of the
// original picture.
private Thumbnail mThumbnail;
// A button that contains the thumbnail and the share icon.
private View mShareButton;
// An imageview showing showing the last captured picture thumbnail.
private RotateImageView mThumbnailView;
private RotateImageView mShareIcon;
private ModePicker mModePicker;
// mCropValue and mSaveUri are used only if isImageCaptureIntent() is true.
private String mCropValue;
private Uri mSaveUri;
// GPS on-screen indicator
private View mGpsNoSignalView;
private View mGpsHasSignalView;
/**
* An unpublished intent flag requesting to return as soon as capturing
* is completed.
*
* TODO: consider publishing by moving into MediaStore.
*/
private final static String EXTRA_QUICK_CAPTURE =
"android.intent.extra.quickCapture";
// The display rotation in degrees. This is only valid when mCameraState is
// not PREVIEW_STOPPED.
private int mDisplayRotation;
// The value for android.hardware.Camera.setDisplayOrientation.
private int mDisplayOrientation;
private boolean mPausing;
private boolean mFirstTimeInitialized;
private boolean mIsImageCaptureIntent;
private boolean mRecordLocation;
private static final int PREVIEW_STOPPED = 0;
private static final int IDLE = 1; // preview is active
private static final int FOCUSING = 2;
private static final int FOCUSING_SNAP_ON_FINISH = 3;
private static final int FOCUS_SUCCESS = 4;
private static final int FOCUS_FAIL = 5;
private static final int SNAPSHOT_IN_PROGRESS = 6;
private int mCameraState = PREVIEW_STOPPED;
private ContentResolver mContentResolver;
private boolean mDidRegister = false;
private final ArrayList