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";
377820af14c0252b1f8b5acc14da1a00e7b70c0fdeSunny Goyal
387820af14c0252b1f8b5acc14da1a00e7b70c0fdeSunny Goyal    // An intent extra to indicate the horizontal scroll of the wallpaper.
397820af14c0252b1f8b5acc14da1a00e7b70c0fdeSunny Goyal    public static final String EXTRA_WALLPAPER_OFFSET = "com.android.launcher3.WALLPAPER_OFFSET";
407820af14c0252b1f8b5acc14da1a00e7b70c0fdeSunny Goyal
41748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    public static final float WALLPAPER_SCREENS_SPAN = 2f;
42748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
43748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    public static void saveWallpaperDimensions(int width, int height, Activity activity) {
44748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
45748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            // From Kitkat onwards, ImageWallpaper does not care about the
46748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            // desired width and desired height of the wallpaper.
47748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            return;
48748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        }
49748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        String spKey = WallpaperFiles.WALLPAPER_CROP_PREFERENCES_KEY;
50748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        SharedPreferences sp = activity.getSharedPreferences(spKey, Context.MODE_MULTI_PROCESS);
51748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        SharedPreferences.Editor editor = sp.edit();
52748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        if (width != 0 && height != 0) {
53748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            editor.putInt(WALLPAPER_WIDTH_KEY, width);
54748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            editor.putInt(WALLPAPER_HEIGHT_KEY, height);
55748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        } else {
56748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            editor.remove(WALLPAPER_WIDTH_KEY);
57748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            editor.remove(WALLPAPER_HEIGHT_KEY);
58748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        }
59748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        editor.commit();
60748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        suggestWallpaperDimensionPreK(activity, true);
61748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    }
62748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
63748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    public static void suggestWallpaperDimensionPreK(
64748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            Activity activity, boolean fallBackToDefaults) {
65748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        final Point defaultWallpaperSize = getDefaultWallpaperSize(
66748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal                activity.getResources(), activity.getWindowManager());
67748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
68748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        SharedPreferences sp = activity.getSharedPreferences(
69748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal              WallpaperFiles.WALLPAPER_CROP_PREFERENCES_KEY, Context.MODE_MULTI_PROCESS);
70748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        // If we have saved a wallpaper width/height, use that instead
71748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        int width = sp.getInt(WALLPAPER_WIDTH_KEY, -1);
72748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        int height = sp.getInt(WALLPAPER_HEIGHT_KEY, -1);
73748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
74748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        if (width == -1 || height == -1) {
75748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            if (!fallBackToDefaults) {
76748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal                return;
77748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            } else {
78748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal                width = defaultWallpaperSize.x;
79748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal                height = defaultWallpaperSize.y;
80748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            }
81748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        }
82748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
83748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        WallpaperManager wm = WallpaperManager.getInstance(activity);
84748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        if (width != wm.getDesiredMinimumWidth() || height != wm.getDesiredMinimumHeight()) {
85748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            wm.suggestDesiredDimensions(width, height);
86748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        }
87748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    }
88748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
897820af14c0252b1f8b5acc14da1a00e7b70c0fdeSunny Goyal    public static void suggestWallpaperDimension(Activity activity) {
907820af14c0252b1f8b5acc14da1a00e7b70c0fdeSunny Goyal        // Only live wallpapers care about desired size. Update the size to what launcher expects.
917820af14c0252b1f8b5acc14da1a00e7b70c0fdeSunny Goyal        final Point size = getDefaultWallpaperSize(
927820af14c0252b1f8b5acc14da1a00e7b70c0fdeSunny Goyal                activity.getResources(), activity.getWindowManager());
937820af14c0252b1f8b5acc14da1a00e7b70c0fdeSunny Goyal        WallpaperManager wm = WallpaperManager.getInstance(activity);
947820af14c0252b1f8b5acc14da1a00e7b70c0fdeSunny Goyal        if (size.x != wm.getDesiredMinimumWidth() || size.y != wm.getDesiredMinimumHeight()) {
957820af14c0252b1f8b5acc14da1a00e7b70c0fdeSunny Goyal            wm.suggestDesiredDimensions(size.x, size.y);
967820af14c0252b1f8b5acc14da1a00e7b70c0fdeSunny Goyal        }
977820af14c0252b1f8b5acc14da1a00e7b70c0fdeSunny Goyal    }
987820af14c0252b1f8b5acc14da1a00e7b70c0fdeSunny Goyal
99748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    /**
100748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal     * As a ratio of screen height, the total distance we want the parallax effect to span
101748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal     * horizontally
102748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal     */
103748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    private static float wallpaperTravelToScreenWidthRatio(int width, int height) {
104748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        float aspectRatio = width / (float) height;
105748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
106748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        // At an aspect ratio of 16/10, the wallpaper parallax effect should span 1.5 * screen width
107748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        // At an aspect ratio of 10/16, the wallpaper parallax effect should span 1.2 * screen width
108748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        // We will use these two data points to extrapolate how much the wallpaper parallax effect
109748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        // to span (ie travel) at any aspect ratio:
110748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
111748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        final float ASPECT_RATIO_LANDSCAPE = 16/10f;
112748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        final float ASPECT_RATIO_PORTRAIT = 10/16f;
113748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        final float WALLPAPER_WIDTH_TO_SCREEN_RATIO_LANDSCAPE = 1.5f;
114748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        final float WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT = 1.2f;
115748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
116748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        // To find out the desired width at different aspect ratios, we use the following two
117748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        // formulas, where the coefficient on x is the aspect ratio (width/height):
118748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        //   (16/10)x + y = 1.5
119748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        //   (10/16)x + y = 1.2
120748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        // We solve for x and y and end up with a final formula:
121748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        final float x =
122748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            (WALLPAPER_WIDTH_TO_SCREEN_RATIO_LANDSCAPE - WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT) /
123748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            (ASPECT_RATIO_LANDSCAPE - ASPECT_RATIO_PORTRAIT);
124748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        final float y = WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT - x * ASPECT_RATIO_PORTRAIT;
125748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        return x * aspectRatio + y;
126748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    }
127748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
128748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    private static Point sDefaultWallpaperSize;
129748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
130748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
131748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    public static Point getDefaultWallpaperSize(Resources res, WindowManager windowManager) {
132748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        if (sDefaultWallpaperSize == null) {
133748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            Point realSize = new Point();
134748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            windowManager.getDefaultDisplay().getRealSize(realSize);
135748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            int maxDim = Math.max(realSize.x, realSize.y);
136748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            int minDim = Math.min(realSize.x, realSize.y);
137748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
138748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            // We need to ensure that there is enough extra space in the wallpaper
139748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            // for the intended parallax effects
140748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            final int defaultWidth, defaultHeight;
141748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            if (res.getConfiguration().smallestScreenWidthDp >= 720) {
142748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal                defaultWidth = (int) (maxDim * wallpaperTravelToScreenWidthRatio(maxDim, minDim));
143748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal                defaultHeight = maxDim;
144748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            } else {
145748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal                defaultWidth = Math.max((int) (minDim * WALLPAPER_SCREENS_SPAN), maxDim);
146748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal                defaultHeight = maxDim;
147748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            }
148748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            sDefaultWallpaperSize = new Point(defaultWidth, defaultHeight);
149748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        }
150748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        return sDefaultWallpaperSize;
151748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    }
152748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal
153748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
154748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    public static boolean isRtl(Resources res) {
155748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 &&
156748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal                (res.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
157748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    }
158748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal}
159