Add android:hardwareAccelerated to Activity.

Hardware acceleration can now be enabled/disabled locally on each activity
declared in the manifest. It can also be enabled/disabled directly on a
window through the WindowManager.LayoutParams.

Change-Id: I91dd0b26c4e7eb8cd7288e523ed6b7bda6d0990b
diff --git a/api/current.xml b/api/current.xml
index 76d8eed..5287610 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -51156,6 +51156,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_HARDWARE_ACCELERATED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1024"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_IMMERSIVE"
  type="int"
  transient="false"
@@ -51555,17 +51566,6 @@
  visibility="public"
 >
 </field>
-<field name="FLAG_HARDWARE_ACCELERATED"
- type="int"
- transient="false"
- volatile="false"
- value="2097152"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="FLAG_HAS_CODE"
  type="int"
  transient="false"
@@ -196487,6 +196487,25 @@
 <parameter name="appName" type="java.lang.String">
 </parameter>
 </method>
+<method name="setWindowManager"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="wm" type="android.view.WindowManager">
+</parameter>
+<parameter name="appToken" type="android.os.IBinder">
+</parameter>
+<parameter name="appName" type="java.lang.String">
+</parameter>
+<parameter name="hardwareAccelerated" type="boolean">
+</parameter>
+</method>
 <method name="superDispatchKeyEvent"
  return="boolean"
  abstract="true"
@@ -196635,6 +196654,17 @@
  visibility="public"
 >
 </field>
+<field name="FEATURE_HARDWARE_ACCELERATED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="10"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FEATURE_INDETERMINATE_PROGRESS"
  type="int"
  transient="false"
@@ -197496,6 +197526,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_HARDWARE_ACCELERATED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-2147483648"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_IGNORE_CHEEK_PRESSES"
  type="int"
  transient="false"
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index e3351b0..4b312ec 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4123,7 +4123,7 @@
             mWindow.setSoftInputMode(info.softInputMode);
         }
         mUiThread = Thread.currentThread();
-
+        
         mMainThread = aThread;
         mInstrumentation = instr;
         mToken = token;
@@ -4137,7 +4137,8 @@
         mEmbeddedID = id;
         mLastNonConfigurationInstances = lastNonConfigurationInstances;
 
