OSDN Git Service

resolution support fix/improvement
authorMitsuru Oshima <oshima@google.com>
Wed, 10 Jun 2009 04:16:08 +0000 (21:16 -0700)
committerMitsuru Oshima <oshima@google.com>
Wed, 10 Jun 2009 22:22:17 +0000 (15:22 -0700)
    * adding compatibility menu
    * backup gravity
    * set expanable=true if the screen size is hvga * density.
    * added "supports any density" mode. I'll add sdk check later.
    * disallow to catch orientation change event if the app is not expandable. This
      was causing layout problem under non-expandable mode. I discussed this with Mike C
      and we agreed to do this approach for now. We'll revisit if this causes problem to
      a lot of applications.

core/java/android/content/pm/ApplicationInfo.java
core/java/android/content/res/CompatibilityInfo.java
core/java/android/content/res/Resources.java
core/java/android/provider/Settings.java
core/java/android/util/DisplayMetrics.java
core/java/android/view/ViewRoot.java
core/java/android/view/WindowManager.java
services/java/com/android/server/PackageManagerService.java

index f3dfc5a..f10dd53 100644 (file)
@@ -145,6 +145,13 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
     public static final int FLAG_ALLOW_BACKUP = 1<<10;
     
     /**
+     * Indicates that the application supports any densities;
+     * {@hide}
+     */
+    public static final int ANY_DENSITY = -1;
+    private static final int[] ANY_DENSITIES_ARRAY = { ANY_DENSITY };
+
+    /**
      * Flags associated with the application.  Any combination of
      * {@link #FLAG_SYSTEM}, {@link #FLAG_DEBUGGABLE}, {@link #FLAG_HAS_CODE},
      * {@link #FLAG_PERSISTENT}, {@link #FLAG_FACTORY_TEST}, and
@@ -369,4 +376,14 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
         }
         return null;
     }
+
+    /**
+     * Disable compatibility mode
+     * 
+     * @hide
+     */
+    public void disableCompatibilityMode() {
+        expandable = true;
+        supportsDensities = ANY_DENSITIES_ARRAY;
+    }
 }
