diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/app/UiAutomationConnection.java | 4 | ||||
-rw-r--r-- | core/java/android/net/CaptivePortalTracker.java | 60 | ||||
-rw-r--r-- | core/java/android/net/ConnectivityManager.java | 15 | ||||
-rw-r--r-- | core/java/android/view/Choreographer.java | 2 | ||||
-rw-r--r-- | core/java/android/view/DisplayEventReceiver.java | 4 | ||||
-rw-r--r-- | core/java/android/view/GLES20Canvas.java | 6 | ||||
-rw-r--r-- | core/java/android/view/IWindowManager.aidl | 3 | ||||
-rw-r--r-- | core/java/android/view/Surface.java | 576 | ||||
-rw-r--r-- | core/java/android/view/SurfaceControl.java | 575 | ||||
-rw-r--r-- | core/jni/Android.mk | 1 | ||||
-rw-r--r-- | core/jni/AndroidRuntime.cpp | 4 | ||||
-rw-r--r-- | core/jni/android_hardware_Camera.cpp | 9 | ||||
-rw-r--r-- | core/jni/android_view_Surface.cpp | 677 | ||||
-rw-r--r-- | core/jni/android_view_SurfaceControl.cpp | 451 | ||||
-rw-r--r-- | core/res/AndroidManifest.xml | 13 |
15 files changed, 1258 insertions, 1142 deletions
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java index 9b5857f..06ef472 100644 --- a/core/java/android/app/UiAutomationConnection.java +++ b/core/java/android/app/UiAutomationConnection.java @@ -27,7 +27,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.view.IWindowManager; import android.view.InputEvent; -import android.view.Surface; +import android.view.SurfaceControl; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.IAccessibilityManager; @@ -135,7 +135,7 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub { } final long identity = Binder.clearCallingIdentity(); try { - return Surface.screenshot(width, height); + return SurfaceControl.screenshot(width, height); } finally { Binder.restoreCallingIdentity(identity); } diff --git a/core/java/android/net/CaptivePortalTracker.java b/core/java/android/net/CaptivePortalTracker.java index 354a8c4..21995c0 100644 --- a/core/java/android/net/CaptivePortalTracker.java +++ b/core/java/android/net/CaptivePortalTracker.java @@ -25,14 +25,15 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; +import android.database.ContentObserver; import android.net.ConnectivityManager; import android.net.IConnectivityManager; +import android.os.Handler; import android.os.UserHandle; import android.os.Message; import android.os.RemoteException; import android.provider.Settings; import android.telephony.TelephonyManager; -import android.util.Log; import com.android.internal.util.State; import com.android.internal.util.StateMachine; @@ -81,15 +82,21 @@ public class CaptivePortalTracker extends StateMachine { private State mActiveNetworkState = new ActiveNetworkState(); private State mDelayedCaptiveCheckState = new DelayedCaptiveCheckState(); + private static final String SETUP_WIZARD_PACKAGE = "com.google.android.setupwizard"; + private boolean mDeviceProvisioned = false; + private ProvisioningObserver mProvisioningObserver; + private CaptivePortalTracker(Context context, IConnectivityManager cs) { super(TAG); mContext = context; mConnService = cs; mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + mProvisioningObserver = new ProvisioningObserver(); IntentFilter filter = new IntentFilter(); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); + filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE); mContext.registerReceiver(mReceiver, filter); mServer = Settings.Global.getString(mContext.getContentResolver(), @@ -106,11 +113,31 @@ public class CaptivePortalTracker extends StateMachine { setInitialState(mNoActiveNetworkState); } + private class ProvisioningObserver extends ContentObserver { + ProvisioningObserver() { + super(new Handler()); + mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor( + Settings.Global.DEVICE_PROVISIONED), false, this); + onChange(false); // load initial value + } + + @Override + public void onChange(boolean selfChange) { + mDeviceProvisioned = Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.DEVICE_PROVISIONED, 0) != 0; + } + } + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); - if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { + // Normally, we respond to CONNECTIVITY_ACTION, allowing time for the change in + // connectivity to stabilize, but if the device is not yet provisioned, respond + // immediately to speed up transit through the setup wizard. + if ((mDeviceProvisioned && action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) + || (!mDeviceProvisioned + && action.equals(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE))) { NetworkInfo info = intent.getParcelableExtra( ConnectivityManager.EXTRA_NETWORK_INFO); sendMessage(obtainMessage(CMD_CONNECTIVITY_CHANGE, info)); @@ -222,8 +249,12 @@ public class CaptivePortalTracker extends StateMachine { @Override public void enter() { if (DBG) log(getName() + "\n"); - sendMessageDelayed(obtainMessage(CMD_DELAYED_CAPTIVE_CHECK, - ++mDelayedCheckToken, 0), DELAYED_CHECK_INTERVAL_MS); + Message message = obtainMessage(CMD_DELAYED_CAPTIVE_CHECK, ++mDelayedCheckToken, 0); + if (mDeviceProvisioned) { + sendMessageDelayed(message, DELAYED_CHECK_INTERVAL_MS); + } else { + sendMessage(message); + } } @Override @@ -233,13 +264,26 @@ public class CaptivePortalTracker extends StateMachine { case CMD_DELAYED_CAPTIVE_CHECK: if (message.arg1 == mDelayedCheckToken) { InetAddress server = lookupHost(mServer); - if (server != null) { - if (isCaptivePortal(server)) { - if (DBG) log("Captive network " + mNetworkInfo); + boolean captive = server != null && isCaptivePortal(server); + if (captive) { + if (DBG) log("Captive network " + mNetworkInfo); + } else { + if (DBG) log("Not captive network " + mNetworkInfo); + } + if (mDeviceProvisioned) { + if (captive) { + // Setup Wizard will assist the user in connecting to a captive + // portal, so make the notification visible unless during setup setNotificationVisible(true); } + } else { + Intent intent = new Intent( + ConnectivityManager.ACTION_CAPTIVE_PORTAL_TEST_COMPLETED); + intent.putExtra(ConnectivityManager.EXTRA_IS_CAPTIVE_PORTAL, captive); + intent.setPackage(SETUP_WIZARD_PACKAGE); + mContext.sendBroadcast(intent); } - if (DBG) log("Not captive network " + mNetworkInfo); + transitionTo(mActiveNetworkState); } break; diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index a8a68d0..000c56c 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -228,6 +228,21 @@ public class ConnectivityManager { public static final String EXTRA_ERRORED_TETHER = "erroredArray"; /** + * Broadcast Action: The captive portal tracker has finished its test. + * Sent only while running Setup Wizard, in lieu of showing a user + * notification. + * @hide + */ + public static final String ACTION_CAPTIVE_PORTAL_TEST_COMPLETED = + "android.net.conn.CAPTIVE_PORTAL_TEST_COMPLETED"; + /** + * The lookup key for a boolean that indicates whether a captive portal was detected. + * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}. + * @hide + */ + public static final String EXTRA_IS_CAPTIVE_PORTAL = "captivePortal"; + + /** * The absence of APN.. * @hide */ diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java index b661748..f28e4b5 100644 --- a/core/java/android/view/Choreographer.java +++ b/core/java/android/view/Choreographer.java @@ -693,7 +693,7 @@ public final class Choreographer { // At this time Surface Flinger won't send us vsyncs for secondary displays // but that could change in the future so let's log a message to help us remember // that we need to fix this. - if (builtInDisplayId != Surface.BUILT_IN_DISPLAY_ID_MAIN) { + if (builtInDisplayId != SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) { Log.d(TAG, "Received vsync from secondary display, but we don't support " + "this case yet. Choreographer needs a way to explicitly request " + "vsync for a specific display to ensure it doesn't lose track " diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java index a919ffc..4dade20 100644 --- a/core/java/android/view/DisplayEventReceiver.java +++ b/core/java/android/view/DisplayEventReceiver.java @@ -102,7 +102,7 @@ public abstract class DisplayEventReceiver { * @param timestampNanos The timestamp of the pulse, in the {@link System#nanoTime()} * timebase. * @param builtInDisplayId The surface flinger built-in display id such as - * {@link Surface#BUILT_IN_DISPLAY_ID_MAIN}. + * {@link SurfaceControl#BUILT_IN_DISPLAY_ID_MAIN}. * @param frame The frame number. Increases by one for each vertical sync interval. */ public void onVsync(long timestampNanos, int builtInDisplayId, int frame) { @@ -114,7 +114,7 @@ public abstract class DisplayEventReceiver { * @param timestampNanos The timestamp of the event, in the {@link System#nanoTime()} * timebase. * @param builtInDisplayId The surface flinger built-in display id such as - * {@link Surface#BUILT_IN_DISPLAY_ID_HDMI}. + * {@link SurfaceControl#BUILT_IN_DISPLAY_ID_HDMI}. * @param connected True if the display is connected, false if it disconnected. */ public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) { diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index 1810205..40f2261 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -901,9 +901,9 @@ class GLES20Canvas extends HardwareCanvas { final int count = (meshWidth + 1) * (meshHeight + 1); checkRange(verts.length, vertOffset, count * 2); - // TODO: Colors are ignored for now - colors = null; - colorOffset = 0; + if (colors != null) { + checkRange(colors.length, colorOffset, count); + } int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; try { diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index a9ad97f..885327c 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -97,9 +97,6 @@ interface IWindowManager void startAppFreezingScreen(IBinder token, int configChanges); void stopAppFreezingScreen(IBinder token, boolean force); void removeAppToken(IBinder token); - void moveAppToken(int index, IBinder token); - void moveAppTokensToTop(in List<IBinder> tokens); - void moveAppTokensToBottom(in List<IBinder> tokens); // Re-evaluate the current orientation from the caller's state. // If there is a change, the new Configuration is returned and the diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index a972b75..63f0e1f 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -16,20 +16,15 @@ package android.view; -import dalvik.system.CloseGuard; - import android.content.res.CompatibilityInfo.Translator; -import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Rect; -import android.graphics.Region; import android.graphics.SurfaceTexture; -import android.os.IBinder; -import android.os.Parcelable; import android.os.Parcel; -import android.os.SystemProperties; +import android.os.Parcelable; import android.util.Log; +import dalvik.system.CloseGuard; /** * Handle onto a raw buffer that is being managed by the screen compositor. @@ -37,9 +32,6 @@ import android.util.Log; public class Surface implements Parcelable { private static final String TAG = "Surface"; - private static final boolean HEADLESS = "1".equals( - SystemProperties.get("ro.config.headless", "0")); - public static final Parcelable.Creator<Surface> CREATOR = new Parcelable.Creator<Surface>() { public Surface createFromParcel(Parcel source) { @@ -78,130 +70,6 @@ public class Surface implements Parcelable { */ public static final int ROTATION_270 = 3; - /* built-in physical display ids (keep in sync with ISurfaceComposer.h) - * these are different from the logical display ids used elsewhere in the framework */ - - /** - * Built-in physical display id: Main display. - * Use only with {@link #getBuiltInDisplay()}. - * @hide - */ - public static final int BUILT_IN_DISPLAY_ID_MAIN = 0; - - /** - * Built-in physical display id: Attached HDMI display. - * Use only with {@link #getBuiltInDisplay()}. - * @hide - */ - public static final int BUILT_IN_DISPLAY_ID_HDMI = 1; - - /* flags used in constructor (keep in sync with ISurfaceComposerClient.h) */ - - /** - * Surface creation flag: Surface is created hidden - * @hide */ - public static final int HIDDEN = 0x00000004; - - /** - * Surface creation flag: The surface contains secure content, special - * measures will be taken to disallow the surface's content to be copied - * from another process. In particular, screenshots and VNC servers will - * be disabled, but other measures can take place, for instance the - * surface might not be hardware accelerated. - * @hide - */ - public static final int SECURE = 0x00000080; - - /** - * Surface creation flag: Creates a surface where color components are interpreted - * as "non pre-multiplied" by their alpha channel. Of course this flag is - * meaningless for surfaces without an alpha channel. By default - * surfaces are pre-multiplied, which means that each color component is - * already multiplied by its alpha value. In this case the blending - * equation used is: - * - * DEST = SRC + DEST * (1-SRC_ALPHA) - * - * By contrast, non pre-multiplied surfaces use the following equation: - * - * DEST = SRC * SRC_ALPHA * DEST * (1-SRC_ALPHA) - * - * pre-multiplied surfaces must always be used if transparent pixels are - * composited on top of each-other into the surface. A pre-multiplied - * surface can never lower the value of the alpha component of a given - * pixel. - * - * In some rare situations, a non pre-multiplied surface is preferable. - * @hide - */ - public static final int NON_PREMULTIPLIED = 0x00000100; - - /** - * Surface creation flag: Indicates that the surface must be considered opaque, - * even if its pixel format is set to translucent. This can be useful if an - * application needs full RGBA 8888 support for instance but will - * still draw every pixel opaque. - * @hide - */ - public static final int OPAQUE = 0x00000400; - - /** - * Surface creation flag: Application requires a hardware-protected path to an - * external display sink. If a hardware-protected path is not available, - * then this surface will not be displayed on the external sink. - * @hide - */ - public static final int PROTECTED_APP = 0x00000800; - - // 0x1000 is reserved for an independent DRM protected flag in framework - - /** - * Surface creation flag: Creates a normal surface. - * This is the default. - * @hide - */ - public static final int FX_SURFACE_NORMAL = 0x00000000; - - /** - * Surface creation flag: Creates a Blur surface. - * Everything behind this surface is blurred by some amount. - * The quality and refresh speed of the blur effect is not settable or guaranteed. - * It is an error to lock a Blur surface, since it doesn't have a backing store. - * @hide - * @deprecated - */ - @Deprecated - public static final int FX_SURFACE_BLUR = 0x00010000; - - /** - * Surface creation flag: Creates a Dim surface. - * Everything behind this surface is dimmed by the amount specified - * in {@link #setAlpha}. It is an error to lock a Dim surface, since it - * doesn't have a backing store. - * @hide - */ - public static final int FX_SURFACE_DIM = 0x00020000; - - /** - * @hide - */ - public static final int FX_SURFACE_SCREENSHOT = 0x00030000; - - /** - * Mask used for FX values above. - * @hide - */ - public static final int FX_SURFACE_MASK = 0x000F0000; - - /* flags used with setFlags() (keep in sync with ISurfaceComposer.h) */ - - /** - * Surface flag: Hide the surface. - * Equivalent to calling hide(). - * @hide - */ - public static final int SURFACE_HIDDEN = 0x01; - private final CloseGuard mCloseGuard = CloseGuard.get(); private String mName; @@ -211,8 +79,8 @@ public class Surface implements Parcelable { // server or system processes. When this class is parceled we defer to the // mSurfaceControl to do the parceling. Otherwise we parcel the // mNativeSurface. - private int mNativeSurface; // Surface* - private int mNativeSurfaceControl; // SurfaceControl* + int mNativeObject; // package scope only for SurfaceControl access + private int mGenerationId; // incremented each time mNativeSurface changes private final Canvas mCanvas = new CompatibleCanvas(); private int mCanvasSaveCount; // Canvas save count at time of lockCanvas() @@ -225,113 +93,12 @@ public class Surface implements Parcelable { // non compatibility mode. private Matrix mCompatibleMatrix; - private native void nativeCreate(SurfaceSession session, String name, - int w, int h, int format, int flags) - throws OutOfResourcesException; - private native void nativeCreateFromSurfaceTexture(SurfaceTexture surfaceTexture) - throws OutOfResourcesException; - private native void nativeRelease(); - private native void nativeDestroy(); - - private native boolean nativeIsValid(); - private native int nativeGetIdentity(); - private native boolean nativeIsConsumerRunningBehind(); - - private native Canvas nativeLockCanvas(Rect dirty); - private native void nativeUnlockCanvasAndPost(Canvas canvas); - - private static native Bitmap nativeScreenshot(IBinder displayToken, - int width, int height, int minLayer, int maxLayer, boolean allLayers); - - private static native void nativeOpenTransaction(); - private static native void nativeCloseTransaction(); - private static native void nativeSetAnimationTransaction(); - - private native void nativeSetLayer(int zorder); - private native void nativeSetPosition(float x, float y); - private native void nativeSetSize(int w, int h); - private native void nativeSetTransparentRegionHint(Region region); - private native void nativeSetAlpha(float alpha); - private native void nativeSetMatrix(float dsdx, float dtdx, float dsdy, float dtdy); - private native void nativeSetFlags(int flags, int mask); - private native void nativeSetWindowCrop(Rect crop); - private native void nativeSetLayerStack(int layerStack); - - private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId); - private static native IBinder nativeCreateDisplay(String name, boolean secure); - private static native void nativeSetDisplaySurface( - IBinder displayToken, Surface surface); - private static native void nativeSetDisplayLayerStack( - IBinder displayToken, int layerStack); - private static native void nativeSetDisplayProjection( - IBinder displayToken, int orientation, Rect layerStackRect, Rect displayRect); - private static native boolean nativeGetDisplayInfo( - IBinder displayToken, PhysicalDisplayInfo outInfo); - private static native void nativeBlankDisplay(IBinder displayToken); - private static native void nativeUnblankDisplay(IBinder displayToken); - - private native void nativeCopyFrom(Surface other); - private native void nativeTransferFrom(Surface other); - private native void nativeReadFromParcel(Parcel source); - private native void nativeWriteToParcel(Parcel dest); - /** * Create an empty surface, which will later be filled in by readFromParcel(). * @hide */ public Surface() { - checkHeadless(); - - mCloseGuard.open("release"); - } - - /** - * Create a surface with a name. - * - * The surface creation flags specify what kind of surface to create and - * certain options such as whether the surface can be assumed to be opaque - * and whether it should be initially hidden. Surfaces should always be - * created with the {@link #HIDDEN} flag set to ensure that they are not - * made visible prematurely before all of the surface's properties have been - * configured. - * - * Good practice is to first create the surface with the {@link #HIDDEN} flag - * specified, open a transaction, set the surface layer, layer stack, alpha, - * and position, call {@link #show} if appropriate, and close the transaction. - * - * @param session The surface session, must not be null. - * @param name The surface name, must not be null. - * @param w The surface initial width. - * @param h The surface initial height. - * @param flags The surface creation flags. Should always include {@link #HIDDEN} - * in the creation flags. - * @hide - */ - public Surface(SurfaceSession session, - String name, int w, int h, int format, int flags) - throws OutOfResourcesException { - if (session == null) { - throw new IllegalArgumentException("session must not be null"); - } - if (name == null) { - throw new IllegalArgumentException("name must not be null"); - } - - if ((flags & HIDDEN) == 0) { - Log.w(TAG, "Surfaces should always be created with the HIDDEN flag set " - + "to ensure that they are not made visible prematurely before " - + "all of the surface's properties have been configured. " - + "Set the other properties and make the surface visible within " - + "a transaction. New surface name: " + name, - new Throwable()); - } - - checkHeadless(); - - mName = name; - nativeCreate(session, name, w, h, format, flags); - mCloseGuard.open("release"); } @@ -350,11 +117,9 @@ public class Surface implements Parcelable { throw new IllegalArgumentException("surfaceTexture must not be null"); } - checkHeadless(); - mName = surfaceTexture.toString(); try { - nativeCreateFromSurfaceTexture(surfaceTexture); + mNativeObject = nativeCreateFromSurfaceTexture(surfaceTexture); } catch (OutOfResourcesException ex) { // We can't throw OutOfResourcesException because it would be an API change. throw new RuntimeException(ex); @@ -363,13 +128,20 @@ public class Surface implements Parcelable { mCloseGuard.open("release"); } + private Surface(int nativeObject) { + mNativeObject = nativeObject; + mCloseGuard.open("release"); + } + @Override protected void finalize() throws Throwable { try { if (mCloseGuard != null) { mCloseGuard.warnIfOpen(); } - nativeRelease(); + if (mNativeObject != 0) { + nativeRelease(mNativeObject); + } } finally { super.finalize(); } @@ -381,7 +153,10 @@ public class Surface implements Parcelable { * This will make the surface invalid. */ public void release() { - nativeRelease(); + if (mNativeObject != 0) { + nativeRelease(mNativeObject); + mNativeObject = 0; + } mCloseGuard.close(); } @@ -392,7 +167,10 @@ public class Surface implements Parcelable { * @hide */ public void destroy() { - nativeDestroy(); + if (mNativeObject != 0) { + nativeDestroy(mNativeObject); + mNativeObject = 0; + } mCloseGuard.close(); } @@ -403,7 +181,8 @@ public class Surface implements Parcelable { * Otherwise returns false. */ public boolean isValid() { - return nativeIsValid(); + if (mNativeObject == 0) return false; + return nativeIsValid(mNativeObject); } /** @@ -424,7 +203,8 @@ public class Surface implements Parcelable { * @hide */ public boolean isConsumerRunningBehind() { - return nativeIsConsumerRunningBehind(); + checkNotReleased(); + return nativeIsConsumerRunningBehind(mNativeObject); } /** @@ -433,7 +213,7 @@ public class Surface implements Parcelable { * After drawing into the provided {@link Canvas}, the caller should * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface. * - * @param dirty A rectangle that represents the dirty region that the caller wants + * @param inOutDirty A rectangle that represents the dirty region that the caller wants * to redraw. This function may choose to expand the dirty rectangle if for example * the surface has been resized or if the previous contents of the surface were * not available. The caller should redraw the entire dirty region as represented @@ -442,9 +222,10 @@ public class Surface implements Parcelable { * entire surface should be redrawn. * @return A canvas for drawing into the surface. */ - public Canvas lockCanvas(Rect dirty) + public Canvas lockCanvas(Rect inOutDirty) throws OutOfResourcesException, IllegalArgumentException { - return nativeLockCanvas(dirty); + checkNotReleased(); + return nativeLockCanvas(mNativeObject, inOutDirty); } /** @@ -454,7 +235,8 @@ public class Surface implements Parcelable { * @param canvas The canvas previously obtained from {@link #lockCanvas}. */ public void unlockCanvasAndPost(Canvas canvas) { - nativeUnlockCanvasAndPost(canvas); + checkNotReleased(); + nativeUnlockCanvasAndPost(mNativeObject, canvas); } /** @@ -477,190 +259,6 @@ public class Surface implements Parcelable { } } - /** - * Like {@link #screenshot(int, int, int, int)} but includes all - * Surfaces in the screenshot. - * - * @hide - */ - public static Bitmap screenshot(int width, int height) { - // TODO: should take the display as a parameter - IBinder displayToken = getBuiltInDisplay(BUILT_IN_DISPLAY_ID_MAIN); - return nativeScreenshot(displayToken, width, height, 0, 0, true); - } - - /** - * Copy the current screen contents into a bitmap and return it. - * - * @param width The desired width of the returned bitmap; the raw - * screen will be scaled down to this size. - * @param height The desired height of the returned bitmap; the raw - * screen will be scaled down to this size. - * @param minLayer The lowest (bottom-most Z order) surface layer to - * include in the screenshot. - * @param maxLayer The highest (top-most Z order) surface layer to - * include in the screenshot. - * @return Returns a Bitmap containing the screen contents, or null - * if an error occurs. - * - * @hide - */ - public static Bitmap screenshot(int width, int height, int minLayer, int maxLayer) { - // TODO: should take the display as a parameter - IBinder displayToken = getBuiltInDisplay(BUILT_IN_DISPLAY_ID_MAIN); - return nativeScreenshot(displayToken, width, height, minLayer, maxLayer, false); - } - - /* - * set surface parameters. - * needs to be inside open/closeTransaction block - */ - - /** start a transaction @hide */ - public static void openTransaction() { - nativeOpenTransaction(); - } - - /** end a transaction @hide */ - public static void closeTransaction() { - nativeCloseTransaction(); - } - - /** flag the transaction as an animation @hide */ - public static void setAnimationTransaction() { - nativeSetAnimationTransaction(); - } - - /** @hide */ - public void setLayer(int zorder) { - nativeSetLayer(zorder); - } - - /** @hide */ - public void setPosition(int x, int y) { - nativeSetPosition((float)x, (float)y); - } - - /** @hide */ - public void setPosition(float x, float y) { - nativeSetPosition(x, y); - } - - /** @hide */ - public void setSize(int w, int h) { - nativeSetSize(w, h); - } - - /** @hide */ - public void hide() { - nativeSetFlags(SURFACE_HIDDEN, SURFACE_HIDDEN); - } - - /** @hide */ - public void show() { - nativeSetFlags(0, SURFACE_HIDDEN); - } - - /** @hide */ - public void setTransparentRegionHint(Region region) { - nativeSetTransparentRegionHint(region); - } - - /** @hide */ - public void setAlpha(float alpha) { - nativeSetAlpha(alpha); - } - - /** @hide */ - public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { - nativeSetMatrix(dsdx, dtdx, dsdy, dtdy); - } - - /** @hide */ - public void setFlags(int flags, int mask) { - nativeSetFlags(flags, mask); - } - - /** @hide */ - public void setWindowCrop(Rect crop) { - nativeSetWindowCrop(crop); - } - - /** @hide */ - public void setLayerStack(int layerStack) { - nativeSetLayerStack(layerStack); - } - - /** @hide */ - public static IBinder getBuiltInDisplay(int builtInDisplayId) { - return nativeGetBuiltInDisplay(builtInDisplayId); - } - - /** @hide */ - public static IBinder createDisplay(String name, boolean secure) { - if (name == null) { - throw new IllegalArgumentException("name must not be null"); - } - return nativeCreateDisplay(name, secure); - } - - /** @hide */ - public static void setDisplaySurface(IBinder displayToken, Surface surface) { - if (displayToken == null) { - throw new IllegalArgumentException("displayToken must not be null"); - } - nativeSetDisplaySurface(displayToken, surface); - } - - /** @hide */ - public static void setDisplayLayerStack(IBinder displayToken, int layerStack) { - if (displayToken == null) { - throw new IllegalArgumentException("displayToken must not be null"); - } - nativeSetDisplayLayerStack(displayToken, layerStack); - } - - /** @hide */ - public static void setDisplayProjection(IBinder displayToken, - int orientation, Rect layerStackRect, Rect displayRect) { - if (displayToken == null) { - throw new IllegalArgumentException("displayToken must not be null"); - } - if (layerStackRect == null) { - throw new IllegalArgumentException("layerStackRect must not be null"); - } - if (displayRect == null) { - throw new IllegalArgumentException("displayRect must not be null"); - } - nativeSetDisplayProjection(displayToken, orientation, layerStackRect, displayRect); - } - - /** @hide */ - public static boolean getDisplayInfo(IBinder displayToken, PhysicalDisplayInfo outInfo) { - if (displayToken == null) { - throw new IllegalArgumentException("displayToken must not be null"); - } - if (outInfo == null) { - throw new IllegalArgumentException("outInfo must not be null"); - } - return nativeGetDisplayInfo(displayToken, outInfo); - } - - /** @hide */ - public static void blankDisplay(IBinder displayToken) { - if (displayToken == null) { - throw new IllegalArgumentException("displayToken must not be null"); - } - nativeBlankDisplay(displayToken); - } - - /** @hide */ - public static void unblankDisplay(IBinder displayToken) { - if (displayToken == null) { - throw new IllegalArgumentException("displayToken must not be null"); - } - nativeUnblankDisplay(displayToken); - } /** * Copy another surface to this one. This surface now holds a reference @@ -671,13 +269,15 @@ public class Surface implements Parcelable { * in to it. * @hide */ - public void copyFrom(Surface other) { + public void copyFrom(SurfaceControl other) { if (other == null) { throw new IllegalArgumentException("other must not be null"); } - if (other != this) { - nativeCopyFrom(other); + if (other.mNativeObject == 0) { + throw new NullPointerException( + "SurfaceControl native object is null. Are you using a released SurfaceControl?"); } + mNativeObject = nativeCopyFrom(mNativeObject, other.mNativeObject); } /** @@ -693,7 +293,13 @@ public class Surface implements Parcelable { throw new IllegalArgumentException("other must not be null"); } if (other != this) { - nativeTransferFrom(other); + if (mNativeObject != 0) { + // release our reference to our native object + nativeRelease(mNativeObject); + } + // transfer the reference from other to us + mNativeObject = other.mNativeObject; + other.mNativeObject = 0; } } @@ -706,9 +312,8 @@ public class Surface implements Parcelable { if (source == null) { throw new IllegalArgumentException("source must not be null"); } - mName = source.readString(); - nativeReadFromParcel(source); + mNativeObject = nativeReadFromParcel(mNativeObject, source); } @Override @@ -716,9 +321,8 @@ public class Surface implements Parcelable { if (dest == null) { throw new IllegalArgumentException("dest must not be null"); } - dest.writeString(mName); - nativeWriteToParcel(dest); + nativeWriteToParcel(mNativeObject, dest); if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) { release(); } @@ -726,13 +330,7 @@ public class Surface implements Parcelable { @Override public String toString() { - return "Surface(name=" + mName + ", identity=" + nativeGetIdentity() + ")"; - } - - private static void checkHeadless() { - if (HEADLESS) { - throw new UnsupportedOperationException("Device is headless"); - } + return "Surface(name=" + mName + ")"; } /** @@ -741,73 +339,12 @@ public class Surface implements Parcelable { public static class OutOfResourcesException extends Exception { public OutOfResourcesException() { } - public OutOfResourcesException(String name) { super(name); } } /** - * Describes the properties of a physical display known to surface flinger. - * @hide - */ - public static final class PhysicalDisplayInfo { - public int width; - public int height; - public float refreshRate; - public float density; - public float xDpi; - public float yDpi; - public boolean secure; - - public PhysicalDisplayInfo() { - } - - public PhysicalDisplayInfo(PhysicalDisplayInfo other) { - copyFrom(other); - } - - @Override - public boolean equals(Object o) { - return o instanceof PhysicalDisplayInfo && equals((PhysicalDisplayInfo)o); - } - - public boolean equals(PhysicalDisplayInfo other) { - return other != null - && width == other.width - && height == other.height - && refreshRate == other.refreshRate - && density == other.density - && xDpi == other.xDpi - && yDpi == other.yDpi - && secure == other.secure; - } - - @Override - public int hashCode() { - return 0; // don't care - } - - public void copyFrom(PhysicalDisplayInfo other) { - width = other.width; - height = other.height; - refreshRate = other.refreshRate; - density = other.density; - xDpi = other.xDpi; - yDpi = other.yDpi; - secure = other.secure; - } - - // For debugging purposes - @Override - public String toString() { - return "PhysicalDisplayInfo{" + width + " x " + height + ", " + refreshRate + " fps, " - + "density " + density + ", " + xDpi + " x " + yDpi + " dpi, secure " + secure - + "}"; - } - } - - /** * Returns a human readable representation of a rotation. * * @param rotation The rotation. @@ -894,4 +431,25 @@ public class Surface implements Parcelable { mOrigMatrix.set(m); } } + + private void checkNotReleased() { + if (mNativeObject == 0) throw new NullPointerException( + "mNativeObject is null. Have you called release() already?"); + } + + private native int nativeCreateFromSurfaceTexture(SurfaceTexture surfaceTexture) + throws OutOfResourcesException; + + private native void nativeRelease(int nativeObject); + private native void nativeDestroy(int nativeObject); + private native boolean nativeIsValid(int nativeObject); + + private native boolean nativeIsConsumerRunningBehind(int nativeObject); + + private native Canvas nativeLockCanvas(int nativeObject, Rect dirty); + private native void nativeUnlockCanvasAndPost(int nativeObject, Canvas canvas); + + private native int nativeCopyFrom(int nativeObject, int surfaceControlNativeObject); + private native int nativeReadFromParcel(int nativeObject, Parcel source); + private native void nativeWriteToParcel(int nativeObject, Parcel dest); } diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java new file mode 100644 index 0000000..dd288b9 --- /dev/null +++ b/core/java/android/view/SurfaceControl.java @@ -0,0 +1,575 @@ +/* + * Copyright (C) 2013 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 android.view; + +import dalvik.system.CloseGuard; +import android.graphics.Bitmap; +import android.graphics.Rect; +import android.graphics.Region; +import android.os.IBinder; +import android.os.SystemProperties; +import android.util.Log; + +/** + * SurfaceControl + * @hide + */ +public class SurfaceControl { + private static final String TAG = "SurfaceControl"; + private final CloseGuard mCloseGuard = CloseGuard.get(); + private String mName; + int mNativeObject; // package visibility only for Surface.java access + + private static final boolean HEADLESS = "1".equals( + SystemProperties.get("ro.config.headless", "0")); + + /** + * Exception thrown when a surface couldn't be created or resized. + */ + public static class OutOfResourcesException extends Exception { + public OutOfResourcesException() { + } + public OutOfResourcesException(String name) { + super(name); + } + } + + /* flags used in constructor (keep in sync with ISurfaceComposerClient.h) */ + + /** + * Surface creation flag: Surface is created hidden + */ + public static final int HIDDEN = 0x00000004; + + /** + * Surface creation flag: The surface contains secure content, special + * measures will be taken to disallow the surface's content to be copied + * from another process. In particular, screenshots and VNC servers will + * be disabled, but other measures can take place, for instance the + * surface might not be hardware accelerated. + * + */ + public static final int SECURE = 0x00000080; + + /** + * Surface creation flag: Creates a surface where color components are interpreted + * as "non pre-multiplied" by their alpha channel. Of course this flag is + * meaningless for surfaces without an alpha channel. By default + * surfaces are pre-multiplied, which means that each color component is + * already multiplied by its alpha value. In this case the blending + * equation used is: + * + * DEST = SRC + DEST * (1-SRC_ALPHA) + * + * By contrast, non pre-multiplied surfaces use the following equation: + * + * DEST = SRC * SRC_ALPHA * DEST * (1-SRC_ALPHA) + * + * pre-multiplied surfaces must always be used if transparent pixels are + * composited on top of each-other into the surface. A pre-multiplied + * surface can never lower the value of the alpha component of a given + * pixel. + * + * In some rare situations, a non pre-multiplied surface is preferable. + * + */ + public static final int NON_PREMULTIPLIED = 0x00000100; + + /** + * Surface creation flag: Indicates that the surface must be considered opaque, + * even if its pixel format is set to translucent. This can be useful if an + * application needs full RGBA 8888 support for instance but will + * still draw every pixel opaque. + * + */ + public static final int OPAQUE = 0x00000400; + + /** + * Surface creation flag: Application requires a hardware-protected path to an + * external display sink. If a hardware-protected path is not available, + * then this surface will not be displayed on the external sink. + * + */ + public static final int PROTECTED_APP = 0x00000800; + + // 0x1000 is reserved for an independent DRM protected flag in framework + + /** + * Surface creation flag: Creates a normal surface. + * This is the default. + * + */ + public static final int FX_SURFACE_NORMAL = 0x00000000; + + /** + * Surface creation flag: Creates a Blur surface. + * Everything behind this surface is blurred by some amount. + * The quality and refresh speed of the blur effect is not settable or guaranteed. + * It is an error to lock a Blur surface, since it doesn't have a backing store. + * + * @deprecated + */ + @Deprecated + public static final int FX_SURFACE_BLUR = 0x00010000; + + /** + * Surface creation flag: Creates a Dim surface. + * Everything behind this surface is dimmed by the amount specified + * in {@link #setAlpha}. It is an error to lock a Dim surface, since it + * doesn't have a backing store. + * + */ + public static final int FX_SURFACE_DIM = 0x00020000; + + /** + * + */ + public static final int FX_SURFACE_SCREENSHOT = 0x00030000; + + /** + * Mask used for FX values above. + * + */ + public static final int FX_SURFACE_MASK = 0x000F0000; + + /* flags used with setFlags() (keep in sync with ISurfaceComposer.h) */ + + /** + * Surface flag: Hide the surface. + * Equivalent to calling hide(). + */ + public static final int SURFACE_HIDDEN = 0x01; + + + /* built-in physical display ids (keep in sync with ISurfaceComposer.h) + * these are different from the logical display ids used elsewhere in the framework */ + + /** + * Built-in physical display id: Main display. + * Use only with {@link SurfaceControl#getBuiltInDisplay()}. + */ + public static final int BUILT_IN_DISPLAY_ID_MAIN = 0; + + /** + * Built-in physical display id: Attached HDMI display. + * Use only with {@link SurfaceControl#getBuiltInDisplay()}. + */ + public static final int BUILT_IN_DISPLAY_ID_HDMI = 1; + + + + /** + * Create a surface with a name. + * + * The surface creation flags specify what kind of surface to create and + * certain options such as whether the surface can be assumed to be opaque + * and whether it should be initially hidden. Surfaces should always be + * created with the {@link #HIDDEN} flag set to ensure that they are not + * made visible prematurely before all of the surface's properties have been + * configured. + * + * Good practice is to first create the surface with the {@link #HIDDEN} flag + * specified, open a transaction, set the surface layer, layer stack, alpha, + * and position, call {@link #show} if appropriate, and close the transaction. + * + * @param session The surface session, must not be null. + * @param name The surface name, must not be null. + * @param w The surface initial width. + * @param h The surface initial height. + * @param flags The surface creation flags. Should always include {@link #HIDDEN} + * in the creation flags. + */ + public SurfaceControl(SurfaceSession session, + String name, int w, int h, int format, int flags) + throws OutOfResourcesException { + if (session == null) { + throw new IllegalArgumentException("session must not be null"); + } + if (name == null) { + throw new IllegalArgumentException("name must not be null"); + } + + if ((flags & SurfaceControl.HIDDEN) == 0) { + Log.w(TAG, "Surfaces should always be created with the HIDDEN flag set " + + "to ensure that they are not made visible prematurely before " + + "all of the surface's properties have been configured. " + + "Set the other properties and make the surface visible within " + + "a transaction. New surface name: " + name, + new Throwable()); + } + + checkHeadless(); + + mName = name; + mNativeObject = nativeCreate(session, name, w, h, format, flags); + if (mNativeObject == 0) { + throw new OutOfResourcesException( + "Couldn't allocate SurfaceControl native object"); + } + + mCloseGuard.open("release"); + } + + @Override + protected void finalize() throws Throwable { + try { + if (mCloseGuard != null) { + mCloseGuard.warnIfOpen(); + } + if (mNativeObject != 0) { + nativeRelease(mNativeObject); + } + } finally { + super.finalize(); + } + } + + @Override + public String toString() { + return "Surface(name=" + mName + ")"; + } + + /** + * Release the local reference to the server-side surface. + * Always call release() when you're done with a Surface. + * This will make the surface invalid. + */ + public void release() { + if (mNativeObject != 0) { + nativeRelease(mNativeObject); + mNativeObject = 0; + } + mCloseGuard.close(); + } + + /** + * Free all server-side state associated with this surface and + * release this object's reference. This method can only be + * called from the process that created the service. + */ + public void destroy() { + if (mNativeObject != 0) { + nativeDestroy(mNativeObject); + mNativeObject = 0; + } + mCloseGuard.close(); + } + + private void checkNotReleased() { + if (mNativeObject == 0) throw new NullPointerException( + "mNativeObject is null. Have you called release() already?"); + } + + /* + * set surface parameters. + * needs to be inside open/closeTransaction block + */ + + /** start a transaction */ + public static void openTransaction() { + nativeOpenTransaction(); + } + + /** end a transaction */ + public static void closeTransaction() { + nativeCloseTransaction(); + } + + /** flag the transaction as an animation */ + public static void setAnimationTransaction() { + nativeSetAnimationTransaction(); + } + + public void setLayer(int zorder) { + checkNotReleased(); + nativeSetLayer(mNativeObject, zorder); + } + + public void setPosition(int x, int y) { + checkNotReleased(); + nativeSetPosition(mNativeObject, (float)x, (float)y); + } + + public void setPosition(float x, float y) { + checkNotReleased(); + nativeSetPosition(mNativeObject, x, y); + } + + public void setSize(int w, int h) { + checkNotReleased(); + nativeSetSize(mNativeObject, w, h); + } + + public void hide() { + checkNotReleased(); + nativeSetFlags(mNativeObject, SURFACE_HIDDEN, SURFACE_HIDDEN); + } + + public void show() { + checkNotReleased(); + nativeSetFlags(mNativeObject, 0, SURFACE_HIDDEN); + } + + public void setTransparentRegionHint(Region region) { + checkNotReleased(); + nativeSetTransparentRegionHint(mNativeObject, region); + } + + public void setAlpha(float alpha) { + checkNotReleased(); + nativeSetAlpha(mNativeObject, alpha); + } + + public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { + checkNotReleased(); + nativeSetMatrix(mNativeObject, dsdx, dtdx, dsdy, dtdy); + } + + public void setFlags(int flags, int mask) { + checkNotReleased(); + nativeSetFlags(mNativeObject, flags, mask); + } + + public void setWindowCrop(Rect crop) { + checkNotReleased(); + if (crop != null) { + nativeSetWindowCrop(mNativeObject, + crop.left, crop.top, crop.right, crop.bottom); + } else { + nativeSetWindowCrop(mNativeObject, 0, 0, 0, 0); + } + } + + public void setLayerStack(int layerStack) { + checkNotReleased(); + nativeSetLayerStack(mNativeObject, layerStack); + } + + /* + * set display parameters. + * needs to be inside open/closeTransaction block + */ + + /** + * Describes the properties of a physical display known to surface flinger. + */ + public static final class PhysicalDisplayInfo { + public int width; + public int height; + public float refreshRate; + public float density; + public float xDpi; + public float yDpi; + public boolean secure; + + public PhysicalDisplayInfo() { + } + + public PhysicalDisplayInfo(PhysicalDisplayInfo other) { + copyFrom(other); + } + + @Override + public boolean equals(Object o) { + return o instanceof PhysicalDisplayInfo && equals((PhysicalDisplayInfo)o); + } + + public boolean equals(PhysicalDisplayInfo other) { + return other != null + && width == other.width + && height == other.height + && refreshRate == other.refreshRate + && density == other.density + && xDpi == other.xDpi + && yDpi == other.yDpi + && secure == other.secure; + } + + @Override + public int hashCode() { + return 0; // don't care + } + + public void copyFrom(PhysicalDisplayInfo other) { + width = other.width; + height = other.height; + refreshRate = other.refreshRate; + density = other.density; + xDpi = other.xDpi; + yDpi = other.yDpi; + secure = other.secure; + } + + // For debugging purposes + @Override + public String toString() { + return "PhysicalDisplayInfo{" + width + " x " + height + ", " + refreshRate + " fps, " + + "density " + density + ", " + xDpi + " x " + yDpi + " dpi, secure " + secure + + "}"; + } + } + + public static void unblankDisplay(IBinder displayToken) { + if (displayToken == null) { + throw new IllegalArgumentException("displayToken must not be null"); + } + nativeUnblankDisplay(displayToken); + } + + public static void blankDisplay(IBinder displayToken) { + if (displayToken == null) { + throw new IllegalArgumentException("displayToken must not be null"); + } + nativeBlankDisplay(displayToken); + } + + public static boolean getDisplayInfo(IBinder displayToken, SurfaceControl.PhysicalDisplayInfo outInfo) { + if (displayToken == null) { + throw new IllegalArgumentException("displayToken must not be null"); + } + if (outInfo == null) { + throw new IllegalArgumentException("outInfo must not be null"); + } + return nativeGetDisplayInfo(displayToken, outInfo); + } + + public static void setDisplayProjection(IBinder displayToken, + int orientation, Rect layerStackRect, Rect displayRect) { + if (displayToken == null) { + throw new IllegalArgumentException("displayToken must not be null"); + } + if (layerStackRect == null) { + throw new IllegalArgumentException("layerStackRect must not be null"); + } + if (displayRect == null) { + throw new IllegalArgumentException("displayRect must not be null"); + } + nativeSetDisplayProjection(displayToken, orientation, + layerStackRect.left, layerStackRect.top, layerStackRect.right, layerStackRect.bottom, + displayRect.left, displayRect.top, displayRect.right, displayRect.bottom); + } + + public static void setDisplayLayerStack(IBinder displayToken, int layerStack) { + if (displayToken == null) { + throw new IllegalArgumentException("displayToken must not be null"); + } + nativeSetDisplayLayerStack(displayToken, layerStack); + } + + public static void setDisplaySurface(IBinder displayToken, Surface surface) { + if (displayToken == null) { + throw new IllegalArgumentException("displayToken must not be null"); + } + if (surface == null) { + throw new IllegalArgumentException("surface must not be null"); + } + if (surface.mNativeObject == 0) + throw new NullPointerException("Surface native object is null. Are you using a released surface?"); + + nativeSetDisplaySurface(displayToken, surface.mNativeObject); + } + + public static IBinder createDisplay(String name, boolean secure) { + if (name == null) { + throw new IllegalArgumentException("name must not be null"); + } + return nativeCreateDisplay(name, secure); + } + + public static IBinder getBuiltInDisplay(int builtInDisplayId) { + return nativeGetBuiltInDisplay(builtInDisplayId); + } + + + /** + * Copy the current screen contents into a bitmap and return it. + * + * @param width The desired width of the returned bitmap; the raw + * screen will be scaled down to this size. + * @param height The desired height of the returned bitmap; the raw + * screen will be scaled down to this size. + * @param minLayer The lowest (bottom-most Z order) surface layer to + * include in the screenshot. + * @param maxLayer The highest (top-most Z order) surface layer to + * include in the screenshot. + * @return Returns a Bitmap containing the screen contents, or null + * if an error occurs. + * + */ + public static Bitmap screenshot(int width, int height, int minLayer, int maxLayer) { + // TODO: should take the display as a parameter + IBinder displayToken = SurfaceControl.getBuiltInDisplay(SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN); + return nativeScreenshot(displayToken, width, height, minLayer, maxLayer, false); + } + + /** + * Like {@link SurfaceControl#screenshot(int, int, int, int)} but includes all + * Surfaces in the screenshot. + * + */ + public static Bitmap screenshot(int width, int height) { + // TODO: should take the display as a parameter + IBinder displayToken = SurfaceControl.getBuiltInDisplay(SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN); + return nativeScreenshot(displayToken, width, height, 0, 0, true); + } + + private static void checkHeadless() { + if (HEADLESS) { + throw new UnsupportedOperationException("Device is headless"); + } + } + + + + private native int nativeCreate(SurfaceSession session, String name, + int w, int h, int format, int flags) + throws OutOfResourcesException; + private native void nativeRelease(int nativeObject); + private native void nativeDestroy(int nativeObject); + + private static native Bitmap nativeScreenshot(IBinder displayToken, + int width, int height, int minLayer, int maxLayer, boolean allLayers); + + private static native void nativeOpenTransaction(); + private static native void nativeCloseTransaction(); + private static native void nativeSetAnimationTransaction(); + + private native void nativeSetLayer(int nativeObject, int zorder); + private native void nativeSetPosition(int nativeObject, float x, float y); + private native void nativeSetSize(int nativeObject, int w, int h); + private native void nativeSetTransparentRegionHint(int nativeObject, Region region); + private native void nativeSetAlpha(int nativeObject, float alpha); + private native void nativeSetMatrix(int nativeObject, float dsdx, float dtdx, float dsdy, float dtdy); + private native void nativeSetFlags(int nativeObject, int flags, int mask); + private native void nativeSetWindowCrop(int nativeObject, int l, int t, int r, int b); + private native void nativeSetLayerStack(int nativeObject, int layerStack); + + private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId); + private static native IBinder nativeCreateDisplay(String name, boolean secure); + private static native void nativeSetDisplaySurface( + IBinder displayToken, int nativeSurfaceObject); + private static native void nativeSetDisplayLayerStack( + IBinder displayToken, int layerStack); + private static native void nativeSetDisplayProjection( + IBinder displayToken, int orientation, + int l, int t, int r, int b, + int L, int T, int R, int B); + private static native boolean nativeGetDisplayInfo( + IBinder displayToken, SurfaceControl.PhysicalDisplayInfo outInfo); + private static native void nativeBlankDisplay(IBinder displayToken); + private static native void nativeUnblankDisplay(IBinder displayToken); +} diff --git a/core/jni/Android.mk b/core/jni/Android.mk index 5337329..c6b7631 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -42,6 +42,7 @@ LOCAL_SRC_FILES:= \ android_emoji_EmojiFactory.cpp \ android_view_DisplayEventReceiver.cpp \ android_view_Surface.cpp \ + android_view_SurfaceControl.cpp \ android_view_SurfaceSession.cpp \ android_view_TextureView.cpp \ android_view_InputChannel.cpp \ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index aa59b43..86d3cb6 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -47,8 +47,6 @@ using namespace android; -extern void register_BindTest(); - extern int register_android_os_Binder(JNIEnv* env); extern int register_android_os_Process(JNIEnv* env); extern int register_android_graphics_Bitmap(JNIEnv*); @@ -121,6 +119,7 @@ extern int register_android_view_GLES20DisplayList(JNIEnv* env); extern int register_android_view_GLES20Canvas(JNIEnv* env); extern int register_android_view_HardwareRenderer(JNIEnv* env); extern int register_android_view_Surface(JNIEnv* env); +extern int register_android_view_SurfaceControl(JNIEnv* env); extern int register_android_view_SurfaceSession(JNIEnv* env); extern int register_android_view_TextureView(JNIEnv* env); extern int register_android_database_CursorWindow(JNIEnv* env); @@ -1113,6 +1112,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_view_GLES20Canvas), REG_JNI(register_android_view_HardwareRenderer), REG_JNI(register_android_view_Surface), + REG_JNI(register_android_view_SurfaceControl), REG_JNI(register_android_view_SurfaceSession), REG_JNI(register_android_view_TextureView), REG_JNI(register_com_google_android_gles_jni_EGLImpl), diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index 0e0893b..7c65662 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -23,6 +23,7 @@ #include "JNIHelp.h" #include "android_runtime/AndroidRuntime.h" #include <android_runtime/android_graphics_SurfaceTexture.h> +#include <android_runtime/android_view_Surface.h> #include <cutils/properties.h> #include <utils/Vector.h> @@ -36,7 +37,6 @@ using namespace android; struct fields_t { jfieldID context; - jfieldID surface; jfieldID facing; jfieldID orientation; jfieldID canDisableShutterSound; @@ -537,10 +537,8 @@ static void android_hardware_Camera_setPreviewDisplay(JNIEnv *env, jobject thiz, sp<Camera> camera = get_native_camera(env, thiz, NULL); if (camera == 0) return; - sp<Surface> surface = NULL; - if (jSurface != NULL) { - surface = reinterpret_cast<Surface*>(env->GetIntField(jSurface, fields.surface)); - } + sp<Surface> surface = android_view_Surface_getSurface(env, jSurface); + if (camera->setPreviewDisplay(surface) != NO_ERROR) { jniThrowException(env, "java/io/IOException", "setPreviewDisplay failed"); } @@ -965,7 +963,6 @@ int register_android_hardware_Camera(JNIEnv *env) { field fields_to_find[] = { { "android/hardware/Camera", "mNativeContext", "I", &fields.context }, - { "android/view/Surface", ANDROID_VIEW_SURFACE_JNI_ID, "I", &fields.surface }, { "android/hardware/Camera$CameraInfo", "facing", "I", &fields.facing }, { "android/hardware/Camera$CameraInfo", "orientation", "I", &fields.orientation }, { "android/hardware/Camera$CameraInfo", "canDisableShutterSound", "Z", diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index 1f15370..6f71868 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -18,41 +18,30 @@ #include <stdio.h> +#include "jni.h" +#include "JNIHelp.h" #include "android_os_Parcel.h" -#include "android_util_Binder.h" #include "android/graphics/GraphicsJNI.h" -#include "android/graphics/Region.h" -#include <binder/IMemory.h> +#include <android_runtime/AndroidRuntime.h> +#include <android_runtime/android_view_Surface.h> +#include <android_runtime/android_graphics_SurfaceTexture.h> -#include <gui/ISurfaceComposer.h> #include <gui/Surface.h> -#include <gui/SurfaceComposerClient.h> #include <gui/GLConsumer.h> -#include <ui/DisplayInfo.h> #include <ui/Rect.h> #include <ui/Region.h> -#include <EGL/egl.h> - #include <SkCanvas.h> #include <SkBitmap.h> #include <SkRegion.h> -#include <SkPixelRef.h> -#include "jni.h" -#include "JNIHelp.h" -#include <android_runtime/AndroidRuntime.h> -#include <android_runtime/android_view_Surface.h> -#include <android_runtime/android_view_SurfaceSession.h> -#include <android_runtime/android_graphics_SurfaceTexture.h> #include <utils/misc.h> #include <utils/Log.h> #include <ScopedUtfChars.h> - // ---------------------------------------------------------------------------- namespace android { @@ -62,8 +51,7 @@ static const char* const OutOfResourcesException = static struct { jclass clazz; - jfieldID mNativeSurface; - jfieldID mNativeSurfaceControl; + jfieldID mNativeObject; jfieldID mGenerationId; jfieldID mCanvas; jfieldID mCanvasSaveCount; @@ -82,166 +70,19 @@ static struct { jfieldID mSurfaceFormat; } gCanvasClassInfo; -static struct { - jfieldID width; - jfieldID height; - jfieldID refreshRate; - jfieldID density; - jfieldID xDpi; - jfieldID yDpi; - jfieldID secure; -} gPhysicalDisplayInfoClassInfo; - - -class ScreenshotPixelRef : public SkPixelRef { -public: - ScreenshotPixelRef(SkColorTable* ctable) { - fCTable = ctable; - SkSafeRef(ctable); - setImmutable(); - } - - virtual ~ScreenshotPixelRef() { - SkSafeUnref(fCTable); - } - - status_t update(const sp<IBinder>& display, int width, int height, - int minLayer, int maxLayer, bool allLayers) { - status_t res = (width > 0 && height > 0) - ? (allLayers - ? mScreenshot.update(display, width, height) - : mScreenshot.update(display, width, height, minLayer, maxLayer)) - : mScreenshot.update(display); - if (res != NO_ERROR) { - return res; - } - - return NO_ERROR; - } - - uint32_t getWidth() const { - return mScreenshot.getWidth(); - } - - uint32_t getHeight() const { - return mScreenshot.getHeight(); - } - - uint32_t getStride() const { - return mScreenshot.getStride(); - } - - uint32_t getFormat() const { - return mScreenshot.getFormat(); - } - -protected: - // overrides from SkPixelRef - virtual void* onLockPixels(SkColorTable** ct) { - *ct = fCTable; - return (void*)mScreenshot.getPixels(); - } - - virtual void onUnlockPixels() { - } - -private: - ScreenshotClient mScreenshot; - SkColorTable* fCTable; - - typedef SkPixelRef INHERITED; -}; - - // ---------------------------------------------------------------------------- -static sp<SurfaceControl> getSurfaceControl(JNIEnv* env, jobject surfaceObj) { - return reinterpret_cast<SurfaceControl*>( - env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl)); -} - -static void setSurfaceControl(JNIEnv* env, jobject surfaceObj, - const sp<SurfaceControl>& surface) { - SurfaceControl* const p = reinterpret_cast<SurfaceControl*>( - env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl)); - if (surface.get()) { - surface->incStrong(surfaceObj); - } - if (p) { - p->decStrong(surfaceObj); - } - env->SetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl, - reinterpret_cast<jint>(surface.get())); -} - -static sp<Surface> getSurface(JNIEnv* env, jobject surfaceObj) { - sp<Surface> result(android_view_Surface_getSurface(env, surfaceObj)); - if (result == NULL) { - /* - * if this method is called from the WindowManager's process, it means - * the client is is not remote, and therefore is allowed to have - * a Surface (data), so we create it here. - * If we don't have a SurfaceControl, it means we're in a different - * process. - */ - - SurfaceControl* const control = reinterpret_cast<SurfaceControl*>( - env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl)); - if (control) { - result = control->getSurface(); - if (result != NULL) { - result->incStrong(surfaceObj); - env->SetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface, - reinterpret_cast<jint>(result.get())); - } - } - } - return result; -} - -sp<ANativeWindow> android_view_Surface_getNativeWindow(JNIEnv* env, jobject surfaceObj) { - return getSurface(env, surfaceObj); -} - bool android_view_Surface_isInstanceOf(JNIEnv* env, jobject obj) { return env->IsInstanceOf(obj, gSurfaceClassInfo.clazz); } -sp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj) { - return reinterpret_cast<Surface*>( - env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface)); -} - -static void setSurface(JNIEnv* env, jobject surfaceObj, const sp<Surface>& surface) { - Surface* const p = reinterpret_cast<Surface*>( - env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface)); - if (surface.get()) { - surface->incStrong(surfaceObj); - } - if (p) { - p->decStrong(surfaceObj); - } - env->SetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface, - reinterpret_cast<jint>(surface.get())); - - // This test is conservative and it would be better to compare the ISurfaces - if (p && p != surface.get()) { - jint generationId = env->GetIntField(surfaceObj, - gSurfaceClassInfo.mGenerationId); - generationId++; - env->SetIntField(surfaceObj, - gSurfaceClassInfo.mGenerationId, generationId); - } +sp<ANativeWindow> android_view_Surface_getNativeWindow(JNIEnv* env, jobject surfaceObj) { + return android_view_Surface_getSurface(env, surfaceObj); } -static sp<IGraphicBufferProducer> getISurfaceTexture(JNIEnv* env, jobject surfaceObj) { - if (surfaceObj) { - sp<Surface> surface(getSurface(env, surfaceObj)); - if (surface != NULL) { - return surface->getSurfaceTexture(); - } - } - return NULL; +sp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj) { + return reinterpret_cast<Surface *>( + env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeObject)); } jobject android_view_Surface_createFromISurfaceTexture(JNIEnv* env, @@ -255,7 +96,7 @@ jobject android_view_Surface_createFromISurfaceTexture(JNIEnv* env, return NULL; } - jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz, gSurfaceClassInfo.ctor); + jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz, gSurfaceClassInfo.ctor, surface.get()); if (surfaceObj == NULL) { if (env->ExceptionCheck()) { ALOGE("Could not create instance of Surface from IGraphicBufferProducer."); @@ -264,96 +105,55 @@ jobject android_view_Surface_createFromISurfaceTexture(JNIEnv* env, } return NULL; } - - setSurface(env, surfaceObj, surface); + surface->incStrong(surfaceObj); return surfaceObj; } - // ---------------------------------------------------------------------------- -static void nativeCreate(JNIEnv* env, jobject surfaceObj, jobject sessionObj, - jstring nameStr, jint w, jint h, jint format, jint flags) { - ScopedUtfChars name(env, nameStr); - sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj)); - - sp<SurfaceControl> surface = client->createSurface( - String8(name.c_str()), w, h, format, flags); - if (surface == NULL) { - jniThrowException(env, OutOfResourcesException, NULL); - return; - } - - setSurfaceControl(env, surfaceObj, surface); -} - -static void nativeCreateFromSurfaceTexture(JNIEnv* env, jobject surfaceObj, +static jint nativeCreateFromSurfaceTexture(JNIEnv* env, jobject surfaceObj, jobject surfaceTextureObj) { sp<GLConsumer> st(SurfaceTexture_getSurfaceTexture(env, surfaceTextureObj)); if (st == NULL) { jniThrowException(env, "java/lang/IllegalArgumentException", "SurfaceTexture has already been released"); - return; + return 0; } sp<IGraphicBufferProducer> bq = st->getBufferQueue(); - sp<Surface> surface(new Surface(bq)); if (surface == NULL) { jniThrowException(env, OutOfResourcesException, NULL); - return; + return 0; } - setSurface(env, surfaceObj, surface); -} - -static void nativeRelease(JNIEnv* env, jobject surfaceObj) { - setSurfaceControl(env, surfaceObj, NULL); - setSurface(env, surfaceObj, NULL); + surface->incStrong(surfaceObj); + return int(surface.get()); } -static void nativeDestroy(JNIEnv* env, jobject surfaceObj) { - sp<SurfaceControl> surfaceControl(getSurfaceControl(env, surfaceObj)); - if (SurfaceControl::isValid(surfaceControl)) { - surfaceControl->clear(); - } - setSurfaceControl(env, surfaceObj, NULL); - setSurface(env, surfaceObj, NULL); +static void nativeRelease(JNIEnv* env, jobject surfaceObj, jint nativeObject) { + sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject)); + sur->decStrong(surfaceObj); } -static jboolean nativeIsValid(JNIEnv* env, jobject surfaceObj) { - sp<SurfaceControl> surfaceControl(getSurfaceControl(env, surfaceObj)); - if (surfaceControl != NULL) { - return SurfaceControl::isValid(surfaceControl) ? JNI_TRUE : JNI_FALSE; - } - - sp<Surface> surface(getSurface(env, surfaceObj)); - return Surface::isValid(surface) ? JNI_TRUE : JNI_FALSE; +static void nativeDestroy(JNIEnv* env, jobject surfaceObj, jint nativeObject) { + sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject)); + sur->decStrong(surfaceObj); } -static jint nativeGetIdentity(JNIEnv* env, jobject surfaceObj) { - sp<SurfaceControl> control(getSurfaceControl(env, surfaceObj)); - if (control != NULL) { - return jint(control->getIdentity()); - } - - sp<Surface> surface(getSurface(env, surfaceObj)); - if (surface != NULL) { - return jint(surface->getIdentity()); - } - - return -1; +static jboolean nativeIsValid(JNIEnv* env, jobject surfaceObj, jint nativeObject) { + sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject)); + return Surface::isValid(sur) ? JNI_TRUE : JNI_FALSE; } -static jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jobject surfaceObj) { - sp<Surface> surface(getSurface(env, surfaceObj)); - if (!Surface::isValid(surface)) { +static jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jobject surfaceObj, jint nativeObject) { + sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject)); + if (!Surface::isValid(sur)) { doThrowIAE(env); return JNI_FALSE; } - int value = 0; - ANativeWindow* anw = static_cast<ANativeWindow*>(surface.get()); + ANativeWindow* anw = static_cast<ANativeWindow*>(sur.get()); anw->query(anw, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value); return value; } @@ -373,8 +173,9 @@ static inline SkBitmap::Config convertPixelFormat(PixelFormat format) { } } -static jobject nativeLockCanvas(JNIEnv* env, jobject surfaceObj, jobject dirtyRectObj) { - sp<Surface> surface(getSurface(env, surfaceObj)); +static jobject nativeLockCanvas(JNIEnv* env, jobject surfaceObj, jint nativeObject, jobject dirtyRectObj) { + sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject)); + if (!Surface::isValid(surface)) { doThrowIAE(env); return NULL; @@ -454,14 +255,14 @@ static jobject nativeLockCanvas(JNIEnv* env, jobject surfaceObj, jobject dirtyRe return canvasObj; } -static void nativeUnlockCanvasAndPost(JNIEnv* env, jobject surfaceObj, jobject canvasObj) { +static void nativeUnlockCanvasAndPost(JNIEnv* env, jobject surfaceObj, jint nativeObject, jobject canvasObj) { jobject ownCanvasObj = env->GetObjectField(surfaceObj, gSurfaceClassInfo.mCanvas); if (!env->IsSameObject(ownCanvasObj, canvasObj)) { doThrowIAE(env); return; } - sp<Surface> surface(getSurface(env, surfaceObj)); + sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject)); if (!Surface::isValid(surface)) { return; } @@ -481,395 +282,81 @@ static void nativeUnlockCanvasAndPost(JNIEnv* env, jobject surfaceObj, jobject c } } -static jobject nativeScreenshot(JNIEnv* env, jclass clazz, jobject displayTokenObj, - jint width, jint height, jint minLayer, jint maxLayer, bool allLayers) { - sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj); - if (displayToken == NULL) { - return NULL; - } - - ScreenshotPixelRef* pixels = new ScreenshotPixelRef(NULL); - if (pixels->update(displayToken, width, height, - minLayer, maxLayer, allLayers) != NO_ERROR) { - delete pixels; - return NULL; - } - - uint32_t w = pixels->getWidth(); - uint32_t h = pixels->getHeight(); - uint32_t s = pixels->getStride(); - uint32_t f = pixels->getFormat(); - ssize_t bpr = s * android::bytesPerPixel(f); - - SkBitmap* bitmap = new SkBitmap(); - bitmap->setConfig(convertPixelFormat(f), w, h, bpr); - if (f == PIXEL_FORMAT_RGBX_8888) { - bitmap->setIsOpaque(true); - } - - if (w > 0 && h > 0) { - bitmap->setPixelRef(pixels)->unref(); - bitmap->lockPixels(); - } else { - // be safe with an empty bitmap. - delete pixels; - bitmap->setPixels(NULL); - } - - return GraphicsJNI::createBitmap(env, bitmap, false, NULL); -} - -static void nativeOpenTransaction(JNIEnv* env, jclass clazz) { - SurfaceComposerClient::openGlobalTransaction(); -} - -static void nativeCloseTransaction(JNIEnv* env, jclass clazz) { - SurfaceComposerClient::closeGlobalTransaction(); -} - -static void nativeSetAnimationTransaction(JNIEnv* env, jclass clazz) { - SurfaceComposerClient::setAnimationTransaction(); -} - -static void nativeSetLayer(JNIEnv* env, jobject surfaceObj, jint zorder) { - sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); - if (surface == NULL) return; - - status_t err = surface->setLayer(zorder); - if (err < 0 && err != NO_INIT) { - doThrowIAE(env); - } -} - -static void nativeSetPosition(JNIEnv* env, jobject surfaceObj, jfloat x, jfloat y) { - sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); - if (surface == NULL) return; - - status_t err = surface->setPosition(x, y); - if (err < 0 && err != NO_INIT) { - doThrowIAE(env); - } -} - -static void nativeSetSize(JNIEnv* env, jobject surfaceObj, jint w, jint h) { - sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); - if (surface == NULL) return; - - status_t err = surface->setSize(w, h); - if (err < 0 && err != NO_INIT) { - doThrowIAE(env); - } -} - -static void nativeSetFlags(JNIEnv* env, jobject surfaceObj, jint flags, jint mask) { - sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); - if (surface == NULL) return; - - status_t err = surface->setFlags(flags, mask); - if (err < 0 && err != NO_INIT) { - doThrowIAE(env); - } -} - -static void nativeSetTransparentRegionHint(JNIEnv* env, jobject surfaceObj, jobject regionObj) { - sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); - if (surface == NULL) return; - - SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj); - if (!region) { - doThrowIAE(env); - return; - } - - const SkIRect& b(region->getBounds()); - Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom)); - if (region->isComplex()) { - SkRegion::Iterator it(*region); - while (!it.done()) { - const SkIRect& r(it.rect()); - reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom); - it.next(); - } - } - - status_t err = surface->setTransparentRegionHint(reg); - if (err < 0 && err != NO_INIT) { - doThrowIAE(env); - } -} - -static void nativeSetAlpha(JNIEnv* env, jobject surfaceObj, jfloat alpha) { - sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); - if (surface == NULL) return; - - status_t err = surface->setAlpha(alpha); - if (err < 0 && err != NO_INIT) { - doThrowIAE(env); - } -} - -static void nativeSetMatrix(JNIEnv* env, jobject surfaceObj, - jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy) { - sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); - if (surface == NULL) return; - - status_t err = surface->setMatrix(dsdx, dtdx, dsdy, dtdy); - if (err < 0 && err != NO_INIT) { - doThrowIAE(env); - } -} - -static void nativeSetWindowCrop(JNIEnv* env, jobject surfaceObj, jobject cropObj) { - const sp<SurfaceControl>& surface(getSurfaceControl(env, surfaceObj)); - if (surface == NULL) return; - - Rect crop; - if (cropObj) { - crop.left = env->GetIntField(cropObj, gRectClassInfo.left); - crop.top = env->GetIntField(cropObj, gRectClassInfo.top); - crop.right = env->GetIntField(cropObj, gRectClassInfo.right); - crop.bottom = env->GetIntField(cropObj, gRectClassInfo.bottom); - } else { - crop.left = crop.top = crop.right = crop.bottom = 0; - } - - status_t err = surface->setCrop(crop); - if (err < 0 && err != NO_INIT) { - doThrowIAE(env); - } -} - -static void nativeSetLayerStack(JNIEnv* env, jobject surfaceObj, jint layerStack) { - sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); - if (surface == NULL) return; - - status_t err = surface->setLayerStack(layerStack); - if (err < 0 && err != NO_INIT) { - doThrowIAE(env); - } -} - -static jobject nativeGetBuiltInDisplay(JNIEnv* env, jclass clazz, jint id) { - sp<IBinder> token(SurfaceComposerClient::getBuiltInDisplay(id)); - return javaObjectForIBinder(env, token); -} - -static jobject nativeCreateDisplay(JNIEnv* env, jclass clazz, jstring nameObj, - jboolean secure) { - ScopedUtfChars name(env, nameObj); - sp<IBinder> token(SurfaceComposerClient::createDisplay( - String8(name.c_str()), bool(secure))); - return javaObjectForIBinder(env, token); -} - -static void nativeSetDisplaySurface(JNIEnv* env, jclass clazz, - jobject tokenObj, jobject surfaceObj) { - sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); - if (token == NULL) return; - - sp<IGraphicBufferProducer> bufferProducer(getISurfaceTexture(env, surfaceObj)); - SurfaceComposerClient::setDisplaySurface(token, bufferProducer); -} - -static void nativeSetDisplayLayerStack(JNIEnv* env, jclass clazz, - jobject tokenObj, jint layerStack) { - sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); - if (token == NULL) return; - - SurfaceComposerClient::setDisplayLayerStack(token, layerStack); -} - -static void nativeSetDisplayProjection(JNIEnv* env, jclass clazz, - jobject tokenObj, jint orientation, jobject layerStackRectObj, jobject displayRectObj) { - sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); - if (token == NULL) return; - - Rect layerStackRect; - layerStackRect.left = env->GetIntField(layerStackRectObj, gRectClassInfo.left); - layerStackRect.top = env->GetIntField(layerStackRectObj, gRectClassInfo.top); - layerStackRect.right = env->GetIntField(layerStackRectObj, gRectClassInfo.right); - layerStackRect.bottom = env->GetIntField(layerStackRectObj, gRectClassInfo.bottom); - - Rect displayRect; - displayRect.left = env->GetIntField(displayRectObj, gRectClassInfo.left); - displayRect.top = env->GetIntField(displayRectObj, gRectClassInfo.top); - displayRect.right = env->GetIntField(displayRectObj, gRectClassInfo.right); - displayRect.bottom = env->GetIntField(displayRectObj, gRectClassInfo.bottom); - - SurfaceComposerClient::setDisplayProjection(token, orientation, layerStackRect, displayRect); -} - -static jboolean nativeGetDisplayInfo(JNIEnv* env, jclass clazz, - jobject tokenObj, jobject infoObj) { - sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); - if (token == NULL) return JNI_FALSE; - - DisplayInfo info; - if (SurfaceComposerClient::getDisplayInfo(token, &info)) { - return JNI_FALSE; - } - - env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.width, info.w); - env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.height, info.h); - env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.refreshRate, info.fps); - env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.density, info.density); - env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.xDpi, info.xdpi); - env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.yDpi, info.ydpi); - env->SetBooleanField(infoObj, gPhysicalDisplayInfoClassInfo.secure, info.secure); - return JNI_TRUE; -} - -static void nativeBlankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) { - sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); - if (token == NULL) return; - - ALOGD_IF_SLOW(100, "Excessive delay in blankDisplay() while turning screen off"); - SurfaceComposerClient::blankDisplay(token); -} - -static void nativeUnblankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) { - sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); - if (token == NULL) return; - - ALOGD_IF_SLOW(100, "Excessive delay in unblankDisplay() while turning screen on"); - SurfaceComposerClient::unblankDisplay(token); -} - // ---------------------------------------------------------------------------- -static void nativeCopyFrom(JNIEnv* env, jobject surfaceObj, jobject otherObj) { +static jint nativeCopyFrom(JNIEnv* env, jobject surfaceObj, + jint nativeObject, jint surfaceControlNativeObj) { /* * This is used by the WindowManagerService just after constructing * a Surface and is necessary for returning the Surface reference to * the caller. At this point, we should only have a SurfaceControl. */ - sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); - sp<SurfaceControl> other(getSurfaceControl(env, otherObj)); - if (!SurfaceControl::isSameSurface(surface, other)) { - // we reassign the surface only if it's a different one - // otherwise we would loose our client-side state. - setSurfaceControl(env, surfaceObj, other); + sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj)); + sp<Surface> other(ctrl->getSurface()); + if (other != NULL) { + other->incStrong(surfaceObj); + } + + sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject)); + if (sur != NULL) { + sur->decStrong(surfaceObj); } -} -static void nativeTransferFrom(JNIEnv* env, jobject surfaceObj, jobject otherObj) { - sp<SurfaceControl> control(getSurfaceControl(env, otherObj)); - sp<Surface> surface(android_view_Surface_getSurface(env, otherObj)); - setSurfaceControl(env, surfaceObj, control); - setSurface(env, surfaceObj, surface); - setSurfaceControl(env, otherObj, NULL); - setSurface(env, otherObj, NULL); + return int(other.get()); } -static void nativeReadFromParcel(JNIEnv* env, jobject surfaceObj, jobject parcelObj) { +static jint nativeReadFromParcel(JNIEnv* env, jobject surfaceObj, + jint nativeObject, jobject parcelObj) { Parcel* parcel = parcelForJavaObject(env, parcelObj); if (parcel == NULL) { doThrowNPE(env); - return; + return 0; } - - sp<Surface> surface(Surface::readFromParcel(*parcel)); - setSurfaceControl(env, surfaceObj, NULL); - setSurface(env, surfaceObj, surface); + sp<Surface> self(reinterpret_cast<Surface *>(nativeObject)); + if (self != NULL) { + self->decStrong(surfaceObj); + } + sp<Surface> sur(Surface::readFromParcel(*parcel)); + if (sur != NULL) { + sur->incStrong(surfaceObj); + } + return int(sur.get()); } -static void nativeWriteToParcel(JNIEnv* env, jobject surfaceObj, jobject parcelObj) { +static void nativeWriteToParcel(JNIEnv* env, jobject surfaceObj, + jint nativeObject, jobject parcelObj) { Parcel* parcel = parcelForJavaObject(env, parcelObj); if (parcel == NULL) { doThrowNPE(env); return; } - - // The Java instance may have a SurfaceControl (in the case of the - // WindowManager or a system app). In that case, we defer to the - // SurfaceControl to send its ISurface. Otherwise, if the Surface is - // available we let it parcel itself. Finally, if the Surface is also - // NULL we fall back to using the SurfaceControl path which sends an - // empty surface; this matches legacy behavior. - sp<SurfaceControl> control(getSurfaceControl(env, surfaceObj)); - if (control != NULL) { - SurfaceControl::writeSurfaceToParcel(control, parcel); - } else { - sp<Surface> surface(android_view_Surface_getSurface(env, surfaceObj)); - if (surface != NULL) { - Surface::writeToParcel(surface, parcel); - } else { - SurfaceControl::writeSurfaceToParcel(NULL, parcel); - } - } + sp<Surface> self(reinterpret_cast<Surface *>(nativeObject)); + Surface::writeToParcel(self, parcel); } // ---------------------------------------------------------------------------- static JNINativeMethod gSurfaceMethods[] = { - {"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIII)V", - (void*)nativeCreate }, - {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)V", + {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)I", (void*)nativeCreateFromSurfaceTexture }, - {"nativeRelease", "()V", + {"nativeRelease", "(I)V", (void*)nativeRelease }, - {"nativeDestroy", "()V", + {"nativeDestroy", "(I)V", (void*)nativeDestroy }, - {"nativeIsValid", "()Z", + {"nativeIsValid", "(I)Z", (void*)nativeIsValid }, - {"nativeGetIdentity", "()I", - (void*)nativeGetIdentity }, - {"nativeIsConsumerRunningBehind", "()Z", + {"nativeIsConsumerRunningBehind", "(I)Z", (void*)nativeIsConsumerRunningBehind }, - {"nativeLockCanvas", "(Landroid/graphics/Rect;)Landroid/graphics/Canvas;", + {"nativeLockCanvas", "(ILandroid/graphics/Rect;)Landroid/graphics/Canvas;", (void*)nativeLockCanvas }, - {"nativeUnlockCanvasAndPost", "(Landroid/graphics/Canvas;)V", + {"nativeUnlockCanvasAndPost", "(ILandroid/graphics/Canvas;)V", (void*)nativeUnlockCanvasAndPost }, - {"nativeScreenshot", "(Landroid/os/IBinder;IIIIZ)Landroid/graphics/Bitmap;", - (void*)nativeScreenshot }, - {"nativeOpenTransaction", "()V", - (void*)nativeOpenTransaction }, - {"nativeCloseTransaction", "()V", - (void*)nativeCloseTransaction }, - {"nativeSetAnimationTransaction", "()V", - (void*)nativeSetAnimationTransaction }, - {"nativeSetLayer", "(I)V", - (void*)nativeSetLayer }, - {"nativeSetPosition", "(FF)V", - (void*)nativeSetPosition }, - {"nativeSetSize", "(II)V", - (void*)nativeSetSize }, - {"nativeSetTransparentRegionHint", "(Landroid/graphics/Region;)V", - (void*)nativeSetTransparentRegionHint }, - {"nativeSetAlpha", "(F)V", - (void*)nativeSetAlpha }, - {"nativeSetMatrix", "(FFFF)V", - (void*)nativeSetMatrix }, - {"nativeSetFlags", "(II)V", - (void*)nativeSetFlags }, - {"nativeSetWindowCrop", "(Landroid/graphics/Rect;)V", - (void*)nativeSetWindowCrop }, - {"nativeSetLayerStack", "(I)V", - (void*)nativeSetLayerStack }, - {"nativeGetBuiltInDisplay", "(I)Landroid/os/IBinder;", - (void*)nativeGetBuiltInDisplay }, - {"nativeCreateDisplay", "(Ljava/lang/String;Z)Landroid/os/IBinder;", - (void*)nativeCreateDisplay }, - {"nativeSetDisplaySurface", "(Landroid/os/IBinder;Landroid/view/Surface;)V", - (void*)nativeSetDisplaySurface }, - {"nativeSetDisplayLayerStack", "(Landroid/os/IBinder;I)V", - (void*)nativeSetDisplayLayerStack }, - {"nativeSetDisplayProjection", "(Landroid/os/IBinder;ILandroid/graphics/Rect;Landroid/graphics/Rect;)V", - (void*)nativeSetDisplayProjection }, - {"nativeGetDisplayInfo", "(Landroid/os/IBinder;Landroid/view/Surface$PhysicalDisplayInfo;)Z", - (void*)nativeGetDisplayInfo }, - {"nativeBlankDisplay", "(Landroid/os/IBinder;)V", - (void*)nativeBlankDisplay }, - {"nativeUnblankDisplay", "(Landroid/os/IBinder;)V", - (void*)nativeUnblankDisplay }, - {"nativeCopyFrom", "(Landroid/view/Surface;)V", + {"nativeCopyFrom", "(II)I", (void*)nativeCopyFrom }, - {"nativeTransferFrom", "(Landroid/view/Surface;)V", - (void*)nativeTransferFrom }, - {"nativeReadFromParcel", "(Landroid/os/Parcel;)V", + {"nativeReadFromParcel", "(ILandroid/os/Parcel;)I", (void*)nativeReadFromParcel }, - {"nativeWriteToParcel", "(Landroid/os/Parcel;)V", + {"nativeWriteToParcel", "(ILandroid/os/Parcel;)V", (void*)nativeWriteToParcel }, }; @@ -880,17 +367,15 @@ int register_android_view_Surface(JNIEnv* env) jclass clazz = env->FindClass("android/view/Surface"); gSurfaceClassInfo.clazz = jclass(env->NewGlobalRef(clazz)); - gSurfaceClassInfo.mNativeSurface = - env->GetFieldID(gSurfaceClassInfo.clazz, ANDROID_VIEW_SURFACE_JNI_ID, "I"); - gSurfaceClassInfo.mNativeSurfaceControl = - env->GetFieldID(gSurfaceClassInfo.clazz, "mNativeSurfaceControl", "I"); + gSurfaceClassInfo.mNativeObject = + env->GetFieldID(gSurfaceClassInfo.clazz, "mNativeObject", "I"); gSurfaceClassInfo.mGenerationId = env->GetFieldID(gSurfaceClassInfo.clazz, "mGenerationId", "I"); gSurfaceClassInfo.mCanvas = env->GetFieldID(gSurfaceClassInfo.clazz, "mCanvas", "Landroid/graphics/Canvas;"); gSurfaceClassInfo.mCanvasSaveCount = env->GetFieldID(gSurfaceClassInfo.clazz, "mCanvasSaveCount", "I"); - gSurfaceClassInfo.ctor = env->GetMethodID(gSurfaceClassInfo.clazz, "<init>", "()V"); + gSurfaceClassInfo.ctor = env->GetMethodID(gSurfaceClassInfo.clazz, "<init>", "(I)V"); clazz = env->FindClass("android/graphics/Canvas"); gCanvasClassInfo.mNativeCanvas = env->GetFieldID(clazz, "mNativeCanvas", "I"); @@ -902,14 +387,6 @@ int register_android_view_Surface(JNIEnv* env) gRectClassInfo.right = env->GetFieldID(clazz, "right", "I"); gRectClassInfo.bottom = env->GetFieldID(clazz, "bottom", "I"); - clazz = env->FindClass("android/view/Surface$PhysicalDisplayInfo"); - gPhysicalDisplayInfoClassInfo.width = env->GetFieldID(clazz, "width", "I"); - gPhysicalDisplayInfoClassInfo.height = env->GetFieldID(clazz, "height", "I"); - gPhysicalDisplayInfoClassInfo.refreshRate = env->GetFieldID(clazz, "refreshRate", "F"); - gPhysicalDisplayInfoClassInfo.density = env->GetFieldID(clazz, "density", "F"); - gPhysicalDisplayInfoClassInfo.xDpi = env->GetFieldID(clazz, "xDpi", "F"); - gPhysicalDisplayInfoClassInfo.yDpi = env->GetFieldID(clazz, "yDpi", "F"); - gPhysicalDisplayInfoClassInfo.secure = env->GetFieldID(clazz, "secure", "Z"); return err; } diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp new file mode 100644 index 0000000..7398895 --- /dev/null +++ b/core/jni/android_view_SurfaceControl.cpp @@ -0,0 +1,451 @@ +/* + * Copyright (C) 2013 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. + */ + +#define LOG_TAG "SurfaceControl" + +#include <stdio.h> + +#include "jni.h" +#include "JNIHelp.h" + +#include "android_os_Parcel.h" +#include "android_util_Binder.h" +#include "android/graphics/GraphicsJNI.h" +#include "android/graphics/Region.h" + +#include <android_runtime/AndroidRuntime.h> +#include <android_runtime/android_view_SurfaceSession.h> + +#include <gui/Surface.h> +#include <gui/SurfaceComposerClient.h> + +#include <ui/DisplayInfo.h> +#include <ui/Rect.h> +#include <ui/Region.h> + +#include <utils/Log.h> + +#include <ScopedUtfChars.h> + +// ---------------------------------------------------------------------------- + +namespace android { + +static const char* const OutOfResourcesException = + "android/view/Surface$OutOfResourcesException"; + +static struct { + jfieldID width; + jfieldID height; + jfieldID refreshRate; + jfieldID density; + jfieldID xDpi; + jfieldID yDpi; + jfieldID secure; +} gPhysicalDisplayInfoClassInfo; + + +class ScreenshotPixelRef : public SkPixelRef { +public: + ScreenshotPixelRef(SkColorTable* ctable) { + fCTable = ctable; + SkSafeRef(ctable); + setImmutable(); + } + + virtual ~ScreenshotPixelRef() { + SkSafeUnref(fCTable); + } + + status_t update(const sp<IBinder>& display, int width, int height, + int minLayer, int maxLayer, bool allLayers) { + status_t res = (width > 0 && height > 0) + ? (allLayers + ? mScreenshot.update(display, width, height) + : mScreenshot.update(display, width, height, minLayer, maxLayer)) + : mScreenshot.update(display); + if (res != NO_ERROR) { + return res; + } + + return NO_ERROR; + } + + uint32_t getWidth() const { + return mScreenshot.getWidth(); + } + + uint32_t getHeight() const { + return mScreenshot.getHeight(); + } + + uint32_t getStride() const { + return mScreenshot.getStride(); + } + + uint32_t getFormat() const { + return mScreenshot.getFormat(); + } + +protected: + // overrides from SkPixelRef + virtual void* onLockPixels(SkColorTable** ct) { + *ct = fCTable; + return (void*)mScreenshot.getPixels(); + } + + virtual void onUnlockPixels() { + } + +private: + ScreenshotClient mScreenshot; + SkColorTable* fCTable; + + typedef SkPixelRef INHERITED; +}; + + +// ---------------------------------------------------------------------------- + +static jint nativeCreate(JNIEnv* env, jobject surfaceObj, jobject sessionObj, + jstring nameStr, jint w, jint h, jint format, jint flags) { + ScopedUtfChars name(env, nameStr); + sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj)); + sp<SurfaceControl> surface = client->createSurface( + String8(name.c_str()), w, h, format, flags); + if (surface == NULL) { + jniThrowException(env, OutOfResourcesException, NULL); + return 0; + } + surface->incStrong(surfaceObj); + return int(surface.get()); +} + +static void nativeRelease(JNIEnv* env, jobject surfaceObj, jint nativeObject) { + sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject)); + ctrl->decStrong(surfaceObj); +} + +static void nativeDestroy(JNIEnv* env, jobject surfaceObj, jint nativeObject) { + sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject)); + ctrl->clear(); + ctrl->decStrong(surfaceObj); +} + +static inline SkBitmap::Config convertPixelFormat(PixelFormat format) { + /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then + we can map to SkBitmap::kARGB_8888_Config, and optionally call + bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator) + */ + switch (format) { + case PIXEL_FORMAT_RGBX_8888: return SkBitmap::kARGB_8888_Config; + case PIXEL_FORMAT_RGBA_8888: return SkBitmap::kARGB_8888_Config; + case PIXEL_FORMAT_RGBA_4444: return SkBitmap::kARGB_4444_Config; + case PIXEL_FORMAT_RGB_565: return SkBitmap::kRGB_565_Config; + case PIXEL_FORMAT_A_8: return SkBitmap::kA8_Config; + default: return SkBitmap::kNo_Config; + } +} + +static jobject nativeScreenshot(JNIEnv* env, jclass clazz, jobject displayTokenObj, + jint width, jint height, jint minLayer, jint maxLayer, bool allLayers) { + sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj); + if (displayToken == NULL) { + return NULL; + } + + ScreenshotPixelRef* pixels = new ScreenshotPixelRef(NULL); + if (pixels->update(displayToken, width, height, + minLayer, maxLayer, allLayers) != NO_ERROR) { + delete pixels; + return NULL; + } + + uint32_t w = pixels->getWidth(); + uint32_t h = pixels->getHeight(); + uint32_t s = pixels->getStride(); + uint32_t f = pixels->getFormat(); + ssize_t bpr = s * android::bytesPerPixel(f); + + SkBitmap* bitmap = new SkBitmap(); + bitmap->setConfig(convertPixelFormat(f), w, h, bpr); + if (f == PIXEL_FORMAT_RGBX_8888) { + bitmap->setIsOpaque(true); + } + + if (w > 0 && h > 0) { + bitmap->setPixelRef(pixels)->unref(); + bitmap->lockPixels(); + } else { + // be safe with an empty bitmap. + delete pixels; + bitmap->setPixels(NULL); + } + + return GraphicsJNI::createBitmap(env, bitmap, false, NULL); +} + +static void nativeOpenTransaction(JNIEnv* env, jclass clazz) { + SurfaceComposerClient::openGlobalTransaction(); +} + +static void nativeCloseTransaction(JNIEnv* env, jclass clazz) { + SurfaceComposerClient::closeGlobalTransaction(); +} + +static void nativeSetAnimationTransaction(JNIEnv* env, jclass clazz) { + SurfaceComposerClient::setAnimationTransaction(); +} + +static void nativeSetLayer(JNIEnv* env, jobject surfaceObj, jint nativeObject, jint zorder) { + SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + status_t err = ctrl->setLayer(zorder); + if (err < 0 && err != NO_INIT) { + doThrowIAE(env); + } +} + +static void nativeSetPosition(JNIEnv* env, jobject surfaceObj, jint nativeObject, jfloat x, jfloat y) { + SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + status_t err = ctrl->setPosition(x, y); + if (err < 0 && err != NO_INIT) { + doThrowIAE(env); + } +} + +static void nativeSetSize(JNIEnv* env, jobject surfaceObj, jint nativeObject, jint w, jint h) { + SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + status_t err = ctrl->setSize(w, h); + if (err < 0 && err != NO_INIT) { + doThrowIAE(env); + } +} + +static void nativeSetFlags(JNIEnv* env, jobject surfaceObj, jint nativeObject, jint flags, jint mask) { + SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + status_t err = ctrl->setFlags(flags, mask); + if (err < 0 && err != NO_INIT) { + doThrowIAE(env); + } +} + +static void nativeSetTransparentRegionHint(JNIEnv* env, jobject surfaceObj, jint nativeObject, jobject regionObj) { + SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj); + if (!region) { + doThrowIAE(env); + return; + } + + const SkIRect& b(region->getBounds()); + Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom)); + if (region->isComplex()) { + SkRegion::Iterator it(*region); + while (!it.done()) { + const SkIRect& r(it.rect()); + reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom); + it.next(); + } + } + + status_t err = ctrl->setTransparentRegionHint(reg); + if (err < 0 && err != NO_INIT) { + doThrowIAE(env); + } +} + +static void nativeSetAlpha(JNIEnv* env, jobject surfaceObj, jint nativeObject, jfloat alpha) { + SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + status_t err = ctrl->setAlpha(alpha); + if (err < 0 && err != NO_INIT) { + doThrowIAE(env); + } +} + +static void nativeSetMatrix(JNIEnv* env, jobject surfaceObj, jint nativeObject, + jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy) { + SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + status_t err = ctrl->setMatrix(dsdx, dtdx, dsdy, dtdy); + if (err < 0 && err != NO_INIT) { + doThrowIAE(env); + } +} + +static void nativeSetWindowCrop(JNIEnv* env, jobject surfaceObj, jint nativeObject, + jint l, jint t, jint r, jint b) { + SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + Rect crop(l, t, r, b); + status_t err = ctrl->setCrop(crop); + if (err < 0 && err != NO_INIT) { + doThrowIAE(env); + } +} + +static void nativeSetLayerStack(JNIEnv* env, jobject surfaceObj, jint nativeObject, jint layerStack) { + SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + status_t err = ctrl->setLayerStack(layerStack); + if (err < 0 && err != NO_INIT) { + doThrowIAE(env); + } +} + +static jobject nativeGetBuiltInDisplay(JNIEnv* env, jclass clazz, jint id) { + sp<IBinder> token(SurfaceComposerClient::getBuiltInDisplay(id)); + return javaObjectForIBinder(env, token); +} + +static jobject nativeCreateDisplay(JNIEnv* env, jclass clazz, jstring nameObj, + jboolean secure) { + ScopedUtfChars name(env, nameObj); + sp<IBinder> token(SurfaceComposerClient::createDisplay( + String8(name.c_str()), bool(secure))); + return javaObjectForIBinder(env, token); +} + +static void nativeSetDisplaySurface(JNIEnv* env, jclass clazz, + jobject tokenObj, jint nativeSurfaceObject) { + sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); + if (token == NULL) return; + sp<Surface> sur(reinterpret_cast<Surface *>(nativeSurfaceObject)); + sp<IGraphicBufferProducer> bufferProducer(sur->getSurfaceTexture()); + SurfaceComposerClient::setDisplaySurface(token, bufferProducer); +} + +static void nativeSetDisplayLayerStack(JNIEnv* env, jclass clazz, + jobject tokenObj, jint layerStack) { + sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); + if (token == NULL) return; + + SurfaceComposerClient::setDisplayLayerStack(token, layerStack); +} + +static void nativeSetDisplayProjection(JNIEnv* env, jclass clazz, + jobject tokenObj, jint orientation, + jint layerStackRect_left, jint layerStackRect_top, jint layerStackRect_right, jint layerStackRect_bottom, + jint displayRect_left, jint displayRect_top, jint displayRect_right, jint displayRect_bottom) { + sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); + if (token == NULL) return; + Rect layerStackRect(layerStackRect_left, layerStackRect_top, layerStackRect_right, layerStackRect_bottom); + Rect displayRect(displayRect_left, displayRect_top, displayRect_right, displayRect_bottom); + SurfaceComposerClient::setDisplayProjection(token, orientation, layerStackRect, displayRect); +} + +static jboolean nativeGetDisplayInfo(JNIEnv* env, jclass clazz, + jobject tokenObj, jobject infoObj) { + sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); + if (token == NULL) return JNI_FALSE; + + DisplayInfo info; + if (SurfaceComposerClient::getDisplayInfo(token, &info)) { + return JNI_FALSE; + } + + env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.width, info.w); + env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.height, info.h); + env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.refreshRate, info.fps); + env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.density, info.density); + env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.xDpi, info.xdpi); + env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.yDpi, info.ydpi); + env->SetBooleanField(infoObj, gPhysicalDisplayInfoClassInfo.secure, info.secure); + return JNI_TRUE; +} + +static void nativeBlankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) { + sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); + if (token == NULL) return; + + ALOGD_IF_SLOW(100, "Excessive delay in blankDisplay() while turning screen off"); + SurfaceComposerClient::blankDisplay(token); +} + +static void nativeUnblankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) { + sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); + if (token == NULL) return; + + ALOGD_IF_SLOW(100, "Excessive delay in unblankDisplay() while turning screen on"); + SurfaceComposerClient::unblankDisplay(token); +} + +// ---------------------------------------------------------------------------- + +static JNINativeMethod sSurfaceControlMethods[] = { + {"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIII)I", + (void*)nativeCreate }, + {"nativeRelease", "(I)V", + (void*)nativeRelease }, + {"nativeDestroy", "(I)V", + (void*)nativeDestroy }, + {"nativeScreenshot", "(Landroid/os/IBinder;IIIIZ)Landroid/graphics/Bitmap;", + (void*)nativeScreenshot }, + {"nativeOpenTransaction", "()V", + (void*)nativeOpenTransaction }, + {"nativeCloseTransaction", "()V", + (void*)nativeCloseTransaction }, + {"nativeSetAnimationTransaction", "()V", + (void*)nativeSetAnimationTransaction }, + {"nativeSetLayer", "(II)V", + (void*)nativeSetLayer }, + {"nativeSetPosition", "(IFF)V", + (void*)nativeSetPosition }, + {"nativeSetSize", "(III)V", + (void*)nativeSetSize }, + {"nativeSetTransparentRegionHint", "(ILandroid/graphics/Region;)V", + (void*)nativeSetTransparentRegionHint }, + {"nativeSetAlpha", "(IF)V", + (void*)nativeSetAlpha }, + {"nativeSetMatrix", "(IFFFF)V", + (void*)nativeSetMatrix }, + {"nativeSetFlags", "(III)V", + (void*)nativeSetFlags }, + {"nativeSetWindowCrop", "(IIIII)V", + (void*)nativeSetWindowCrop }, + {"nativeSetLayerStack", "(II)V", + (void*)nativeSetLayerStack }, + {"nativeGetBuiltInDisplay", "(I)Landroid/os/IBinder;", + (void*)nativeGetBuiltInDisplay }, + {"nativeCreateDisplay", "(Ljava/lang/String;Z)Landroid/os/IBinder;", + (void*)nativeCreateDisplay }, + {"nativeSetDisplaySurface", "(Landroid/os/IBinder;I)V", + (void*)nativeSetDisplaySurface }, + {"nativeSetDisplayLayerStack", "(Landroid/os/IBinder;I)V", + (void*)nativeSetDisplayLayerStack }, + {"nativeSetDisplayProjection", "(Landroid/os/IBinder;IIIIIIIII)V", + (void*)nativeSetDisplayProjection }, + {"nativeGetDisplayInfo", "(Landroid/os/IBinder;Landroid/view/SurfaceControl$PhysicalDisplayInfo;)Z", + (void*)nativeGetDisplayInfo }, + {"nativeBlankDisplay", "(Landroid/os/IBinder;)V", + (void*)nativeBlankDisplay }, + {"nativeUnblankDisplay", "(Landroid/os/IBinder;)V", + (void*)nativeUnblankDisplay }, +}; + +int register_android_view_SurfaceControl(JNIEnv* env) +{ + int err = AndroidRuntime::registerNativeMethods(env, "android/view/SurfaceControl", + sSurfaceControlMethods, NELEM(sSurfaceControlMethods)); + + jclass clazz = env->FindClass("android/view/SurfaceControl$PhysicalDisplayInfo"); + gPhysicalDisplayInfoClassInfo.width = env->GetFieldID(clazz, "width", "I"); + gPhysicalDisplayInfoClassInfo.height = env->GetFieldID(clazz, "height", "I"); + gPhysicalDisplayInfoClassInfo.refreshRate = env->GetFieldID(clazz, "refreshRate", "F"); + gPhysicalDisplayInfoClassInfo.density = env->GetFieldID(clazz, "density", "F"); + gPhysicalDisplayInfoClassInfo.xDpi = env->GetFieldID(clazz, "xDpi", "F"); + gPhysicalDisplayInfoClassInfo.yDpi = env->GetFieldID(clazz, "yDpi", "F"); + gPhysicalDisplayInfoClassInfo.secure = env->GetFieldID(clazz, "secure", "Z"); + return err; +} + +}; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 5d0614c..d77b504 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -129,6 +129,7 @@ <protected-broadcast android:name="android.net.conn.CONNECTIVITY_CHANGE" /> <protected-broadcast android:name="android.net.conn.CONNECTIVITY_CHANGE_IMMEDIATE" /> <protected-broadcast android:name="android.net.conn.DATA_ACTIVITY_CHANGE" /> + <protected-broadcast android:name="android.net.conn.CAPTIVE_PORTAL_TEST_COMPLETED" /> <protected-broadcast android:name="android.nfc.action.LLCP_LINK_STATE_CHANGED" /> <protected-broadcast android:name="com.android.nfc_extras.action.RF_FIELD_ON_DETECTED" /> @@ -641,7 +642,7 @@ android:protectionLevel="normal" android:description="@string/permdesc_accessWifiState" android:label="@string/permlab_accessWifiState" /> - + <!-- Allows applications to change Wi-Fi connectivity state --> <permission android:name="android.permission.CHANGE_WIFI_STATE" android:permissionGroup="android.permission-group.NETWORK" @@ -681,14 +682,14 @@ android:protectionLevel="dangerous" android:description="@string/permdesc_bluetooth" android:label="@string/permlab_bluetooth" /> - + <!-- Allows applications to discover and pair bluetooth devices --> <permission android:name="android.permission.BLUETOOTH_ADMIN" android:permissionGroup="android.permission-group.BLUETOOTH_NETWORK" android:protectionLevel="dangerous" android:description="@string/permdesc_bluetoothAdmin" android:label="@string/permlab_bluetoothAdmin" /> - + <!-- Allows bluetooth stack to access files @hide This should only be used by Bluetooth apk. --> @@ -719,7 +720,7 @@ <permission android:name="android.permission.LOOP_RADIO" android:permissionGroup="android.permission-group.NETWORK" android:protectionLevel="signature|system" /> - + <!-- ================================== --> <!-- Permissions for accessing accounts --> <!-- ================================== --> @@ -1129,7 +1130,7 @@ android:protectionLevel="signature|system" android:label="@string/permlab_manageUsers" android:description="@string/permdesc_manageUsers" /> - + <!-- Allows an application to get full detailed information about recently running tasks, with full fidelity to the real state. @hide --> @@ -1671,7 +1672,7 @@ android:label="@string/permlab_freezeScreen" android:description="@string/permdesc_freezeScreen" android:protectionLevel="signature" /> - + <!-- Allows an application to inject user events (keys, touch, trackball) into the event stream and deliver them to ANY window. Without this permission, you can only deliver events to windows in your own process. |