-        mWindow.setWindowManager(null, mToken, mComponent.flattenToString());
+        mWindow.setWindowManager(null, mToken, mComponent.flattenToString(),
+                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
         if (mParent != null) {
             mWindow.setContainer(mParent.getWindow());
         }
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 364c91e..e21cb97 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -166,6 +166,11 @@
      */
     public static final int FLAG_IMMERSIVE = 0x0200;
     /**
+     * Value for {@link #flags}: true when the application's rendering should
+     * be hardware accelerated.
+     */
+    public static final int FLAG_HARDWARE_ACCELERATED = 0x0400;
+    /**
      * Options that have been set in the activity declaration in the
      * manifest.
      * These include:
@@ -175,7 +180,7 @@
      * {@link #FLAG_STATE_NOT_NEEDED}, {@link #FLAG_EXCLUDE_FROM_RECENTS},
      * {@link #FLAG_ALLOW_TASK_REPARENTING}, {@link #FLAG_NO_HISTORY},
      * {@link #FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS},
-     * {@link #FLAG_IMMERSIVE}
+     * {@link #FLAG_IMMERSIVE}, {@link #FLAG_HARDWARE_ACCELERATED}
      */
     public int flags;
 
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 35f22dc..7901b155 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -284,12 +284,6 @@
     public static final int FLAG_HEAVY_WEIGHT = 1<<20;
     
     /**
-     * Value for {@link #flags}: true when the application's rendering should
-     * be hardware accelerated.
-     */
-    public static final int FLAG_HARDWARE_ACCELERATED = 1<<21;
-    
-    /**
      * Value for {@link #flags}: this is true if the application has set
      * its android:neverEncrypt to true, false otherwise. It is used to specify
      * that this package specifically "opts-out" of a secured file system solution,
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index bc78d37..8c9cc4e 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -16,9 +16,6 @@
 
 package android.content.pm;
 
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -30,14 +27,14 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.PatternMatcher;
-import android.provider.Settings;
 import android.util.AttributeSet;
 import android.util.Config;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.TypedValue;
-
 import com.android.internal.util.XmlUtils;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.File;
 import java.io.IOException;
@@ -48,7 +45,6 @@
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.Iterator;
-import java.util.List;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 
@@ -1535,11 +1531,9 @@
             ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
         }
 
-        if (sa.getBoolean(
+        boolean hardwareAccelerated = sa.getBoolean(
                 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
-                false)) {
-            ai.flags |= ApplicationInfo.FLAG_HARDWARE_ACCELERATED;
-        }
+                false);
 
         if (sa.getBoolean(
                 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
@@ -1638,7 +1632,8 @@
 
             String tagName = parser.getName();
             if (tagName.equals("activity")) {
-                Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false);
+                Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false,
+                        hardwareAccelerated);
                 if (a == null) {
                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                     return false;
@@ -1647,7 +1642,7 @@
                 owner.activities.add(a);
 
             } else if (tagName.equals("receiver")) {
-                Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true);
+                Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);
                 if (a == null) {
                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                     return false;
@@ -1782,7 +1777,8 @@
 
     private Activity parseActivity(Package owner, Resources res,
             XmlPullParser parser, AttributeSet attrs, int flags, String[] outError,
-            boolean receiver) throws XmlPullParserException, IOException {
+            boolean receiver, boolean hardwareAccelerated)
+            throws XmlPullParserException, IOException {
         TypedArray sa = res.obtainAttributes(attrs,
                 com.android.internal.R.styleable.AndroidManifestActivity);
 
@@ -1892,8 +1888,14 @@
                 false)) {
             a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
         }
-
+        
         if (!receiver) {
+            if (sa.getBoolean(
+                    com.android.internal.R.styleable.AndroidManifestActivity_hardwareAccelerated,
+                    hardwareAccelerated)) {
+                a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
+            }
+
             a.info.launchMode = sa.getInt(
                     com.android.internal.R.styleable.AndroidManifestActivity_launchMode,
                     ActivityInfo.LAUNCH_MULTIPLE);
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 877a302..8abbf58 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -16,7 +16,6 @@
 
 package android.view;
 
-import android.content.pm.ApplicationInfo;
 import com.android.internal.view.BaseSurfaceHolder;
 import com.android.internal.view.IInputMethodCallback;
 import com.android.internal.view.IInputMethodSession;
@@ -329,7 +328,7 @@
                 mWindowAttributes.copyFrom(attrs);
                 attrs = mWindowAttributes;
                 
-                enableHardwareAcceleration(view, attrs);
+                enableHardwareAcceleration(attrs);
 
                 if (view instanceof RootViewSurfaceTaker) {
                     mSurfaceHolderCallback =
@@ -460,14 +459,14 @@
         }
     }
 
-    private void enableHardwareAcceleration(View view, WindowManager.LayoutParams attrs) {
+    private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) {
         // Only enable hardware acceleration if we are not in the system process
         // The window manager creates ViewRoots to display animated preview windows
         // of launching apps and we don't want those to be hardware accelerated
         if (Process.myUid() != Process.SYSTEM_UID) {
             // Try to enable hardware acceleration if requested
-            if ((view.getContext().getApplicationInfo().flags &
-                    ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
+            if (attrs != null &&
+                    (attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0) {
                 final boolean translucent = attrs.format != PixelFormat.OPAQUE;
                 mHwRenderer = HardwareRenderer.createGlRenderer(2, translucent);
             }
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 0d4e84b..f32ff77 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -68,6 +68,10 @@
      * If overlay is enabled, the action mode UI will be allowed to cover existing window content.
      */
     public static final int FEATURE_ACTION_MODE_OVERLAY = 9;
+    /**
+     * Flag for requesting this window to be hardware accelerated, if possible. 
+     */
+    public static final int FEATURE_HARDWARE_ACCELERATED = 10;
     /** Flag for setting the progress bar's visibility to VISIBLE */
     public static final int PROGRESS_VISIBILITY_ON = -1;
     /** Flag for setting the progress bar's visibility to GONE */
@@ -375,21 +379,35 @@
      *
      * @param wm The ViewManager for adding new windows.
      */
-    public void setWindowManager(WindowManager wm,
-            IBinder appToken, String appName) {
+    public void setWindowManager(WindowManager wm, IBinder appToken, String appName) {
+        setWindowManager(wm, appToken, appName, false);
+    }
+
+    /**
+     * Set the window manager for use by this Window to, for example,
+     * display panels.  This is <em>not</em> used for displaying the
+     * Window itself -- that must be done by the client.
+     *
+     * @param wm The ViewManager for adding new windows.
+     */
+    public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
+            boolean hardwareAccelerated) {
         mAppToken = appToken;
         mAppName = appName;
         if (wm == null) {
             wm = WindowManagerImpl.getDefault();
         }
-        mWindowManager = new LocalWindowManager(wm);
+        mWindowManager = new LocalWindowManager(wm, hardwareAccelerated);
     }
 
     private class LocalWindowManager implements WindowManager {
-        LocalWindowManager(WindowManager wm) {
+        private boolean mHardwareAccelerated;
+
+        LocalWindowManager(WindowManager wm, boolean hardwareAccelerated) {
             mWindowManager = wm;
             mDefaultDisplay = mContext.getResources().getDefaultDisplay(
                     mWindowManager.getDefaultDisplay());
+            mHardwareAccelerated = hardwareAccelerated;
         }
 
         public final void addView(View view, ViewGroup.LayoutParams params) {
@@ -436,6 +454,9 @@
             if (wp.packageName == null) {
                 wp.packageName = mContext.getPackageName();
             }
+            if (mHardwareAccelerated) {
+                wp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+            }
             mWindowManager.addView(view, params);
         }
 
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index eebbc93..c147b74 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -72,6 +72,7 @@
          * When using {@link Gravity#LEFT} or {@link Gravity#RIGHT} it provides
          * an offset from the given edge.
          */
+        @ViewDebug.ExportedProperty
         public int x;
         
         /**
@@ -79,6 +80,7 @@
          * When using {@link Gravity#TOP} or {@link Gravity#BOTTOM} it provides
          * an offset from the given edge.
          */
+        @ViewDebug.ExportedProperty
         public int y;
 
         /**
@@ -87,6 +89,7 @@
          * should not be stretched. Otherwise the extra pixels will be pro-rated
          * among all views whose weight is greater than 0.
          */
+        @ViewDebug.ExportedProperty
         public float horizontalWeight;
 
         /**
@@ -95,8 +98,9 @@
          * should not be stretched. Otherwise the extra pixels will be pro-rated
          * among all views whose weight is greater than 0.
          */
+        @ViewDebug.ExportedProperty
         public float verticalWeight;
-        
+
         /**
          * The general type of window.  There are three main classes of
          * window types:
@@ -389,6 +393,7 @@
          * @see #FLAG_FULLSCREEN
          * @see #FLAG_FORCE_NOT_FULLSCREEN
          * @see #FLAG_IGNORE_CHEEK_PRESSES
+         * @see #FLAG_HARDWARE_ACCELERATED
          */
         @ViewDebug.ExportedProperty(flagMapping = {
             @ViewDebug.FlagToString(mask = FLAG_BLUR_BEHIND, equals = FLAG_BLUR_BEHIND,
@@ -420,7 +425,9 @@
             @ViewDebug.FlagToString(mask = FLAG_FORCE_NOT_FULLSCREEN,
                     equals = FLAG_FORCE_NOT_FULLSCREEN, name = "FLAG_FORCE_NOT_FULLSCREEN"),
             @ViewDebug.FlagToString(mask = FLAG_IGNORE_CHEEK_PRESSES,
-                    equals = FLAG_IGNORE_CHEEK_PRESSES, name = "FLAG_IGNORE_CHEEK_PRESSES")
+                    equals = FLAG_IGNORE_CHEEK_PRESSES, name = "FLAG_IGNORE_CHEEK_PRESSES"),
+            @ViewDebug.FlagToString(mask = FLAG_HARDWARE_ACCELERATED,
+                    equals = FLAG_HARDWARE_ACCELERATED, name = "FLAG_HARDWARE_ACCELERATED")
         })
         public int flags;
         
@@ -603,6 +610,12 @@
          * it is created.
          * {@hide} */
         public static final int FLAG_SYSTEM_ERROR = 0x40000000;
+        
+        /**
+         * Indicates whether this window should be hardware accelerated.
+         * Requesting hardware acceleration does not guarantee it will happen.
+         */
+        public static final int FLAG_HARDWARE_ACCELERATED = 0x80000000;        
 
         /**
          * Given a particular set of window manager flags, determine whether
@@ -1075,6 +1088,7 @@
                 screenOrientation = o.screenOrientation;
                 changes |= SCREEN_ORIENTATION_CHANGED;
             }
+
             return changes;
         }
     
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 5e8c618..bc130f2 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1210,6 +1210,7 @@
              any value in the theme. -->
         <attr name="windowSoftInputMode" />
         <attr name="immersive" />
+        <attr name="hardwareAccelerated" />
     </declare-styleable>
     
     <!-- The <code>activity-alias</code> tag declares a new
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index b615657..ef18787 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -142,6 +142,16 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+
+        <activity
+                android:name="LinesActivity"
+                android:label="_Lines"
+                android:hardwareAccelerated="false">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
                 
     </application>
 </manifest>
diff --git a/tests/HwAccelerationTest/src/com/google/android/test/hwui/LinesActivity.java b/tests/HwAccelerationTest/src/com/google/android/test/hwui/LinesActivity.java
new file mode 100644
index 0000000..c800d42
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/google/android/test/hwui/LinesActivity.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2010 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 com.google.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.os.Bundle;
+import android.view.View;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class LinesActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        final LinesView view = new LinesView(this);
+        setContentView(view);
+    }
+
+    static class LinesView extends View {
+        private final Bitmap mBitmap1;
+        private final Paint mSmallPaint;
+        private final Paint mMediumPaint;
+        private final Paint mLargePaint;
+        private final BitmapShader mShader;
+        private final float[] mPoints;
+        private final Paint mAlphaPaint;
+
+        LinesView(Context c) {
+            super(c);
+
+            mBitmap1 = BitmapFactory.decodeResource(c.getResources(), R.drawable.sunset1);
+
+            mSmallPaint = new Paint();
+            mSmallPaint.setAntiAlias(true);
+            mSmallPaint.setColor(0xffff0000);
+            mSmallPaint.setStrokeWidth(1.0f);
+
+            mMediumPaint = new Paint();
+            mMediumPaint.setAntiAlias(true);
+            mMediumPaint.setColor(0xff0000ff);
+            mMediumPaint.setStrokeWidth(4.0f);
+
+            mLargePaint = new Paint();
+            mLargePaint.setAntiAlias(true);
+            mLargePaint.setColor(0xff00ff00);
+            mLargePaint.setStrokeWidth(15.0f);
+
+            mAlphaPaint = new Paint();
+            mAlphaPaint.setAntiAlias(true);
+            mAlphaPaint.setColor(0x7fff0050);
+            mAlphaPaint.setStrokeWidth(10.0f);
+            
+            mShader = new BitmapShader(mBitmap1, BitmapShader.TileMode.MIRROR,
+                    BitmapShader.TileMode.MIRROR);
+
+            mPoints = new float[] {
+                    62.0f, 0.0f, 302.0f, 400.0f,
+                    302.0f, 400.0f, 352.0f, 400.0f,
+                    352.0f, 400.0f, 352.0f, 500.0f
+            };
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            super.onDraw(canvas);
+
+            canvas.drawARGB(255, 255, 255, 255);
+
+            canvas.save();
+            canvas.translate(100.0f, 20.0f);
+
+            canvas.drawLine(0.0f, 0.0f, 40.0f, 400.0f, mSmallPaint);
+            canvas.drawLine(5.0f, 0.0f, 95.0f, 400.0f, mMediumPaint);
+            canvas.drawLine(22.0f, 0.0f, 162.0f, 400.0f, mLargePaint);
+            
+            mLargePaint.setShader(mShader);
+            canvas.drawLine(42.0f, 0.0f, 222.0f, 400.0f, mLargePaint);
+            mLargePaint.setShader(null);
+            
+            canvas.drawLines(mPoints, mAlphaPaint);
+            
+            canvas.translate(120.0f, 0.0f);
+            mAlphaPaint.setShader(mShader);            
+            canvas.drawLines(mPoints, mAlphaPaint);
+            mAlphaPaint.setShader(null);
+
+            canvas.restore();
+        }
+    }
+}