Home | History | Annotate | Download | only in wallpaperpicker
      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 
     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 
     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 
     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      */
    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)
    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)
    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