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