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    /**
660f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn     * Application must always run in compatibility mode?
670f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn     */
688ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn    private static final int ALWAYS_NEEDS_COMPAT = 2;
690f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
700f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    /**
710f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn     * Application never should run in compatibility mode?
720f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn     */
738ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn    private static final int NEVER_NEEDS_COMPAT = 4;
740f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
750f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    /**
76e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn     * Set if the application needs to run in screen size compatibility mode.
7714cee9f688c32d63d8521188e7422811629bb7c2Dianne Hackborn     */
788ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn    private static final int NEEDS_SCREEN_COMPAT = 8;
7964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
8064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    /**
812784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn     * The effective screen density we have selected for this application.
822784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn     */
832784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn    public final int applicationDensity;
842784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn
852784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn    /**
8664f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima     * Application's scale.
879189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima     */
8864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    public final float applicationScale;
89e5fb328825995aa33b5b7ecf8b5bee2b17f81715Mitsuru Oshima
90e5fb328825995aa33b5b7ecf8b5bee2b17f81715Mitsuru Oshima    /**
9164f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima     * Application's inverted scale.
92e5fb328825995aa33b5b7ecf8b5bee2b17f81715Mitsuru Oshima     */
9364f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    public final float applicationInvertedScale;
9464f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
95df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn    public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, int sw,
96df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            boolean forceCompat) {
97e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        int compatFlags = 0;
98e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
992762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn        if (appInfo.requiresSmallestWidthDp != 0 || appInfo.compatibleWidthLimitDp != 0
1002762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn                || appInfo.largestWidthLimitDp != 0) {
101df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            // New style screen requirements spec.
102df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            int required = appInfo.requiresSmallestWidthDp != 0
103df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                    ? appInfo.requiresSmallestWidthDp
104df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                    : appInfo.compatibleWidthLimitDp;
1052762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn            if (required == 0) {
1062762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn                required = appInfo.largestWidthLimitDp;
1072762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn            }
108df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            int compat = appInfo.compatibleWidthLimitDp != 0
1092762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn                    ? appInfo.compatibleWidthLimitDp : required;
110df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            if (compat < required)  {
111df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                compat = required;
112e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            }
1132762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn            int largest = appInfo.largestWidthLimitDp;
1142762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn
1152762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn            if (required > DEFAULT_NORMAL_SHORT_DIMENSION) {
1162762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn                // For now -- if they require a size larger than the only
1172762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn                // size we can do in compatibility mode, then don't ever
1182762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn                // allow the app to go in to compat mode.  Trying to run
1192762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn                // it at a smaller size it can handle will make it far more
1202762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn                // broken than running at a larger size than it wants or
1212762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn                // thinks it can handle.
1222762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn                compatFlags |= NEVER_NEEDS_COMPAT;
1232762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn            } else if (largest != 0 && sw > largest) {
1242762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn                // If the screen size is larger than the largest size the
1252762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn                // app thinks it can work with, then always force it in to
1262762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn                // compatibility mode.
1272762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn                compatFlags |= NEEDS_SCREEN_COMPAT | ALWAYS_NEEDS_COMPAT;
1282762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn            } else if (compat >= sw) {
1292762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn                // The screen size is something the app says it was designed
1302762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn                // for, so never do compatibility mode.
1318ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                compatFlags |= NEVER_NEEDS_COMPAT;
132df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            } else if (forceCompat) {
1332762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn                // The app may work better with or without compatibility mode.
1342762ff3dc864018352362f6d103de471f9529ba6Dianne Hackborn                // Let the user decide.
135df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                compatFlags |= NEEDS_SCREEN_COMPAT;
13636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            }
1375be8de3420ba4c9d816b98e29bdec11715f6b626Dianne Hackborn
138df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            // Modern apps always support densities.
139df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            applicationDensity = DisplayMetrics.DENSITY_DEVICE;
140df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            applicationScale = 1.0f;
141df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            applicationInvertedScale = 1.0f;
142e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
143df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn        } else {
1448ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            /**
1458ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn             * Has the application said that its UI is expandable?  Based on the
1468ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn             * <supports-screen> android:expandible in the manifest.
1478ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn             */
1488ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            final int EXPANDABLE = 2;
1498ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn
1508ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            /**
1518ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn             * Has the application said that its UI supports large screens?  Based on the
1528ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn             * <supports-screen> android:largeScreens in the manifest.
1538ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn             */
1548ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            final int LARGE_SCREENS = 8;
1558ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn
1568ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            /**
1578ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn             * Has the application said that its UI supports xlarge screens?  Based on the
1588ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn             * <supports-screen> android:xlargeScreens in the manifest.
1598ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn             */
1608ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            final int XLARGE_SCREENS = 32;
1618ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn
1628ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            int sizeInfo = 0;
1638ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn
164df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            // We can't rely on the application always setting
165df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            // FLAG_RESIZEABLE_FOR_SCREENS so will compute it based on various input.
166df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            boolean anyResizeable = false;
167df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn
168df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
1698ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                sizeInfo |= LARGE_SCREENS;
170df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                anyResizeable = true;
171df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                if (!forceCompat) {
172df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                    // If we aren't forcing the app into compatibility mode, then
173df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                    // assume if it supports large screens that we should allow it
174df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                    // to use the full space of an xlarge screen as well.
1758ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                    sizeInfo |= XLARGE_SCREENS | EXPANDABLE;
176e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn                }
177df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            }
178df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) {
179df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                anyResizeable = true;
180df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                if (!forceCompat) {
1818ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                    sizeInfo |= XLARGE_SCREENS | EXPANDABLE;
1820f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn                }
183df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            }
184df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            if ((appInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
185df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                anyResizeable = true;
1868ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                sizeInfo |= EXPANDABLE;
187df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            }
188df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn
189df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            if (forceCompat) {
190df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                // If we are forcing compatibility mode, then ignore an app that
191df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                // just says it is resizable for screens.  We'll only have it fill
192df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                // the screen if it explicitly says it supports the screen size we
193df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                // are running in.
1948ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                sizeInfo &= ~EXPANDABLE;
195df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            }
196df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn
1978ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            compatFlags |= NEEDS_SCREEN_COMPAT;
198df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            switch (screenLayout&Configuration.SCREENLAYOUT_SIZE_MASK) {
199df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                case Configuration.SCREENLAYOUT_SIZE_XLARGE:
2008ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                    if ((sizeInfo&XLARGE_SCREENS) != 0) {
2018ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                        compatFlags &= ~NEEDS_SCREEN_COMPAT;
202df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                    }
203df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                    if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) {
2048ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                        compatFlags |= NEVER_NEEDS_COMPAT;
205df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                    }
206df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                    break;
207df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                case Configuration.SCREENLAYOUT_SIZE_LARGE:
2088ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                    if ((sizeInfo&LARGE_SCREENS) != 0) {
2098ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                        compatFlags &= ~NEEDS_SCREEN_COMPAT;
210df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                    }
211df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                    if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
2128ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                        compatFlags |= NEVER_NEEDS_COMPAT;
213df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                    }
214df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                    break;
215df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            }
216df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn
217df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            if ((screenLayout&Configuration.SCREENLAYOUT_COMPAT_NEEDED) != 0) {
2188ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                if ((sizeInfo&EXPANDABLE) != 0) {
2198ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                    compatFlags &= ~NEEDS_SCREEN_COMPAT;
220df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                } else if (!anyResizeable) {
2218ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn                    compatFlags |= ALWAYS_NEEDS_COMPAT;
222e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn                }
22339ec8fb9572b6f7a6c3dbc135f32f2a8cbcd640fDianne Hackborn            } else {
22439ec8fb9572b6f7a6c3dbc135f32f2a8cbcd640fDianne Hackborn                compatFlags &= ~NEEDS_SCREEN_COMPAT;
22539ec8fb9572b6f7a6c3dbc135f32f2a8cbcd640fDianne Hackborn                compatFlags |= NEVER_NEEDS_COMPAT;
226df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            }
227e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
228df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
229df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                applicationDensity = DisplayMetrics.DENSITY_DEVICE;
230df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                applicationScale = 1.0f;
231df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                applicationInvertedScale = 1.0f;
232df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            } else {
233df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                applicationDensity = DisplayMetrics.DENSITY_DEFAULT;
234df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                applicationScale = DisplayMetrics.DENSITY_DEVICE
235df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                        / (float) DisplayMetrics.DENSITY_DEFAULT;
236df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                applicationInvertedScale = 1.0f / applicationScale;
237df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn                compatFlags |= SCALING_REQUIRED;
238df6e980e3f63eb0f6f9eb437fa925d5009cd9c44Dianne Hackborn            }
2399189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima        }
240e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
241e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        mCompatibilityFlags = compatFlags;
2429189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima    }
2439189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima
244e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    private CompatibilityInfo(int compFlags,
2452784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn            int dens, float scale, float invertedScale) {
246569076c9f6bdadb4d3285a26e069634a839b5b87Mitsuru Oshima        mCompatibilityFlags = compFlags;
2472784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn        applicationDensity = dens;
248569076c9f6bdadb4d3285a26e069634a839b5b87Mitsuru Oshima        applicationScale = scale;
249569076c9f6bdadb4d3285a26e069634a839b5b87Mitsuru Oshima        applicationInvertedScale = invertedScale;
250569076c9f6bdadb4d3285a26e069634a839b5b87Mitsuru Oshima    }
251569076c9f6bdadb4d3285a26e069634a839b5b87Mitsuru Oshima
2529189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima    private CompatibilityInfo() {
2538ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        this(NEVER_NEEDS_COMPAT, DisplayMetrics.DENSITY_DEVICE,
254569076c9f6bdadb4d3285a26e069634a839b5b87Mitsuru Oshima                1.0f,
255569076c9f6bdadb4d3285a26e069634a839b5b87Mitsuru Oshima                1.0f);
2569189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima    }
2579189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima
25864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    /**
25964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima     * @return true if the scaling is required
26064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima     */
26164f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    public boolean isScalingRequired() {
2628ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        return (mCompatibilityFlags&SCALING_REQUIRED) != 0;
26364f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    }
26464f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
2651ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima    public boolean supportsScreen() {
266e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        return (mCompatibilityFlags&NEEDS_SCREEN_COMPAT) == 0;
2671ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima    }
2681ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima
2690f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    public boolean neverSupportsScreen() {
2702f0b17573d4324832f7a20402a3d2b5920bc4866Dianne Hackborn        return (mCompatibilityFlags&ALWAYS_NEEDS_COMPAT) != 0;
2710f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    }
2720f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn
2730f1de9adde0b52d2a385a76232bd7ac30c3eeea2Dianne Hackborn    public boolean alwaysSupportsScreen() {
2742f0b17573d4324832f7a20402a3d2b5920bc4866Dianne Hackborn        return (mCompatibilityFlags&NEVER_NEEDS_COMPAT) != 0;
27564f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    }
27664f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
27764f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    /**
278589cebe2d58591403de4a77077941c0454bc91bcMitsuru Oshima     * Returns the translator which translates the coordinates in compatibility mode.
27964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima     * @param params the window's parameter
28064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima     */
281589cebe2d58591403de4a77077941c0454bc91bcMitsuru Oshima    public Translator getTranslator() {
282589cebe2d58591403de4a77077941c0454bc91bcMitsuru Oshima        return isScalingRequired() ? new Translator() : null;
28364f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    }
28464f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
28564f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    /**
28664f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima     * A helper object to translate the screen and window coordinates back and forth.
28764f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima     * @hide
28864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima     */
28964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima    public class Translator {
29064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        final public float applicationScale;
29164f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        final public float applicationInvertedScale;
29264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
29364f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        private Rect mContentInsetsBuffer = null;
2941ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima        private Rect mVisibleInsetsBuffer = null;
295fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        private Region mTouchableAreaBuffer = null;
29664f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
2971ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima        Translator(float applicationScale, float applicationInvertedScale) {
29864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima            this.applicationScale = applicationScale;
29964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima            this.applicationInvertedScale = applicationInvertedScale;
30064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
30164f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
30264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        Translator() {
3031ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            this(CompatibilityInfo.this.applicationScale,
3041ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima                    CompatibilityInfo.this.applicationInvertedScale);
30564f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
30664f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
30764f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        /**
30864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * Translate the screen rect to the application frame.
30964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         */
31064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        public void translateRectInScreenToAppWinFrame(Rect rect) {
3111ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            rect.scale(applicationInvertedScale);
31264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
31364f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
31464f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        /**
31564f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * Translate the region in window to screen.
31664f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         */
31764f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        public void translateRegionInWindowToScreen(Region transparentRegion) {
3181ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            transparentRegion.scale(applicationScale);
31964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
32064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
32164f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        /**
32264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * Apply translation to the canvas that is necessary to draw the content.
32364f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         */
32464f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        public void translateCanvas(Canvas canvas) {
325b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed            if (applicationScale == 1.5f) {
326b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                /*  When we scale for compatibility, we can put our stretched
327b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                    bitmaps and ninepatches on exacty 1/2 pixel boundaries,
328b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                    which can give us inconsistent drawing due to imperfect
329b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                    float precision in the graphics engine's inverse matrix.
330b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed
331b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                    As a work-around, we translate by a tiny amount to avoid
332b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                    landing on exact pixel centers and boundaries, giving us
333b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                    the slop we need to draw consistently.
334b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed
335b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                    This constant is meant to resolve to 1/255 after it is
336b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                    scaled by 1.5 (applicationScale). Note, this is just a guess
337b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                    as to what is small enough not to create its own artifacts,
338b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                    and big enough to avoid the precision problems. Feel free
339b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                    to experiment with smaller values as you choose.
340b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                 */
341b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                final float tinyOffset = 2.0f / (3 * 255);
342b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed                canvas.translate(tinyOffset, tinyOffset);
343b5c17a64edbdac47d8aa48951b50ea0a8e982655Mike Reed            }
3441ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            canvas.scale(applicationScale, applicationScale);
34564f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
34664f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
34764f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        /**
34864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * Translate the motion event captured on screen to the application's window.
34964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         */
35064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        public void translateEventInScreenToAppWindow(MotionEvent event) {
3511ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            event.scale(applicationInvertedScale);
35264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
35364f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
35464f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        /**
35564f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * Translate the window's layout parameter, from application's view to
35664f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * Screen's view.
35764f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         */
35864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        public void translateWindowLayout(WindowManager.LayoutParams params) {
3591ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            params.scale(applicationScale);
36064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
36164f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
36264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        /**
36364f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * Translate a Rect in application's window to screen.
36464f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         */
36564f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        public void translateRectInAppWindowToScreen(Rect rect) {
3661ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            rect.scale(applicationScale);
36764f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
36864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
36964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        /**
37064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * Translate a Rect in screen coordinates into the app window's coordinates.
37164f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         */
37264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        public void translateRectInScreenToAppWindow(Rect rect) {
3731ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            rect.scale(applicationInvertedScale);
37464f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
37564f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
37664f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        /**
377a53146c5569f8ff5f7eb55e9ad35d23ddacf2addChristopher Tate         * Translate a Point in screen coordinates into the app window's coordinates.
378a53146c5569f8ff5f7eb55e9ad35d23ddacf2addChristopher Tate         */
379a53146c5569f8ff5f7eb55e9ad35d23ddacf2addChristopher Tate        public void translatePointInScreenToAppWindow(PointF point) {
380a53146c5569f8ff5f7eb55e9ad35d23ddacf2addChristopher Tate            final float scale = applicationInvertedScale;
381a53146c5569f8ff5f7eb55e9ad35d23ddacf2addChristopher Tate            if (scale != 1.0f) {
382a53146c5569f8ff5f7eb55e9ad35d23ddacf2addChristopher Tate                point.x *= scale;
383a53146c5569f8ff5f7eb55e9ad35d23ddacf2addChristopher Tate                point.y *= scale;
384a53146c5569f8ff5f7eb55e9ad35d23ddacf2addChristopher Tate            }
385a53146c5569f8ff5f7eb55e9ad35d23ddacf2addChristopher Tate        }
386a53146c5569f8ff5f7eb55e9ad35d23ddacf2addChristopher Tate
387a53146c5569f8ff5f7eb55e9ad35d23ddacf2addChristopher Tate        /**
38864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * Translate the location of the sub window.
38964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * @param params
39064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         */
39164f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        public void translateLayoutParamsInAppWindowToScreen(LayoutParams params) {
3921ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            params.scale(applicationScale);
39364f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
39464f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
39564f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        /**
39664f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * Translate the content insets in application window to Screen. This uses
39764f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * the internal buffer for content insets to avoid extra object allocation.
39864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         */
39964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        public Rect getTranslatedContentInsets(Rect contentInsets) {
40064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima            if (mContentInsetsBuffer == null) mContentInsetsBuffer = new Rect();
40164f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima            mContentInsetsBuffer.set(contentInsets);
40264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima            translateRectInAppWindowToScreen(mContentInsetsBuffer);
40364f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima            return mContentInsetsBuffer;
40464f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
40564f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima
40664f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        /**
40764f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         * Translate the visible insets in application window to Screen. This uses
408fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * the internal buffer for visible insets to avoid extra object allocation.
40964f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima         */
410fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        public Rect getTranslatedVisibleInsets(Rect visibleInsets) {
4111ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            if (mVisibleInsetsBuffer == null) mVisibleInsetsBuffer = new Rect();
4121ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            mVisibleInsetsBuffer.set(visibleInsets);
4131ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            translateRectInAppWindowToScreen(mVisibleInsetsBuffer);
4141ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima            return mVisibleInsetsBuffer;
4151ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima        }
416fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown
417fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        /**
418fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * Translate the touchable area in application window to Screen. This uses
419fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * the internal buffer for touchable area to avoid extra object allocation.
420fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         */
421fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        public Region getTranslatedTouchableArea(Region touchableArea) {
422fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown            if (mTouchableAreaBuffer == null) mTouchableAreaBuffer = new Region();
423fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown            mTouchableAreaBuffer.set(touchableArea);
424fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown            mTouchableAreaBuffer.scale(applicationScale);
425fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown            return mTouchableAreaBuffer;
426fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        }
4271ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima    }
4281ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima
429e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    public void applyToDisplayMetrics(DisplayMetrics inoutDm) {
430e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        if (!supportsScreen()) {
431e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            // This is a larger screen device and the app is not
432e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            // compatible with large screens, so diddle it.
4332f0b17573d4324832f7a20402a3d2b5920bc4866Dianne Hackborn            CompatibilityInfo.computeCompatibleScaling(inoutDm, inoutDm);
4345be8de3420ba4c9d816b98e29bdec11715f6b626Dianne Hackborn        } else {
4352b31d53161789358de57fd396716a6503855c5daDianne Hackborn            inoutDm.widthPixels = inoutDm.noncompatWidthPixels;
4362b31d53161789358de57fd396716a6503855c5daDianne Hackborn            inoutDm.heightPixels = inoutDm.noncompatHeightPixels;
437e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
438e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
439e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        if (isScalingRequired()) {
440e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            float invertedRatio = applicationInvertedScale;
4412b31d53161789358de57fd396716a6503855c5daDianne Hackborn            inoutDm.density = inoutDm.noncompatDensity * invertedRatio;
442908aecc3a63c5520d5b11da14a9383f885b7d126Dianne Hackborn            inoutDm.densityDpi = (int)((inoutDm.noncompatDensityDpi * invertedRatio) + .5f);
4432b31d53161789358de57fd396716a6503855c5daDianne Hackborn            inoutDm.scaledDensity = inoutDm.noncompatScaledDensity * invertedRatio;
4442b31d53161789358de57fd396716a6503855c5daDianne Hackborn            inoutDm.xdpi = inoutDm.noncompatXdpi * invertedRatio;
4452b31d53161789358de57fd396716a6503855c5daDianne Hackborn            inoutDm.ydpi = inoutDm.noncompatYdpi * invertedRatio;
446e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            inoutDm.widthPixels = (int) (inoutDm.widthPixels * invertedRatio + 0.5f);
447e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            inoutDm.heightPixels = (int) (inoutDm.heightPixels * invertedRatio + 0.5f);
448e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
449e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    }
450e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
451908aecc3a63c5520d5b11da14a9383f885b7d126Dianne Hackborn    public void applyToConfiguration(int displayDensity, Configuration inoutConfig) {
452e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        if (!supportsScreen()) {
453e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            // This is a larger screen device and the app is not
454e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            // compatible with large screens, so we are forcing it to
455e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            // run as if the screen is normal size.
456e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            inoutConfig.screenLayout =
457e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn                    (inoutConfig.screenLayout&~Configuration.SCREENLAYOUT_SIZE_MASK)
458e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn                    | Configuration.SCREENLAYOUT_SIZE_NORMAL;
4595fd2169eabd77e6bfafaf456e58051a3bafb2bcaDianne Hackborn            inoutConfig.screenWidthDp = inoutConfig.compatScreenWidthDp;
4605fd2169eabd77e6bfafaf456e58051a3bafb2bcaDianne Hackborn            inoutConfig.screenHeightDp = inoutConfig.compatScreenHeightDp;
4615fd2169eabd77e6bfafaf456e58051a3bafb2bcaDianne Hackborn            inoutConfig.smallestScreenWidthDp = inoutConfig.compatSmallestScreenWidthDp;
462e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
463908aecc3a63c5520d5b11da14a9383f885b7d126Dianne Hackborn        inoutConfig.densityDpi = displayDensity;
464908aecc3a63c5520d5b11da14a9383f885b7d126Dianne Hackborn        if (isScalingRequired()) {
465908aecc3a63c5520d5b11da14a9383f885b7d126Dianne Hackborn            float invertedRatio = applicationInvertedScale;
466908aecc3a63c5520d5b11da14a9383f885b7d126Dianne Hackborn            inoutConfig.densityDpi = (int)((inoutConfig.densityDpi * invertedRatio) + .5f);
467908aecc3a63c5520d5b11da14a9383f885b7d126Dianne Hackborn        }
468e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    }
469e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
4701ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima    /**
471e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn     * Compute the frame Rect for applications runs under compatibility mode.
4721ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima     *
4731ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima     * @param dm the display metrics used to compute the frame size.
47448d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner     * @param outDm If non-null the width and height will be set to their scaled values.
475e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn     * @return Returns the scaling factor for the window.
4761ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima     */
4772f0b17573d4324832f7a20402a3d2b5920bc4866Dianne Hackborn    public static float computeCompatibleScaling(DisplayMetrics dm, DisplayMetrics outDm) {
4782b31d53161789358de57fd396716a6503855c5daDianne Hackborn        final int width = dm.noncompatWidthPixels;
4792b31d53161789358de57fd396716a6503855c5daDianne Hackborn        final int height = dm.noncompatHeightPixels;
480e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        int shortSize, longSize;
481e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        if (width < height) {
482e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            shortSize = width;
483e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            longSize = height;
484e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        } else {
485e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            shortSize = height;
486e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            longSize = width;
487e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
488e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        int newShortSize = (int)(DEFAULT_NORMAL_SHORT_DIMENSION * dm.density + 0.5f);
489e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        float aspect = ((float)longSize) / shortSize;
490e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        if (aspect > MAXIMUM_ASPECT_RATIO) {
491e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            aspect = MAXIMUM_ASPECT_RATIO;
492e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
493e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        int newLongSize = (int)(newShortSize * aspect + 0.5f);
494e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        int newWidth, newHeight;
495e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        if (width < height) {
496e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            newWidth = newShortSize;
497e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            newHeight = newLongSize;
4981ecf5d28817f0a051e77488380dcd5bc622ea169Mitsuru Oshima        } else {
499e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            newWidth = newLongSize;
500e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            newHeight = newShortSize;
501e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
502e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
503e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        float sw = width/(float)newWidth;
504e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        float sh = height/(float)newHeight;
505e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        float scale = sw < sh ? sw : sh;
506e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        if (scale < 1) {
507e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            scale = 1;
50864f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima        }
509e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
510e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        if (outDm != null) {
511e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            outDm.widthPixels = newWidth;
512e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            outDm.heightPixels = newHeight;
513e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
514e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
515e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        return scale;
516e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    }
517e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
518e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    @Override
519e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    public boolean equals(Object o) {
52048d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner        if (this == o) {
52148d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner            return true;
52248d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner        }
523e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        try {
524e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            CompatibilityInfo oc = (CompatibilityInfo)o;
525e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            if (mCompatibilityFlags != oc.mCompatibilityFlags) return false;
526e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            if (applicationDensity != oc.applicationDensity) return false;
527e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            if (applicationScale != oc.applicationScale) return false;
528e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            if (applicationInvertedScale != oc.applicationInvertedScale) return false;
529e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            return true;
530e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        } catch (ClassCastException e) {
531e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            return false;
532e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
533e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    }
534e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
535e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    @Override
5368ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn    public String toString() {
5378ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        StringBuilder sb = new StringBuilder(128);
5388ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        sb.append("{");
5398ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        sb.append(applicationDensity);
5408ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        sb.append("dpi");
5418ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        if (isScalingRequired()) {
5422b31d53161789358de57fd396716a6503855c5daDianne Hackborn            sb.append(" ");
5432b31d53161789358de57fd396716a6503855c5daDianne Hackborn            sb.append(applicationScale);
5442b31d53161789358de57fd396716a6503855c5daDianne Hackborn            sb.append("x");
5458ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        }
5468ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        if (!supportsScreen()) {
5478ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            sb.append(" resizing");
5488ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        }
5498ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        if (neverSupportsScreen()) {
5508ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            sb.append(" never-compat");
5518ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        }
5528ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        if (alwaysSupportsScreen()) {
5538ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn            sb.append(" always-compat");
5548ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        }
5558ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        sb.append("}");
5568ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn        return sb.toString();
5578ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn    }
5588ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn
5598ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn    @Override
560e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    public int hashCode() {
561e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        int result = 17;
562e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        result = 31 * result + mCompatibilityFlags;
563e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        result = 31 * result + applicationDensity;
564e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        result = 31 * result + Float.floatToIntBits(applicationScale);
565e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        result = 31 * result + Float.floatToIntBits(applicationInvertedScale);
566e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        return result;
567e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    }
568e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
569e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    @Override
570e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    public int describeContents() {
571e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        return 0;
572e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    }
573e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
574e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    @Override
575e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    public void writeToParcel(Parcel dest, int flags) {
576e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        dest.writeInt(mCompatibilityFlags);
577e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        dest.writeInt(applicationDensity);
578e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        dest.writeFloat(applicationScale);
579e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        dest.writeFloat(applicationInvertedScale);
580e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    }
581e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
582e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    public static final Parcelable.Creator<CompatibilityInfo> CREATOR
583e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            = new Parcelable.Creator<CompatibilityInfo>() {
58448d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner        @Override
585e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        public CompatibilityInfo createFromParcel(Parcel source) {
586e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            return new CompatibilityInfo(source);
587e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
588e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
58948d0d1886731ff19ed3fb47a5997be5df0d1bba8Craig Mautner        @Override
590e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        public CompatibilityInfo[] newArray(int size) {
591e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn            return new CompatibilityInfo[size];
592e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        }
593e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    };
594e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
595e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    private CompatibilityInfo(Parcel source) {
596e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        mCompatibilityFlags = source.readInt();
597e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        applicationDensity = source.readInt();
598e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        applicationScale = source.readFloat();
599e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        applicationInvertedScale = source.readFloat();
6009189cabb0b6c6c28232fe6f412b7ba7a37352a6aMitsuru Oshima    }
601569076c9f6bdadb4d3285a26e069634a839b5b87Mitsuru Oshima}
602