1524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy/* 2524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy * Copyright (C) 2009 The Android Open Source Project 3524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy * 4524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy * Licensed under the Apache License, Version 2.0 (the "License"); 5524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy * you may not use this file except in compliance with the License. 6524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy * You may obtain a copy of the License at 7524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy * 8524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy * http://www.apache.org/licenses/LICENSE-2.0 9524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy * 10524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy * Unless required by applicable law or agreed to in writing, software 11524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy * distributed under the License is distributed on an "AS IS" BASIS, 12524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy * See the License for the specific language governing permissions and 14524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy * limitations under the License. 15524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy */ 16524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 17524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guypackage com.android.wallpaper.walkaround; 18524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 19524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guyimport android.service.wallpaper.WallpaperService; 20524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guyimport android.view.SurfaceHolder; 21524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guyimport android.hardware.Camera; 22524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guyimport android.util.Log; 23524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guyimport android.util.DisplayMetrics; 24524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guyimport android.graphics.Canvas; 25524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guyimport android.content.res.Configuration; 26524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guyimport android.content.res.Resources; 27524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 28524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guyimport java.io.IOException; 29524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guyimport java.util.List; 30524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 31524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guypublic class WalkAroundWallpaper extends WallpaperService { 32524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy private static final String LOG_TAG = "WalkAround"; 33524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 34524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy private Camera mCamera; 35524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy private WalkAroundEngine mOwner; 36524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 37524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy public Engine onCreateEngine() { 38524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy return mOwner = new WalkAroundEngine(); 39524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 40524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 41524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy @Override 42524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy public void onDestroy() { 43524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy super.onDestroy(); 44524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy stopCamera(); 45524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 46524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 47524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy @Override 48524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy public void onCreate() { 49524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy super.onCreate(); 50524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 51524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 52376b3510c6d37e4a9ffc175f33e92726efa753ddRomain Guy @Override 53376b3510c6d37e4a9ffc175f33e92726efa753ddRomain Guy public void onConfigurationChanged(Configuration newConfig) { 54376b3510c6d37e4a9ffc175f33e92726efa753ddRomain Guy super.onConfigurationChanged(newConfig); 55376b3510c6d37e4a9ffc175f33e92726efa753ddRomain Guy 56376b3510c6d37e4a9ffc175f33e92726efa753ddRomain Guy if (mCamera != null) { 57376b3510c6d37e4a9ffc175f33e92726efa753ddRomain Guy if (mCamera.previewEnabled()) { 58376b3510c6d37e4a9ffc175f33e92726efa753ddRomain Guy boolean portrait = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT; 59376b3510c6d37e4a9ffc175f33e92726efa753ddRomain Guy final Camera.Parameters params = mCamera.getParameters(); 60376b3510c6d37e4a9ffc175f33e92726efa753ddRomain Guy params.set("orientation", portrait ? "portrait" : "landscape"); 61376b3510c6d37e4a9ffc175f33e92726efa753ddRomain Guy mCamera.setParameters(params); 62376b3510c6d37e4a9ffc175f33e92726efa753ddRomain Guy 63376b3510c6d37e4a9ffc175f33e92726efa753ddRomain Guy if (mCamera.previewEnabled()) mCamera.stopPreview(); 64376b3510c6d37e4a9ffc175f33e92726efa753ddRomain Guy mCamera.startPreview(); 65376b3510c6d37e4a9ffc175f33e92726efa753ddRomain Guy } 66376b3510c6d37e4a9ffc175f33e92726efa753ddRomain Guy } 67376b3510c6d37e4a9ffc175f33e92726efa753ddRomain Guy } 68376b3510c6d37e4a9ffc175f33e92726efa753ddRomain Guy 69524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy private void startCamera() { 70524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy if (mCamera == null) { 71524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy mCamera = Camera.open(); 72524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } else { 73524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy try { 74524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy mCamera.reconnect(); 75524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } catch (IOException e) { 76524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy mCamera.release(); 77524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy mCamera = null; 78524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 79524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy Log.e(LOG_TAG, "Error opening the camera", e); 80524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 81524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 82524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 83524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 84524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy private void stopCamera() { 85524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy if (mCamera != null) { 86524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy try { 87524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy mCamera.stopPreview(); 88524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } catch (Exception e) { 89524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy // Ignore 90524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 91524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 92524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy try { 93524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy mCamera.release(); 94524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } catch (Exception e) { 95524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy // Ignore 96524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 97524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 98524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy mCamera = null; 99524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 100524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 101524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 102524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy class WalkAroundEngine extends Engine { 103524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy private SurfaceHolder mHolder; 104524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 105524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy WalkAroundEngine() { 106524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 107524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 108524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy @Override 109524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy public void onCreate(SurfaceHolder surfaceHolder) { 110524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy super.onCreate(surfaceHolder); 111524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 112524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 113524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy mHolder = surfaceHolder; 114524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 115524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 116524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy @Override 117524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy public void onVisibilityChanged(boolean visible) { 118524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy if (!visible) { 119524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy if (mOwner == this) { 120524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy stopCamera(); 121524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 122524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } else { 123524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy try { 124524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy startCamera(); 125524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy mCamera.setPreviewDisplay(mHolder); 126524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy startPreview(); 127524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } catch (IOException e) { 128524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy mCamera.release(); 129524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy mCamera = null; 130524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 131524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy Log.e(LOG_TAG, "Error opening the camera", e); 132524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 133524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 134524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 135524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 136524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy @Override 137524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { 138524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy super.onSurfaceChanged(holder, format, width, height); 139524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 140524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy if (holder.isCreating()) { 141524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy try { 142524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy if (mCamera.previewEnabled()) mCamera.stopPreview(); 143524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy mCamera.setPreviewDisplay(holder); 144524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } catch (IOException e) { 145524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy mCamera.release(); 146524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy mCamera = null; 147524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 148524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy Log.e(LOG_TAG, "Error opening the camera", e); 149524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 150524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 151524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 152524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy if (isVisible()) startPreview(); 153524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 154524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 155524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy @Override 156524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy public void onSurfaceCreated(SurfaceHolder holder) { 157524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy super.onSurfaceCreated(holder); 158524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy startCamera(); 159524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 160524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 161524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy private void startPreview() { 162524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy final Resources resources = getResources(); 163524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy final boolean portrait = resources.getConfiguration().orientation == 164524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy Configuration.ORIENTATION_PORTRAIT; 165524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 166524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy final Camera.Parameters params = mCamera.getParameters(); 167524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 168524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy final DisplayMetrics metrics = resources.getDisplayMetrics(); 169524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy final List<Camera.Size> sizes = params.getSupportedPreviewSizes(); 170524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 171524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy // Try to find a preview size that matches the screen first 172524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy boolean found = false; 173524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy for (Camera.Size size : sizes) { 174524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy if ((portrait && 175524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy size.width == metrics.heightPixels && size.height == metrics.widthPixels) || 176524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy (!portrait && 177524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy size.width == metrics.widthPixels && size.height == metrics.heightPixels)) { 178524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy params.setPreviewSize(size.width, size.height); 179524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy found = true; 180524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 181524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 182524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 183524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy // If no suitable preview size was found, try to find something large enough 184524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy if (!found) { 185524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy for (Camera.Size size : sizes) { 186524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy if (size.width >= metrics.widthPixels && size.height >= metrics.heightPixels) { 187524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy params.setPreviewSize(size.width, size.height); 188524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy found = true; 189524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 190524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 191524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 192524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 193524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy // If no suitable preview size was found, pick the first one 194524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy if (!found) { 195524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy // Fill the canvas with black 196524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy Canvas canvas = null; 197524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy try { 198524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy canvas = mHolder.lockCanvas(); 199524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy if (canvas != null) canvas.drawColor(0); 200524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } finally { 201524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy if (canvas != null) mHolder.unlockCanvasAndPost(canvas); 202524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 203524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 204524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 205524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy Camera.Size size = sizes.get(0); 206524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy params.setPreviewSize(size.width, size.height); 207524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 208524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy 209524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy params.set("orientation", portrait ? "portrait" : "landscape"); 210524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy mCamera.setParameters(params); 211376b3510c6d37e4a9ffc175f33e92726efa753ddRomain Guy 212524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy mCamera.startPreview(); 213524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 214524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy } 215524a658626fa667e6cee3b4b1a3ed9b605b9fdb5Romain Guy} 216