Merge "Add support for a circular bitmap overlay for round android wear emulator." into lmp-dev

This commit is contained in:
Griff Hazen
2014-09-09 17:25:46 +00:00
committed by Android (Google) Code Review
6 changed files with 215 additions and 8 deletions

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 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.
-->
<!-- Default to an empty shape drawable -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
</shape>

View File

@ -1611,6 +1611,10 @@
<!-- default window ShowCircularMask property -->
<bool name="config_windowShowCircularMask">false</bool>
<!-- default value for whether circular emulators (ro.emulator.circular)
should show a display overlay on the screen -->
<bool name="config_windowEnableCircularEmulatorDisplayOverlay">false</bool>
<!-- Defines the default set of global actions. Actions may still be disabled or hidden based
on the current state of the device.
Each item must be one of the following strings:

View File

@ -293,6 +293,7 @@
<java-symbol type="bool" name="config_windowIsRound" />
<java-symbol type="bool" name="config_hasRecents" />
<java-symbol type="bool" name="config_windowShowCircularMask" />
<java-symbol type="bool" name="config_windowEnableCircularEmulatorDisplayOverlay" />
<java-symbol type="integer" name="config_bluetooth_max_advertisers" />
<java-symbol type="integer" name="config_bluetooth_max_scan_filters" />
@ -1155,6 +1156,7 @@
<java-symbol type="drawable" name="ic_corp_badge" />
<java-symbol type="drawable" name="ic_corp_icon_badge" />
<java-symbol type="drawable" name="ic_corp_icon" />
<java-symbol type="drawable" name="emulator_circular_window_overlay" />
<java-symbol type="drawable" name="sim_light_blue" />
<java-symbol type="drawable" name="sim_light_green" />

View File

