WallpaperUtils.java revision 748dfe025b128ea88ba626c8bfb7da315d5af29c
1748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal/*
2748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal * Copyright (C) 2015 The Android Open Source Project
3748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal *
4748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal * Licensed under the Apache License, Version 2.0 (the "License");
5748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal * you may not use this file except in compliance with the License.
6748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal * You may obtain a copy of the License at
7748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal *
8748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal *      http://www.apache.org/licenses/LICENSE-2.0
9748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal *
10748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal * Unless required by applicable law or agreed to in writing, software
11748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal * distributed under the License is distributed on an "AS IS" BASIS,
12748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal * See the License for the specific language governing permissions and
14748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal * limitations under the License.
15748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal */
16748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
17748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyalpackage com.android.wallpaperpicker;
18748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
19748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyalimport android.annotation.TargetApi;
20748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyalimport android.app.Activity;
21748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyalimport android.app.WallpaperManager;
22748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyalimport android.content.Context;
23748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyalimport android.content.SharedPreferences;
24748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyalimport android.content.res.Resources;
25748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyalimport android.graphics.Point;
26748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyalimport android.os.Build;
27748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyalimport android.view.View;
28748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyalimport android.view.WindowManager;
29748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
30748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal/**
31748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal * Utility methods for wallpaper management.
32748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal */
33748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyalpublic final class WallpaperUtils {
34748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
35748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    public static final String WALLPAPER_WIDTH_KEY = "wallpaper.width";
36748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    public static final String WALLPAPER_HEIGHT_KEY = "wallpaper.height";
37748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    public static final float WALLPAPER_SCREENS_SPAN = 2f;
38748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
39748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    public static void saveWallpaperDimensions(int width, int height, Activity activity) {
40748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
41748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            // From Kitkat onwards, ImageWallpaper does not care about the
42748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            // desired width and desired height of the wallpaper.
43748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            return;
44748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        }
45748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        String spKey = WallpaperFiles.WALLPAPER_CROP_PREFERENCES_KEY;
46748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        SharedPreferences sp = activity.getSharedPreferences(spKey, Context.MODE_MULTI_PROCESS);
47748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        SharedPreferences.Editor editor = sp.edit();
48748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        if (width != 0 && height != 0) {
49748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            editor.putInt(WALLPAPER_WIDTH_KEY, width);
50748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            editor.putInt(WALLPAPER_HEIGHT_KEY, height);
51748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        } else {
52748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            editor.remove(WALLPAPER_WIDTH_KEY);
53748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            editor.remove(WALLPAPER_HEIGHT_KEY);
54748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        }
55748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        editor.commit();
56748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        suggestWallpaperDimensionPreK(activity, true);
57748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    }
58748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
59748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    public static void suggestWallpaperDimensionPreK(
60748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            Activity activity, boolean fallBackToDefaults) {
61748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        final Point defaultWallpaperSize = getDefaultWallpaperSize(
62748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal                activity.getResources(), activity.getWindowManager());
63748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
64748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        SharedPreferences sp = activity.getSharedPreferences(
65748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal              WallpaperFiles.WALLPAPER_CROP_PREFERENCES_KEY, Context.MODE_MULTI_PROCESS);
66748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        // If we have saved a wallpaper width/height, use that instead
67748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        int width = sp.getInt(WALLPAPER_WIDTH_KEY, -1);
68748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        int height = sp.getInt(WALLPAPER_HEIGHT_KEY, -1);
69748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
70748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        if (width == -1 || height == -1) {
71748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            if (!fallBackToDefaults) {
72748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal                return;
73748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            } else {
74748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal                width = defaultWallpaperSize.x;
75748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal                height = defaultWallpaperSize.y;
76748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            }
77748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        }
78748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
79748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        WallpaperManager wm = WallpaperManager.getInstance(activity);
80748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        if (width != wm.getDesiredMinimumWidth() || height != wm.getDesiredMinimumHeight()) {
81748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            wm.suggestDesiredDimensions(width, height);
82748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        }
83748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    }
84748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
85748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    public static void suggestWallpaperDimension(Activity activity) {
86748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        // Only live wallpapers care about desired size. Update the size to what launcher expects.
87748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        final Point size = getDefaultWallpaperSize(
88748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal                activity.getResources(), activity.getWindowManager());
89748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        WallpaperManager wm = WallpaperManager.getInstance(activity);
90748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        if (size.x != wm.getDesiredMinimumWidth() || size.y != wm.getDesiredMinimumHeight()) {
91748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            wm.suggestDesiredDimensions(size.x, size.y);
92748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        }
93748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    }
94748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
95748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    /**
96748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal     * As a ratio of screen height, the total distance we want the parallax effect to span
97748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal     * horizontally
98748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal     */
99748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    private static float wallpaperTravelToScreenWidthRatio(int width, int height) {
100748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        float aspectRatio = width / (float) height;
101748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
102748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        // At an aspect ratio of 16/10, the wallpaper parallax effect should span 1.5 * screen width
103748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        // At an aspect ratio of 10/16, the wallpaper parallax effect should span 1.2 * screen width
104748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        // We will use these two data points to extrapolate how much the wallpaper parallax effect
105748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        // to span (ie travel) at any aspect ratio:
106748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
107748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        final float ASPECT_RATIO_LANDSCAPE = 16/10f;
108748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        final float ASPECT_RATIO_PORTRAIT = 10/16f;
109748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        final float WALLPAPER_WIDTH_TO_SCREEN_RATIO_LANDSCAPE = 1.5f;
110748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        final float WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT = 1.2f;
111748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
112748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        // To find out the desired width at different aspect ratios, we use the following two
113748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        // formulas, where the coefficient on x is the aspect ratio (width/height):
114748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        //   (16/10)x + y = 1.5
115748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        //   (10/16)x + y = 1.2
116748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        // We solve for x and y and end up with a final formula:
117748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        final float x =
118748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            (WALLPAPER_WIDTH_TO_SCREEN_RATIO_LANDSCAPE - WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT) /
119748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            (ASPECT_RATIO_LANDSCAPE - ASPECT_RATIO_PORTRAIT);
120748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        final float y = WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT - x * ASPECT_RATIO_PORTRAIT;
121748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        return x * aspectRatio + y;
122748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    }
123748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
124748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    private static Point sDefaultWallpaperSize;
125748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
126748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
127748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    public static Point getDefaultWallpaperSize(Resources res, WindowManager windowManager) {
128748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        if (sDefaultWallpaperSize == null) {
129748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            Point realSize = new Point();
130748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            windowManager.getDefaultDisplay().getRealSize(realSize);
131748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            int maxDim = Math.max(realSize.x, realSize.y);
132748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            int minDim = Math.min(realSize.x, realSize.y);
133748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
134748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            // We need to ensure that there is enough extra space in the wallpaper
135748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            // for the intended parallax effects
136748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            final int defaultWidth, defaultHeight;
137748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            if (res.getConfiguration().smallestScreenWidthDp >= 720) {
138748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal                defaultWidth = (int) (maxDim * wallpaperTravelToScreenWidthRatio(maxDim, minDim));
139748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal                defaultHeight = maxDim;
140748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            } else {
141748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal                defaultWidth = Math.max((int) (minDim * WALLPAPER_SCREENS_SPAN), maxDim);
142748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal                defaultHeight = maxDim;
143748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            }
144748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            sDefaultWallpaperSize = new Point(defaultWidth, defaultHeight);
145748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        }
146748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        return sDefaultWallpaperSize;
147748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    }
148748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
149748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
150748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    public static boolean isRtl(Resources res) {
151748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 &&
152748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal                (res.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
153748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    }
154748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal}
155