Add API to convert translucent Activity to opaque.

Fixes bug 9298778.

Change-Id: If6198f42bdea8aa727a2abc672eb0062aaf63ca3
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 7f2f744..e87d805 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4862,6 +4862,25 @@
     }
 
     /**
+     * Convert a translucent themed Activity {@link android.R.attr#windowIsTranslucent} to a
+     * fullscreen opaque Activity.
+     *
+     * Call this whenever the background of a translucent Activity has changed to become opaque.
+     * Doing so will allow the previously visible Activity behind this one to be stopped. Stopped
+     * apps consume no CPU cycles and are eligible for removal when reclaiming memory.
+     *
+     * This call has no effect on non-translucent activities or on activities with the
+     * {@link android.R.attr#windowIsFloating} attribute.
+     */
+    public void convertToOpaque() {
+        try {
+            ActivityManagerNative.getDefault().convertToOpaque(mToken);
+        } catch (RemoteException e) {
+            // pass
+        }
+    }
+
+    /**
      * Adjust the current immersive mode setting.
      *
      * Note that changing this value will have no effect on the activity's
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 1573398..b966d6d 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1499,6 +1499,14 @@
             return true;
         }
 
+        case CONVERT_TO_OPAQUE_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IBinder token = data.readStrongBinder();
+            convertToOpaque(token);
+            reply.writeNoException();
+            return true;
+        }
+
         case SET_IMMERSIVE_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder token = data.readStrongBinder();
@@ -3823,7 +3831,19 @@
         data.recycle();
         reply.recycle();
     }
-    
+
+    public void convertToOpaque(IBinder token)
+            throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(token);
+        mRemote.transact(CONVERT_TO_OPAQUE_TRANSACTION, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+
     public void setImmersive(IBinder token, boolean immersive)
             throws RemoteException {
         Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index c8791a4..39f4cfa 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -301,6 +301,8 @@
 
     public void finishHeavyWeightApp() throws RemoteException;
 
+    public void convertToOpaque(IBinder token) throws RemoteException;
+
     public void setImmersive(IBinder token, boolean immersive) throws RemoteException;
     public boolean isImmersive(IBinder token) throws RemoteException;
     public boolean isTopActivityImmersive() throws RemoteException;
@@ -666,4 +668,5 @@
     int GET_STACK_BOXES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+170;
     int SET_FOCUSED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+171;
     int GET_STACK_BOX_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+172;
+    int CONVERT_TO_OPAQUE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+173;
 }