summaryrefslogtreecommitdiffstats
path: root/src/com/android/gallery3d/app
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/gallery3d/app')
-rw-r--r--src/com/android/gallery3d/app/AlbumPage.java6
-rw-r--r--src/com/android/gallery3d/app/CameraScreenNail.java225
-rw-r--r--src/com/android/gallery3d/app/CameraView.java117
-rw-r--r--src/com/android/gallery3d/app/PhotoDataAdapter.java2
-rw-r--r--src/com/android/gallery3d/app/PhotoPage.java72
-rw-r--r--src/com/android/gallery3d/app/ScreenNailBridge.java122
6 files changed, 262 insertions, 282 deletions
diff --git a/src/com/android/gallery3d/app/AlbumPage.java b/src/com/android/gallery3d/app/AlbumPage.java
index 8bd2badf8..37ddb184c 100644
--- a/src/com/android/gallery3d/app/AlbumPage.java
+++ b/src/com/android/gallery3d/app/AlbumPage.java
@@ -51,6 +51,7 @@ import com.android.gallery3d.ui.HighlightDrawer;
import com.android.gallery3d.ui.PositionProvider;
import com.android.gallery3d.ui.PositionRepository;
import com.android.gallery3d.ui.PositionRepository.Position;
+import com.android.gallery3d.ui.ScreenNailHolder;
import com.android.gallery3d.ui.SelectionManager;
import com.android.gallery3d.ui.SlotView;
import com.android.gallery3d.util.Future;
@@ -77,6 +78,7 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
private static final int BIT_LOADING_SYNC = 2;
private static final float USER_DISTANCE_METER = 0.3f;
+ private static final boolean TEST_CAMERA_PREVIEW = false;
private boolean mIsActive = false;
private AlbumView mAlbumView;
@@ -196,6 +198,10 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
mMediaSetPath.toString());
data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH,
item.getPath().toString());
+ if (TEST_CAMERA_PREVIEW) {
+ ScreenNailHolder holder = new CameraScreenNailHolder(mActivity);
+ data.putParcelable(PhotoPage.KEY_SCREENNAIL_HOLDER, holder);
+ }
mActivity.getStateManager().startStateForResult(
PhotoPage.class, REQUEST_PHOTO, data);
}
diff --git a/src/com/android/gallery3d/app/CameraScreenNail.java b/src/com/android/gallery3d/app/CameraScreenNail.java
new file mode 100644
index 000000000..f68ab72f8
--- /dev/null
+++ b/src/com/android/gallery3d/app/CameraScreenNail.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2012 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.gallery3d.app;
+
+import android.app.Activity;
+import android.graphics.SurfaceTexture;
+import android.hardware.Camera;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Message;
+import android.util.Log;
+import android.view.Surface;
+
+import com.android.gallery3d.ui.GLCanvas;
+import com.android.gallery3d.ui.ScreenNail;
+import com.android.gallery3d.ui.ScreenNailHolder;
+import com.android.gallery3d.ui.SurfaceTextureScreenNail;
+
+// This is a ScreenNail which displays camera preview. This demos the usage of
+// SurfaceTextureScreenNail. It is not intended for production use.
+class CameraScreenNail extends SurfaceTextureScreenNail {
+ private static final String TAG = "CameraScreenNail";
+ private static final int CAMERA_ID = 0;
+ private static final int PREVIEW_WIDTH = 960;
+ private static final int PREVIEW_HEIGHT = 720;
+ private static final int MSG_START_CAMERA = 1;
+ private static final int MSG_STOP_CAMERA = 2;
+
+ public interface Listener {
+ void requestRender();
+ }
+
+ private Activity mActivity;
+ private Listener mListener;
+ private int mOrientation;
+ private Camera mCamera;
+
+ private HandlerThread mHandlerThread;
+ private Handler mHandler;
+ private volatile boolean mVisible;
+ private volatile boolean mHasFrame;
+
+ public CameraScreenNail(Activity activity, Listener listener) {
+ mActivity = activity;
+ mListener = listener;
+
+ mOrientation = getCameraDisplayOrientation(mActivity, CAMERA_ID);
+ if (mOrientation % 180 == 0) {
+ setSize(PREVIEW_WIDTH, PREVIEW_HEIGHT);
+ } else {
+ setSize(PREVIEW_HEIGHT, PREVIEW_WIDTH);
+ }
+
+ mHandlerThread = new HandlerThread("Camera");
+ mHandlerThread.start();
+ mHandler = new Handler(mHandlerThread.getLooper()) {
+ public void handleMessage(Message message) {
+ if (message.what == MSG_START_CAMERA && mCamera == null) {
+ startCamera();
+ } else if (message.what == MSG_STOP_CAMERA && mCamera != null) {
+ stopCamera();
+ }
+ }
+ };
+ mHandler.sendEmptyMessage(MSG_START_CAMERA);
+ }
+
+ private void startCamera() {
+ try {
+ acquireSurfaceTexture();
+ Camera camera = Camera.open(CAMERA_ID);
+ Camera.Parameters param = camera.getParameters();
+ param.setPreviewSize(PREVIEW_WIDTH, PREVIEW_HEIGHT);
+ camera.setParameters(param);
+ camera.setDisplayOrientation(mOrientation);
+ camera.setPreviewTexture(getSurfaceTexture());
+ camera.startPreview();
+ synchronized (this) {
+ mCamera = camera;
+ }
+ } catch (Throwable th) {
+ Log.e(TAG, "cannot open camera", th);
+ }
+ }
+
+ private void stopCamera() {
+ releaseSurfaceTexture();
+ mCamera.stopPreview();
+ mCamera.release();
+ synchronized (this) {
+ mCamera = null;
+ notifyAll();
+ }
+ mHasFrame = false;
+ }
+
+ @Override
+ public void draw(GLCanvas canvas, int x, int y, int width, int height) {
+ if (!mVisible) {
+ mVisible = true;
+ // Only send one message when mVisible makes transition from
+ // false to true.
+ mHandler.sendEmptyMessage(MSG_START_CAMERA);
+ }
+
+ if (mVisible && mHasFrame) {
+ super.draw(canvas, x, y, width, height);
+ }
+ }
+
+ @Override
+ public void noDraw() {
+ mVisible = false;
+ }
+
+ @Override
+ public void pauseDraw() {
+ mVisible = false;
+ }
+
+ @Override
+ public void onFrameAvailable(SurfaceTexture surfaceTexture) {
+ mHasFrame = true;
+ if (mVisible) {
+ // We need to ask for re-render if the SurfaceTexture receives a new
+ // frame (and we are visible).
+ mListener.requestRender();
+ }
+ }
+
+ public void destroy() {
+ synchronized (this) {
+ mHandler.sendEmptyMessage(MSG_STOP_CAMERA);
+
+ // Wait until camera is closed.
+ while (mCamera != null) {
+ try {
+ wait();
+ } catch (Exception ex) {
+ // ignore.
+ }
+ }
+ }
+ mHandlerThread.quit();
+ }
+
+ // The three methods below are copied from Camera.java
+ private static int getCameraDisplayOrientation(
+ Activity activity, int cameraId) {
+ int displayRotation = getDisplayRotation(activity);
+ int displayOrientation = getDisplayOrientation(
+ displayRotation, cameraId);
+ return displayOrientation;
+ }
+
+ private static int getDisplayRotation(Activity activity) {
+ int rotation = activity.getWindowManager().getDefaultDisplay()
+ .getRotation();
+ switch (rotation) {
+ case Surface.ROTATION_0: return 0;
+ case Surface.ROTATION_90: return 90;
+ case Surface.ROTATION_180: return 180;
+ case Surface.ROTATION_270: return 270;
+ }
+ return 0;
+ }
+
+ private static int getDisplayOrientation(int degrees, int cameraId) {
+ // See android.hardware.Camera.setDisplayOrientation for
+ // documentation.
+ Camera.CameraInfo info = new Camera.CameraInfo();
+ Camera.getCameraInfo(cameraId, info);
+ int result;
+ if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
+ result = (info.orientation + degrees) % 360;
+ result = (360 - result) % 360; // compensate the mirror
+ } else { // back-facing
+ result = (info.orientation - degrees + 360) % 360;
+ }
+ return result;
+ }
+}
+
+// This holds a CameraScreenNail, so we can pass it to a PhotoPage.
+class CameraScreenNailHolder extends ScreenNailHolder
+ implements CameraScreenNail.Listener {
+ private static final String TAG = "CameraScreenNailHolder";
+ private GalleryActivity mActivity;
+ private CameraScreenNail mCameraScreenNail;
+
+ public CameraScreenNailHolder(GalleryActivity activity) {
+ mActivity = activity;
+ }
+
+ @Override
+ public void requestRender() {
+ mActivity.getGLRoot().requestRender();
+ }
+
+ @Override
+ public ScreenNail attach() {
+ mCameraScreenNail = new CameraScreenNail((Activity) mActivity, this);
+ return mCameraScreenNail;
+ }
+
+ @Override
+ public void detach() {
+ mCameraScreenNail.destroy();
+ mCameraScreenNail = null;
+ }
+}
diff --git a/src/com/android/gallery3d/app/CameraView.java b/src/com/android/gallery3d/app/CameraView.java
deleted file mode 100644
index a6c233291..000000000
--- a/src/com/android/gallery3d/app/CameraView.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2012 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.gallery3d.app;
-
-import android.content.Context;
-import android.graphics.SurfaceTexture;
-import android.hardware.Camera;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.TextureView;
-import android.view.View;
-
-import java.io.IOException;
-
-// This is a sample View which demos the usage of ScreenNailBridge. It
-// is not intended for production use.
-public class CameraView extends TextureView implements
- TextureView.SurfaceTextureListener, ScreenNailBridge.Listener {
- private static final String TAG = "CameraView";
- private static final int PREVIEW_WIDTH = 960;
- private static final int PREVIEW_HEIGHT = 720;
- private Camera mCamera;
- private ScreenNailBridge mScreenNailBridge;
-
- public CameraView(Context context) {
- super(context);
- init();
- }
-
- public CameraView(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
-
- private void init() {
- setVisibility(View.INVISIBLE);
- setSurfaceTextureListener(this);
- }
-
- public void setScreenNailBridge(ScreenNailBridge s) {
- mScreenNailBridge = s;
- }
-
- @Override
- public void onMeasure(int widthSpec, int heightSpec) {
- int width = getDefaultSize(PREVIEW_WIDTH, widthSpec);
- int height = getDefaultSize(PREVIEW_HEIGHT, heightSpec);
- // Keep aspect ratio
- if (width * PREVIEW_HEIGHT > PREVIEW_WIDTH * height) {
- width = PREVIEW_WIDTH * height / PREVIEW_HEIGHT;
- } else {
- height = PREVIEW_HEIGHT * width / PREVIEW_WIDTH;
- }
- setMeasuredDimension(width, height);
- }
-
- @Override
- public void onSizeChanged(int w, int h, int oldw, int oldh) {
- mScreenNailBridge.setSize(w, h);
- }
-
- @Override
- public void updateView(boolean visible, int x, int y, int w, int h) {
- if (!visible) {
- setVisibility(View.INVISIBLE);
- } else {
- setVisibility(View.VISIBLE);
- setTranslationX(x);
- setTranslationY(y);
- }
- }
-
- @Override
- public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
- try {
- mCamera = Camera.open();
-
- Camera.Parameters param = mCamera.getParameters();
- param.setPreviewSize(PREVIEW_WIDTH, PREVIEW_HEIGHT);
- mCamera.setParameters(param);
-
- mCamera.setPreviewTexture(surface);
- mCamera.startPreview();
- } catch (Throwable ex) {
- Log.e(TAG, "failed to open camera", ex);
- }
- }
-
- @Override
- public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
- mCamera.stopPreview();
- mCamera.release();
- return true;
- }
-
- @Override
- public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
- }
-
- @Override
- public void onSurfaceTextureUpdated(SurfaceTexture surface) {
- }
-}
diff --git a/src/com/android/gallery3d/app/PhotoDataAdapter.java b/src/com/android/gallery3d/app/PhotoDataAdapter.java
index a4fd411af..109323c1c 100644
--- a/src/com/android/gallery3d/app/PhotoDataAdapter.java
+++ b/src/com/android/gallery3d/app/PhotoDataAdapter.java
@@ -221,7 +221,7 @@ public class PhotoDataAdapter implements PhotoPage.Model {
ScreenNail screenNail = future.get();
if (entry == null || entry.screenNailTask != future) {
- if (screenNail != null) screenNail.recycle();
+ if (screenNail != null) screenNail.pauseDraw();
return;
}
diff --git a/src/com/android/gallery3d/app/PhotoPage.java b/src/com/android/gallery3d/app/PhotoPage.java
index 3a18dd2e4..9a1992e54 100644
--- a/src/com/android/gallery3d/app/PhotoPage.java
+++ b/src/com/android/gallery3d/app/PhotoPage.java
@@ -55,6 +55,8 @@ import com.android.gallery3d.ui.GLCanvas;
import com.android.gallery3d.ui.GLView;
import com.android.gallery3d.ui.ImportCompleteListener;
import com.android.gallery3d.ui.MenuExecutor;
+import com.android.gallery3d.ui.ScreenNail;
+import com.android.gallery3d.ui.ScreenNailHolder;
import com.android.gallery3d.ui.PhotoView;
import com.android.gallery3d.ui.PositionRepository;
import com.android.gallery3d.ui.PositionRepository.Position;
@@ -80,6 +82,7 @@ public class PhotoPage extends ActivityState
public static final String KEY_MEDIA_ITEM_PATH = "media-item-path";
public static final String KEY_INDEX_HINT = "index-hint";
public static final String KEY_OPEN_ANIMATION_RECT = "open-animation-rect";
+ public static final String KEY_SCREENNAIL_HOLDER = "screennail-holder";
private GalleryApp mApplication;
private SelectionManager mSelectionManager;
@@ -109,11 +112,8 @@ public class PhotoPage extends ActivityState
private boolean mIsActive;
private ShareActionProvider mShareActionProvider;
private String mSetPathString;
-
- // This is for testing only. It should be removed once we have the real
- // Camera view.
- private CameraView mCameraView;
- private ScreenNailBridge mScreenNail;
+ private ScreenNailHolder mScreenNailHolder;
+ private ScreenNail mScreenNail;
public static interface Model extends PhotoView.Model {
public void resume();
@@ -190,14 +190,24 @@ public class PhotoPage extends ActivityState
Path itemPath = Path.fromString(data.getString(KEY_MEDIA_ITEM_PATH));
if (mSetPathString != null) {
- // Uncomment the block below to test camera screennail.
- /*
- Path cameraScreenNailSetPath = addCameraScreenNail();
-
- // Combine the original MediaSet with the one for camera ScreenNail.
- mSetPathString = "/combo/item/{" + cameraScreenNailSetPath + "," +
- mSetPathString + "}";
- */
+ mScreenNailHolder =
+ (ScreenNailHolder) data.getParcelable(KEY_SCREENNAIL_HOLDER);
+ if (mScreenNailHolder != null) {
+ mScreenNail = mScreenNailHolder.attach();
+
+ // Get the ScreenNail from ScreenNailHolder and register it.
+ int id = SnailSource.registerScreenNail(mScreenNail);
+ Path screenNailSetPath = SnailSource.getSetPath(id);
+ Path screenNailItemPath = SnailSource.getItemPath(id);
+
+ // Combine the original MediaSet with the one for CameraScreenNail.
+ mSetPathString = "/combo/item/{" + screenNailSetPath +
+ "," + mSetPathString + "}";
+
+ // Start from the screen nail.
+ itemPath = screenNailItemPath;
+ }
+
mMediaSet = mActivity.getDataManager().getMediaSet(mSetPathString);
mCurrentIndex = data.getInt(KEY_INDEX_HINT, 0);
mMediaSet = (MediaSet)
@@ -279,34 +289,6 @@ public class PhotoPage extends ActivityState
}
}
- // We create a Camera View and a ScreenNail. The two work together
- // to present the view together with other pictures. Returns the
- // Path of the MediaItem hosting the ScreenNail.
- private Path addCameraScreenNail() {
- // Create a camera view and add it to the root.
- Activity activity = (Activity) mActivity;
- mCameraView = new CameraView(activity);
- ViewGroup galleryRoot = (ViewGroup) activity.findViewById(R.id.gallery_root);
- galleryRoot.addView(mCameraView);
-
- // Create a ScreenNail and register it.
- mScreenNail = new ScreenNailBridge(mCameraView);
- mCameraView.setScreenNailBridge(mScreenNail);
- return SnailSource.registerScreenNail(mScreenNail);
- }
-
- private void removeCameraScreenNail() {
- if (mCameraView == null) return;
-
- // Remove the camera view.
- ((ViewGroup) mCameraView.getParent()).removeView(mCameraView);
- mCameraView = null;
-
- // Unregister the ScreenNail.
- SnailSource.unregisterScreenNail(mScreenNail);
- mScreenNail = null;
- }
-
private void updateShareURI(Path path) {
if (mShareActionProvider != null) {
DataManager manager = mActivity.getDataManager();
@@ -690,7 +672,13 @@ public class PhotoPage extends ActivityState
@Override
protected void onDestroy() {
- removeCameraScreenNail();
+ if (mScreenNailHolder != null) {
+ // Unregister the ScreenNail and notify mScreenNailHolder.
+ SnailSource.unregisterScreenNail(mScreenNail);
+ mScreenNailHolder.detach();
+ mScreenNailHolder = null;
+ mScreenNail = null;
+ }
super.onDestroy();
}
diff --git a/src/com/android/gallery3d/app/ScreenNailBridge.java b/src/com/android/gallery3d/app/ScreenNailBridge.java
deleted file mode 100644
index 9da197dca..000000000
--- a/src/com/android/gallery3d/app/ScreenNailBridge.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2012 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.gallery3d.app;
-
-import android.graphics.RectF;
-import android.os.Handler;
-import android.util.Log;
-
-import com.android.gallery3d.ui.GLCanvas;
-import com.android.gallery3d.ui.ScreenNail;
-
-// This is a ScreenNail whose actually display is done by an foreign component.
-// The foreign component tells the ScreenNail its size by setSize(). The
-// ScreenNail tells the foreign component the position to display by
-// updateView().
-class ScreenNailBridge implements ScreenNail {
- private static final String TAG = "ScreenNailBridge";
- private int mWidth, mHeight;
- private boolean mVisible = false;
- private int mDrawX, mDrawY, mDrawWidth, mDrawHeight;
- private Listener mListener;
- private Handler mMainHandler;
-
- public interface Listener {
- // This is called from the main thread.
- void updateView(boolean visible, int x, int y, int width, int height);
- };
-
- // The constructor should be called from the main thread.
- public ScreenNailBridge(Listener listener) {
- mListener = listener;
- mMainHandler = new Handler();
- }
-
- // This can be called from any thread. (We expect it to be called from the
- // main thread).
- public synchronized void setSize(int w, int h) {
- mWidth = w;
- mHeight = h;
- }
-
- // This can be called from any thread. (We expect it to be called from GL
- // thread)
- @Override
- public synchronized int getWidth() {
- return mWidth;
- }
-
- // This can be called from any thread. (We expect it to be called from GL
- // thread)
- @Override
- public synchronized int getHeight() {
- return mHeight;
- }
-
- @Override
- public int getRotation() {
- return 0;
- }
-
- // This is run in the main thread.
- private Runnable mUpdateViewRunnable = new Runnable() {
- public void run() {
- boolean v;
- int x, y, width, height;
- synchronized (ScreenNailBridge.this) {
- v = mVisible;
- x = mDrawX;
- y = mDrawY;
- width = mDrawWidth;
- height = mDrawHeight;
- }
- mListener.updateView(v, x, y, width, height);
- }
- };
-
- @Override
- public synchronized void draw(GLCanvas canvas, int x, int y, int width, int height) {
- if (mVisible && mDrawX == x && mDrawY == y && mDrawWidth == width &&
- mDrawHeight == height) {
- return;
- }
- mVisible = true;
- mDrawX = x;
- mDrawY = y;
- mDrawWidth = width;
- mDrawHeight = height;
- mMainHandler.post(mUpdateViewRunnable);
- }
-
- @Override
- public synchronized void disableDraw() {
- if (!mVisible) return;
- mVisible = false;
- mMainHandler.post(mUpdateViewRunnable);
- }
-
- @Override
- public void recycle() {
- // Make sure we will not draw anymore.
- disableDraw();
- }
-
- @Override
- public void draw(GLCanvas canvas, RectF source, RectF dest) {
- throw new UnsupportedOperationException();
- }
-}