diff options
| author | Mitsuru Oshima <oshima@google.com> | 2009-06-03 11:19:12 -0700 | 
|---|---|---|
| committer | Mitsuru Oshima <oshima@google.com> | 2009-06-03 16:28:10 -0700 | 
| commit | 9189cabb0b6c6c28232fe6f412b7ba7a37352a6a (patch) | |
| tree | 6ddc6a8eb0158cba32cc6139b04c6b6eb9f0ba5f /core/java | |
| parent | eaeb663bcd7a82b654954b42663232cbd7bef7e7 (diff) | |
| download | frameworks_base-9189cabb0b6c6c28232fe6f412b7ba7a37352a6a.zip frameworks_base-9189cabb0b6c6c28232fe6f412b7ba7a37352a6a.tar.gz frameworks_base-9189cabb0b6c6c28232fe6f412b7ba7a37352a6a.tar.bz2 | |
* Moved supports-density tag under manifest
* Refactored Compatibility code
  * Added CompatibilityInfo class
  * Removed getApplicationScale from Context
  * Added Resources#getCompatibilityInfo so that RootView can get the compatibility info w/o going through Context
* Expandable support
  * Added expandable tag under manifest
  * Old application w/o expandable is given the default screen size  ([320, 480] x density).
  * The non-expandable window is centered.
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/app/ActivityThread.java | 79 | ||||
| -rw-r--r-- | core/java/android/app/ApplicationContext.java | 16 | ||||
| -rw-r--r-- | core/java/android/content/Context.java | 10 | ||||
| -rw-r--r-- | core/java/android/content/ContextWrapper.java | 8 | ||||
| -rw-r--r-- | core/java/android/content/pm/ApplicationInfo.java | 11 | ||||
| -rw-r--r-- | core/java/android/content/pm/PackageManager.java | 6 | ||||
| -rw-r--r-- | core/java/android/content/pm/PackageParser.java | 49 | ||||
| -rw-r--r-- | core/java/android/content/res/CompatibilityInfo.java | 102 | ||||
| -rw-r--r-- | core/java/android/content/res/Resources.java | 44 | ||||
| -rw-r--r-- | core/java/android/util/DisplayMetrics.java | 51 | ||||
| -rw-r--r-- | core/java/android/view/SurfaceView.java | 66 | ||||
| -rw-r--r-- | core/java/android/view/ViewRoot.java | 166 | 
12 files changed, 381 insertions, 227 deletions
| diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 29e57cd..d08fc11 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -162,7 +162,7 @@ public final class ActivityThread {          return metrics;      } -    Resources getTopLevelResources(String appDir, float applicationScale) { +    Resources getTopLevelResources(String appDir, PackageInfo pkgInfo) {          synchronized (mPackages) {              //Log.w(TAG, "getTopLevelResources: " + appDir);              WeakReference<Resources> wr = mActiveResources.get(appDir); @@ -181,23 +181,17 @@ public final class ActivityThread {              if (assets.addAssetPath(appDir) == 0) {                  return null;              } -            DisplayMetrics metrics = getDisplayMetricsLocked(false); -            // density used to load resources -            // scaledDensity is calculated in Resources constructor -            // -            boolean usePreloaded = true; - -            // TODO: use explicit flag to indicate the compatibility mode. -            if (applicationScale != 1.0f) { -                usePreloaded = false; -                DisplayMetrics newMetrics = new DisplayMetrics(); -                newMetrics.setTo(metrics); -                float newDensity = metrics.density / applicationScale; -                newMetrics.updateDensity(newDensity); -                metrics = newMetrics; +            ApplicationInfo appInfo; +            try { +                appInfo = getPackageManager().getApplicationInfo( +                        pkgInfo.getPackageName(), +                        PackageManager.GET_SUPPORTS_DENSITIES | PackageManager.GET_EXPANDABLE); +            } catch (RemoteException e) { +                throw new AssertionError(e);              }              //Log.i(TAG, "Resource:" + appDir + ", display metrics=" + metrics); -            r = new Resources(assets, metrics, getConfiguration(), usePreloaded); +            DisplayMetrics metrics = getDisplayMetricsLocked(false); +            r = new Resources(assets, metrics, getConfiguration(), appInfo);              //Log.i(TAG, "Created app resources " + r + ": " + r.getConfiguration());              // XXX need to remove entries when weak references go away              mActiveResources.put(appDir, new WeakReference<Resources>(r)); @@ -225,7 +219,6 @@ public final class ActivityThread {          private Resources mResources;          private ClassLoader mClassLoader;          private Application mApplication; -        private float mApplicationScale;          private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers              = new HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>>(); @@ -268,8 +261,6 @@ public final class ActivityThread {                  mClassLoader = mSystemContext.getClassLoader();                  mResources = mSystemContext.getResources();              } - -            mApplicationScale = -1.0f;          }          public PackageInfo(ActivityThread activityThread, String name, @@ -288,7 +279,6 @@ public final class ActivityThread {              mIncludeCode = true;              mClassLoader = systemContext.getClassLoader();              mResources = systemContext.getResources(); -            mApplicationScale = systemContext.getApplicationScale();          }          public String getPackageName() { @@ -299,45 +289,6 @@ public final class ActivityThread {              return mSecurityViolation;          } -        public float getApplicationScale() { -            if (mApplicationScale > 0.0f) { -                return mApplicationScale; -            } -            DisplayMetrics metrics = mActivityThread.getDisplayMetricsLocked(false); -            // Find out the density scale (relative to 160) of the supported density  that -            // is closest to the system's density. -            try { -                ApplicationInfo ai = getPackageManager().getApplicationInfo( -                        mPackageName, PackageManager.GET_SUPPORTS_DENSITIES); - -                float appScale = -1.0f; -                if (ai.supportsDensities != null) { -                    int minDiff = Integer.MAX_VALUE; -                    for (int density : ai.supportsDensities) { -                        int tmpDiff = (int) Math.abs(DisplayMetrics.DEVICE_DENSITY - density); -                        if (tmpDiff == 0) { -                            appScale = 1.0f; -                            break; -                        } -                        // prefer higher density (appScale>1.0), unless that's only option. -                        if (tmpDiff < minDiff && appScale < 1.0f) { -                            appScale = DisplayMetrics.DEVICE_DENSITY / density; -                            minDiff = tmpDiff; -                        } -                    } -                } -                if (appScale < 0.0f) { -                    mApplicationScale = metrics.density; -                } else { -                    mApplicationScale = appScale; -                } -            } catch (RemoteException e) { -                throw new AssertionError(e); -            } -            if (localLOGV) Log.v(TAG, "appScale=" + mApplicationScale + ", pkg=" + mPackageName); -            return mApplicationScale; -        } -          /**           * Gets the array of shared libraries that are listed as           * used by the given package. @@ -495,7 +446,7 @@ public final class ActivityThread {          public Resources getResources(ActivityThread mainThread) {              if (mResources == null) { -                mResources = mainThread.getTopLevelResources(mResDir, getApplicationScale()); +                mResources = mainThread.getTopLevelResources(mResDir, this);              }              return mResources;          } @@ -3606,8 +3557,6 @@ public final class ActivityThread {              }              mConfiguration.updateFrom(config);              DisplayMetrics dm = getDisplayMetricsLocked(true); -            DisplayMetrics appDm = new DisplayMetrics(); -            appDm.setTo(dm);              // set it for java, this also affects newly created Resources              if (config.locale != null) { @@ -3627,11 +3576,7 @@ public final class ActivityThread {                      WeakReference<Resources> v = it.next();                      Resources r = v.get();                      if (r != null) { -                        // keep the original density based on application cale. -                        appDm.updateDensity(r.getDisplayMetrics().density); -                        r.updateConfiguration(config, appDm); -                        // reset -                        appDm.setTo(dm); +                        r.updateConfiguration(config, dm);                          //Log.i(TAG, "Updated app resources " + v.getKey()                          //        + " " + r + ": " + r.getConfiguration());                      } else { diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java index 2d6381a..98bbf7b 100644 --- a/core/java/android/app/ApplicationContext.java +++ b/core/java/android/app/ApplicationContext.java @@ -551,19 +551,6 @@ class ApplicationContext extends Context {          }      } -    /** -     * @hide -     */ -    @Override -    public float getApplicationScale() { -        if (mPackageInfo != null) { -            return mPackageInfo.getApplicationScale(); -        } else { -            // same as system density -            return 1.0f; -        } -    } -      @Override      public void setWallpaper(Bitmap bitmap) throws IOException  {          try { @@ -2028,8 +2015,7 @@ class ApplicationContext extends Context {              ActivityThread.PackageInfo pi = mContext.mMainThread.getPackageInfoNoCheck(app);              Resources r = mContext.mMainThread.getTopLevelResources(                      app.uid == Process.myUid() ? app.sourceDir -                    : app.publicSourceDir, -                    pi.getApplicationScale()); +                    : app.publicSourceDir, pi);              if (r != null) {                  return r;              } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index c328d16..ec847a4 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -527,16 +527,6 @@ public abstract class Context {      public abstract int getWallpaperDesiredMinimumHeight();      /** -     * Returns the scale in which the application will be drawn on the -     * screen. This is usually 1.0f if the application supports the device's -     * resolution/density. This will be 1.5f, for example, if the application -     * that supports only 160 density runs on 240 density screen. -     * -     * @hide -     */ -    public abstract float getApplicationScale(); - -    /**       * Change the current system wallpaper to a bitmap.  The given bitmap is       * converted to a PNG and stored as the wallpaper.  On success, the intent       * {@link Intent#ACTION_WALLPAPER_CHANGED} is broadcast. diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index 25b2cae..36e1c34 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -419,12 +419,4 @@ public class ContextWrapper extends Context {          throws PackageManager.NameNotFoundException {          return mBase.createPackageContext(packageName, flags);      } - -    /** -     * @hide -     */ -    @Override -    public float getApplicationScale() { -        return mBase.getApplicationScale(); -    }  } diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index f16eb74..f3dfc5a 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -186,7 +186,6 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {       */      public int uid; -      /**       * The list of densities in DPI that application supprots. This       * field is only set if the {@link PackageManager#GET_SUPPORTS_DENSITIES} flag was @@ -195,6 +194,12 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {      public int[] supportsDensities;      /** +     * True when the application's window can be expanded over default window +     * size in target density (320x480 for 1.0 density, 480x720 for 1.5 density etc) +     */ +    public boolean expandable = false; + +    /**       * The minimum SDK version this application targets.  It may run on earilier       * versions, but it knows how to work with any new behavior added at this       * version.  Will be {@link android.os.Build.VERSION_CODES#CUR_DEVELOPMENT} @@ -228,6 +233,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {          pw.println(prefix + "manageSpaceActivityName="+manageSpaceActivityName);          pw.println(prefix + "description=0x"+Integer.toHexString(descriptionRes));          pw.println(prefix + "supportsDensities=" + supportsDensities); +        pw.println(prefix + "expandable=" + expandable);          super.dumpBack(pw, prefix);      } @@ -275,6 +281,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {          manageSpaceActivityName = orig.manageSpaceActivityName;          descriptionRes = orig.descriptionRes;          supportsDensities = orig.supportsDensities; +        expandable = orig.expandable;      } @@ -307,6 +314,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {          dest.writeString(backupAgentName);          dest.writeInt(descriptionRes);          dest.writeIntArray(supportsDensities); +        dest.writeInt(expandable ? 1 : 0);      }      public static final Parcelable.Creator<ApplicationInfo> CREATOR @@ -338,6 +346,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {          backupAgentName = source.readString();          descriptionRes = source.readInt();          supportsDensities = source.createIntArray(); +        expandable = source.readInt() != 0;      }      /** diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index a2c82e8..6578391 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -180,6 +180,12 @@ public abstract class PackageManager {      public static final int MATCH_DEFAULT_ONLY   = 0x00010000;      /** +     * {@link ApplicationInfo} flag: return the +     * {link ApplicationInfo#expandable} boolean flag of the package. +     */ +    public static final int GET_EXPANDABLE = 0x00020000; + +    /**       * Permission check result: this is returned by {@link #checkPermission}       * if the permission has been granted to the given package.       */ diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 212b590..e2c0fe6 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -835,6 +835,26 @@ public class PackageParser {                      + parser.getName();                  mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;                  return null; + + +            } else if (tagName.equals("supports-density")) { +                sa = res.obtainAttributes(attrs, +                        com.android.internal.R.styleable.AndroidManifestSupportsDensity); + +                int density = sa.getInteger( +                        com.android.internal.R.styleable.AndroidManifestSupportsDensity_density, -1); + +                sa.recycle(); + +                if (density != -1 && !pkg.supportsDensityList.contains(density)) { +                    pkg.supportsDensityList.add(density); +                } + +                XmlUtils.skipCurrentTag(parser); + +            } else if (tagName.equals("expandable")) { +                pkg.expandable = true; +                XmlUtils.skipCurrentTag(parser);              } else {                  Log.w(TAG, "Bad element under <manifest>: "                        + parser.getName()); @@ -866,7 +886,8 @@ public class PackageParser {              pkg.usesLibraryFiles = new String[pkg.usesLibraries.size()];              pkg.usesLibraries.toArray(pkg.usesLibraryFiles);          } - +        // TODO: enable all density & expandable if target sdk is higher than donut  +                  int size = pkg.supportsDensityList.size();          if (size > 0) {              int densities[] = pkg.supportsDensities = new int[size]; @@ -1345,21 +1366,6 @@ public class PackageParser {                  XmlUtils.skipCurrentTag(parser); -            } else if (tagName.equals("supports-density")) { -                sa = res.obtainAttributes(attrs, -                        com.android.internal.R.styleable.AndroidManifestSupportsDensity); - -                int density = sa.getInteger( -                        com.android.internal.R.styleable.AndroidManifestSupportsDensity_density, -1); - -                sa.recycle(); - -                if (density != -1 && !owner.supportsDensityList.contains(density)) { -                    owner.supportsDensityList.add(density); -                } - -                XmlUtils.skipCurrentTag(parser); -              } else {                  if (!RIGID_PARSER) {                      Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); @@ -2244,6 +2250,9 @@ public class PackageParser {          public final ArrayList<Integer> supportsDensityList = new ArrayList<Integer>();          public int[] supportsDensities = null; +        // If the application's window is expandable. +        public boolean expandable; +                  // If this is a 3rd party app, this is the path of the zip file.          public String mPath; @@ -2415,7 +2424,10 @@ public class PackageParser {              return true;          }          if ((flags & PackageManager.GET_SUPPORTS_DENSITIES) != 0 -            && p.supportsDensities != null) { +                && p.supportsDensities != null) { +            return true; +        } +        if ((flags & PackageManager.GET_EXPANDABLE) != 0) {              return true;          }          return false; @@ -2438,6 +2450,9 @@ public class PackageParser {          if ((flags & PackageManager.GET_SUPPORTS_DENSITIES) != 0) {              ai.supportsDensities = p.supportsDensities;          } +        if ((flags & PackageManager.GET_EXPANDABLE) != 0) { +            ai.expandable = p.expandable; +        }          return ai;      } diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java new file mode 100644 index 0000000..8a6a6f0 --- /dev/null +++ b/core/java/android/content/res/CompatibilityInfo.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.content.res; + +import android.content.pm.ApplicationInfo; +import android.util.DisplayMetrics; +import android.view.Gravity; + +/** + * CompatibilityInfo class keeps the information about compatibility mode that the application is + * running under. + *  + *  {@hide}  + */ +public class CompatibilityInfo { +    /** default compatibility info object for compatible applications */ +    public static final CompatibilityInfo DEFAULT_COMPATIBILITY_INFO = new CompatibilityInfo();  + +    /** +     * The default width of the screen in portrait mode.  +     */ +    public static final int DEFAULT_PORTRAIT_WIDTH = 320; + +    /** +     * The default height of the screen in portrait mode.  +     */     +    public static final int DEFAULT_PORTRAIT_HEIGHT = 480; + +    /** +     * Application's scale. +     */ +    public final float mApplicationScale; + +    /** +     * Application's inverted scale. +     */ +    public final float mApplicationInvertedScale; +     +    /** +     *  +     * A boolean flag to indicates that the application can expand over the original size. +     */ +    public final boolean mExpandable; +     +    /** +     * A boolean flag to tell if the application needs scaling (when mApplicationScale != 1.0f) +     */ +    public final boolean mScalingRequired; + +    public CompatibilityInfo(ApplicationInfo appInfo) { +        mExpandable = appInfo.expandable; +        float packageDensityScale = -1.0f; +        if (appInfo.supportsDensities != null) { +            int minDiff = Integer.MAX_VALUE; +            for (int density : appInfo.supportsDensities) { +                int tmpDiff = Math.abs(DisplayMetrics.DEVICE_DENSITY - density); +                if (tmpDiff == 0) { +                    packageDensityScale = 1.0f; +                    break; +                } +                // prefer higher density (appScale>1.0), unless that's only option. +                if (tmpDiff < minDiff && packageDensityScale < 1.0f) { +                    packageDensityScale = DisplayMetrics.DEVICE_DENSITY / (float) density; +                    minDiff = tmpDiff; +                } +            } +        } +        if (packageDensityScale > 0.0f) { +            mApplicationScale = packageDensityScale; +        } else { +            mApplicationScale = DisplayMetrics.DEVICE_DENSITY / (float) DisplayMetrics.DEFAULT_DENSITY; +        } +        mApplicationInvertedScale = 1.0f / mApplicationScale; +        mScalingRequired = mApplicationScale != 1.0f; +    } + +    private CompatibilityInfo() { +        mApplicationScale = mApplicationInvertedScale = 1.0f; +        mExpandable = true; +        mScalingRequired = false; +    } + +    @Override +    public String toString() { +        return "CompatibilityInfo{scale=" + mApplicationScale + +                ", expandable=" + mExpandable + "}";  +    } +} diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 665e40c..976b618 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -22,6 +22,8 @@ import com.android.internal.util.XmlUtils;  import org.xmlpull.v1.XmlPullParser;  import org.xmlpull.v1.XmlPullParserException; +import android.app.ActivityThread.PackageInfo; +import android.content.pm.ApplicationInfo;  import android.graphics.Movie;  import android.graphics.drawable.Drawable;  import android.graphics.drawable.BitmapDrawable; @@ -84,7 +86,9 @@ public class Resources {      private final Configuration mConfiguration = new Configuration();      /*package*/ final DisplayMetrics mMetrics = new DisplayMetrics();      PluralRules mPluralRule; - +     +    private final CompatibilityInfo mCompatibilityInfo; +          private static final SparseArray<Object> EMPTY_ARRAY = new SparseArray<Object>() {          @Override          public void put(int k, Object o) { @@ -126,23 +130,36 @@ public class Resources {       */      public Resources(AssetManager assets, DisplayMetrics metrics,              Configuration config) { -        this(assets, metrics, config, true); +        this(assets, metrics, config, null);      }      /** -     * Create a resource with an additional flag for preloaded -     * drawable cache. Used by {@link ActivityThread}. -     * +     * Creates a new Resources object with ApplicationInfo. +     *  +     * @param assets Previously created AssetManager.  +     * @param metrics Current display metrics to consider when  +     *                selecting/computing resource values. +     * @param config Desired device configuration to consider when  +     *               selecting/computing resource values (optional). +     * @param appInfo this resource's application info.       * @hide       */      public Resources(AssetManager assets, DisplayMetrics metrics, -        Configuration config, boolean usePreloadedCache) { +            Configuration config, ApplicationInfo appInfo) {          mAssets = assets;          mConfiguration.setToDefaults();          mMetrics.setToDefaults(); +        if (appInfo != null) { +            mCompatibilityInfo = new CompatibilityInfo(appInfo); +            if (DEBUG_CONFIG) { +                Log.d(TAG, "compatibility for " + appInfo.packageName + " : " + mCompatibilityInfo); +            } +        } else { +            mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO; +        }          updateConfiguration(config, metrics);          assets.ensureStringBlocks(); -        if (usePreloadedCache) { +        if (!mCompatibilityInfo.mScalingRequired) {              mPreloadedDrawables = sPreloadedDrawables;          } else {              mPreloadedDrawables = emptySparseArray(); @@ -1251,6 +1268,7 @@ public class Resources {              }              if (metrics != null) {                  mMetrics.setTo(metrics); +                mMetrics.updateMetrics(mCompatibilityInfo, mConfiguration);              }              mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale; @@ -1356,6 +1374,17 @@ public class Resources {      public Configuration getConfiguration() {          return mConfiguration;      } +     +    /** +     * Return the compatibility mode information for the application. +     * The returned object should be treated as read-only. +     *  +     * @return compatibility info. null if the app does not require compatibility mode. +     * @hide +     */ +    public CompatibilityInfo getCompatibilityInfo() { +        return mCompatibilityInfo; +    }      /**       * Return a resource identifier for the given resource name.  A fully @@ -1920,5 +1949,6 @@ public class Resources {          updateConfiguration(null, null);          mAssets.ensureStringBlocks();          mPreloadedDrawables = sPreloadedDrawables; +        mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;      }  } diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java index e4dd020..987be2b 100644 --- a/core/java/android/util/DisplayMetrics.java +++ b/core/java/android/util/DisplayMetrics.java @@ -16,6 +16,8 @@  package android.util; +import android.content.res.CompatibilityInfo; +import android.content.res.Configuration;  import android.os.*; @@ -101,17 +103,46 @@ public class DisplayMetrics {      }      /** -     * Set the display metrics' density and update parameters depend on it. -     * @hide +     * Update the display metrics based on the compatibility info and configuration. +     * {@hide}       */ -    public void updateDensity(float newDensity) { -        float ratio = newDensity / density; -        density = newDensity; -        scaledDensity = density; -        widthPixels *= ratio; -        heightPixels *= ratio; -        xdpi *= ratio; -        ydpi *= ratio; +    public void updateMetrics(CompatibilityInfo compatibilityInfo, Configuration configuration) { +        if (compatibilityInfo.mScalingRequired) { +            float invertedRatio = compatibilityInfo.mApplicationInvertedScale; +            density *= invertedRatio; +            scaledDensity *= invertedRatio; +            xdpi *= invertedRatio; +            ydpi *= invertedRatio; +            widthPixels *= invertedRatio; +            heightPixels *= invertedRatio; +        } +        if (!compatibilityInfo.mExpandable) { +            // Note: this assume that configuration is updated before calling +            // updateMetrics method. +            int defaultWidth; +            int defaultHeight; +            switch (configuration.orientation) { +                case Configuration.ORIENTATION_LANDSCAPE: { +                    defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density); +                    defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density); +                    break; +                } +                case Configuration.ORIENTATION_UNDEFINED: +                case Configuration.ORIENTATION_PORTRAIT: +                case Configuration.ORIENTATION_SQUARE: +                default: { +                    defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density); +                    defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density); +                } +            } +            // adjust the size only when the device's screen is bigger. +            if (defaultWidth < widthPixels) { +                widthPixels = defaultWidth; +            } +            if (defaultHeight < heightPixels) { +                heightPixels = defaultHeight; +            } +        }      }      public String toString() { diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 0dc2570..082cca2 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -17,6 +17,7 @@  package android.view;  import android.content.Context; +import android.content.res.CompatibilityInfo;  import android.graphics.Canvas;  import android.graphics.PixelFormat;  import android.graphics.PorterDuff; @@ -137,28 +138,24 @@ public class SurfaceView extends View {      int mFormat = -1;      int mType = -1;      final Rect mSurfaceFrame = new Rect(); -    private final float mAppScale; -    private final float mAppScaleInverted; +    private final CompatibilityInfo mCompatibilityInfo;      public SurfaceView(Context context) {          super(context);          setWillNotDraw(true); -        mAppScale = context.getApplicationScale(); -        mAppScaleInverted = 1.0f / mAppScale; +        mCompatibilityInfo = context.getResources().getCompatibilityInfo();      }      public SurfaceView(Context context, AttributeSet attrs) {          super(context, attrs);          setWillNotDraw(true); -        mAppScale = context.getApplicationScale(); -        mAppScaleInverted = 1.0f / mAppScale; +        mCompatibilityInfo = context.getResources().getCompatibilityInfo();      }      public SurfaceView(Context context, AttributeSet attrs, int defStyle) {          super(context, attrs, defStyle);          setWillNotDraw(true); -        mAppScale = context.getApplicationScale(); -        mAppScaleInverted = 1.0f / mAppScale; +        mCompatibilityInfo = context.getResources().getCompatibilityInfo();      }      /** @@ -261,9 +258,9 @@ public class SurfaceView extends View {      public boolean dispatchTouchEvent(MotionEvent event) {          // SurfaceView uses pre-scaled size unless fixed size is requested. This hook          // scales the event back to the pre-scaled coordinates for such surface. -        if (mRequestedWidth < 0 && mAppScale != 1.0f) { +        if (mRequestedWidth < 0 && mCompatibilityInfo.mScalingRequired) {              MotionEvent scaledBack = MotionEvent.obtain(event); -            scaledBack.scale(mAppScale); +            scaledBack.scale(mCompatibilityInfo.mApplicationScale);              try {                  return super.dispatchTouchEvent(scaledBack);              } finally { @@ -300,6 +297,7 @@ public class SurfaceView extends View {          if (!mHaveFrame) {              return;          } +        float appScale = mCompatibilityInfo.mApplicationScale;          int myWidth = mRequestedWidth;          if (myWidth <= 0) myWidth = getWidth(); @@ -307,9 +305,9 @@ public class SurfaceView extends View {          if (myHeight <= 0) myHeight = getHeight();          // Use original size for surface unless fixed size is requested. -        if (mRequestedWidth <= 0) { -            myWidth *= mAppScale; -            myHeight *= mAppScale; +        if (mRequestedWidth <= 0 && mCompatibilityInfo.mScalingRequired) { +            myWidth *= appScale; +            myHeight *= appScale;          }          getLocationInWindow(mLocation); @@ -337,11 +335,11 @@ public class SurfaceView extends View {                  mFormat = mRequestedFormat;                  mType = mRequestedType; -                // Scaling window's layout here beause mLayout is not used elsewhere. -                mLayout.x = (int) (mLeft * mAppScale); -                mLayout.y = (int) (mTop * mAppScale); -                mLayout.width = (int) (getWidth() * mAppScale); -                mLayout.height = (int) (getHeight() * mAppScale); +                // Scaling window's layout here because mLayout is not used elsewhere. +                mLayout.x = (int) (mLeft * appScale); +                mLayout.y = (int) (mTop * appScale); +                mLayout.width = (int) (getWidth() * appScale); +                mLayout.height = (int) (getHeight() * appScale);                  mLayout.format = mRequestedFormat;                  mLayout.flags |=WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS                                | WindowManager.LayoutParams.FLAG_SCALED @@ -367,14 +365,18 @@ public class SurfaceView extends View {                  mSurfaceLock.lock();                  mDrawingStopped = !visible; +                  final int relayoutResult = mSession.relayout(                      mWindow, mLayout, mWidth, mHeight,                          visible ? VISIBLE : GONE, false, mWinFrame, mContentInsets,                          mVisibleInsets, mSurface); -                mContentInsets.scale(mAppScaleInverted); -                mVisibleInsets.scale(mAppScaleInverted); -                mWinFrame.scale(mAppScaleInverted); +                if (mCompatibilityInfo.mScalingRequired) { +                    float invertedScale = mCompatibilityInfo.mApplicationInvertedScale; +                    mContentInsets.scale(invertedScale); +                    mVisibleInsets.scale(invertedScale); +                    mWinFrame.scale(invertedScale); +                }                  if (localLOGV) Log.i(TAG, "New surface: " + mSurface                          + ", vis=" + visible + ", frame=" + mWinFrame); @@ -444,23 +446,23 @@ public class SurfaceView extends View {      private static class MyWindow extends IWindow.Stub {          private final WeakReference<SurfaceView> mSurfaceView; -        private final float mAppScale; -        private final float mAppScaleInverted; +        private final CompatibilityInfo mCompatibilityInfo;          public MyWindow(SurfaceView surfaceView) {              mSurfaceView = new WeakReference<SurfaceView>(surfaceView); -            mAppScale = surfaceView.getContext().getApplicationScale(); -            mAppScaleInverted = 1.0f / mAppScale; +            mCompatibilityInfo = surfaceView.getContext().getResources().getCompatibilityInfo();          }          public void resized(int w, int h, Rect coveredInsets,                  Rect visibleInsets, boolean reportDraw) {              SurfaceView surfaceView = mSurfaceView.get(); -            float scale = mAppScaleInverted; -            w *= scale; -            h *= scale; -            coveredInsets.scale(scale); -            visibleInsets.scale(scale); +            if (mCompatibilityInfo.mScalingRequired) { +                float scale = mCompatibilityInfo.mApplicationInvertedScale; +                w *= scale; +                h *= scale; +                coveredInsets.scale(scale); +                visibleInsets.scale(scale); +            }              if (surfaceView != null) {                  if (localLOGV) Log.v( @@ -624,7 +626,9 @@ public class SurfaceView extends View {              Canvas c = null;              if (!mDrawingStopped && mWindow != null) {                  Rect frame = dirty != null ? dirty : mSurfaceFrame; -                frame.scale(mAppScale); +                if (mCompatibilityInfo.mScalingRequired) { +                    frame.scale(mCompatibilityInfo.mApplicationScale); +                }                  try {                      c = mSurface.lockCanvas(frame);                  } catch (Exception e) { diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index 7cd65e2..d8bab56 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -30,6 +30,7 @@ import android.os.Process;  import android.os.SystemProperties;  import android.util.AndroidRuntimeException;  import android.util.Config; +import android.util.DisplayMetrics;  import android.util.Log;  import android.util.EventLog;  import android.util.SparseArray; @@ -40,6 +41,7 @@ import android.view.inputmethod.InputConnection;  import android.view.inputmethod.InputMethodManager;  import android.widget.Scroller;  import android.content.pm.PackageManager; +import android.content.res.CompatibilityInfo;  import android.content.Context;  import android.app.ActivityManagerNative;  import android.Manifest; @@ -125,9 +127,8 @@ public final class ViewRoot extends Handler implements ViewParent,      int mHeight;      Rect mDirty; // will be a graphics.Region soon      boolean mIsAnimating; -    // TODO: change these to scalar class. -    private float mAppScale; -    private float mAppScaleInverted; // = 1.0f / mAppScale +     +    private CompatibilityInfo mCompatibilityInfo;      private int[] mWindowLayoutParamsBackup = null;      final View.AttachInfo mAttachInfo; @@ -386,12 +387,15 @@ public final class ViewRoot extends Handler implements ViewParent,          synchronized (this) {              if (mView == null) {                  mView = view; -                mAppScale = mView.getContext().getApplicationScale(); -                if (mAppScale != 1.0f) { +                mWindowAttributes.copyFrom(attrs); +                mCompatibilityInfo = +                        mView.getContext().getResources().getCompatibilityInfo(); +                if (mCompatibilityInfo.mScalingRequired) {                      mWindowLayoutParamsBackup = new int[4];                  } -                mAppScaleInverted = 1.0f / mAppScale; -                mWindowAttributes.copyFrom(attrs); +                if (!mCompatibilityInfo.mExpandable) { +                    adjustWindowAttributesForCompatibleMode(mWindowAttributes); +                }                  mSoftInputMode = attrs.softInputMode;                  mWindowAttributesChanged = true;                  mAttachInfo.mRootView = view; @@ -406,9 +410,8 @@ public final class ViewRoot extends Handler implements ViewParent,                  // manager, to make sure we do the relayout before receiving                  // any other events from the system.                  requestLayout(); -                  try { -                    res = sWindowSession.add(mWindow, attrs, +                    res = sWindowSession.add(mWindow, mWindowAttributes,                              getHostVisibility(), mAttachInfo.mContentInsets);                  } catch (RemoteException e) {                      mAdded = false; @@ -417,7 +420,10 @@ public final class ViewRoot extends Handler implements ViewParent,                      unscheduleTraversals();                      throw new RuntimeException("Adding window failed", e);                  } -                mAttachInfo.mContentInsets.scale(mAppScaleInverted); +                if (mCompatibilityInfo.mScalingRequired) { +                    mAttachInfo.mContentInsets.scale( +                            mCompatibilityInfo.mApplicationInvertedScale); +                }                  mPendingContentInsets.set(mAttachInfo.mContentInsets);                  mPendingVisibleInsets.set(0, 0, 0, 0);                  if (Config.LOGV) Log.v("ViewRoot", "Added window " + mWindow); @@ -529,13 +535,13 @@ public final class ViewRoot extends Handler implements ViewParent,      public void invalidateChild(View child, Rect dirty) {          checkThread();          if (LOCAL_LOGV) Log.v(TAG, "Invalidate child: " + dirty); -        if (mCurScrollY != 0 || mAppScale != 1.0f) { +        if (mCurScrollY != 0 || mCompatibilityInfo.mScalingRequired) {              mTempRect.set(dirty);              if (mCurScrollY != 0) {                 mTempRect.offset(0, -mCurScrollY);              } -            if (mAppScale != 1.0f) { -                mTempRect.scale(mAppScale); +            if (mCompatibilityInfo.mScalingRequired) { +                mTempRect.scale(mCompatibilityInfo.mApplicationScale);              }              dirty = mTempRect;          } @@ -615,6 +621,8 @@ public final class ViewRoot extends Handler implements ViewParent,          boolean viewVisibilityChanged = mViewVisibility != viewVisibility                  || mNewSurfaceNeeded; +        float appScale = mCompatibilityInfo.mApplicationScale; +          WindowManager.LayoutParams params = null;          if (mWindowAttributesChanged) {              mWindowAttributesChanged = false; @@ -625,9 +633,10 @@ public final class ViewRoot extends Handler implements ViewParent,              fullRedrawNeeded = true;              mLayoutRequested = true; -            Display d = new Display(0); -            desiredWindowWidth = (int) (d.getWidth() * mAppScaleInverted); -            desiredWindowHeight = (int) (d.getHeight() * mAppScaleInverted); +            DisplayMetrics packageMetrics =  +                mView.getContext().getResources().getDisplayMetrics(); +            desiredWindowWidth = packageMetrics.widthPixels; +            desiredWindowHeight = packageMetrics.heightPixels;              // For the very first time, tell the view hierarchy that it              // is attached to the window.  Note that at this point the surface @@ -696,9 +705,10 @@ public final class ViewRoot extends Handler implements ViewParent,                          || lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {                      windowResizesToFitContent = true; -                    Display d = new Display(0); -                    desiredWindowWidth = (int) (d.getWidth() * mAppScaleInverted); -                    desiredWindowHeight = (int) (d.getHeight() * mAppScaleInverted); +                    DisplayMetrics packageMetrics =  +                        mView.getContext().getResources().getDisplayMetrics(); +                    desiredWindowWidth = packageMetrics.widthPixels; +                    desiredWindowHeight = packageMetrics.heightPixels;                  }              } @@ -878,7 +888,7 @@ public final class ViewRoot extends Handler implements ViewParent,              mHeight = frame.height();              if (initialized) { -                mGlCanvas.setViewport((int) (mWidth * mAppScale), (int) (mHeight * mAppScale)); +                mGlCanvas.setViewport((int) (mWidth * appScale), (int) (mHeight * appScale));              }              boolean focusChangedDueToTouchMode = ensureTouchModeLocally( @@ -968,11 +978,7 @@ public final class ViewRoot extends Handler implements ViewParent,                          mTmpLocation[1] + host.mBottom - host.mTop);                  host.gatherTransparentRegion(mTransparentRegion); - -                // TODO: scale the region, like: -                // Region uses native methods. We probabl should have ScalableRegion class. - -                // Region does not have equals method ? +                mTransparentRegion.scale(appScale);                                  if (!mTransparentRegion.equals(mPreviousTransparentRegion)) {                      mPreviousTransparentRegion.set(mTransparentRegion);                      // reconfigure window manager @@ -983,7 +989,6 @@ public final class ViewRoot extends Handler implements ViewParent,                  }              } -              if (DBG) {                  System.out.println("======================================");                  System.out.println("performTraversals -- after setFrame"); @@ -1003,10 +1008,11 @@ public final class ViewRoot extends Handler implements ViewParent,              givenContent.left = givenContent.top = givenContent.right                      = givenContent.bottom = givenVisible.left = givenVisible.top                      = givenVisible.right = givenVisible.bottom = 0; -            insets.contentInsets.scale(mAppScale); -            insets.visibleInsets.scale(mAppScale); -              attachInfo.mTreeObserver.dispatchOnComputeInternalInsets(insets); +            if (mCompatibilityInfo.mScalingRequired) { +                insets.contentInsets.scale(appScale); +                insets.visibleInsets.scale(appScale); +            }              if (insetsPending || !mLastGivenInsets.equals(insets)) {                  mLastGivenInsets.set(insets);                  try { @@ -1154,6 +1160,8 @@ public final class ViewRoot extends Handler implements ViewParent,              mCurScrollY = yoff;              fullRedrawNeeded = true;          } +        float appScale = mCompatibilityInfo.mApplicationScale; +        boolean scalingRequired = mCompatibilityInfo.mScalingRequired;          Rect dirty = mDirty;          if (mUseGL) { @@ -1169,12 +1177,11 @@ public final class ViewRoot extends Handler implements ViewParent,                      mAttachInfo.mIgnoreDirtyState = true;                      mView.mPrivateFlags |= View.DRAWN; -                    float scale = mAppScale;                      int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);                      try {                          canvas.translate(0, -yoff); -                        if (scale != 1.0f) { -                            canvas.scale(scale, scale); +                        if (scalingRequired) { +                            canvas.scale(appScale, appScale);                          }                          mView.draw(canvas);                          if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) { @@ -1206,8 +1213,8 @@ public final class ViewRoot extends Handler implements ViewParent,          }          if (fullRedrawNeeded) { -            mAttachInfo.mIgnoreDirtyState = true;             -            dirty.union(0, 0, (int) (mWidth * mAppScale), (int) (mHeight * mAppScale)); +            mAttachInfo.mIgnoreDirtyState = true; +            dirty.union(0, 0, (int) (mWidth * appScale), (int) (mHeight * appScale));          }          if (DEBUG_ORIENTATION || DEBUG_DRAW) { @@ -1215,7 +1222,8 @@ public final class ViewRoot extends Handler implements ViewParent,                      + mWindowAttributes.getTitle()                      + ": dirty={" + dirty.left + "," + dirty.top                      + "," + dirty.right + "," + dirty.bottom + "} surface=" -                    + surface + " surface.isValid()=" + surface.isValid()); +                    + surface + " surface.isValid()=" + surface.isValid() + ", appScale:" + +                    appScale + ", width=" + mWidth + ", height=" + mHeight);          }          Canvas canvas; @@ -1272,18 +1280,16 @@ public final class ViewRoot extends Handler implements ViewParent,                  mAttachInfo.mDrawingTime = SystemClock.uptimeMillis();                  mView.mPrivateFlags |= View.DRAWN; -                float scale = mAppScale;                  if (DEBUG_DRAW) {                      Context cxt = mView.getContext();                      Log.i(TAG, "Drawing: package:" + cxt.getPackageName() + -                            ", appScale=" + mAppScale); +                            ", metrics=" + mView.getContext().getResources().getDisplayMetrics());                  } -                int saveCount =  canvas.save(Canvas.MATRIX_SAVE_FLAG); +                int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);                  try {                      canvas.translate(0, -yoff); -                    if (scale != 1.0f) { -                        // re-scale this -                        canvas.scale(scale, scale); +                    if (scalingRequired) { +                        canvas.scale(appScale, appScale);                      }                      mView.draw(canvas);                  } finally { @@ -1586,8 +1592,8 @@ public final class ViewRoot extends Handler implements ViewParent,              } else {                  didFinish = event.getAction() == MotionEvent.ACTION_OUTSIDE;              } -            if (event != null) { -                event.scale(mAppScaleInverted); +            if (event != null && mCompatibilityInfo.mScalingRequired) { +                event.scale(mCompatibilityInfo.mApplicationInvertedScale);              }              try { @@ -1709,8 +1715,9 @@ public final class ViewRoot extends Handler implements ViewParent,                          if (mGlWanted && !mUseGL) {                              initializeGL();                              if (mGlCanvas != null) { -                                mGlCanvas.setViewport((int) (mWidth * mAppScale), -                                        (int) (mHeight * mAppScale)); +                                float appScale = mCompatibilityInfo.mApplicationScale; +                                mGlCanvas.setViewport( +                                        (int) (mWidth * appScale), (int) (mHeight * appScale));                              }                          }                      } @@ -1914,8 +1921,8 @@ public final class ViewRoot extends Handler implements ViewParent,          } else {              didFinish = false;          } -        if (event != null) { -            event.scale(mAppScaleInverted); +        if (event != null && mCompatibilityInfo.mScalingRequired) { +            event.scale(mCompatibilityInfo.mApplicationInvertedScale);          }          if (DEBUG_TRACKBALL) Log.v(TAG, "Motion event:" + event); @@ -2345,27 +2352,59 @@ public final class ViewRoot extends Handler implements ViewParent,      private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,              boolean insetsPending) throws RemoteException { -          boolean restore = false; -        if (params != null && mAppScale != 1.0f) { +        float appScale = mCompatibilityInfo.mApplicationScale; +        boolean scalingRequired = mCompatibilityInfo.mScalingRequired; +         +        if (params != null && !mCompatibilityInfo.mExpandable) { +            adjustWindowAttributesForCompatibleMode(params); +        } +        if (params != null && scalingRequired) {              restore = true; -            params.scale(mAppScale, mWindowLayoutParamsBackup); +            params.scale(appScale, mWindowLayoutParamsBackup);          }          int relayoutResult = sWindowSession.relayout(                  mWindow, params, -                (int) (mView.mMeasuredWidth * mAppScale), -                (int) (mView.mMeasuredHeight * mAppScale), +                (int) (mView.mMeasuredWidth * appScale), +                (int) (mView.mMeasuredHeight * appScale),                  viewVisibility, insetsPending, mWinFrame,                  mPendingContentInsets, mPendingVisibleInsets, mSurface);          if (restore) {              params.restore(mWindowLayoutParamsBackup);          } - -        mPendingContentInsets.scale(mAppScaleInverted); -        mPendingVisibleInsets.scale(mAppScaleInverted); -        mWinFrame.scale(mAppScaleInverted); +        if (scalingRequired) { +            float invertedScale = mCompatibilityInfo.mApplicationInvertedScale; +            mPendingContentInsets.scale(invertedScale); +            mPendingVisibleInsets.scale(invertedScale); +            mWinFrame.scale(invertedScale); +        }          return relayoutResult;      } +     +    /** +     * Adjust the window's layout parameter for compatibility mode. It replaces FILL_PARENT +     * with the default window size, and centers if the window wanted to fill +     * horizontally. +     *  +     * @param attrs the window's layout params to adjust +     */ +    private void adjustWindowAttributesForCompatibleMode(WindowManager.LayoutParams attrs) { +        // fix app windows only +        if (attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { +            DisplayMetrics metrics = mView.getContext().getResources().getDisplayMetrics(); +            // TODO: improve gravity logic +            if (attrs.width == ViewGroup.LayoutParams.FILL_PARENT) { +                attrs.width = metrics.widthPixels; +                attrs.gravity |= Gravity.CENTER_HORIZONTAL; +            } +            if (attrs.height == ViewGroup.LayoutParams.FILL_PARENT) { +                attrs.height = metrics.heightPixels; +            } +            if (DEBUG_LAYOUT) { +                Log.d(TAG, "Attributes fixed for compatibility : " + attrs); +            } +        } +    }      /**       * {@inheritDoc} @@ -2470,11 +2509,16 @@ public final class ViewRoot extends Handler implements ViewParent,                  + " visibleInsets=" + visibleInsets.toShortString()                  + " reportDraw=" + reportDraw);          Message msg = obtainMessage(reportDraw ? RESIZED_REPORT :RESIZED); - -        coveredInsets.scale(mAppScaleInverted); -        visibleInsets.scale(mAppScaleInverted); -        msg.arg1 = (int) (w * mAppScaleInverted); -        msg.arg2 = (int) (h * mAppScaleInverted); +        if (mCompatibilityInfo.mScalingRequired) { +            float invertedScale = mCompatibilityInfo.mApplicationInvertedScale; +            coveredInsets.scale(invertedScale); +            visibleInsets.scale(invertedScale); +            msg.arg1 = (int) (w * invertedScale); +            msg.arg2 = (int) (h * invertedScale); +        } else { +            msg.arg1 = w; +            msg.arg2 = h; +        }          msg.obj = new Rect[] { new Rect(coveredInsets), new Rect(visibleInsets) };          sendMessage(msg);      } | 