index 19379fb..836de39 100644 (file)
@@ -51,10 +51,17 @@ public class CompatibilityInfo {
     public final float mApplicationInvertedScale;
     
     /**
-     * 
      * A boolean flag to indicates that the application can expand over the original size.
+     * The flag is set to true if
+     * 1) Application declares its expandable in manifest file using <expandable /> or
+     * 2) The screen size is same as (320 x 480) * density. 
      */
-    public final boolean mExpandable;
+    public boolean mExpandable;
+
+    /**
+     * A expandable flag in the configuration.
+     */
+    public final boolean mConfiguredExpandable;
     
     /**
      * A boolean flag to tell if the application needs scaling (when mApplicationScale != 1.0f)
@@ -62,13 +69,16 @@ public class CompatibilityInfo {
     public final boolean mScalingRequired;
 
     public CompatibilityInfo(ApplicationInfo appInfo) {
-        // A temp workaround to fix rotation issue.
-        // mExpandable = appInfo.expandable;
-        mExpandable = true;
+        mExpandable = mConfiguredExpandable = appInfo.expandable;
+        
         float packageDensityScale = -1.0f;
         if (appInfo.supportsDensities != null) {
             int minDiff = Integer.MAX_VALUE;
             for (int density : appInfo.supportsDensities) {
+                if (density == ApplicationInfo.ANY_DENSITY) { 
+                    packageDensityScale = 1.0f;
+                    break;
+                }
                 int tmpDiff = Math.abs(DisplayMetrics.DEVICE_DENSITY - density);
                 if (tmpDiff == 0) {
                     packageDensityScale = 1.0f;
@@ -92,7 +102,7 @@ public class CompatibilityInfo {
 
     private CompatibilityInfo() {
         mApplicationScale = mApplicationInvertedScale = 1.0f;
-        mExpandable = true;
+        mExpandable = mConfiguredExpandable = true;
         mScalingRequired = false;
     }
 
index 976b618..2f63820 100644 (file)
@@ -88,7 +88,7 @@ public class Resources {
     PluralRules mPluralRule;
     
     private final CompatibilityInfo mCompatibilityInfo;
-    
+
     private static final SparseArray<Object> EMPTY_ARRAY = new SparseArray<Object>() {
         @Override
         public void put(int k, Object o) {
@@ -1255,7 +1255,7 @@ public class Resources {
 
         return array;
     }
-    
+
     /**
      * Store the newly updated configuration.
      */
@@ -1268,7 +1268,7 @@ public class Resources {
             }
             if (metrics != null) {
                 mMetrics.setTo(metrics);
-                mMetrics.updateMetrics(mCompatibilityInfo, mConfiguration);
+                mMetrics.updateMetrics(mCompatibilityInfo, mConfiguration.orientation);
             }
             mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
 
index 52cec22..c2da593 100644 (file)
@@ -1025,6 +1025,14 @@ public final class Settings {
         public static final String SCREEN_OFF_TIMEOUT = "screen_off_timeout";
 
         /**
+         * If 0, the compatibility mode is off for all applications.
+         * If 1, older applications run under compatibility mode.
+         * TODO: remove this settings before code freeze (bug/1907571)
+         * @hide
+         */
+        public static final String COMPATIBILITY_MODE = "compatibility_mode";
+
+        /**
          * The screen backlight brightness between 0 and 255.
          */
         public static final String SCREEN_BRIGHTNESS = "screen_brightness";
index 987be2b..245148d 100644 (file)
@@ -103,10 +103,10 @@ public class DisplayMetrics {
     }
 
     /**
-     * Update the display metrics based on the compatibility info and configuration.
+     * Update the display metrics based on the compatibility info and orientation
      * {@hide}
      */
-    public void updateMetrics(CompatibilityInfo compatibilityInfo, Configuration configuration) {
+    public void updateMetrics(CompatibilityInfo compatibilityInfo, int orientation) {
         if (compatibilityInfo.mScalingRequired) {
             float invertedRatio = compatibilityInfo.mApplicationInvertedScale;
             density *= invertedRatio;
@@ -116,31 +116,42 @@ public class DisplayMetrics {
             widthPixels *= invertedRatio;
             heightPixels *= invertedRatio;
         }
-        if (!compatibilityInfo.mExpandable) {
+        if (!compatibilityInfo.mConfiguredExpandable) {
             // Note: this assume that configuration is updated before calling
             // updateMetrics method.
             int defaultWidth;
             int defaultHeight;
-            switch (configuration.orientation) {
+            switch (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);
+                    break;
+                }
+                case Configuration.ORIENTATION_UNDEFINED: {
+                    // don't change
+                    return;
                 }
             }
-            // adjust the size only when the device's screen is bigger.
-            if (defaultWidth < widthPixels) {
-                widthPixels = defaultWidth;
-            }
-            if (defaultHeight < heightPixels) {
-                heightPixels = defaultHeight;
+            
+            if (defaultWidth == widthPixels && defaultHeight == heightPixels) {
+                // the screen size is same as expected size. make it expandable
+                compatibilityInfo.mExpandable = true;
+            } else {
+                compatibilityInfo.mExpandable = false;
+                // adjust the size only when the device's screen is bigger.
+                if (defaultWidth < widthPixels) {
+                    widthPixels = defaultWidth;
+                }
+                if (defaultHeight < heightPixels) {
+                    heightPixels = defaultHeight;
+                }
             }
         }
     }
index d8bab56..ee8229d 100644 (file)
@@ -129,7 +129,6 @@ public final class ViewRoot extends Handler implements ViewParent,
     boolean mIsAnimating;
     
     private CompatibilityInfo mCompatibilityInfo;
-    private int[] mWindowLayoutParamsBackup = null;
 
     final View.AttachInfo mAttachInfo;
 
@@ -388,10 +387,11 @@ public final class ViewRoot extends Handler implements ViewParent,
             if (mView == null) {
                 mView = view;
                 mWindowAttributes.copyFrom(attrs);
-                mCompatibilityInfo =
-                        mView.getContext().getResources().getCompatibilityInfo();
-                if (mCompatibilityInfo.mScalingRequired) {
-                    mWindowLayoutParamsBackup = new int[4];
+                mCompatibilityInfo = mView.getContext().getResources().getCompatibilityInfo();
+                boolean restore = false;
+                if (mCompatibilityInfo.mScalingRequired || !mCompatibilityInfo.mExpandable) {
+                    restore = true;
+                    mWindowAttributes.backup();
                 }
                 if (!mCompatibilityInfo.mExpandable) {
                     adjustWindowAttributesForCompatibleMode(mWindowAttributes);
@@ -420,6 +420,11 @@ public final class ViewRoot extends Handler implements ViewParent,
                     unscheduleTraversals();
                     throw new RuntimeException("Adding window failed", e);
                 }
+
+                if (restore) {
+                    mWindowAttributes.restore();
+                }
+
                 if (mCompatibilityInfo.mScalingRequired) {
                     mAttachInfo.mContentInsets.scale(
                             mCompatibilityInfo.mApplicationInvertedScale);
@@ -1921,9 +1926,6 @@ public final class ViewRoot extends Handler implements ViewParent,
         } else {
             didFinish = false;
         }
-        if (event != null && mCompatibilityInfo.mScalingRequired) {
-            event.scale(mCompatibilityInfo.mApplicationInvertedScale);
-        }
 
         if (DEBUG_TRACKBALL) Log.v(TAG, "Motion event:" + event);
 
@@ -2355,13 +2357,15 @@ public final class ViewRoot extends Handler implements ViewParent,
         boolean restore = false;
         float appScale = mCompatibilityInfo.mApplicationScale;
         boolean scalingRequired = mCompatibilityInfo.mScalingRequired;
-        
         if (params != null && !mCompatibilityInfo.mExpandable) {
+            restore = true;
+            params.backup();
             adjustWindowAttributesForCompatibleMode(params);
         }
         if (params != null && scalingRequired) {
+            if (!restore) params.backup();
             restore = true;
-            params.scale(appScale, mWindowLayoutParamsBackup);
+            params.scale(appScale);
         }
         int relayoutResult = sWindowSession.relayout(
                 mWindow, params,
@@ -2370,7 +2374,7 @@ public final class ViewRoot extends Handler implements ViewParent,
                 viewVisibility, insetsPending, mWinFrame,
                 mPendingContentInsets, mPendingVisibleInsets, mSurface);
         if (restore) {
-            params.restore(mWindowLayoutParamsBackup);
+            params.restore();
         }
         if (scalingRequired) {
             float invertedScale = mCompatibilityInfo.mApplicationInvertedScale;
@@ -2396,12 +2400,15 @@ public final class ViewRoot extends Handler implements ViewParent,
             if (attrs.width == ViewGroup.LayoutParams.FILL_PARENT) {
                 attrs.width = metrics.widthPixels;
                 attrs.gravity |= Gravity.CENTER_HORIZONTAL;
+                mWindowAttributesChanged = attrs == mWindowAttributes;
             }
             if (attrs.height == ViewGroup.LayoutParams.FILL_PARENT) {
                 attrs.height = metrics.heightPixels;
+                attrs.gravity |= Gravity.TOP;
+                mWindowAttributesChanged = attrs == mWindowAttributes;
             }
             if (DEBUG_LAYOUT) {
-                Log.d(TAG, "Attributes fixed for compatibility : " + attrs);
+                Log.d(TAG, "Adjusted Attributes for compatibility : " + attrs);
             }
         }
     }
index ec2069c..e1c4687 100644 (file)
@@ -818,6 +818,9 @@ public interface WindowManager extends ViewManager {
         public static final int SCREEN_ORIENTATION_CHANGED = 1<<10;
         public static final int SCREEN_BRIGHTNESS_CHANGED = 1<<11;
     
+        // internal buffer to backup/restore parameters under compatibility mode.
+        private int[] mCompatibilityParamsBackup = null;
+        
         public final int copyFrom(LayoutParams o) {
             int changes = 0;
     
@@ -975,37 +978,47 @@ public interface WindowManager extends ViewManager {
 
         /**
          * Scale the layout params' coordinates and size.
-         * Returns the original info as a backup so that the caller can
-         * restore the layout params;
-         */
-        void scale(float scale, int[] backup) {
-            if (scale != 1.0f) {
-                backup[0] = x;
-                backup[1] = y;
-                x *= scale;
-                y *= scale;
-                if (width > 0) {
-                    backup[2] = width;
-                    width *= scale;
-                }
-                if (height > 0) {
-                    backup[3] = height;
-                    height *= scale;
-                }
+         */
+        void scale(float scale) {
+            x *= scale;
+            y *= scale;
+            if (width > 0) {
+                width *= scale;
+            }
+            if (height > 0) {
+                height *= scale;
             }
         }
 
         /**
-         * Restore the layout params' coordinates and size.
-         */
-        void restore(int[] backup) {
-            x = backup[0];
-            y = backup[1];
-            if (width > 0) {
-                width = backup[2];
+         * Backup the layout parameters used in compatibility mode.
+         * @see LayoutParams#restore()
+         */
+        void backup() {
+            int[] backup = mCompatibilityParamsBackup;
+            if (backup == null) {
+                // we backup 5 elements, x, y, width, height and gravity.
+                backup = mCompatibilityParamsBackup = new int[5];
             }
-            if (height > 0) {
+            backup[0] = x;
+            backup[1] = y;
+            backup[2] = width;
+            backup[3] = height;
+            backup[4] = gravity;
+        }
+
+        /**
+         * Restore the layout params' coordinates, size and gravity
+         * @see LayoutParams#backup()
+         */
+        void restore() {
+            int[] backup = mCompatibilityParamsBackup;
+            if (backup != null) {
+                x = backup[0];
+                y = backup[1];
+                width = backup[2];
                 height = backup[3];
+                gravity = backup[4];
             }
         }
 
index 6a2e62f..0d142da 100644 (file)
@@ -58,6 +58,8 @@ import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.Signature;
+import android.content.res.CompatibilityInfo;
+import android.content.res.Configuration;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Build;
@@ -259,6 +261,7 @@ class PackageManagerService extends IPackageManager.Stub {
     final ResolveInfo mResolveInfo = new ResolveInfo();
     ComponentName mResolveComponentName;
     PackageParser.Package mPlatformPackage;
+    private boolean mCompatibilityModeEnabled = true;
 
     public static final IPackageManager main(Context context, boolean factoryTest) {
         PackageManagerService m = new PackageManagerService(context, factoryTest);
@@ -509,7 +512,7 @@ class PackageManagerService extends IPackageManager.Stub {
         } // synchronized (mPackages)
         } // synchronized (mInstallLock)
     }
-    
+
     @Override
     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
             throws RemoteException {
@@ -885,7 +888,11 @@ class PackageManagerService extends IPackageManager.Stub {
                     + ": " + p);
             if (p != null) {
                 // Note: isEnabledLP() does not apply here - always return info
-                return PackageParser.generateApplicationInfo(p, flags);
+                ApplicationInfo appInfo = PackageParser.generateApplicationInfo(p, flags);
+                if (!mCompatibilityModeEnabled) {
+                    appInfo.disableCompatibilityMode();
+                }
+                return appInfo;
             }
             if ("android".equals(packageName)||"system".equals(packageName)) {
                 return mAndroidApplication;
@@ -952,10 +959,35 @@ class PackageManagerService extends IPackageManager.Stub {
     public ActivityInfo getActivityInfo(ComponentName component, int flags) {
         synchronized (mPackages) {
             PackageParser.Activity a = mActivities.mActivities.get(component);
-            if (Config.LOGV) Log.v(
-                TAG, "getActivityInfo " + component + ": " + a);
+
+            if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a);
             if (a != null && mSettings.isEnabledLP(a.info, flags)) {
-                return PackageParser.generateActivityInfo(a, flags);
+                ActivityInfo ainfo = PackageParser.generateActivityInfo(a, flags);
+                if (ainfo != null && (flags & PackageManager.GET_EXPANDABLE) != 0) {
+                    ApplicationInfo appInfo = getApplicationInfo(component.getPackageName(),
+                            PackageManager.GET_EXPANDABLE | PackageManager.GET_SUPPORTS_DENSITIES); 
+                    if (appInfo != null && !appInfo.expandable) {
+                        // Check if the screen size is same as what the application expect.
+                        CompatibilityInfo info = new CompatibilityInfo(appInfo);
+                        DisplayMetrics metrics = new DisplayMetrics();
+                        metrics.setTo(mMetrics);
+                        int orientation = mMetrics.widthPixels > mMetrics.heightPixels ?
+                                Configuration.ORIENTATION_LANDSCAPE :
+                                Configuration.ORIENTATION_PORTRAIT;
+                        metrics.updateMetrics(info, orientation);
+                        if (!info.mExpandable) {
+                            // Don't allow an app that cannot expand to handle rotation.
+                            ainfo.configChanges &= ~ ActivityInfo.CONFIG_ORIENTATION;
+                        } else {
+                            appInfo.expandable = true;
+                        }
+                        if (DEBUG_SETTINGS) {
+                            Log.d(TAG, "component=" + component +
+                                    ", expandable:" + appInfo.expandable);
+                        }
+                    }
+                }
+                return ainfo;
             }
             if (mResolveComponentName.equals(component)) {
                 return mResolveActivity;
@@ -4709,6 +4741,14 @@ class PackageManagerService extends IPackageManager.Stub {
 
     public void systemReady() {
         mSystemReady = true;
+
+        // Read the compatibilty setting when the system is ready.
+        mCompatibilityModeEnabled = android.provider.Settings.System.getInt(
+                mContext.getContentResolver(),
+                android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
+        if (DEBUG_SETTINGS) {
+            Log.d(TAG, "compatibility mode:" + mCompatibilityModeEnabled);
+        }
     }
 
     public boolean isSafeMode() {