1/*
2 * Copyright (C) 2014 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.example.wallpapertest;
18
19import android.service.wallpaper.WallpaperService;
20import android.graphics.Canvas;
21import android.graphics.Rect;
22import android.graphics.Paint;
23import android.graphics.Color;
24import android.graphics.RectF;
25import android.text.TextPaint;
26import android.view.SurfaceHolder;
27import android.content.res.XmlResourceParser;
28
29import android.os.Handler;
30import android.util.Log;
31
32import android.view.WindowInsets;
33
34public class TestWallpaper extends WallpaperService {
35    private static final String LOG_TAG = "PolarClock";
36
37    private final Handler mHandler = new Handler();
38
39    @Override
40    public void onCreate() {
41        super.onCreate();
42    }
43
44    @Override
45    public void onDestroy() {
46        super.onDestroy();
47    }
48
49    public Engine onCreateEngine() {
50        return new ClockEngine();
51    }
52
53    class ClockEngine extends Engine {
54        private static final int OUTER_COLOR = 0xffff0000;
55        private static final int INNER_COLOR = 0xff000080;
56        private static final int STABLE_COLOR = 0xa000ff00;
57        private static final int TEXT_COLOR = 0xa0ffffff;
58
59        private final Paint.FontMetrics mTextMetrics = new Paint.FontMetrics();
60
61        private int mPadding;
62
63        private final Rect mMainInsets = new Rect();
64        private final Rect mStableInsets = new Rect();
65        private boolean mRound = false;
66
67        private int mDesiredWidth;
68        private int mDesiredHeight;
69
70        private float mOffsetX;
71        private float mOffsetY;
72        private float mOffsetXStep;
73        private float mOffsetYStep;
74        private int mOffsetXPixels;
75        private int mOffsetYPixels;
76
77        private final Paint mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
78        private final Paint mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
79        private final TextPaint mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
80
81        private final Runnable mDrawClock = new Runnable() {
82            public void run() {
83                drawFrame();
84            }
85        };
86        private boolean mVisible;
87
88        ClockEngine() {
89        }
90
91        @Override
92        public void onCreate(SurfaceHolder surfaceHolder) {
93            super.onCreate(surfaceHolder);
94
95            mDesiredWidth = getDesiredMinimumWidth();
96            mDesiredHeight = getDesiredMinimumHeight();
97
98            Paint paint = mFillPaint;
99            paint.setStyle(Paint.Style.FILL);
100
101            paint = mStrokePaint;
102            paint.setStrokeWidth(3);
103            paint.setStrokeCap(Paint.Cap.ROUND);
104            paint.setStyle(Paint.Style.STROKE);
105
106            TextPaint tpaint = mTextPaint;
107            tpaint.density = getResources().getDisplayMetrics().density;
108            tpaint.setCompatibilityScaling(getResources().getCompatibilityInfo().applicationScale);
109            tpaint.setColor(TEXT_COLOR);
110            tpaint.setTextSize(18 * getResources().getDisplayMetrics().scaledDensity);
111            tpaint.setShadowLayer(4 * getResources().getDisplayMetrics().density, 0, 0, 0xff000000);
112
113            mTextPaint.getFontMetrics(mTextMetrics);
114
115            mPadding = (int)(16 * getResources().getDisplayMetrics().density);
116
117            if (isPreview()) {
118                mOffsetX = 0.5f;
119                mOffsetY = 0.5f;
120            }
121        }
122
123        @Override
124        public void onDestroy() {
125            super.onDestroy();
126            mHandler.removeCallbacks(mDrawClock);
127        }
128
129        @Override
130        public void onVisibilityChanged(boolean visible) {
131            mVisible = visible;
132            if (!visible) {
133                mHandler.removeCallbacks(mDrawClock);
134            }
135            drawFrame();
136        }
137
138        @Override
139        public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
140            super.onSurfaceChanged(holder, format, width, height);
141            drawFrame();
142        }
143
144        @Override
145        public void onSurfaceCreated(SurfaceHolder holder) {
146            super.onSurfaceCreated(holder);
147
148            // Simulate some slowness, so we can test the loading process in the live wallpaper
149            // picker.
150            try {
151                Thread.sleep(1000);
152            } catch (InterruptedException e) {
153                e.printStackTrace();
154            }
155        }
156
157        @Override
158        public void onSurfaceDestroyed(SurfaceHolder holder) {
159            super.onSurfaceDestroyed(holder);
160            mVisible = false;
161            mHandler.removeCallbacks(mDrawClock);
162        }
163
164        @Override
165        public void onApplyWindowInsets(WindowInsets insets) {
166            super.onApplyWindowInsets(insets);
167            mMainInsets.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(),
168                    insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
169            mStableInsets.set(insets.getStableInsetLeft(), insets.getStableInsetTop(),
170                    insets.getStableInsetRight(), insets.getStableInsetBottom());
171            mRound = insets.isRound();
172            drawFrame();
173        }
174
175        @Override
176        public void onDesiredSizeChanged(int desiredWidth, int desiredHeight) {
177            super.onDesiredSizeChanged(desiredWidth, desiredHeight);
178            mDesiredWidth = desiredWidth;
179            mDesiredHeight = desiredHeight;
180            drawFrame();
181        }
182
183        @Override
184        public void onOffsetsChanged(float xOffset, float yOffset,
185                float xStep, float yStep, int xPixels, int yPixels) {
186            super.onOffsetsChanged(xOffset, yOffset, xStep, yStep, xPixels, yPixels);
187
188            if (isPreview()) return;
189
190            mOffsetX = xOffset;
191            mOffsetY = yOffset;
192            mOffsetXStep = xStep;
193            mOffsetYStep = yStep;
194            mOffsetXPixels = xPixels;
195            mOffsetYPixels = yPixels;
196
197            drawFrame();
198        }
199
200        void drawFrame() {
201            final SurfaceHolder holder = getSurfaceHolder();
202            final Rect frame = holder.getSurfaceFrame();
203            final int width = frame.width();
204            final int height = frame.height();
205
206            Canvas c = null;
207            try {
208                c = holder.lockCanvas();
209                if (c != null) {
210                    final Paint paint = mFillPaint;
211
212                    paint.setColor(OUTER_COLOR);
213                    c.drawRect(0, 0, width, height, paint);
214
215                    paint.setColor(INNER_COLOR);
216                    c.drawRect(0+mMainInsets.left, 0+mMainInsets.top,
217                            width-mMainInsets.right, height-mMainInsets.bottom, paint);
218
219                    mStrokePaint.setColor(STABLE_COLOR);
220                    c.drawRect(0 + mStableInsets.left, 0 + mStableInsets.top,
221                            width - mStableInsets.right, height - mStableInsets.bottom,
222                            mStrokePaint);
223
224                    final int ascdesc = (int)(-mTextMetrics.ascent + mTextMetrics.descent);
225                    final int linegap = (int)(-mTextMetrics.ascent + mTextMetrics.descent
226                            + mTextMetrics.leading);
227
228                    int x = mStableInsets.left + mPadding;
229                    int y = height - mStableInsets.bottom - mPadding - ascdesc;
230                    c.drawText("Surface Size: " + width + " x " + height,
231                            x, y, mTextPaint);
232                    y -= linegap;
233                    c.drawText("Desired Size: " + mDesiredWidth + " x " + mDesiredHeight,
234                            x, y, mTextPaint);
235                    y -= linegap;
236                    c.drawText("Cur Offset Raw: " + mOffsetX + ", " + mOffsetY,
237                            x, y, mTextPaint);
238                    y -= linegap;
239                    c.drawText("Cur Offset Step: " + mOffsetXStep + ", " + mOffsetYStep,
240                            x, y, mTextPaint);
241                    y -= linegap;
242                    c.drawText("Cur Offset Pixels: " + mOffsetXPixels + ", " + mOffsetYPixels,
243                            x, y, mTextPaint);
244                    y -= linegap;
245                    c.drawText("Stable Insets: (" + mStableInsets.left + ", " + mStableInsets.top
246                            + ") - (" + mStableInsets.right + ", " + mStableInsets.bottom + ")",
247                            x, y, mTextPaint);
248                    y -= linegap;
249                    c.drawText("System Insets: (" + mMainInsets.left + ", " + mMainInsets.top
250                            + ") - (" + mMainInsets.right + ", " + mMainInsets.bottom + ")",
251                            x, y, mTextPaint);
252
253                }
254            } finally {
255                if (c != null) holder.unlockCanvasAndPost(c);
256            }
257        }
258    }
259}
260