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.wallpaper.walkaround;
18
19import android.service.wallpaper.WallpaperService;
20import android.view.SurfaceHolder;
21import android.hardware.Camera;
22import android.util.Log;
23import android.util.DisplayMetrics;
24import android.graphics.Canvas;
25import android.content.res.Configuration;
26import android.content.res.Resources;
27
28import java.io.IOException;
29import java.util.List;
30
31public class WalkAroundWallpaper extends WallpaperService {
32    private static final String LOG_TAG = "WalkAround";
33
34    private Camera mCamera;
35    private WalkAroundEngine mOwner;
36
37    public Engine onCreateEngine() {
38        return mOwner = new WalkAroundEngine();
39    }
40
41    @Override
42    public void onDestroy() {
43        super.onDestroy();
44        stopCamera();
45    }
46
47    @Override
48    public void onCreate() {
49        super.onCreate();
50    }
51
52    @Override
53    public void onConfigurationChanged(Configuration newConfig) {
54        super.onConfigurationChanged(newConfig);
55
56        if (mCamera != null) {
57            if (mCamera.previewEnabled()) {
58                boolean portrait = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT;
59                final Camera.Parameters params = mCamera.getParameters();
60                params.set("orientation", portrait ? "portrait" : "landscape");
61                mCamera.setParameters(params);
62
63                if (mCamera.previewEnabled()) mCamera.stopPreview();
64                mCamera.startPreview();
65            }
66        }
67    }
68
69    private void startCamera() {
70        if (mCamera == null) {
71            mCamera = Camera.open();
72        } else {
73            try {
74                mCamera.reconnect();
75            } catch (IOException e) {
76                mCamera.release();
77                mCamera = null;
78
79                Log.e(LOG_TAG, "Error opening the camera", e);
80            }
81        }
82    }
83
84    private void stopCamera() {
85        if (mCamera != null) {
86            try {
87                mCamera.stopPreview();
88            } catch (Exception e) {
89                // Ignore
90            }
91
92            try {
93                mCamera.release();
94            } catch (Exception e) {
95                // Ignore
96            }
97
98            mCamera = null;
99        }
100    }
101
102    class WalkAroundEngine extends Engine {
103        private SurfaceHolder mHolder;
104
105        WalkAroundEngine() {
106        }
107
108        @Override
109        public void onCreate(SurfaceHolder surfaceHolder) {
110            super.onCreate(surfaceHolder);
111
112            surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
113            mHolder = surfaceHolder;
114        }
115
116        @Override
117        public void onVisibilityChanged(boolean visible) {
118            if (!visible) {
119                if (mOwner == this) {
120                    stopCamera();
121                }
122            } else {
123                try {
124                    startCamera();
125                    mCamera.setPreviewDisplay(mHolder);
126                    startPreview();
127                } catch (IOException e) {
128                    mCamera.release();
129                    mCamera = null;
130
131                    Log.e(LOG_TAG, "Error opening the camera", e);
132                }
133            }
134        }
135
136        @Override
137        public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
138            super.onSurfaceChanged(holder, format, width, height);
139
140            if (holder.isCreating()) {
141                try {
142                    if (mCamera.previewEnabled()) mCamera.stopPreview();
143                    mCamera.setPreviewDisplay(holder);
144                } catch (IOException e) {
145                    mCamera.release();
146                    mCamera = null;
147
148                    Log.e(LOG_TAG, "Error opening the camera", e);
149                }
150            }
151
152            if (isVisible()) startPreview();
153        }
154
155        @Override
156        public void onSurfaceCreated(SurfaceHolder holder) {
157            super.onSurfaceCreated(holder);
158            startCamera();
159        }
160
161        private void startPreview() {
162            final Resources resources = getResources();
163            final boolean portrait = resources.getConfiguration().orientation ==
164                    Configuration.ORIENTATION_PORTRAIT;
165
166            final Camera.Parameters params = mCamera.getParameters();
167
168            final DisplayMetrics metrics = resources.getDisplayMetrics();
169            final List<Camera.Size> sizes = params.getSupportedPreviewSizes();
170
171            // Try to find a preview size that matches the screen first
172            boolean found = false;
173            for (Camera.Size size : sizes) {
174                if ((portrait &&
175                        size.width == metrics.heightPixels && size.height == metrics.widthPixels) ||
176                    (!portrait &&
177                        size.width == metrics.widthPixels && size.height == metrics.heightPixels)) {
178                    params.setPreviewSize(size.width, size.height);
179                    found = true;
180                }
181            }
182
183            // If no suitable preview size was found, try to find something large enough
184            if (!found) {
185                for (Camera.Size size : sizes) {
186                    if (size.width >= metrics.widthPixels && size.height >= metrics.heightPixels) {
187                        params.setPreviewSize(size.width, size.height);
188                        found = true;
189                    }
190                }
191            }
192
193            // If no suitable preview size was found, pick the first one
194            if (!found) {
195                // Fill the canvas with black
196                Canvas canvas = null;
197                try {
198                    canvas = mHolder.lockCanvas();
199                    if (canvas != null) canvas.drawColor(0);
200                } finally {
201                    if (canvas != null) mHolder.unlockCanvasAndPost(canvas);
202                }
203
204
205                Camera.Size size = sizes.get(0);
206                params.setPreviewSize(size.width, size.height);
207            }
208
209            params.set("orientation", portrait ? "portrait" : "landscape");
210            mCamera.setParameters(params);
211
212            mCamera.startPreview();
213        }
214    }
215}
216