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
149        @Override
150        public void onSurfaceDestroyed(SurfaceHolder holder) {
151            super.onSurfaceDestroyed(holder);
152            mVisible = false;
153            mHandler.removeCallbacks(mDrawClock);
154        }
155
156        @Override
157        public void onApplyWindowInsets(WindowInsets insets) {
158            super.onApplyWindowInsets(insets);
159            mMainInsets.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(),
160                    insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
161            mStableInsets.set(insets.getStableInsetLeft(), insets.getStableInsetTop(),
162                    insets.getStableInsetRight(), insets.getStableInsetBottom());
163            mRound = insets.isRound();
164            drawFrame();
165        }
166
167        @Override
168        public void onDesiredSizeChanged(int desiredWidth, int desiredHeight) {
169            super.onDesiredSizeChanged(desiredWidth, desiredHeight);
170            mDesiredWidth = desiredWidth;
171            mDesiredHeight = desiredHeight;
172            drawFrame();
173        }
174
175        @Override
176        public void onOffsetsChanged(float xOffset, float yOffset,
177                float xStep, float yStep, int xPixels, int yPixels) {
178            super.onOffsetsChanged(xOffset, yOffset, xStep, yStep, xPixels, yPixels);
179
180            if (isPreview()) return;
181
182            mOffsetX = xOffset;
183            mOffsetY = yOffset;
184            mOffsetXStep = xStep;
185            mOffsetYStep = yStep;
186            mOffsetXPixels = xPixels;
187            mOffsetYPixels = yPixels;
188
189            drawFrame();
190        }
191
192        void drawFrame() {
193            final SurfaceHolder holder = getSurfaceHolder();
194            final Rect frame = holder.getSurfaceFrame();
195            final int width = frame.width();
196            final int height = frame.height();
197
198            Canvas c = null;
199            try {
200                c = holder.lockCanvas();
201                if (c != null) {
202                    final Paint paint = mFillPaint;
203
204                    paint.setColor(OUTER_COLOR);
205                    c.drawRect(0, 0, width, height, paint);
206
207                    paint.setColor(INNER_COLOR);
208                    c.drawRect(0+mMainInsets.left, 0+mMainInsets.top,
209                            width-mMainInsets.right, height-mMainInsets.bottom, paint);
210
211                    mStrokePaint.setColor(STABLE_COLOR);
212                    c.drawRect(0 + mStableInsets.left, 0 + mStableInsets.top,
213                            width - mStableInsets.right, height - mStableInsets.bottom,
214                            mStrokePaint);
215
216                    final int ascdesc = (int)(-mTextMetrics.ascent + mTextMetrics.descent);
217                    final int linegap = (int)(-mTextMetrics.ascent + mTextMetrics.descent
218                            + mTextMetrics.leading);
219
220                    int x = mStableInsets.left + mPadding;
221                    int y = height - mStableInsets.bottom - mPadding - ascdesc;
222                    c.drawText("Surface Size: " + width + " x " + height,
223                            x, y, mTextPaint);
224                    y -= linegap;
225                    c.drawText("Desired Size: " + mDesiredWidth + " x " + mDesiredHeight,
226                            x, y, mTextPaint);
227                    y -= linegap;
228                    c.drawText("Cur Offset Raw: " + mOffsetX + ", " + mOffsetY,
229                            x, y, mTextPaint);
230                    y -= linegap;
231                    c.drawText("Cur Offset Step: " + mOffsetXStep + ", " + mOffsetYStep,
232                            x, y, mTextPaint);
233                    y -= linegap;
234                    c.drawText("Cur Offset Pixels: " + mOffsetXPixels + ", " + mOffsetYPixels,
235                            x, y, mTextPaint);
236                    y -= linegap;
237                    c.drawText("Stable Insets: (" + mStableInsets.left + ", " + mStableInsets.top
238                            + ") - (" + mStableInsets.right + ", " + mStableInsets.bottom + ")",
239                            x, y, mTextPaint);
240                    y -= linegap;
241                    c.drawText("System Insets: (" + mMainInsets.left + ", " + mMainInsets.top
242                            + ") - (" + mMainInsets.right + ", " + mMainInsets.bottom + ")",
243                            x, y, mTextPaint);
244
245                }
246            } finally {
247                if (c != null) holder.unlockCanvasAndPost(c);
248            }
249        }
250    }
251}
252