summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2009-06-25 19:48:04 -0700
committerDianne Hackborn <hackbod@google.com>2009-06-26 13:37:05 -0700
commit723738cfaec3dd7b0fe152c872c41bebf94074c4 (patch)
tree421ddeed166d0a4586c9460c4de581307bf08d44 /core/java
parent77cb40a0b088b02357fbc7d5fad24886d607f0da (diff)
downloadframeworks_base-723738cfaec3dd7b0fe152c872c41bebf94074c4.zip
frameworks_base-723738cfaec3dd7b0fe152c872c41bebf94074c4.tar.gz
frameworks_base-723738cfaec3dd7b0fe152c872c41bebf94074c4.tar.bz2
Expand support for different screen sizes.
Applications can now declare that they support small, normal, or large screens. Resource selection can also be done based on these sizes. By default, pre-Donut apps are false for small and large, and Donut or later apps are assumed to support all sizes. In either case they can use <supports-screens> in their manifest to declare what they actually support.
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/content/pm/ActivityInfo.java10
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java29
-rw-r--r--core/java/android/content/pm/PackageParser.java40
-rw-r--r--core/java/android/content/res/AssetManager.java2
-rw-r--r--core/java/android/content/res/CompatibilityInfo.java33
-rw-r--r--core/java/android/content/res/Configuration.java37
-rw-r--r--core/java/android/content/res/Resources.java5
-rw-r--r--core/java/android/util/DisplayMetrics.java61
8 files changed, 162 insertions, 55 deletions
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 85d877a..27783ef 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -235,6 +235,12 @@ public class ActivityInfo extends ComponentInfo
public static final int CONFIG_ORIENTATION = 0x0080;
/**
* Bit in {@link #configChanges} that indicates that the activity
+ * can itself handle changes to the screen layout. Set from the
+ * {@link android.R.attr#configChanges} attribute.
+ */
+ public static final int CONFIG_SCREEN_LAYOUT = 0x0100;
+ /**
+ * Bit in {@link #configChanges} that indicates that the activity
* can itself handle changes to the font scaling factor. Set from the
* {@link android.R.attr#configChanges} attribute. This is
* not a core resource configutation, but a higher-level value, so its
@@ -248,8 +254,8 @@ public class ActivityInfo extends ComponentInfo
* Contains any combination of {@link #CONFIG_FONT_SCALE},
* {@link #CONFIG_MCC}, {@link #CONFIG_MNC},
* {@link #CONFIG_LOCALE}, {@link #CONFIG_TOUCHSCREEN},
- * {@link #CONFIG_KEYBOARD}, {@link #CONFIG_NAVIGATION}, and
- * {@link #CONFIG_ORIENTATION}. Set from the
+ * {@link #CONFIG_KEYBOARD}, {@link #CONFIG_NAVIGATION},
+ * {@link #CONFIG_ORIENTATION}, and {@link #CONFIG_SCREEN_LAYOUT}. Set from the
* {@link android.R.attr#configChanges} attribute.
*/
public int configChanges;
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 2a2cf93..bcf95b6 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -138,10 +138,27 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
/**
* Value for {@link #flags}: 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)
+ * reduced in size for smaller screens. Corresponds to
+ * {@link android.R.styleable#AndroidManifestSupportsScreens_smallScreens
+ * android:smallScreens}.
*/
- public static final int FLAG_SUPPORTS_LARGE_SCREENS = 1<<9;
+ public static final int FLAG_SUPPORTS_SMALL_SCREENS = 1<<9;
+
+ /**
+ * Value for {@link #flags}: true when the application's window can be
+ * displayed on normal screens. Corresponds to
+ * {@link android.R.styleable#AndroidManifestSupportsScreens_normalScreens
+ * android:normalScreens}.
+ */
+ public static final int FLAG_SUPPORTS_NORMAL_SCREENS = 1<<10;
+
+ /**
+ * Value for {@link #flags}: true when the application's window can be
+ * increased in size for larger screens. Corresponds to
+ * {@link android.R.styleable#AndroidManifestSupportsScreens_largeScreens
+ * android:smallScreens}.
+ */
+ public static final int FLAG_SUPPORTS_LARGE_SCREENS = 1<<11;
/**
* Value for {@link #flags}: this is false if the application has set
@@ -149,7 +166,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
*
* {@hide}
*/
- public static final int FLAG_ALLOW_BACKUP = 1<<10;
+ public static final int FLAG_ALLOW_BACKUP = 1<<12;
/**
* Indicates that the application supports any densities;
@@ -164,7 +181,9 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
* {@link #FLAG_PERSISTENT}, {@link #FLAG_FACTORY_TEST}, and
* {@link #FLAG_ALLOW_TASK_REPARENTING}
* {@link #FLAG_ALLOW_CLEAR_USER_DATA}, {@link #FLAG_UPDATED_SYSTEM_APP},
- * {@link #FLAG_TEST_ONLY}.
+ * {@link #FLAG_TEST_ONLY}, {@link #FLAG_SUPPORTS_SMALL_SCREENS},
+ * {@link #FLAG_SUPPORTS_NORMAL_SCREENS},
+ * {@link #FLAG_SUPPORTS_LARGE_SCREENS}.
*/
public int flags = 0;
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index ab9518e..558b0c3 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -668,6 +668,11 @@ public class PackageParser {
}
sa.recycle();
+ // Resource boolean are -1, so 1 means we don't know the value.
+ int supportsSmallScreens = 1;
+ int supportsNormalScreens = 1;
+ int supportsLargeScreens = 1;
+
int outerDepth = parser.getDepth();
while ((type=parser.next()) != parser.END_DOCUMENT
&& (type != parser.END_TAG || parser.getDepth() > outerDepth)) {
@@ -876,8 +881,24 @@ public class PackageParser {
XmlUtils.skipCurrentTag(parser);
- } else if (tagName.equals("expandable")) {
- pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
+ } else if (tagName.equals("supports-screens")) {
+ sa = res.obtainAttributes(attrs,
+ com.android.internal.R.styleable.AndroidManifestSupportsScreens);
+
+ // This is a trick to get a boolean and still able to detect
+ // if a value was actually set.
+ supportsSmallScreens = sa.getInteger(
+ com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
+ supportsSmallScreens);
+ supportsNormalScreens = sa.getInteger(
+ com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
+ supportsNormalScreens);
+ supportsLargeScreens = sa.getInteger(
+ com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
+ supportsLargeScreens);
+
+ sa.recycle();
+
XmlUtils.skipCurrentTag(parser);
} else {
Log.w(TAG, "Bad element under <manifest>: "
@@ -910,7 +931,20 @@ 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
+
+ if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
+ && pkg.applicationInfo.targetSdkVersion
+ >= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) {
+ pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
+ }
+ if (supportsNormalScreens != 0) {
+ pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
+ }
+ if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
+ && pkg.applicationInfo.targetSdkVersion
+ >= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) {
+ pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
+ }
int size = pkg.supportsDensityList.size();
if (size > 0) {
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 1c91736..5c7b01f 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -601,7 +601,7 @@ public final class AssetManager {
public native final void setConfiguration(int mcc, int mnc, String locale,
int orientation, int touchscreen, int density, int keyboard,
int keyboardHidden, int navigation, int screenWidth, int screenHeight,
- int majorVersion);
+ int screenLayout, int majorVersion);
/**
* Retrieve the resource identifier for the given resource name.
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index 179b9bd..4e6fe07 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -65,7 +65,7 @@ public class CompatibilityInfo {
/**
* A compatibility flags
*/
- private int compatibilityFlags;
+ private int mCompatibilityFlags;
/**
* A flag mask to tell if the application needs scaling (when mApplicationScale != 1.0f)
@@ -101,7 +101,11 @@ public class CompatibilityInfo {
*/
public final float applicationInvertedScale;
-
+ /**
+ * The flags from ApplicationInfo.
+ */
+ public final int appFlags;
+
/**
* Window size in Compatibility Mode, in real pixels. This is updated by
* {@link DisplayMetrics#updateMetrics}.
@@ -117,8 +121,10 @@ public class CompatibilityInfo {
private int mXOffset;
public CompatibilityInfo(ApplicationInfo appInfo) {
+ appFlags = appInfo.flags;
+
if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
- compatibilityFlags = EXPANDABLE | CONFIGURED_EXPANDABLE;
+ mCompatibilityFlags = EXPANDABLE | CONFIGURED_EXPANDABLE;
}
float packageDensityScale = -1.0f;
@@ -149,13 +155,16 @@ public class CompatibilityInfo {
}
applicationInvertedScale = 1.0f / applicationScale;
if (applicationScale != 1.0f) {
- compatibilityFlags |= SCALING_REQUIRED;
+ mCompatibilityFlags |= SCALING_REQUIRED;
}
}
private CompatibilityInfo() {
+ appFlags = ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS
+ | ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS
+ | ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
applicationScale = applicationInvertedScale = 1.0f;
- compatibilityFlags = EXPANDABLE | CONFIGURED_EXPANDABLE;
+ mCompatibilityFlags = EXPANDABLE | CONFIGURED_EXPANDABLE;
}
/**
@@ -175,9 +184,9 @@ public class CompatibilityInfo {
*/
public void setExpandable(boolean expandable) {
if (expandable) {
- compatibilityFlags |= CompatibilityInfo.EXPANDABLE;
+ mCompatibilityFlags |= CompatibilityInfo.EXPANDABLE;
} else {
- compatibilityFlags &= ~CompatibilityInfo.EXPANDABLE;
+ mCompatibilityFlags &= ~CompatibilityInfo.EXPANDABLE;
}
}
@@ -185,20 +194,20 @@ public class CompatibilityInfo {
* @return true if the application is configured to be expandable.
*/
public boolean isConfiguredExpandable() {
- return (compatibilityFlags & CompatibilityInfo.CONFIGURED_EXPANDABLE) != 0;
+ return (mCompatibilityFlags & CompatibilityInfo.CONFIGURED_EXPANDABLE) != 0;
}
/**
* @return true if the scaling is required
*/
public boolean isScalingRequired() {
- return (compatibilityFlags & SCALING_REQUIRED) != 0;
+ return (mCompatibilityFlags & SCALING_REQUIRED) != 0;
}
@Override
public String toString() {
return "CompatibilityInfo{scale=" + applicationScale +
- ", compatibility flag=" + compatibilityFlags + "}";
+ ", compatibility flag=" + mCompatibilityFlags + "}";
}
/**
@@ -222,13 +231,13 @@ public class CompatibilityInfo {
* @param params the window's parameter
*/
public Translator getTranslator(WindowManager.LayoutParams params) {
- if ( (compatibilityFlags & CompatibilityInfo.SCALING_EXPANDABLE_MASK)
+ if ( (mCompatibilityFlags & CompatibilityInfo.SCALING_EXPANDABLE_MASK)
== CompatibilityInfo.EXPANDABLE) {
if (DBG) Log.d(TAG, "no translation required");
return null;
}
- if ((compatibilityFlags & CompatibilityInfo.EXPANDABLE) == 0) {
+ if ((mCompatibilityFlags & CompatibilityInfo.EXPANDABLE) == 0) {
if ((params.flags & WindowManager.LayoutParams.FLAG_NO_COMPATIBILITY_SCALING) != 0) {
if (DBG) Log.d(TAG, "translation for surface view selected");
return new Translator(X_SHIFT_WINDOW, false, 1.0f, 1.0f);
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index bb3486c..577aa60 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -116,6 +116,18 @@ public final class Configuration implements Parcelable, Comparable<Configuration
*/
public int orientation;
+ public static final int SCREENLAYOUT_UNDEFINED = 0;
+ public static final int SCREENLAYOUT_SMALL = 1;
+ public static final int SCREENLAYOUT_NORMAL = 2;
+ public static final int SCREENLAYOUT_LARGE = 3;
+
+ /**
+ * Overall layout of the screen. May be one of
+ * {@link #SCREENLAYOUT_SMALL}, {@link #SCREENLAYOUT_NORMAL},
+ * or {@link #SCREENLAYOUT_LARGE}.
+ */
+ public int screenLayout;
+
/**
* Construct an invalid Configuration. You must call {@link #setToDefaults}
* for this object to be valid. {@more}
@@ -141,6 +153,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
hardKeyboardHidden = o.hardKeyboardHidden;
navigation = o.navigation;
orientation = o.orientation;
+ screenLayout = o.screenLayout;
}
public String toString() {
@@ -165,6 +178,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration
sb.append(navigation);
sb.append(" orien=");
sb.append(orientation);
+ sb.append(" layout=");
+ sb.append(screenLayout);
sb.append('}');
return sb.toString();
}
@@ -183,6 +198,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED;
navigation = NAVIGATION_UNDEFINED;
orientation = ORIENTATION_UNDEFINED;
+ screenLayout = SCREENLAYOUT_UNDEFINED;
}
/** {@hide} */
@@ -253,6 +269,11 @@ public final class Configuration implements Parcelable, Comparable<Configuration
changed |= ActivityInfo.CONFIG_ORIENTATION;
orientation = delta.orientation;
}
+ if (delta.screenLayout != SCREENLAYOUT_UNDEFINED
+ && screenLayout != delta.screenLayout) {
+ changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
+ screenLayout = delta.screenLayout;
+ }
return changed;
}
@@ -276,9 +297,11 @@ public final class Configuration implements Parcelable, Comparable<Configuration
* {@link android.content.pm.ActivityInfo#CONFIG_KEYBOARD
* PackageManager.ActivityInfo.CONFIG_KEYBOARD},
* {@link android.content.pm.ActivityInfo#CONFIG_NAVIGATION
- * PackageManager.ActivityInfo.CONFIG_NAVIGATION}, or
+ * PackageManager.ActivityInfo.CONFIG_NAVIGATION},
* {@link android.content.pm.ActivityInfo#CONFIG_ORIENTATION
- * PackageManager.ActivityInfo.CONFIG_ORIENTATION}.
+ * PackageManager.ActivityInfo.CONFIG_ORIENTATION}, or
+ * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_LAYOUT
+ * PackageManager.ActivityInfo.CONFIG_SCREEN_LAYOUT}.
*/
public int diff(Configuration delta) {
int changed = 0;
@@ -319,6 +342,10 @@ public final class Configuration implements Parcelable, Comparable<Configuration
&& orientation != delta.orientation) {
changed |= ActivityInfo.CONFIG_ORIENTATION;
}
+ if (delta.screenLayout != SCREENLAYOUT_UNDEFINED
+ && screenLayout != delta.screenLayout) {
+ changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
+ }
return changed;
}
@@ -368,6 +395,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
dest.writeInt(hardKeyboardHidden);
dest.writeInt(navigation);
dest.writeInt(orientation);
+ dest.writeInt(screenLayout);
}
public static final Parcelable.Creator<Configuration> CREATOR
@@ -399,6 +427,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
hardKeyboardHidden = source.readInt();
navigation = source.readInt();
orientation = source.readInt();
+ screenLayout = source.readInt();
}
public int compareTo(Configuration that) {
@@ -428,6 +457,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration
n = this.navigation - that.navigation;
if (n != 0) return n;
n = this.orientation - that.orientation;
+ if (n != 0) return n;
+ n = this.screenLayout - that.screenLayout;
//if (n != 0) return n;
return n;
}
@@ -450,6 +481,6 @@ public final class Configuration implements Parcelable, Comparable<Configuration
return ((int)this.fontScale) + this.mcc + this.mnc
+ this.locale.hashCode() + this.touchscreen
+ this.keyboard + this.keyboardHidden + this.hardKeyboardHidden
- + this.navigation + this.orientation;
+ + this.navigation + this.orientation + this.screenLayout;
}
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index cb9d46e..d7512bb 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1267,7 +1267,8 @@ public class Resources {
}
if (metrics != null) {
mMetrics.setTo(metrics);
- mMetrics.updateMetrics(mCompatibilityInfo, mConfiguration.orientation);
+ mMetrics.updateMetrics(mCompatibilityInfo,
+ mConfiguration.orientation, mConfiguration.screenLayout);
}
mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
@@ -1299,7 +1300,7 @@ public class Resources {
mConfiguration.touchscreen,
(int)(mMetrics.density*160), mConfiguration.keyboard,
keyboardHidden, mConfiguration.navigation, width, height,
- sSdkVersion);
+ mConfiguration.screenLayout, sSdkVersion);
int N = mDrawableCache.size();
if (DEBUG_CONFIG) {
Log.d(TAG, "Cleaning up drawables config changes: 0x"
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index d89ada0..4179edb 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -103,40 +103,43 @@ public class DisplayMetrics {
/**
* Update the display metrics based on the compatibility info and orientation
+ * NOTE: DO NOT EXPOSE THIS API! It is introducing a circular dependency
+ * with the higher-level android.res package.
* {@hide}
*/
- public void updateMetrics(CompatibilityInfo compatibilityInfo, int orientation) {
+ public void updateMetrics(CompatibilityInfo compatibilityInfo, int orientation,
+ int screenLayout) {
int xOffset = 0;
if (!compatibilityInfo.isConfiguredExpandable()) {
// Note: this assume that configuration is updated before calling
// updateMetrics method.
- int defaultWidth;
- int defaultHeight;
- switch (orientation) {
- case Configuration.ORIENTATION_LANDSCAPE: {
- defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density);
- defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density);
- break;
- }
- case Configuration.ORIENTATION_PORTRAIT:
- case Configuration.ORIENTATION_SQUARE:
- default: {
- defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density);
- defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density);
- break;
- }
- case Configuration.ORIENTATION_UNDEFINED: {
- // don't change
- return;
- }
- }
-
- if (defaultWidth == widthPixels && defaultHeight == heightPixels) {
- // the screen size is same as expected size. make it expandable
- compatibilityInfo.setExpandable(true);
- } else {
+ if (screenLayout == Configuration.SCREENLAYOUT_LARGE) {
+ // This is a large screen device and the app is not
+ // compatible with large screens, to diddle it.
+
compatibilityInfo.setExpandable(false);
- // adjust the size only when the device's screen is bigger.
+ // Figure out the compatibility width and height of the screen.
+ int defaultWidth;
+ int defaultHeight;
+ switch (orientation) {
+ case Configuration.ORIENTATION_LANDSCAPE: {
+ defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density);
+ defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density);
+ break;
+ }
+ case Configuration.ORIENTATION_PORTRAIT:
+ case Configuration.ORIENTATION_SQUARE:
+ default: {
+ defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density);
+ defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density);
+ break;
+ }
+ case Configuration.ORIENTATION_UNDEFINED: {
+ // don't change
+ return;
+ }
+ }
+
if (defaultWidth < widthPixels) {
// content/window's x offset in original pixels
xOffset = ((widthPixels - defaultWidth) / 2);
@@ -145,6 +148,10 @@ public class DisplayMetrics {
if (defaultHeight < heightPixels) {
heightPixels = defaultHeight;
}
+
+ } else {
+ // the screen size is same as expected size. make it expandable
+ compatibilityInfo.setExpandable(true);
}
}
compatibilityInfo.setVisibleRect(xOffset, widthPixels, heightPixels);