CompatibilityInfo.java revision e2515eebf42c763c0a2d9f873a153711778cfc17
19189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima/*
29189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima * Copyright (C) 2006 The Android Open Source Project
39189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima *
49189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima * Licensed under the Apache License, Version 2.0 (the "License");
59189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima * you may not use this file except in compliance with the License.
69189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima * You may obtain a copy of the License at
79189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima *
89189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima *      http://www.apache.org/licenses/LICENSE-2.0
99189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima *
109189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima * Unless required by applicable law or agreed to in writing, software
119189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima * distributed under the License is distributed on an "AS IS" BASIS,
129189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima * See the License for the specific language governing permissions and
149189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima * limitations under the License.
159189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima */
169189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima
179189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshimapackage android.content.res;
189189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima
199189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshimaimport android.content.pm.ApplicationInfo;
2064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshimaimport android.graphics.Canvas;
21a53146c5569f8ff5f7eb55e9ad35d23ddacf2addChristopher Tateimport android.graphics.PointF;
2264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshimaimport android.graphics.Rect;
2364f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshimaimport android.graphics.Region;
24e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackbornimport android.os.Parcel;
25e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackbornimport android.os.Parcelable;
269189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshimaimport android.util.DisplayMetrics;
2764f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshimaimport android.view.MotionEvent;
2864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshimaimport android.view.WindowManager;
2964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshimaimport android.view.WindowManager.LayoutParams;
309189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima
319189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima/**
329189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima * CompatibilityInfo class keeps the information about compatibility mode that the application is
339189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima * running under.
349189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima *
359189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima *  {@hide}
369189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima */
37e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackbornpublic class CompatibilityInfo implements Parcelable {
389189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima    /** default compatibility info object for compatible applications */
395a2b91dc14e4c92e91c6abcc795f54ac98ee5866Mitsuru Oshima    public static final CompatibilityInfo DEFAULT_COMPATIBILITY_INFO = new CompatibilityInfo() {
405a2b91dc14e4c92e91c6abcc795f54ac98ee5866Mitsuru Oshima    };
419189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima
429189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima    /**
43e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn     * This is the number of pixels we would like to have along the
44e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn     * short axis of an app that needs to run on a normal size screen.
459189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima     */
46e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    public static final int DEFAULT_NORMAL_SHORT_DIMENSION = 320;
479189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima
489189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima    /**
49e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn     * This is the maximum aspect ratio we will allow while keeping
50e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn     * applications in a compatible screen size.
51e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn     */
52e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    public static final float MAXIMUM_ASPECT_RATIO = (854f/480f);
539189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima
549189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima    /**
5564f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima     *  A compatibility flags
569189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima     */
57e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    private final int mCompatibilityFlags;
589189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima
599189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima    /**
6064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima     * A flag mask to tell if the application needs scaling (when mApplicationScale != 1.0f)
6164f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima     * {@see compatibilityFlag}
6264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima     */
6364f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    private static final int SCALING_REQUIRED = 1;
6464f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
6564f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    /**
66e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn     * Has the application said that its UI is expandable?  Based on the
67e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn     * <supports-screen> android:expandible in the manifest.
6864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima     */
6964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    private static final int EXPANDABLE = 2;
7064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
7164f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    /**
72e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn     * Has the application said that its UI supports large screens?  Based on the
73e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn     * <supports-screen> android:largeScreens in the manifest.
74c4db95c077f826585d20be2f3db4043c53d30cf5Dianne Hackborn     */
75c4db95c077f826585d20be2f3db4043c53d30cf5Dianne Hackborn    private static final int LARGE_SCREENS = 8;
76c4db95c077f826585d20be2f3db4043c53d30cf5Dianne Hackborn
77c4db95c077f826585d20be2f3db4043c53d30cf5Dianne Hackborn    /**
78e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn     * Has the application said that its UI supports xlarge screens?  Based on the
79e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn     * <supports-screen> android:xlargeScreens in the manifest.
8014cee9f688c32d63d8521188e7422811629bb7c2Dianne Hackborn     */
8114cee9f688c32d63d8521188e7422811629bb7c2Dianne Hackborn    private static final int XLARGE_SCREENS = 32;
8214cee9f688c32d63d8521188e7422811629bb7c2Dianne Hackborn
8314cee9f688c32d63d8521188e7422811629bb7c2Dianne Hackborn    /**
84e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn     * Set if the application needs to run in screen size compatibility mode.
8514cee9f688c32d63d8521188e7422811629bb7c2Dianne Hackborn     */
86e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    private static final int NEEDS_SCREEN_COMPAT = 128;
8764f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
8864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    /**
892784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn     * The effective screen density we have selected for this application.
902784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn     */
912784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn    public final int applicationDensity;
922784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn
932784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn    /**
9464f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima     * Application's scale.
959189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima     */
9664f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    public final float applicationScale;
97e5fb328825995aa33b5b7ecf8b5bee2b17f81715Mitsuru Oshima
98e5fb328825995aa33b5b7ecf8b5bee2b17f81715Mitsuru Oshima    /**
9964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima     * Application's inverted scale.
100e5fb328825995aa33b5b7ecf8b5bee2b17f81715Mitsuru Oshima     */
10164f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    public final float applicationInvertedScale;
10264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
103e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, boolean forceCompat) {
104e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        int compatFlags = 0;
105e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
10664f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
107e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            compatFlags |= LARGE_SCREENS;
108e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            if (!forceCompat) {
109e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn                // If we aren't forcing the app into compatibility mode, then
110e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn                // assume if it supports large screens that we should allow it
111e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn                // to use the full space of an xlarge screen as well.
112e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn                compatFlags |= XLARGE_SCREENS | EXPANDABLE;
113e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            }
114c4db95c077f826585d20be2f3db4043c53d30cf5Dianne Hackborn        }
11514cee9f688c32d63d8521188e7422811629bb7c2Dianne Hackborn        if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) {
116e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            compatFlags |= XLARGE_SCREENS | EXPANDABLE;
117e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
118e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        if (!forceCompat) {
119e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            // If we are forcing compatibility mode, then ignore an app that
120e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            // just says it is resizable for screens.  We'll only have it fill
121e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            // the screen if it explicitly says it supports the screen size we
122e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            // are running in.
123e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            if ((appInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
124e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn                compatFlags |= EXPANDABLE;
125e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            }
126e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
127e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
128e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        boolean supportsScreen = false;
129e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        switch (screenLayout&Configuration.SCREENLAYOUT_SIZE_MASK) {
130e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            case Configuration.SCREENLAYOUT_SIZE_XLARGE:
131e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn                if ((compatFlags&XLARGE_SCREENS) != 0) {
132e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn                    supportsScreen = true;
133e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn                }
134e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn                break;
135e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            case Configuration.SCREENLAYOUT_SIZE_LARGE:
136e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn                if ((compatFlags&LARGE_SCREENS) != 0) {
137e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn                    supportsScreen = true;
138e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn                }
139e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn                break;
140e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
141e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
142e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        if ((screenLayout&Configuration.SCREENLAYOUT_COMPAT_NEEDED) == 0) {
143e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            if ((compatFlags&EXPANDABLE) != 0) {
144e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn                supportsScreen = true;
145e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            }
14614cee9f688c32d63d8521188e7422811629bb7c2Dianne Hackborn        }
147e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
148e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        if (supportsScreen) {
149e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            compatFlags &= ~NEEDS_SCREEN_COMPAT;
150e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        } else {
151e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            compatFlags |= NEEDS_SCREEN_COMPAT;
15264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
153e5fb328825995aa33b5b7ecf8b5bee2b17f81715Mitsuru Oshima
15411b822d2a91ea17c34c0cb1c11e80a9a30d72864Dianne Hackborn        if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
15511b822d2a91ea17c34c0cb1c11e80a9a30d72864Dianne Hackborn            applicationDensity = DisplayMetrics.DENSITY_DEVICE;
15611b822d2a91ea17c34c0cb1c11e80a9a30d72864Dianne Hackborn            applicationScale = 1.0f;
15711b822d2a91ea17c34c0cb1c11e80a9a30d72864Dianne Hackborn            applicationInvertedScale = 1.0f;
1589189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima        } else {
1592784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn            applicationDensity = DisplayMetrics.DENSITY_DEFAULT;
16011b822d2a91ea17c34c0cb1c11e80a9a30d72864Dianne Hackborn            applicationScale = DisplayMetrics.DENSITY_DEVICE
16111b822d2a91ea17c34c0cb1c11e80a9a30d72864Dianne Hackborn                    / (float) DisplayMetrics.DENSITY_DEFAULT;
16211b822d2a91ea17c34c0cb1c11e80a9a30d72864Dianne Hackborn            applicationInvertedScale = 1.0f / applicationScale;
163e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            compatFlags |= SCALING_REQUIRED;
1649189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima        }
165e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
166e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        mCompatibilityFlags = compatFlags;
1679189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima    }
1689189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima
169e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    private CompatibilityInfo(int compFlags,
1702784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn            int dens, float scale, float invertedScale) {
171569076c9f6bdadb4d3285a26e069634a839b5b87Mitsuru Oshima        mCompatibilityFlags = compFlags;
1722784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn        applicationDensity = dens;
173569076c9f6bdadb4d3285a26e069634a839b5b87Mitsuru Oshima        applicationScale = scale;
174569076c9f6bdadb4d3285a26e069634a839b5b87Mitsuru Oshima        applicationInvertedScale = invertedScale;
175569076c9f6bdadb4d3285a26e069634a839b5b87Mitsuru Oshima    }
176569076c9f6bdadb4d3285a26e069634a839b5b87Mitsuru Oshima
1779189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima    private CompatibilityInfo() {
178e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        this(XLARGE_SCREENS | LARGE_SCREENS | EXPANDABLE,
1792784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn                DisplayMetrics.DENSITY_DEVICE,
180569076c9f6bdadb4d3285a26e069634a839b5b87Mitsuru Oshima                1.0f,
181569076c9f6bdadb4d3285a26e069634a839b5b87Mitsuru Oshima                1.0f);
1829189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima    }
1839189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima
18464f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    /**
18564f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima     * @return true if the scaling is required
18664f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima     */
18764f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    public boolean isScalingRequired() {
188723738cfaec3dd7b0fe152c872c41bebf94074c4Dianne Hackborn        return (mCompatibilityFlags & SCALING_REQUIRED) != 0;
18964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    }
19064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
1911ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima    public boolean supportsScreen() {
192e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        return (mCompatibilityFlags&NEEDS_SCREEN_COMPAT) == 0;
1931ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima    }
1941ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima
1959189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima    @Override
1969189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima    public String toString() {
197e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        return "CompatibilityInfo{scale=" + applicationScale + "}";
19864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    }
19964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
20064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    /**
201589cebe2d58591403de4a77077941c0454bc91bcMitsuru Oshima     * Returns the translator which translates the coordinates in compatibility mode.
20264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima     * @param params the window's parameter
20364f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima     */
204589cebe2d58591403de4a77077941c0454bc91bcMitsuru Oshima    public Translator getTranslator() {
205589cebe2d58591403de4a77077941c0454bc91bcMitsuru Oshima        return isScalingRequired() ? new Translator() : null;
20664f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    }
20764f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
20864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    /**
20964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima     * A helper object to translate the screen and window coordinates back and forth.
21064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima     * @hide
21164f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima     */
21264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    public class Translator {
21364f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        final public float applicationScale;
21464f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        final public float applicationInvertedScale;
21564f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
21664f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        private Rect mContentInsetsBuffer = null;
2171ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima        private Rect mVisibleInsetsBuffer = null;
218fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        private Region mTouchableAreaBuffer = null;
21964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
2201ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima        Translator(float applicationScale, float applicationInvertedScale) {
22164f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima            this.applicationScale = applicationScale;
22264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima            this.applicationInvertedScale = applicationInvertedScale;
22364f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
22464f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
22564f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        Translator() {
2261ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            this(CompatibilityInfo.this.applicationScale,
2271ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima                    CompatibilityInfo.this.applicationInvertedScale);
22864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
22964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
23064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        /**
23164f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * Translate the screen rect to the application frame.
23264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         */
23364f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        public void translateRectInScreenToAppWinFrame(Rect rect) {
2341ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            rect.scale(applicationInvertedScale);
23564f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
23664f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
23764f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        /**
23864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * Translate the region in window to screen.
23964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         */
24064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        public void translateRegionInWindowToScreen(Region transparentRegion) {
2411ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            transparentRegion.scale(applicationScale);
24264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
24364f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
24464f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        /**
24564f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * Apply translation to the canvas that is necessary to draw the content.
24664f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         */
24764f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        public void translateCanvas(Canvas canvas) {
248b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed            if (applicationScale == 1.5f) {
249b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                /*  When we scale for compatibility, we can put our stretched
250b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                    bitmaps and ninepatches on exacty 1/2 pixel boundaries,
251b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                    which can give us inconsistent drawing due to imperfect
252b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                    float precision in the graphics engine's inverse matrix.
253b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed
254b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                    As a work-around, we translate by a tiny amount to avoid
255b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                    landing on exact pixel centers and boundaries, giving us
256b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                    the slop we need to draw consistently.
257b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed
258b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                    This constant is meant to resolve to 1/255 after it is
259b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                    scaled by 1.5 (applicationScale). Note, this is just a guess
260b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                    as to what is small enough not to create its own artifacts,
261b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                    and big enough to avoid the precision problems. Feel free
262b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                    to experiment with smaller values as you choose.
263b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                 */
264b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                final float tinyOffset = 2.0f / (3 * 255);
265b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                canvas.translate(tinyOffset, tinyOffset);
266b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed            }
2671ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            canvas.scale(applicationScale, applicationScale);
26864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
26964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
27064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        /**
27164f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * Translate the motion event captured on screen to the application's window.
27264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         */
27364f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        public void translateEventInScreenToAppWindow(MotionEvent event) {
2741ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            event.scale(applicationInvertedScale);
27564f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
27664f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
27764f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        /**
27864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * Translate the window's layout parameter, from application's view to
27964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * Screen's view.
28064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         */
28164f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        public void translateWindowLayout(WindowManager.LayoutParams params) {
2821ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            params.scale(applicationScale);
28364f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
28464f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
28564f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        /**
28664f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * Translate a Rect in application's window to screen.
28764f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         */
28864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        public void translateRectInAppWindowToScreen(Rect rect) {
2891ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            rect.scale(applicationScale);
29064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
29164f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
29264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        /**
29364f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * Translate a Rect in screen coordinates into the app window's coordinates.
29464f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         */
29564f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        public void translateRectInScreenToAppWindow(Rect rect) {
2961ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            rect.scale(applicationInvertedScale);
29764f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
29864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
29964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        /**
300a53146c5569f8ff5f7eb55e9ad35d23ddacf2addChristopher Tate         * Translate a Point in screen coordinates into the app window's coordinates.
301a53146c5569f8ff5f7eb55e9ad35d23ddacf2addChristopher Tate         */
302a53146c5569f8ff5f7eb55e9ad35d23ddacf2addChristopher Tate        public void translatePointInScreenToAppWindow(PointF point) {
303a53146c5569f8ff5f7eb55e9ad35d23ddacf2addChristopher Tate            final float scale = applicationInvertedScale;
304a53146c5569f8ff5f7eb55e9ad35d23ddacf2addChristopher Tate            if (scale != 1.0f) {
305a53146c5569f8ff5f7eb55e9ad35d23ddacf2addChristopher Tate                point.x *= scale;
306a53146c5569f8ff5f7eb55e9ad35d23ddacf2addChristopher Tate                point.y *= scale;
307a53146c5569f8ff5f7eb55e9ad35d23ddacf2addChristopher Tate            }
308a53146c5569f8ff5f7eb55e9ad35d23ddacf2addChristopher Tate        }
309a53146c5569f8ff5f7eb55e9ad35d23ddacf2addChristopher Tate
310a53146c5569f8ff5f7eb55e9ad35d23ddacf2addChristopher Tate        /**
31164f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * Translate the location of the sub window.
31264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * @param params
31364f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         */
31464f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        public void translateLayoutParamsInAppWindowToScreen(LayoutParams params) {
3151ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            params.scale(applicationScale);
31664f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
31764f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
31864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        /**
31964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * Translate the content insets in application window to Screen. This uses
32064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * the internal buffer for content insets to avoid extra object allocation.
32164f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         */
32264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        public Rect getTranslatedContentInsets(Rect contentInsets) {
32364f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima            if (mContentInsetsBuffer == null) mContentInsetsBuffer = new Rect();
32464f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima            mContentInsetsBuffer.set(contentInsets);
32564f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima            translateRectInAppWindowToScreen(mContentInsetsBuffer);
32664f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima            return mContentInsetsBuffer;
32764f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
32864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
32964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        /**
33064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * Translate the visible insets in application window to Screen. This uses
331fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * the internal buffer for visible insets to avoid extra object allocation.
33264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         */
333fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        public Rect getTranslatedVisibleInsets(Rect visibleInsets) {
3341ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            if (mVisibleInsetsBuffer == null) mVisibleInsetsBuffer = new Rect();
3351ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            mVisibleInsetsBuffer.set(visibleInsets);
3361ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            translateRectInAppWindowToScreen(mVisibleInsetsBuffer);
3371ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            return mVisibleInsetsBuffer;
3381ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima        }
339fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown
340fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        /**
341fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * Translate the touchable area in application window to Screen. This uses
342fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * the internal buffer for touchable area to avoid extra object allocation.
343fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         */
344fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        public Region getTranslatedTouchableArea(Region touchableArea) {
345fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown            if (mTouchableAreaBuffer == null) mTouchableAreaBuffer = new Region();
346fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown            mTouchableAreaBuffer.set(touchableArea);
347fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown            mTouchableAreaBuffer.scale(applicationScale);
348fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown            return mTouchableAreaBuffer;
349fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        }
3501ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima    }
3511ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima
352e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    public void applyToDisplayMetrics(DisplayMetrics inoutDm) {
353e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        if (!supportsScreen()) {
354e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            // This is a larger screen device and the app is not
355e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            // compatible with large screens, so diddle it.
356e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            CompatibilityInfo.updateCompatibleScreenFrame(inoutDm, null, inoutDm);
357e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
358e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
359e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        if (isScalingRequired()) {
360e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            float invertedRatio = applicationInvertedScale;
361e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            inoutDm.density *= invertedRatio;
362e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            inoutDm.densityDpi = (int)((inoutDm.density*DisplayMetrics.DENSITY_DEFAULT)+.5f);
363e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            inoutDm.scaledDensity *= invertedRatio;
364e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            inoutDm.xdpi *= invertedRatio;
365e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            inoutDm.ydpi *= invertedRatio;
366e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            inoutDm.widthPixels = (int) (inoutDm.widthPixels * invertedRatio + 0.5f);
367e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            inoutDm.heightPixels = (int) (inoutDm.heightPixels * invertedRatio + 0.5f);
368e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
369e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    }
370e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
371e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    public void applyToConfiguration(Configuration inoutConfig) {
372e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        if (!supportsScreen()) {
373e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            // This is a larger screen device and the app is not
374e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            // compatible with large screens, so we are forcing it to
375e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            // run as if the screen is normal size.
376e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            inoutConfig.screenLayout =
377e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn                    (inoutConfig.screenLayout&~Configuration.SCREENLAYOUT_SIZE_MASK)
378e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn                    | Configuration.SCREENLAYOUT_SIZE_NORMAL;
379e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
380e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    }
381e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
3821ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima    /**
383e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn     * Compute the frame Rect for applications runs under compatibility mode.
3841ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima     *
3851ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima     * @param dm the display metrics used to compute the frame size.
3861ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima     * @param orientation the orientation of the screen.
3871ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima     * @param outRect the output parameter which will contain the result.
388e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn     * @return Returns the scaling factor for the window.
3891ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima     */
390e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    public static float updateCompatibleScreenFrame(DisplayMetrics dm,
391e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            Rect outRect, DisplayMetrics outDm) {
392e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        final int width = dm.realWidthPixels;
393e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        final int height = dm.realHeightPixels;
394e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        int shortSize, longSize;
395e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        if (width < height) {
396e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            shortSize = width;
397e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            longSize = height;
398e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        } else {
399e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            shortSize = height;
400e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            longSize = width;
401e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
402e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        int newShortSize = (int)(DEFAULT_NORMAL_SHORT_DIMENSION * dm.density + 0.5f);
403e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        float aspect = ((float)longSize) / shortSize;
404e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        if (aspect > MAXIMUM_ASPECT_RATIO) {
405e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            aspect = MAXIMUM_ASPECT_RATIO;
406e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
407e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        int newLongSize = (int)(newShortSize * aspect + 0.5f);
408e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        int newWidth, newHeight;
409e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        if (width < height) {
410e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            newWidth = newShortSize;
411e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            newHeight = newLongSize;
4121ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima        } else {
413e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            newWidth = newLongSize;
414e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            newHeight = newShortSize;
415e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
416e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
417e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        float sw = width/(float)newWidth;
418e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        float sh = height/(float)newHeight;
419e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        float scale = sw < sh ? sw : sh;
420e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        if (scale < 1) {
421e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            scale = 1;
42264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
423e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
424e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        if (outRect != null) {
425e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            final int left = (int)((width-(newWidth*scale))/2);
426e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            final int top = (int)((height-(newHeight*scale))/2);
427e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            outRect.set(left, top, left+newWidth, top+newHeight);
428e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
429e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
430e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        if (outDm != null) {
431e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            outDm.widthPixels = newWidth;
432e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            outDm.heightPixels = newHeight;
433e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
434e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
435e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        return scale;
436e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    }
437e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
438e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    @Override
439e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    public boolean equals(Object o) {
440e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        try {
441e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            CompatibilityInfo oc = (CompatibilityInfo)o;
442e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            if (mCompatibilityFlags != oc.mCompatibilityFlags) return false;
443e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            if (applicationDensity != oc.applicationDensity) return false;
444e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            if (applicationScale != oc.applicationScale) return false;
445e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            if (applicationInvertedScale != oc.applicationInvertedScale) return false;
446e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            return true;
447e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        } catch (ClassCastException e) {
448e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            return false;
449e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
450e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    }
451e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
452e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    @Override
453e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    public int hashCode() {
454e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        int result = 17;
455e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        result = 31 * result + mCompatibilityFlags;
456e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        result = 31 * result + applicationDensity;
457e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        result = 31 * result + Float.floatToIntBits(applicationScale);
458e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        result = 31 * result + Float.floatToIntBits(applicationInvertedScale);
459e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        return result;
460e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    }
461e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
462e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    @Override
463e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    public int describeContents() {
464e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        return 0;
465e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    }
466e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
467e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    @Override
468e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    public void writeToParcel(Parcel dest, int flags) {
469e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        dest.writeInt(mCompatibilityFlags);
470e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        dest.writeInt(applicationDensity);
471e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        dest.writeFloat(applicationScale);
472e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        dest.writeFloat(applicationInvertedScale);
473e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    }
474e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
475e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    public static final Parcelable.Creator<CompatibilityInfo> CREATOR
476e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            = new Parcelable.Creator<CompatibilityInfo>() {
477e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        public CompatibilityInfo createFromParcel(Parcel source) {
478e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            return new CompatibilityInfo(source);
479e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
480e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
481e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        public CompatibilityInfo[] newArray(int size) {
482e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            return new CompatibilityInfo[size];
483e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
484e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    };
485e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
486e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    private CompatibilityInfo(Parcel source) {
487e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        mCompatibilityFlags = source.readInt();
488e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        applicationDensity = source.readInt();
489e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        applicationScale = source.readFloat();
490e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        applicationInvertedScale = source.readFloat();
4919189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima    }
492569076c9f6bdadb4d3285a26e069634a839b5b87Mitsuru Oshima}
493