From df6e980e3f63eb0f6f9eb437fa925d5009cd9c44 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Thu, 26 May 2011 14:20:23 -0700 Subject: Add new supports-screens attributes for declaring the compatible screens. Change-Id: I40d57e4354e48accc1027c9f90916ea73eb5190d android:requiresSmallestWidthDp provides the smallest supported width. android:compatibleWidthLimitDp provides the largest compatible width. --- core/java/android/app/ActivityThread.java | 2 +- core/java/android/content/pm/ApplicationInfo.java | 24 ++++ core/java/android/content/pm/PackageParser.java | 7 + .../android/content/res/CompatibilityInfo.java | 160 ++++++++++++--------- 4 files changed, 125 insertions(+), 68 deletions(-) (limited to 'core/java/android') diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 6c8f85f..d30010a 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -1525,7 +1525,7 @@ public final class ActivityThread { synchronized (this) { ContextImpl context = getSystemContext(); context.init(new LoadedApk(this, "android", context, info, - new CompatibilityInfo(info, 0, false)), null, this); + new CompatibilityInfo(info, 0, 0, false)), null, this); } } diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 92b2c3b..ab31865 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -321,6 +321,22 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public int flags = 0; /** + * The required smallest screen width the application can run on. If 0, + * nothing has been specified. Comes from + * {@link android.R.styleable#AndroidManifestSupportsScreens_requiresSmallestWidthDp + * android:requiresSmallestWidthDp} attribute of the <supports-screens> tag. + */ + public int requiresSmallestWidthDp = 0; + + /** + * The maximum smallest screen width the application is designed for. If 0, + * nothing has been specified. Comes from + * {@link android.R.styleable#AndroidManifestSupportsScreens_compatibleWidthLimitDp + * android:compatibleWidthLimitDp} attribute of the <supports-screens> tag. + */ + public int compatibleWidthLimitDp = 0; + + /** * Full path to the location of this package. */ public String sourceDir; @@ -401,6 +417,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { pw.println(prefix + "taskAffinity=" + taskAffinity); pw.println(prefix + "uid=" + uid + " flags=0x" + Integer.toHexString(flags) + " theme=0x" + Integer.toHexString(theme)); + pw.println(prefix + "requiresSmallestWidthDp=" + requiresSmallestWidthDp + + " compatibleWidthLimitDp=" + compatibleWidthLimitDp); pw.println(prefix + "sourceDir=" + sourceDir); if (sourceDir == null) { if (publicSourceDir != null) { @@ -460,6 +478,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { className = orig.className; theme = orig.theme; flags = orig.flags; + requiresSmallestWidthDp = orig.requiresSmallestWidthDp; + compatibleWidthLimitDp = orig.compatibleWidthLimitDp; sourceDir = orig.sourceDir; publicSourceDir = orig.publicSourceDir; nativeLibraryDir = orig.nativeLibraryDir; @@ -493,6 +513,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { dest.writeString(className); dest.writeInt(theme); dest.writeInt(flags); + dest.writeInt(requiresSmallestWidthDp); + dest.writeInt(compatibleWidthLimitDp); dest.writeString(sourceDir); dest.writeString(publicSourceDir); dest.writeString(nativeLibraryDir); @@ -526,6 +548,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { className = source.readString(); theme = source.readInt(); flags = source.readInt(); + requiresSmallestWidthDp = source.readInt(); + compatibleWidthLimitDp = source.readInt(); sourceDir = source.readString(); publicSourceDir = source.readString(); nativeLibraryDir = source.readString(); diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 10799a4..42e24f9 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -993,6 +993,13 @@ public class PackageParser { sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestSupportsScreens); + pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger( + com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp, + 0); + pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger( + com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp, + 0); + // This is a trick to get a boolean and still able to detect // if a value was actually set. supportsSmallScreens = sa.getInteger( diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java index 8d725cd..c151e32 100644 --- a/core/java/android/content/res/CompatibilityInfo.java +++ b/core/java/android/content/res/CompatibilityInfo.java @@ -110,86 +110,112 @@ public class CompatibilityInfo implements Parcelable { */ public final float applicationInvertedScale; - public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, boolean forceCompat) { + public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, int sw, + boolean forceCompat) { int compatFlags = 0; - // We can't rely on the application always setting - // FLAG_RESIZEABLE_FOR_SCREENS so will compute it based on various input. - boolean anyResizeable = false; - - if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) { - compatFlags |= LARGE_SCREENS; - anyResizeable = true; - if (!forceCompat) { - // If we aren't forcing the app into compatibility mode, then - // assume if it supports large screens that we should allow it - // to use the full space of an xlarge screen as well. - compatFlags |= XLARGE_SCREENS | EXPANDABLE; + if (appInfo.requiresSmallestWidthDp != 0 || appInfo.compatibleWidthLimitDp != 0) { + // New style screen requirements spec. + int required = appInfo.requiresSmallestWidthDp != 0 + ? appInfo.requiresSmallestWidthDp + : appInfo.compatibleWidthLimitDp; + int compat = appInfo.compatibleWidthLimitDp != 0 + ? appInfo.compatibleWidthLimitDp + : appInfo.requiresSmallestWidthDp; + if (compat < required) { + compat = required; } - } - if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) { - anyResizeable = true; - if (!forceCompat) { - compatFlags |= XLARGE_SCREENS | EXPANDABLE; + + if (compat >= sw) { + compatFlags |= NEVER_COMPAT; + } else if (forceCompat) { + compatFlags |= NEEDS_SCREEN_COMPAT; } - } - if ((appInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) { - anyResizeable = true; - compatFlags |= EXPANDABLE; - } - if (forceCompat) { - // If we are forcing compatibility mode, then ignore an app that - // just says it is resizable for screens. We'll only have it fill - // the screen if it explicitly says it supports the screen size we - // are running in. - compatFlags &= ~EXPANDABLE; - } + // Modern apps always support densities. + applicationDensity = DisplayMetrics.DENSITY_DEVICE; + applicationScale = 1.0f; + applicationInvertedScale = 1.0f; - boolean supportsScreen = false; - switch (screenLayout&Configuration.SCREENLAYOUT_SIZE_MASK) { - case Configuration.SCREENLAYOUT_SIZE_XLARGE: - if ((compatFlags&XLARGE_SCREENS) != 0) { - supportsScreen = true; + } else { + // We can't rely on the application always setting + // FLAG_RESIZEABLE_FOR_SCREENS so will compute it based on various input. + boolean anyResizeable = false; + + if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) { + compatFlags |= LARGE_SCREENS; + anyResizeable = true; + if (!forceCompat) { + // If we aren't forcing the app into compatibility mode, then + // assume if it supports large screens that we should allow it + // to use the full space of an xlarge screen as well. + compatFlags |= XLARGE_SCREENS | EXPANDABLE; } - if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) { - compatFlags |= NEVER_COMPAT; + } + if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) { + anyResizeable = true; + if (!forceCompat) { + compatFlags |= XLARGE_SCREENS | EXPANDABLE; } - break; - case Configuration.SCREENLAYOUT_SIZE_LARGE: - if ((compatFlags&LARGE_SCREENS) != 0) { + } + if ((appInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) { + anyResizeable = true; + compatFlags |= EXPANDABLE; + } + + if (forceCompat) { + // If we are forcing compatibility mode, then ignore an app that + // just says it is resizable for screens. We'll only have it fill + // the screen if it explicitly says it supports the screen size we + // are running in. + compatFlags &= ~EXPANDABLE; + } + + boolean supportsScreen = false; + switch (screenLayout&Configuration.SCREENLAYOUT_SIZE_MASK) { + case Configuration.SCREENLAYOUT_SIZE_XLARGE: + if ((compatFlags&XLARGE_SCREENS) != 0) { + supportsScreen = true; + } + if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) { + compatFlags |= NEVER_COMPAT; + } + break; + case Configuration.SCREENLAYOUT_SIZE_LARGE: + if ((compatFlags&LARGE_SCREENS) != 0) { + supportsScreen = true; + } + if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) { + compatFlags |= NEVER_COMPAT; + } + break; + } + + if ((screenLayout&Configuration.SCREENLAYOUT_COMPAT_NEEDED) != 0) { + if ((compatFlags&EXPANDABLE) != 0) { supportsScreen = true; + } else if (!anyResizeable) { + compatFlags |= ALWAYS_COMPAT; } - if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) { - compatFlags |= NEVER_COMPAT; - } - break; - } + } - if ((screenLayout&Configuration.SCREENLAYOUT_COMPAT_NEEDED) != 0) { - if ((compatFlags&EXPANDABLE) != 0) { - supportsScreen = true; - } else if (!anyResizeable) { - compatFlags |= ALWAYS_COMPAT; + if (supportsScreen) { + compatFlags &= ~NEEDS_SCREEN_COMPAT; + } else { + compatFlags |= NEEDS_SCREEN_COMPAT; } - } - if (supportsScreen) { - compatFlags &= ~NEEDS_SCREEN_COMPAT; - } else { - compatFlags |= NEEDS_SCREEN_COMPAT; - } - - if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) { - applicationDensity = DisplayMetrics.DENSITY_DEVICE; - applicationScale = 1.0f; - applicationInvertedScale = 1.0f; - } else { - applicationDensity = DisplayMetrics.DENSITY_DEFAULT; - applicationScale = DisplayMetrics.DENSITY_DEVICE - / (float) DisplayMetrics.DENSITY_DEFAULT; - applicationInvertedScale = 1.0f / applicationScale; - compatFlags |= SCALING_REQUIRED; + if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) { + applicationDensity = DisplayMetrics.DENSITY_DEVICE; + applicationScale = 1.0f; + applicationInvertedScale = 1.0f; + } else { + applicationDensity = DisplayMetrics.DENSITY_DEFAULT; + applicationScale = DisplayMetrics.DENSITY_DEVICE + / (float) DisplayMetrics.DENSITY_DEFAULT; + applicationInvertedScale = 1.0f / applicationScale; + compatFlags |= SCALING_REQUIRED; + } } mCompatibilityFlags = compatFlags; -- cgit v1.1