1 /* 2 * Copyright (C) 2015 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 17 package com.android.wallpaperpicker; 18 19 import android.annotation.TargetApi; 20 import android.app.Activity; 21 import android.app.WallpaperManager; 22 import android.content.Context; 23 import android.content.SharedPreferences; 24 import android.content.res.Resources; 25 import android.graphics.Point; 26 import android.os.Build; 27 import android.view.View; 28 import android.view.WindowManager; 29 30 /** 31 * Utility methods for wallpaper management. 32 */ 33 public final class WallpaperUtils { 34 35 public static final String WALLPAPER_WIDTH_KEY = "wallpaper.width"; 36 public static final String WALLPAPER_HEIGHT_KEY = "wallpaper.height"; 37 38 // An intent extra to indicate the horizontal scroll of the wallpaper. 39 public static final String EXTRA_WALLPAPER_OFFSET = "com.android.launcher3.WALLPAPER_OFFSET"; 40 41 public static final float WALLPAPER_SCREENS_SPAN = 2f; 42 saveWallpaperDimensions(int width, int height, Activity activity)43 public static void saveWallpaperDimensions(int width, int height, Activity activity) { 44 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 45 // From Kitkat onwards, ImageWallpaper does not care about the 46 // desired width and desired height of the wallpaper. 47 return; 48 } 49 String spKey = WallpaperFiles.WALLPAPER_CROP_PREFERENCES_KEY; 50 SharedPreferences sp = activity.getSharedPreferences(spKey, Context.MODE_MULTI_PROCESS); 51 SharedPreferences.Editor editor = sp.edit(); 52 if (width != 0 && height != 0) { 53 editor.putInt(WALLPAPER_WIDTH_KEY, width); 54 editor.putInt(WALLPAPER_HEIGHT_KEY, height); 55 } else { 56 editor.remove(WALLPAPER_WIDTH_KEY); 57 editor.remove(WALLPAPER_HEIGHT_KEY); 58 } 59 editor.commit(); 60 suggestWallpaperDimensionPreK(activity, true); 61 } 62 suggestWallpaperDimensionPreK( Activity activity, boolean fallBackToDefaults)63 public static void suggestWallpaperDimensionPreK( 64 Activity activity, boolean fallBackToDefaults) { 65 final Point defaultWallpaperSize = getDefaultWallpaperSize( 66 activity.getResources(), activity.getWindowManager()); 67 68 SharedPreferences sp = activity.getSharedPreferences( 69 WallpaperFiles.WALLPAPER_CROP_PREFERENCES_KEY, Context.MODE_MULTI_PROCESS); 70 // If we have saved a wallpaper width/height, use that instead 71 int width = sp.getInt(WALLPAPER_WIDTH_KEY, -1); 72 int height = sp.getInt(WALLPAPER_HEIGHT_KEY, -1); 73 74 if (width == -1 || height == -1) { 75 if (!fallBackToDefaults) { 76 return; 77 } else { 78 width = defaultWallpaperSize.x; 79 height = defaultWallpaperSize.y; 80 } 81 } 82 83 WallpaperManager wm = WallpaperManager.getInstance(activity); 84 if (width != wm.getDesiredMinimumWidth() || height != wm.getDesiredMinimumHeight()) { 85 wm.suggestDesiredDimensions(width, height); 86 } 87 } 88 suggestWallpaperDimension(Activity activity)89 public static void suggestWallpaperDimension(Activity activity) { 90 // Only live wallpapers care about desired size. Update the size to what launcher expects. 91 final Point size = getDefaultWallpaperSize( 92 activity.getResources(), activity.getWindowManager()); 93 WallpaperManager wm = WallpaperManager.getInstance(activity); 94 if (size.x != wm.getDesiredMinimumWidth() || size.y != wm.getDesiredMinimumHeight()) { 95 wm.suggestDesiredDimensions(size.x, size.y); 96 } 97 } 98 99 /** 100 * As a ratio of screen height, the total distance we want the parallax effect to span 101 * horizontally 102 */ wallpaperTravelToScreenWidthRatio(int width, int height)103 private static float wallpaperTravelToScreenWidthRatio(int width, int height) { 104 float aspectRatio = width / (float) height; 105 106 // At an aspect ratio of 16/10, the wallpaper parallax effect should span 1.5 * screen width 107 // At an aspect ratio of 10/16, the wallpaper parallax effect should span 1.2 * screen width 108 // We will use these two data points to extrapolate how much the wallpaper parallax effect 109 // to span (ie travel) at any aspect ratio: 110 111 final float ASPECT_RATIO_LANDSCAPE = 16/10f; 112 final float ASPECT_RATIO_PORTRAIT = 10/16f; 113 final float WALLPAPER_WIDTH_TO_SCREEN_RATIO_LANDSCAPE = 1.5f; 114 final float WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT = 1.2f; 115 116 // To find out the desired width at different aspect ratios, we use the following two 117 // formulas, where the coefficient on x is the aspect ratio (width/height): 118 // (16/10)x + y = 1.5 119 // (10/16)x + y = 1.2 120 // We solve for x and y and end up with a final formula: 121 final float x = 122 (WALLPAPER_WIDTH_TO_SCREEN_RATIO_LANDSCAPE - WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT) / 123 (ASPECT_RATIO_LANDSCAPE - ASPECT_RATIO_PORTRAIT); 124 final float y = WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT - x * ASPECT_RATIO_PORTRAIT; 125 return x * aspectRatio + y; 126 } 127 128 private static Point sDefaultWallpaperSize; 129 130 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) getDefaultWallpaperSize(Resources res, WindowManager windowManager)131 public static Point getDefaultWallpaperSize(Resources res, WindowManager windowManager) { 132 if (sDefaultWallpaperSize == null) { 133 Point realSize = new Point(); 134 windowManager.getDefaultDisplay().getRealSize(realSize); 135 int maxDim = Math.max(realSize.x, realSize.y); 136 int minDim = Math.min(realSize.x, realSize.y); 137 138 // We need to ensure that there is enough extra space in the wallpaper 139 // for the intended parallax effects 140 final int defaultWidth, defaultHeight; 141 if (res.getConfiguration().smallestScreenWidthDp >= 720) { 142 defaultWidth = (int) (maxDim * wallpaperTravelToScreenWidthRatio(maxDim, minDim)); 143 defaultHeight = maxDim; 144 } else { 145 defaultWidth = Math.max((int) (minDim * WALLPAPER_SCREENS_SPAN), maxDim); 146 defaultHeight = maxDim; 147 } 148 sDefaultWallpaperSize = new Point(defaultWidth, defaultHeight); 149 } 150 return sDefaultWallpaperSize; 151 } 152 153 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) isRtl(Resources res)154 public static boolean isRtl(Resources res) { 155 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && 156 (res.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL); 157 } 158 } 159