@ -63,8 +63,14 @@ class CircularDisplayMask {
SurfaceControl ctrl = null;
try {
ctrl = new SurfaceControl(session, "CircularDisplayMask",
mScreenSize.x, mScreenSize.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
if (WindowManagerService.DEBUG_SURFACE_TRACE) {
ctrl = new WindowStateAnimator.SurfaceTrace(session, "CircularDisplayMask",
mScreenSize.x, mScreenSize.y, PixelFormat.TRANSLUCENT,
SurfaceControl.HIDDEN);
} else {
ctrl = new SurfaceControl(session, "CircularDisplayMask", mScreenSize.x,
mScreenSize.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
}
ctrl.setLayerStack(display.getLayerStack());
ctrl.setLayer(zOrder);
ctrl.setPosition(0, 0);

View File

@ -0,0 +1,127 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.wm;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.Slog;
import android.view.Display;
import android.view.Surface;
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
class EmulatorDisplayOverlay {
private static final String TAG = "EmulatorDisplayOverlay";
// Display dimensions
private Point mScreenSize;
private final SurfaceControl mSurfaceControl;
private final Surface mSurface = new Surface();
private int mLastDW;
private int mLastDH;
private boolean mDrawNeeded;
private Drawable mOverlay;
private int mRotation;
private boolean mVisible;
public EmulatorDisplayOverlay(Context context, Display display, SurfaceSession session,
int zOrder) {
mScreenSize = new Point();
display.getSize(mScreenSize);
SurfaceControl ctrl = null;
try {
if (WindowManagerService.DEBUG_SURFACE_TRACE) {
ctrl = new WindowStateAnimator.SurfaceTrace(session, "EmulatorDisplayOverlay",
mScreenSize.x, mScreenSize.y, PixelFormat.TRANSLUCENT,
SurfaceControl.HIDDEN);
} else {
ctrl = new SurfaceControl(session, "EmulatorDisplayOverlay", mScreenSize.x,
mScreenSize.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
}
ctrl.setLayerStack(display.getLayerStack());
ctrl.setLayer(zOrder);
ctrl.setPosition(0, 0);
ctrl.show();
mSurface.copyFrom(ctrl);
} catch (OutOfResourcesException e) {
}
mSurfaceControl = ctrl;
mDrawNeeded = true;
mOverlay = context.getDrawable(
com.android.internal.R.drawable.emulator_circular_window_overlay);
}
private void drawIfNeeded() {
if (!mDrawNeeded || !mVisible) {
return;
}
mDrawNeeded = false;
Rect dirty = new Rect(0, 0, mScreenSize.x, mScreenSize.y);
Canvas c = null;
try {
c = mSurface.lockCanvas(dirty);
} catch (IllegalArgumentException e) {
} catch (OutOfResourcesException e) {
}
if (c == null) {
return;
}
c.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SRC);
mSurfaceControl.setPosition(0, 0);
mOverlay.setBounds(0, 0, mScreenSize.x, mScreenSize.y);
mOverlay.draw(c);
mSurface.unlockCanvasAndPost(c);
}
// Note: caller responsible for being inside
// Surface.openTransaction() / closeTransaction()
public void setVisibility(boolean on) {
if (mSurfaceControl == null) {
return;
}
mVisible = on;
drawIfNeeded();
if (on) {
mSurfaceControl.show();
} else {
mSurfaceControl.hide();
}
}
void positionSurface(int dw, int dh, int rotation) {
if (mLastDW == dw && mLastDH == dh && mRotation == rotation) {
return;
}
mLastDW = dw;
mLastDH = dh;
mDrawNeeded = true;
mRotation = rotation;
drawIfNeeded();
}
}

View File

@ -20,6 +20,7 @@ import static android.view.WindowManager.LayoutParams.*;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import android.app.AppOpsManager;
import android.os.Build;
import android.util.ArraySet;
import android.util.TimeUtils;
import android.view.IWindowId;
@ -295,6 +296,8 @@ public class WindowManagerService extends IWindowManager.Stub
private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN =
View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
final private KeyguardDisableHandler mKeyguardDisableHandler;
final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@ -441,6 +444,7 @@ public class WindowManagerService extends IWindowManager.Stub
Watermark mWatermark;
StrictModeFlash mStrictModeFlash;
CircularDisplayMask mCircularDisplayMask;
EmulatorDisplayOverlay mEmulatorDisplayOverlay;
FocusedStackFrame mFocusedStackFrame;
int mFocusedStackLayer;
@ -881,6 +885,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
showCircularDisplayMaskIfNeeded();
showEmulatorDisplayOverlayIfNeeded();
}
public InputMonitor getInputMonitor() {
@ -5767,7 +5772,16 @@ public class WindowManagerService extends IWindowManager.Stub
com.android.internal.R.bool.config_windowIsRound)
&& mContext.getResources().getBoolean(
com.android.internal.R.bool.config_windowShowCircularMask)) {
mH.sendMessage(mH.obtainMessage(H.SHOW_DISPLAY_MASK));
mH.sendMessage(mH.obtainMessage(H.SHOW_CIRCULAR_DISPLAY_MASK));
}
}
public void showEmulatorDisplayOverlayIfNeeded() {
if (mContext.getResources().getBoolean(
com.android.internal.R.bool.config_windowEnableCircularEmulatorDisplayOverlay)
&& SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false)
&& Build.HARDWARE.contains("goldfish")) {
mH.sendMessage(mH.obtainMessage(H.SHOW_EMULATOR_DISPLAY_OVERLAY));
}
}
@ -5775,12 +5789,12 @@ public class WindowManagerService extends IWindowManager.Stub
synchronized(mWindowMap) {
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
">>> OPEN TRANSACTION showDisplayMask");
">>> OPEN TRANSACTION showCircularMask");
SurfaceControl.openTransaction();
try {
// TODO(multi-display): support multiple displays
if (mCircularDisplayMask == null) {
int screenOffset = (int) mContext.getResources().getDimensionPixelSize(
int screenOffset = mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.circular_display_mask_offset);
mCircularDisplayMask = new CircularDisplayMask(
@ -5794,7 +5808,32 @@ public class WindowManagerService extends IWindowManager.Stub
} finally {
SurfaceControl.closeTransaction();
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
"<<< CLOSE TRANSACTION showDisplayMask");
"<<< CLOSE TRANSACTION showCircularMask");
}
}
}
public void showEmulatorDisplayOverlay() {
synchronized(mWindowMap) {
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
">>> OPEN TRANSACTION showEmulatorDisplayOverlay");
SurfaceControl.openTransaction();
try {
if (mEmulatorDisplayOverlay == null) {
mEmulatorDisplayOverlay = new EmulatorDisplayOverlay(
mContext,
getDefaultDisplayContentLocked().getDisplay(),
mFxSession,
mPolicy.windowTypeToLayerLw(
WindowManager.LayoutParams.TYPE_POINTER)
* TYPE_LAYER_MULTIPLIER + 10);
}
mEmulatorDisplayOverlay.setVisibility(true);
} finally {
SurfaceControl.closeTransaction();
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
"<<< CLOSE TRANSACTION showEmulatorDisplayOverlay");
}
}
}
@ -7425,7 +7464,8 @@ public class WindowManagerService extends IWindowManager.Stub
public static final int NEW_ANIMATOR_SCALE = 34;
public static final int SHOW_DISPLAY_MASK = 35;
public static final int SHOW_CIRCULAR_DISPLAY_MASK = 35;
public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36;
@Override
public void handleMessage(Message msg) {
@ -7821,11 +7861,16 @@ public class WindowManagerService extends IWindowManager.Stub
break;
}
case SHOW_DISPLAY_MASK: {
case SHOW_CIRCULAR_DISPLAY_MASK: {
showCircularMask();
break;
}
case SHOW_EMULATOR_DISPLAY_OVERLAY: {
showEmulatorDisplayOverlay();
break;
}
case DO_ANIMATION_CALLBACK: {
try {
((IRemoteCallback)msg.obj).sendResult(null);
@ -9395,6 +9440,9 @@ public class WindowManagerService extends IWindowManager.Stub
if (mCircularDisplayMask != null) {
mCircularDisplayMask.positionSurface(defaultDw, defaultDh, mRotation);
}
if (mEmulatorDisplayOverlay != null) {
mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh, mRotation);
}
boolean focusDisplayed = false;