ActivityBase.java revision 475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687
1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.camera;
18
19import android.app.Activity;
20import android.app.KeyguardManager;
21import android.content.ContentResolver;
22import android.content.Context;
23import android.content.Intent;
24import android.content.pm.ActivityInfo;
25import android.os.AsyncTask;
26import android.os.Bundle;
27import android.util.Log;
28import android.view.KeyEvent;
29import android.view.View;
30import android.view.WindowManager;
31
32import com.android.camera.ui.PopupManager;
33import com.android.camera.ui.RotateImageView;
34
35import java.io.File;
36
37/**
38 * Superclass of Camera and VideoCamera activities.
39 */
40abstract public class ActivityBase extends Activity {
41    private static final String TAG = "ActivityBase";
42    private static boolean LOGV = false;
43    private int mResultCodeForTesting;
44    private boolean mOnResumePending;
45    private Intent mResultDataForTesting;
46    private OnScreenHint mStorageHint;
47    // The bitmap of the last captured picture thumbnail and the URI of the
48    // original picture.
49    protected Thumbnail mThumbnail;
50    // An imageview showing showing the last captured picture thumbnail.
51    protected RotateImageView mThumbnailView;
52    protected AsyncTask<Void, Void, Thumbnail> mLoadThumbnailTask;
53    protected boolean mOpenCameraFail;
54    protected boolean mCameraDisabled;
55    protected CameraManager.CameraProxy mCameraDevice;
56
57    // multiple cameras support
58    protected int mNumberOfCameras;
59    protected int mCameraId;
60
61    protected class CameraOpenThread extends Thread {
62        @Override
63        public void run() {
64            try {
65                mCameraDevice = Util.openCamera(ActivityBase.this, mCameraId);
66            } catch (CameraHardwareException e) {
67                mOpenCameraFail = true;
68            } catch (CameraDisabledException e) {
69                mCameraDisabled = true;
70            }
71        }
72    }
73
74    @Override
75    public void onCreate(Bundle icicle) {
76        if (Util.isTabletUI()) {
77            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
78        } else {
79            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
80        }
81        getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
82        super.onCreate(icicle);
83    }
84
85    @Override
86    public void onWindowFocusChanged(boolean hasFocus) {
87        if (LOGV) Log.v(TAG, "onWindowFocusChanged.hasFocus=" + hasFocus
88                + ".mOnResumePending=" + mOnResumePending);
89        if (hasFocus && mOnResumePending) {
90            doOnResume();
91            mOnResumePending = false;
92        }
93    }
94
95    @Override
96    protected void onResume() {
97        super.onResume();
98        // Don't grab the camera if in use by lockscreen. For example, face
99        // unlock may be using the camera. Camera may be already opened in
100        // onCreate. doOnResume should continue if mCameraDevice != null.
101        // Suppose camera app is in the foreground. If users turn off and turn
102        // on the screen very fast, camera app can still have the focus when the
103        // lock screen shows up. The keyguard takes input focus, so the camera
104        // app will lose focus when it is displayed.
105        if (LOGV) Log.v(TAG, "onResume. hasWindowFocus()=" + hasWindowFocus());
106        if (mCameraDevice == null && isKeyguardLocked()) {
107            if (LOGV) Log.v(TAG, "onResume. mOnResumePending=true");
108            mOnResumePending = true;
109        } else {
110            if (LOGV) Log.v(TAG, "onResume. mOnResumePending=false");
111            doOnResume();
112            mOnResumePending = false;
113        }
114    }
115
116    @Override
117    protected void onPause() {
118        if (LOGV) Log.v(TAG, "onPause");
119        saveThumbnailToFile();
120        super.onPause();
121
122        if (mLoadThumbnailTask != null) {
123            mLoadThumbnailTask.cancel(true);
124            mLoadThumbnailTask = null;
125        }
126
127        if (mStorageHint != null) {
128            mStorageHint.cancel();
129            mStorageHint = null;
130        }
131
132        mOnResumePending = false;
133    }
134
135    // Put the code of onResume in this method.
136    abstract protected void doOnResume();
137
138    @Override
139    public boolean onSearchRequested() {
140        return false;
141    }
142
143    @Override
144    public boolean onKeyDown(int keyCode, KeyEvent event) {
145        // Prevent software keyboard or voice search from showing up.
146        if (keyCode == KeyEvent.KEYCODE_SEARCH
147                || keyCode == KeyEvent.KEYCODE_MENU) {
148            if (event.isLongPress()) return true;
149        }
150
151        return super.onKeyDown(keyCode, event);
152    }
153
154    protected void setResultEx(int resultCode) {
155        mResultCodeForTesting = resultCode;
156        setResult(resultCode);
157    }
158
159    protected void setResultEx(int resultCode, Intent data) {
160        mResultCodeForTesting = resultCode;
161        mResultDataForTesting = data;
162        setResult(resultCode, data);
163    }
164
165    public int getResultCode() {
166        return mResultCodeForTesting;
167    }
168
169    public Intent getResultData() {
170        return mResultDataForTesting;
171    }
172
173    @Override
174    protected void onDestroy() {
175        PopupManager.removeInstance(this);
176        super.onDestroy();
177    }
178
179    private boolean isKeyguardLocked() {
180        KeyguardManager kgm = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
181        if (LOGV) {
182            if (kgm != null) {
183                Log.v(TAG, "kgm.isKeyguardLocked()="+kgm.isKeyguardLocked()
184                        + ". kgm.isKeyguardSecure()="+kgm.isKeyguardSecure());
185            }
186        }
187        // isKeyguardSecure excludes the slide lock case.
188        return (kgm != null) && kgm.isKeyguardLocked() && kgm.isKeyguardSecure();
189    }
190
191    protected void updateStorageHint(long storageSpace) {
192        String message = null;
193        if (storageSpace == Storage.UNAVAILABLE) {
194            message = getString(R.string.no_storage);
195        } else if (storageSpace == Storage.PREPARING) {
196            message = getString(R.string.preparing_sd);
197        } else if (storageSpace == Storage.UNKNOWN_SIZE) {
198            message = getString(R.string.access_sd_fail);
199        } else if (storageSpace < Storage.LOW_STORAGE_THRESHOLD) {
200            message = getString(R.string.spaceIsLow_content);
201        }
202
203        if (message != null) {
204            if (mStorageHint == null) {
205                mStorageHint = OnScreenHint.makeText(this, message);
206            } else {
207                mStorageHint.setText(message);
208            }
209            mStorageHint.show();
210        } else if (mStorageHint != null) {
211            mStorageHint.cancel();
212            mStorageHint = null;
213        }
214    }
215
216    private void updateThumbnailView() {
217        if (mThumbnail != null) {
218            mThumbnailView.setBitmap(mThumbnail.getBitmap());
219            mThumbnailView.setVisibility(View.VISIBLE);
220        } else {
221            mThumbnailView.setBitmap(null);
222            mThumbnailView.setVisibility(View.GONE);
223        }
224    }
225
226    protected void getLastThumbnail() {
227        mThumbnail = ThumbnailHolder.getLastThumbnail(getContentResolver());
228        // Suppose users tap the thumbnail view, go to the gallery, delete the
229        // image, and coming back to the camera. Thumbnail file will be invalid.
230        // Since the new thumbnail will be loaded in another thread later, the
231        // view should be set to gone to prevent from opening the invalid image.
232        updateThumbnailView();
233        if (mThumbnail == null) {
234            mLoadThumbnailTask = new LoadThumbnailTask().execute();
235        }
236    }
237
238    private class LoadThumbnailTask extends AsyncTask<Void, Void, Thumbnail> {
239        @Override
240        protected Thumbnail doInBackground(Void... params) {
241            // Load the thumbnail from the file.
242            ContentResolver resolver = getContentResolver();
243            Thumbnail t = Thumbnail.getLastThumbnailFromFile(getFilesDir(), resolver);
244
245            if (isCancelled()) return null;
246
247            if (t == null) {
248                // Load the thumbnail from the media provider.
249                t = Thumbnail.getLastThumbnailFromContentResolver(resolver);
250            }
251            return t;
252        }
253
254        @Override
255        protected void onPostExecute(Thumbnail thumbnail) {
256            mThumbnail = thumbnail;
257            updateThumbnailView();
258        }
259    }
260
261    protected void gotoGallery() {
262        Util.viewUri(mThumbnail.getUri(), this);
263    }
264
265    protected void saveThumbnailToFile() {
266        if (mThumbnail != null && !mThumbnail.fromFile()) {
267            new SaveThumbnailTask().execute(mThumbnail);
268        }
269    }
270
271    private class SaveThumbnailTask extends AsyncTask<Thumbnail, Void, Void> {
272        @Override
273        protected Void doInBackground(Thumbnail... params) {
274            final int n = params.length;
275            final File filesDir = getFilesDir();
276            for (int i = 0; i < n; i++) {
277                params[i].saveLastThumbnailToFile(filesDir);
278            }
279            return null;
280        }
281    }
282}
283