Merge "Adding render stats APIs to UiAutomation (framework)."
This commit is contained in:
@@ -420,6 +420,8 @@ aidl_files := \
|
||||
frameworks/base/core/java/android/view/MotionEvent.aidl \
|
||||
frameworks/base/core/java/android/view/Surface.aidl \
|
||||
frameworks/base/core/java/android/view/WindowManager.aidl \
|
||||
frameworks/base/core/java/android/view/WindowAnimationFrameStats.aidl \
|
||||
frameworks/base/core/java/android/view/WindowContentFrameStats.aidl \
|
||||
frameworks/base/core/java/android/widget/RemoteViews.aidl \
|
||||
frameworks/base/core/java/com/android/internal/textservice/ISpellCheckerService.aidl \
|
||||
frameworks/base/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl \
|
||||
|
||||
@@ -4752,9 +4752,13 @@ package android.app {
|
||||
}
|
||||
|
||||
public final class UiAutomation {
|
||||
method public void clearWindowAnimationFrameStats();
|
||||
method public boolean clearWindowContentFrameStats(int);
|
||||
method public android.view.accessibility.AccessibilityEvent executeAndWaitForEvent(java.lang.Runnable, android.app.UiAutomation.AccessibilityEventFilter, long) throws java.util.concurrent.TimeoutException;
|
||||
method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
|
||||
method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
|
||||
method public android.view.WindowAnimationFrameStats getWindowAnimationFrameStats();
|
||||
method public android.view.WindowContentFrameStats getWindowContentFrameStats(int);
|
||||
method public java.util.List<android.view.accessibility.AccessibilityWindowInfo> getWindows();
|
||||
method public boolean injectInputEvent(android.view.InputEvent, boolean);
|
||||
method public final boolean performGlobalAction(int);
|
||||
@@ -28445,6 +28449,18 @@ package android.view {
|
||||
method public static android.view.FocusFinder getInstance();
|
||||
}
|
||||
|
||||
public abstract class FrameStats {
|
||||
ctor public FrameStats();
|
||||
method public final long getEndTimeNano();
|
||||
method public final int getFrameCount();
|
||||
method public final long getFramePresentedTimeNano(int);
|
||||
method public final long getRefreshPeriodNano();
|
||||
method public final long getStartTimeNano();
|
||||
field public static final long UNDEFINED_TIME_NANO = -1L; // 0xffffffffffffffffL
|
||||
field protected long[] mFramesPresentedTimeNano;
|
||||
field protected long mRefreshPeriodNano;
|
||||
}
|
||||
|
||||
public class GestureDetector {
|
||||
ctor public deprecated GestureDetector(android.view.GestureDetector.OnGestureListener, android.os.Handler);
|
||||
ctor public deprecated GestureDetector(android.view.GestureDetector.OnGestureListener);
|
||||
@@ -30769,6 +30785,20 @@ package android.view {
|
||||
method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
|
||||
}
|
||||
|
||||
public final class WindowAnimationFrameStats extends android.view.FrameStats implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator CREATOR;
|
||||
}
|
||||
|
||||
public final class WindowContentFrameStats extends android.view.FrameStats implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public long getFramePostedTimeNano(int);
|
||||
method public long getFrameReadyTimeNano(int);
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator CREATOR;
|
||||
}
|
||||
|
||||
public class WindowId implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public boolean isFocused();
|
||||
|
||||
@@ -19,6 +19,8 @@ package android.app;
|
||||
import android.accessibilityservice.IAccessibilityServiceClient;
|
||||
import android.graphics.Bitmap;
|
||||
import android.view.InputEvent;
|
||||
import android.view.WindowContentFrameStats;
|
||||
import android.view.WindowAnimationFrameStats;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
|
||||
/**
|
||||
@@ -26,7 +28,7 @@ import android.os.ParcelFileDescriptor;
|
||||
* on behalf of an instrumentation that it runs. These operations require
|
||||
* special permissions which the shell user has but the instrumentation does
|
||||
* not. Running privileged operations by the shell user on behalf of an
|
||||
* instrumentation is needed for running UiTestCases.
|
||||
* instrumentation is needed for running UiTestCases.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@@ -37,4 +39,8 @@ interface IUiAutomationConnection {
|
||||
boolean setRotation(int rotation);
|
||||
Bitmap takeScreenshot(int width, int height);
|
||||
void shutdown();
|
||||
boolean clearWindowContentFrameStats(int windowId);
|
||||
WindowContentFrameStats getWindowContentFrameStats(int windowId);
|
||||
void clearWindowAnimationFrameStats();
|
||||
WindowAnimationFrameStats getWindowAnimationFrameStats();
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@ import android.view.Display;
|
||||
import android.view.InputEvent;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Surface;
|
||||
import android.view.WindowAnimationFrameStats;
|
||||
import android.view.WindowContentFrameStats;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityInteractionClient;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
@@ -674,6 +676,148 @@ public final class UiAutomation {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the frame statistics for the content of a given window. These
|
||||
* statistics contain information about the most recently rendered content
|
||||
* frames.
|
||||
*
|
||||
* @param windowId The window id.
|
||||
* @return Whether the window is present and its frame statistics
|
||||
* were cleared.
|
||||
*
|
||||
* @see android.view.WindowContentFrameStats
|
||||
* @see #getWindowContentFrameStats(int)
|
||||
* @see #getWindows()
|
||||
* @see AccessibilityWindowInfo#getId() AccessibilityWindowInfo.getId()
|
||||
*/
|
||||
public boolean clearWindowContentFrameStats(int windowId) {
|
||||
synchronized (mLock) {
|
||||
throwIfNotConnectedLocked();
|
||||
}
|
||||
try {
|
||||
if (DEBUG) {
|
||||
Log.i(LOG_TAG, "Clearing content frame stats for window: " + windowId);
|
||||
}
|
||||
// Calling out without a lock held.
|
||||
return mUiAutomationConnection.clearWindowContentFrameStats(windowId);
|
||||
} catch (RemoteException re) {
|
||||
Log.e(LOG_TAG, "Error clearing window content frame stats!", re);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the frame statistics for a given window. These statistics contain
|
||||
* information about the most recently rendered content frames.
|
||||
* <p>
|
||||
* A typical usage requires clearing the window frame statistics via {@link
|
||||
* #clearWindowContentFrameStats(int)} followed by an interaction with the UI and
|
||||
* finally getting the window frame statistics via calling this method.
|
||||
* </p>
|
||||
* <pre>
|
||||
* // Assume we have at least one window.
|
||||
* final int windowId = getWindows().get(0).getId();
|
||||
*
|
||||
* // Start with a clean slate.
|
||||
* uiAutimation.clearWindowContentFrameStats(windowId);
|
||||
*
|
||||
* // Do stuff with the UI.
|
||||
*
|
||||
* // Get the frame statistics.
|
||||
* WindowContentFrameStats stats = uiAutomation.getWindowContentFrameStats(windowId);
|
||||
* </pre>
|
||||
*
|
||||
* @param windowId The window id.
|
||||
* @return The window frame statistics, or null if the window is not present.
|
||||
*
|
||||
* @see android.view.WindowContentFrameStats
|
||||
* @see #clearWindowContentFrameStats(int)
|
||||
* @see #getWindows()
|
||||
* @see AccessibilityWindowInfo#getId() AccessibilityWindowInfo.getId()
|
||||
*/
|
||||
public WindowContentFrameStats getWindowContentFrameStats(int windowId) {
|
||||
synchronized (mLock) {
|
||||
throwIfNotConnectedLocked();
|
||||
}
|
||||
try {
|
||||
if (DEBUG) {
|
||||
Log.i(LOG_TAG, "Getting content frame stats for window: " + windowId);
|
||||
}
|
||||
// Calling out without a lock held.
|
||||
return mUiAutomationConnection.getWindowContentFrameStats(windowId);
|
||||
} catch (RemoteException re) {
|
||||
Log.e(LOG_TAG, "Error getting window content frame stats!", re);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the window animation rendering statistics. These statistics contain
|
||||
* information about the most recently rendered window animation frames, i.e.
|
||||
* for window transition animations.
|
||||
*
|
||||
* @see android.view.WindowAnimationFrameStats
|
||||
* @see #getWindowAnimationFrameStats()
|
||||
* @see android.R.styleable#WindowAnimation
|
||||
*/
|
||||
public void clearWindowAnimationFrameStats() {
|
||||
synchronized (mLock) {
|
||||
throwIfNotConnectedLocked();
|
||||
}
|
||||
try {
|
||||
if (DEBUG) {
|
||||
Log.i(LOG_TAG, "Clearing window animation frame stats");
|
||||
}
|
||||
// Calling out without a lock held.
|
||||
mUiAutomationConnection.clearWindowAnimationFrameStats();
|
||||
} catch (RemoteException re) {
|
||||
Log.e(LOG_TAG, "Error clearing window animation frame stats!", re);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the window animation frame statistics. These statistics contain
|
||||
* information about the most recently rendered window animation frames, i.e.
|
||||
* for window transition animations.
|
||||
*
|
||||
* <p>
|
||||
* A typical usage requires clearing the window animation frame statistics via
|
||||
* {@link #clearWindowAnimationFrameStats()} followed by an interaction that causes
|
||||
* a window transition which uses a window animation and finally getting the window
|
||||
* animation frame statistics by calling this method.
|
||||
* </p>
|
||||
* <pre>
|
||||
* // Start with a clean slate.
|
||||
* uiAutimation.clearWindowAnimationFrameStats();
|
||||
*
|
||||
* // Do stuff to trigger a window transition.
|
||||
*
|
||||
* // Get the frame statistics.
|
||||
* WindowAnimationFrameStats stats = uiAutomation.getWindowAnimationFrameStats();
|
||||
* </pre>
|
||||
*
|
||||
* @return The window animation frame statistics.
|
||||
*
|
||||
* @see android.view.WindowAnimationFrameStats
|
||||
* @see #clearWindowAnimationFrameStats()
|
||||
* @see android.R.styleable#WindowAnimation
|
||||
*/
|
||||
public WindowAnimationFrameStats getWindowAnimationFrameStats() {
|
||||
synchronized (mLock) {
|
||||
throwIfNotConnectedLocked();
|
||||
}
|
||||
try {
|
||||
if (DEBUG) {
|
||||
Log.i(LOG_TAG, "Getting window animation frame stats");
|
||||
}
|
||||
// Calling out without a lock held.
|
||||
return mUiAutomationConnection.getWindowAnimationFrameStats();
|
||||
} catch (RemoteException re) {
|
||||
Log.e(LOG_TAG, "Error getting window animation frame stats!", re);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static float getDegreesForRotation(int value) {
|
||||
switch (value) {
|
||||
case Surface.ROTATION_90: {
|
||||
|
||||
@@ -22,12 +22,15 @@ import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.hardware.input.InputManager;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.view.IWindowManager;
|
||||
import android.view.InputEvent;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.WindowAnimationFrameStats;
|
||||
import android.view.WindowContentFrameStats;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.IAccessibilityManager;
|
||||
|
||||
@@ -47,6 +50,9 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
|
||||
private final IWindowManager mWindowManager = IWindowManager.Stub.asInterface(
|
||||
ServiceManager.getService(Service.WINDOW_SERVICE));
|
||||
|
||||
private final IAccessibilityManager mAccessibilityManager = IAccessibilityManager.Stub.asInterface(
|
||||
ServiceManager.getService(Service.ACCESSIBILITY_SERVICE));
|
||||
|
||||
private final Object mLock = new Object();
|
||||
|
||||
private final Binder mToken = new Binder();
|
||||
@@ -143,6 +149,76 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearWindowContentFrameStats(int windowId) throws RemoteException {
|
||||
synchronized (mLock) {
|
||||
throwIfCalledByNotTrustedUidLocked();
|
||||
throwIfShutdownLocked();
|
||||
throwIfNotConnectedLocked();
|
||||
}
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
IBinder token = mAccessibilityManager.getWindowToken(windowId);
|
||||
if (token == null) {
|
||||
return false;
|
||||
}
|
||||
return mWindowManager.clearWindowContentFrameStats(token);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindowContentFrameStats getWindowContentFrameStats(int windowId) throws RemoteException {
|
||||
synchronized (mLock) {
|
||||
throwIfCalledByNotTrustedUidLocked();
|
||||
throwIfShutdownLocked();
|
||||
throwIfNotConnectedLocked();
|
||||
}
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
IBinder token = mAccessibilityManager.getWindowToken(windowId);
|
||||
if (token == null) {
|
||||
return null;
|
||||
}
|
||||
return mWindowManager.getWindowContentFrameStats(token);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearWindowAnimationFrameStats() {
|
||||
synchronized (mLock) {
|
||||
throwIfCalledByNotTrustedUidLocked();
|
||||
throwIfShutdownLocked();
|
||||
throwIfNotConnectedLocked();
|
||||
}
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
SurfaceControl.clearAnimationFrameStats();
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindowAnimationFrameStats getWindowAnimationFrameStats() {
|
||||
synchronized (mLock) {
|
||||
throwIfCalledByNotTrustedUidLocked();
|
||||
throwIfShutdownLocked();
|
||||
throwIfNotConnectedLocked();
|
||||
}
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
WindowAnimationFrameStats stats = new WindowAnimationFrameStats();
|
||||
SurfaceControl.getAnimationFrameStats(stats);
|
||||
return stats;
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
synchronized (mLock) {
|
||||
|
||||
19
core/java/android/view/AnimationRenderStats.aidl
Normal file
19
core/java/android/view/AnimationRenderStats.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* 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 android.view;
|
||||
|
||||
parcelable AnimationRenderStats;
|
||||
97
core/java/android/view/FrameStats.java
Normal file
97
core/java/android/view/FrameStats.java
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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 android.view;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* This is the base class for frame statistics.
|
||||
*/
|
||||
public abstract class FrameStats {
|
||||
/**
|
||||
* Undefined time.
|
||||
*/
|
||||
public static final long UNDEFINED_TIME_NANO = -1;
|
||||
|
||||
protected long mRefreshPeriodNano;
|
||||
protected long[] mFramesPresentedTimeNano;
|
||||
|
||||
/**
|
||||
* Gets the refresh period of the display hosting the window(s) for
|
||||
* which these statistics apply.
|
||||
*
|
||||
* @return The refresh period in nanoseconds.
|
||||
*/
|
||||
public final long getRefreshPeriodNano() {
|
||||
return mRefreshPeriodNano;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of frames for which there is data.
|
||||
*
|
||||
* @return The number of frames.
|
||||
*/
|
||||
public final int getFrameCount() {
|
||||
return mFramesPresentedTimeNano != null
|
||||
? mFramesPresentedTimeNano.length : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the start time of the interval for which these statistics
|
||||
* apply. The start interval is the time when the first frame was
|
||||
* presented.
|
||||
*
|
||||
* @return The start time in nanoseconds or {@link #UNDEFINED_TIME_NANO}
|
||||
* if there is no frame data.
|
||||
*/
|
||||
public final long getStartTimeNano() {
|
||||
if (getFrameCount() <= 0) {
|
||||
return UNDEFINED_TIME_NANO;
|
||||
}
|
||||
return mFramesPresentedTimeNano[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the end time of the interval for which these statistics
|
||||
* apply. The end interval is the time when the last frame was
|
||||
* presented.
|
||||
*
|
||||
* @return The end time in nanoseconds or {@link #UNDEFINED_TIME_NANO}
|
||||
* if there is no frame data.
|
||||
*/
|
||||
public final long getEndTimeNano() {
|
||||
if (getFrameCount() <= 0) {
|
||||
return UNDEFINED_TIME_NANO;
|
||||
}
|
||||
return mFramesPresentedTimeNano[mFramesPresentedTimeNano.length - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the time a frame at a given index was presented.
|
||||
*
|
||||
* @param index The frame index.
|
||||
* @return The presented time in nanoseconds or {@link #UNDEFINED_TIME_NANO}
|
||||
* if the frame is not presented yet.
|
||||
*/
|
||||
public final long getFramePresentedTimeNano(int index) {
|
||||
if (mFramesPresentedTimeNano == null) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
return mFramesPresentedTimeNano[index];
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ import android.view.MotionEvent;
|
||||
import android.view.InputChannel;
|
||||
import android.view.InputDevice;
|
||||
import android.view.IInputFilter;
|
||||
import android.view.WindowContentFrameStats;
|
||||
|
||||
/**
|
||||
* System private interface to the window manager.
|
||||
@@ -233,4 +234,20 @@ interface IWindowManager
|
||||
* Device is in safe mode.
|
||||
*/
|
||||
boolean isSafeModeEnabled();
|
||||
|
||||
/**
|
||||
* Clears the frame statistics for a given window.
|
||||
*
|
||||
* @param token The window token.
|
||||
* @return Whether the frame statistics were cleared.
|
||||
*/
|
||||
boolean clearWindowContentFrameStats(IBinder token);
|
||||
|
||||
/**
|
||||
* Gets the content frame statistics for a given window.
|
||||
*
|
||||
* @param token The window token.
|
||||
* @return The frame statistics or null if the window does not exist.
|
||||
*/
|
||||
WindowContentFrameStats getWindowContentFrameStats(IBinder token);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import dalvik.system.CloseGuard;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.view.Surface;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
import android.view.Surface.OutOfResourcesException;
|
||||
@@ -59,6 +58,11 @@ public class SurfaceControl {
|
||||
private static native void nativeSetWindowCrop(long nativeObject, int l, int t, int r, int b);
|
||||
private static native void nativeSetLayerStack(long nativeObject, int layerStack);
|
||||
|
||||
private static native boolean nativeClearContentFrameStats(long nativeObject);
|
||||
private static native boolean nativeGetContentFrameStats(long nativeObject, WindowContentFrameStats outStats);
|
||||
private static native boolean nativeClearAnimationFrameStats();
|
||||
private static native boolean nativeGetAnimationFrameStats(WindowAnimationFrameStats outStats);
|
||||
|
||||
private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId);
|
||||
private static native IBinder nativeCreateDisplay(String name, boolean secure);
|
||||
private static native void nativeDestroyDisplay(IBinder displayToken);
|
||||
@@ -357,6 +361,24 @@ public class SurfaceControl {
|
||||
nativeSetTransparentRegionHint(mNativeObject, region);
|
||||
}
|
||||
|
||||
public boolean clearContentFrameStats() {
|
||||
checkNotReleased();
|
||||
return nativeClearContentFrameStats(mNativeObject);
|
||||
}
|
||||
|
||||
public boolean getContentFrameStats(WindowContentFrameStats outStats) {
|
||||
checkNotReleased();
|
||||
return nativeGetContentFrameStats(mNativeObject, outStats);
|
||||
}
|
||||
|
||||
public static boolean clearAnimationFrameStats() {
|
||||
return nativeClearAnimationFrameStats();
|
||||
}
|
||||
|
||||
public static boolean getAnimationFrameStats(WindowAnimationFrameStats outStats) {
|
||||
return nativeGetAnimationFrameStats(outStats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an alpha value for the entire Surface. This value is combined with the
|
||||
* per-pixel alpha. It may be used with opaque Surfaces.
|
||||
@@ -542,7 +564,6 @@ public class SurfaceControl {
|
||||
return nativeGetBuiltInDisplay(builtInDisplayId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy the current screen contents into the provided {@link Surface}
|
||||
*
|
||||
@@ -592,7 +613,6 @@ public class SurfaceControl {
|
||||
screenshot(display, consumer, 0, 0, 0, 0, true, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy the current screen contents into a bitmap and return it.
|
||||
*
|
||||
@@ -626,8 +646,8 @@ public class SurfaceControl {
|
||||
}
|
||||
|
||||
/**
|
||||
* Like {@link SurfaceControl#screenshot(int, int, int, int)} but includes all
|
||||
* Surfaces in the screenshot.
|
||||
* Like {@link SurfaceControl#screenshot(int, int, int, int, boolean)} but
|
||||
* includes all Surfaces in the screenshot.
|
||||
*
|
||||
* @param width The desired width of the returned bitmap; the raw
|
||||
* screen will be scaled down to this size.
|
||||
|
||||
19
core/java/android/view/WindowAnimationFrameStats.aidl
Normal file
19
core/java/android/view/WindowAnimationFrameStats.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* 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 android.view;
|
||||
|
||||
parcelable WindowAnimationFrameStats;
|
||||
94
core/java/android/view/WindowAnimationFrameStats.java
Normal file
94
core/java/android/view/WindowAnimationFrameStats.java
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 android.view;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* This class contains window animation frame statistics. For example, a window
|
||||
* animation is usually performed when the application is transitioning from one
|
||||
* activity to another. The frame statistics are a snapshot for the time interval
|
||||
* from {@link #getStartTimeNano()} to {@link #getEndTimeNano()}.
|
||||
* <p>
|
||||
* The key idea is that in order to provide a smooth user experience the system should
|
||||
* run window animations at a specific time interval obtained by calling {@link
|
||||
* #getRefreshPeriodNano()}. If the system does not render a frame every refresh
|
||||
* period the user will see irregular window transitions. The time when the frame was
|
||||
* actually presented on the display by calling {@link #getFramePresentedTimeNano(int)}.
|
||||
*/
|
||||
public final class WindowAnimationFrameStats extends FrameStats implements Parcelable {
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public WindowAnimationFrameStats() {
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes this isntance.
|
||||
*
|
||||
* @param refreshPeriodNano The display refresh period.
|
||||
* @param framesPresentedTimeNano The presented frame times.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public void init(long refreshPeriodNano, long[] framesPresentedTimeNano) {
|
||||
mRefreshPeriodNano = refreshPeriodNano;
|
||||
mFramesPresentedTimeNano = framesPresentedTimeNano;
|
||||
}
|
||||
|
||||
private WindowAnimationFrameStats(Parcel parcel) {
|
||||
mRefreshPeriodNano = parcel.readLong();
|
||||
mFramesPresentedTimeNano = parcel.createLongArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int flags) {
|
||||
parcel.writeLong(mRefreshPeriodNano);
|
||||
parcel.writeLongArray(mFramesPresentedTimeNano);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("WindowAnimationFrameStats[");
|
||||
builder.append("frameCount:" + getFrameCount());
|
||||
builder.append(", fromTimeNano:" + getStartTimeNano());
|
||||
builder.append(", toTimeNano:" + getEndTimeNano());
|
||||
builder.append(']');
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public static final Creator<WindowAnimationFrameStats> CREATOR =
|
||||
new Creator<WindowAnimationFrameStats>() {
|
||||
@Override
|
||||
public WindowAnimationFrameStats createFromParcel(Parcel parcel) {
|
||||
return new WindowAnimationFrameStats(parcel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindowAnimationFrameStats[] newArray(int size) {
|
||||
return new WindowAnimationFrameStats[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
19
core/java/android/view/WindowContentFrameStats.aidl
Normal file
19
core/java/android/view/WindowContentFrameStats.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* 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 android.view;
|
||||
|
||||
parcelable WindowContentFrameStats;
|
||||
152
core/java/android/view/WindowContentFrameStats.java
Normal file
152
core/java/android/view/WindowContentFrameStats.java
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* 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 android.view;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* This class contains window content frame statistics. For example, a window content
|
||||
* is rendred in frames when a view is scrolled. The frame statistics are a snapshot
|
||||
* for the time interval from {@link #getStartTimeNano()} to {@link #getEndTimeNano()}.
|
||||
* <p>
|
||||
* The key idea is that in order to provide a smooth user experience an application
|
||||
* has to draw a frame at a specific time interval obtained by calling {@link
|
||||
* #getRefreshPeriodNano()}. If the application does not render a frame every refresh
|
||||
* period the user will see irregular UI transitions.
|
||||
* </p>
|
||||
* <p>
|
||||
* An application posts a frame for presentation by synchronously rendering its contents
|
||||
* in a buffer which is then posted or posting a buffer to which the application is
|
||||
* asychronously rendering the content via GL. After the frame is posted and rendered
|
||||
* (potentially asynchronosly) it is presented to the user. The time a frame was posted
|
||||
* can be obtained via {@link #getFramePostedTimeNano(int)}, the time a frame content
|
||||
* was rendered and ready for dsiplay (GL case) via {@link #getFrameReadyTimeNano(int)},
|
||||
* and the time a frame was presented on the screen via {@link #getFramePresentedTimeNano(int)}.
|
||||
* </p>
|
||||
*/
|
||||
public final class WindowContentFrameStats extends FrameStats implements Parcelable {
|
||||
private long[] mFramesPostedTimeNano;
|
||||
private long[] mFramesReadyTimeNano;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public WindowContentFrameStats() {
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes this isntance.
|
||||
*
|
||||
* @param refreshPeriodNano The display refresh period.
|
||||
* @param framesPostedTimeNano The times in milliseconds for when the frame contents were posted.
|
||||
* @param framesPresentedTimeNano The times in milliseconds for when the frame contents were presented.
|
||||
* @param framesReadyTimeNano The times in milliseconds for when the frame contents were ready to be presented.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public void init(long refreshPeriodNano, long[] framesPostedTimeNano,
|
||||
long[] framesPresentedTimeNano, long[] framesReadyTimeNano) {
|
||||
mRefreshPeriodNano = refreshPeriodNano;
|
||||
mFramesPostedTimeNano = framesPostedTimeNano;
|
||||
mFramesPresentedTimeNano = framesPresentedTimeNano;
|
||||
mFramesReadyTimeNano = framesReadyTimeNano;
|
||||
}
|
||||
|
||||
private WindowContentFrameStats(Parcel parcel) {
|
||||
mRefreshPeriodNano = parcel.readLong();
|
||||
mFramesPostedTimeNano = parcel.createLongArray();
|
||||
mFramesPresentedTimeNano = parcel.createLongArray();
|
||||
mFramesReadyTimeNano = parcel.createLongArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the time a frame at a given index was posted by the producer (e.g. the application).
|
||||
* It is either explicitly set or defaulted to the time when the render buffer was posted.
|
||||
* <p>
|
||||
* <strong>Note:</strong> A frame can be posted and still it contents being rendered
|
||||
* asynchronously in GL. To get the time the frame content was completely rendered and
|
||||
* ready to display call {@link #getFrameReadyTimeNano(int)}.
|
||||
* </p>
|
||||
*
|
||||
* @param index The frame index.
|
||||
* @return The posted time in nanoseconds.
|
||||
*/
|
||||
public long getFramePostedTimeNano(int index) {
|
||||
if (mFramesPostedTimeNano == null) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
return mFramesPostedTimeNano[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the time a frame at a given index was ready for presentation.
|
||||
* <p>
|
||||
* <strong>Note:</strong> A frame can be posted and still it contents being rendered
|
||||
* asynchronously in GL. In such a case this is the time when the frame contents were
|
||||
* completely rendered.
|
||||
* </p>
|
||||
*
|
||||
* @param index The frame index.
|
||||
* @return The ready time in nanoseconds or {@link #UNDEFINED_TIME_NANO}
|
||||
* if the frame is not ready yet.
|
||||
*/
|
||||
public long getFrameReadyTimeNano(int index) {
|
||||
if (mFramesReadyTimeNano == null) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
return mFramesReadyTimeNano[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int flags) {
|
||||
parcel.writeLong(mRefreshPeriodNano);
|
||||
parcel.writeLongArray(mFramesPostedTimeNano);
|
||||
parcel.writeLongArray(mFramesPresentedTimeNano);
|
||||
parcel.writeLongArray(mFramesReadyTimeNano);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("WindowContentFrameStats[");
|
||||
builder.append("frameCount:" + getFrameCount());
|
||||
builder.append(", fromTimeNano:" + getStartTimeNano());
|
||||
builder.append(", toTimeNano:" + getEndTimeNano());
|
||||
builder.append(']');
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<WindowContentFrameStats> CREATOR =
|
||||
new Creator<WindowContentFrameStats>() {
|
||||
@Override
|
||||
public WindowContentFrameStats createFromParcel(Parcel parcel) {
|
||||
return new WindowContentFrameStats(parcel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindowContentFrameStats[] newArray(int size) {
|
||||
return new WindowContentFrameStats[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -57,4 +57,6 @@ interface IAccessibilityManager {
|
||||
|
||||
void temporaryEnableAccessibilityStateUntilKeyguardRemoved(in ComponentName service,
|
||||
boolean touchExplorationEnabled);
|
||||
|
||||
IBinder getWindowToken(int windowId);
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <gui/SurfaceComposerClient.h>
|
||||
|
||||
#include <ui/DisplayInfo.h>
|
||||
#include <ui/FrameStats.h>
|
||||
#include <ui/Rect.h>
|
||||
#include <ui/Region.h>
|
||||
|
||||
@@ -64,6 +65,16 @@ void DeleteScreenshot(void* addr, void* context) {
|
||||
delete ((ScreenshotClient*) context);
|
||||
}
|
||||
|
||||
static struct {
|
||||
nsecs_t UNDEFINED_TIME_NANO;
|
||||
jmethodID init;
|
||||
} gWindowContentFrameStatsClassInfo;
|
||||
|
||||
static struct {
|
||||
nsecs_t UNDEFINED_TIME_NANO;
|
||||
jmethodID init;
|
||||
} gWindowAnimationFrameStatsClassInfo;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
|
||||
@@ -371,6 +382,151 @@ static void nativeUnblankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
|
||||
SurfaceComposerClient::unblankDisplay(token);
|
||||
}
|
||||
|
||||
static jboolean nativeClearContentFrameStats(JNIEnv* env, jclass clazz, jlong nativeObject) {
|
||||
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
|
||||
status_t err = ctrl->clearLayerFrameStats();
|
||||
|
||||
if (err < 0 && err != NO_INIT) {
|
||||
doThrowIAE(env);
|
||||
}
|
||||
|
||||
// The other end is not ready, just report we failed.
|
||||
if (err == NO_INIT) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
static jboolean nativeGetContentFrameStats(JNIEnv* env, jclass clazz, jlong nativeObject,
|
||||
jobject outStats) {
|
||||
FrameStats stats;
|
||||
|
||||
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
|
||||
status_t err = ctrl->getLayerFrameStats(&stats);
|
||||
if (err < 0 && err != NO_INIT) {
|
||||
doThrowIAE(env);
|
||||
}
|
||||
|
||||
// The other end is not ready, fine just return empty stats.
|
||||
if (err == NO_INIT) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
jlong refreshPeriodNano = static_cast<jlong>(stats.refreshPeriodNano);
|
||||
size_t frameCount = stats.desiredPresentTimesNano.size();
|
||||
|
||||
jlongArray postedTimesNanoDst = env->NewLongArray(frameCount);
|
||||
if (postedTimesNanoDst == NULL) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
jlongArray presentedTimesNanoDst = env->NewLongArray(frameCount);
|
||||
if (presentedTimesNanoDst == NULL) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
jlongArray readyTimesNanoDst = env->NewLongArray(frameCount);
|
||||
if (readyTimesNanoDst == NULL) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
nsecs_t postedTimesNanoSrc[frameCount];
|
||||
nsecs_t presentedTimesNanoSrc[frameCount];
|
||||
nsecs_t readyTimesNanoSrc[frameCount];
|
||||
|
||||
for (size_t i = 0; i < frameCount; i++) {
|
||||
nsecs_t postedTimeNano = stats.desiredPresentTimesNano[i];
|
||||
if (postedTimeNano == INT64_MAX) {
|
||||
postedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
|
||||
}
|
||||
postedTimesNanoSrc[i] = postedTimeNano;
|
||||
|
||||
nsecs_t presentedTimeNano = stats.actualPresentTimesNano[i];
|
||||
if (presentedTimeNano == INT64_MAX) {
|
||||
presentedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
|
||||
}
|
||||
presentedTimesNanoSrc[i] = presentedTimeNano;
|
||||
|
||||
nsecs_t readyTimeNano = stats.frameReadyTimesNano[i];
|
||||
if (readyTimeNano == INT64_MAX) {
|
||||
readyTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
|
||||
}
|
||||
readyTimesNanoSrc[i] = readyTimeNano;
|
||||
}
|
||||
|
||||
env->SetLongArrayRegion(postedTimesNanoDst, 0, frameCount, postedTimesNanoSrc);
|
||||
env->SetLongArrayRegion(presentedTimesNanoDst, 0, frameCount, presentedTimesNanoSrc);
|
||||
env->SetLongArrayRegion(readyTimesNanoDst, 0, frameCount, readyTimesNanoSrc);
|
||||
|
||||
env->CallVoidMethod(outStats, gWindowContentFrameStatsClassInfo.init, refreshPeriodNano,
|
||||
postedTimesNanoDst, presentedTimesNanoDst, readyTimesNanoDst);
|
||||
|
||||
if (env->ExceptionCheck()) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
static jboolean nativeClearAnimationFrameStats(JNIEnv* env, jclass clazz) {
|
||||
status_t err = SurfaceComposerClient::clearAnimationFrameStats();
|
||||
|
||||
if (err < 0 && err != NO_INIT) {
|
||||
doThrowIAE(env);
|
||||
}
|
||||
|
||||
// The other end is not ready, just report we failed.
|
||||
if (err == NO_INIT) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
static jboolean nativeGetAnimationFrameStats(JNIEnv* env, jclass clazz, jobject outStats) {
|
||||
FrameStats stats;
|
||||
|
||||
status_t err = SurfaceComposerClient::getAnimationFrameStats(&stats);
|
||||
if (err < 0 && err != NO_INIT) {
|
||||
doThrowIAE(env);
|
||||
}
|
||||
|
||||
// The other end is not ready, fine just return empty stats.
|
||||
if (err == NO_INIT) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
jlong refreshPeriodNano = static_cast<jlong>(stats.refreshPeriodNano);
|
||||
size_t frameCount = stats.desiredPresentTimesNano.size();
|
||||
|
||||
jlongArray presentedTimesNanoDst = env->NewLongArray(frameCount);
|
||||
if (presentedTimesNanoDst == NULL) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
nsecs_t presentedTimesNanoSrc[frameCount];
|
||||
|
||||
for (size_t i = 0; i < frameCount; i++) {
|
||||
nsecs_t presentedTimeNano = stats.desiredPresentTimesNano[i];
|
||||
if (presentedTimeNano == INT64_MAX) {
|
||||
presentedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
|
||||
}
|
||||
presentedTimesNanoSrc[i] = presentedTimeNano;
|
||||
}
|
||||
|
||||
env->SetLongArrayRegion(presentedTimesNanoDst, 0, frameCount, presentedTimesNanoSrc);
|
||||
|
||||
env->CallVoidMethod(outStats, gWindowAnimationFrameStatsClassInfo.init, refreshPeriodNano,
|
||||
presentedTimesNanoDst);
|
||||
|
||||
if (env->ExceptionCheck()) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static JNINativeMethod sSurfaceControlMethods[] = {
|
||||
@@ -426,6 +582,14 @@ static JNINativeMethod sSurfaceControlMethods[] = {
|
||||
(void*)nativeBlankDisplay },
|
||||
{"nativeUnblankDisplay", "(Landroid/os/IBinder;)V",
|
||||
(void*)nativeUnblankDisplay },
|
||||
{"nativeClearContentFrameStats", "(J)Z",
|
||||
(void*)nativeClearContentFrameStats },
|
||||
{"nativeGetContentFrameStats", "(JLandroid/view/WindowContentFrameStats;)Z",
|
||||
(void*)nativeGetContentFrameStats },
|
||||
{"nativeClearAnimationFrameStats", "()Z",
|
||||
(void*)nativeClearAnimationFrameStats },
|
||||
{"nativeGetAnimationFrameStats", "(Landroid/view/WindowAnimationFrameStats;)Z",
|
||||
(void*)nativeGetAnimationFrameStats },
|
||||
};
|
||||
|
||||
int register_android_view_SurfaceControl(JNIEnv* env)
|
||||
@@ -441,6 +605,19 @@ int register_android_view_SurfaceControl(JNIEnv* env)
|
||||
gPhysicalDisplayInfoClassInfo.xDpi = env->GetFieldID(clazz, "xDpi", "F");
|
||||
gPhysicalDisplayInfoClassInfo.yDpi = env->GetFieldID(clazz, "yDpi", "F");
|
||||
gPhysicalDisplayInfoClassInfo.secure = env->GetFieldID(clazz, "secure", "Z");
|
||||
|
||||
jclass frameStatsClazz = env->FindClass("android/view/FrameStats");
|
||||
jfieldID undefined_time_nano_field = env->GetStaticFieldID(frameStatsClazz, "UNDEFINED_TIME_NANO", "J");
|
||||
nsecs_t undefined_time_nano = env->GetStaticLongField(frameStatsClazz, undefined_time_nano_field);
|
||||
|
||||
jclass contFrameStatsClazz = env->FindClass("android/view/WindowContentFrameStats");
|
||||
gWindowContentFrameStatsClassInfo.init = env->GetMethodID(contFrameStatsClazz, "init", "(J[J[J[J)V");
|
||||
gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO = undefined_time_nano;
|
||||
|
||||
jclass animFrameStatsClazz = env->FindClass("android/view/WindowAnimationFrameStats");
|
||||
gWindowAnimationFrameStatsClassInfo.init = env->GetMethodID(animFrameStatsClazz, "init", "(J[J)V");
|
||||
gWindowAnimationFrameStatsClassInfo.UNDEFINED_TIME_NANO = undefined_time_nano;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -1921,6 +1921,18 @@
|
||||
android:description="@string/permdesc_filter_events"
|
||||
android:protectionLevel="signature" />
|
||||
|
||||
<!-- @hide Allows an application to retrieve the window token from the accessibility manager. -->
|
||||
<permission android:name="android.permission.RETRIEVE_WINDOW_TOKEN"
|
||||
android:label="@string/permlab_retrieveWindowToken"
|
||||
android:description="@string/permdesc_retrieveWindowToken"
|
||||
android:protectionLevel="signature" />
|
||||
|
||||
<!-- @hide Allows an application to collect frame statistics -->
|
||||
<permission android:name="android.permission.FRAME_STATS"
|
||||
android:label="@string/permlab_frameStats"
|
||||
android:description="@string/permdesc_frameStats"
|
||||
android:protectionLevel="signature" />
|
||||
|
||||
<!-- @hide Allows an application to temporary enable accessibility on the device. -->
|
||||
<permission android:name="android.permission.TEMPORARY_ENABLE_ACCESSIBILITY"
|
||||
android:label="@string/permlab_temporary_enable_accessibility"
|
||||
|
||||
@@ -829,6 +829,20 @@
|
||||
enable accessibility on the device. Malicious apps may enable accessibility without
|
||||
user consent.</string>
|
||||
|
||||
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
||||
<string name="permlab_retrieveWindowToken">retrieve window token</string>
|
||||
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
||||
<string name="permdesc_retrieveWindowToken">Allows an application to retrieve
|
||||
the window token. Malicious apps may perfrom unauthorized interaction with
|
||||
the application window impersonating the system.</string>
|
||||
|
||||
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
||||
<string name="permlab_frameStats">retrieve frame statistics</string>
|
||||
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
||||
<string name="permdesc_frameStats">Allows an application to collect
|
||||
frame statistics. Malicious apps may observe the frame statistics
|
||||
of windows from other apps.</string>
|
||||
|
||||
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
||||
<string name="permlab_filter_events">filter events</string>
|
||||
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
||||
|
||||
@@ -87,6 +87,8 @@
|
||||
<uses-permission android:name="android.permission.MANAGE_USERS" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_STACK" />
|
||||
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
||||
<uses-permission android:name="android.permission.RETRIEVE_WINDOW_TOKEN" />
|
||||
<uses-permission android:name="android.permission.RENDER_STATS" />
|
||||
|
||||
<application android:label="@string/app_label">
|
||||
<provider
|
||||
|
||||
@@ -132,6 +132,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
private static final String TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED =
|
||||
"temporaryEnableAccessibilityStateUntilKeyguardRemoved";
|
||||
|
||||
private static final String GET_WINDOW_TOKEN = "getWindowToken";
|
||||
|
||||
private static final ComponentName sFakeAccessibilityServiceComponentName =
|
||||
new ComponentName("foo.bar", "FakeService");
|
||||
|
||||
@@ -360,6 +362,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
}, UserHandle.ALL, intentFilter, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int addClient(IAccessibilityManagerClient client, int userId) {
|
||||
synchronized (mLock) {
|
||||
final int resolvedUserId = mSecurityPolicy
|
||||
@@ -388,6 +391,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendAccessibilityEvent(AccessibilityEvent event, int userId) {
|
||||
synchronized (mLock) {
|
||||
final int resolvedUserId = mSecurityPolicy
|
||||
@@ -412,6 +416,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
return (OWN_PROCESS_ID != Binder.getCallingPid());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId) {
|
||||
synchronized (mLock) {
|
||||
final int resolvedUserId = mSecurityPolicy
|
||||
@@ -430,6 +435,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType,
|
||||
int userId) {
|
||||
List<AccessibilityServiceInfo> result = null;
|
||||
@@ -463,6 +469,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interrupt(int userId) {
|
||||
CopyOnWriteArrayList<Service> services;
|
||||
synchronized (mLock) {
|
||||
@@ -485,6 +492,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int addAccessibilityInteractionConnection(IWindow windowToken,
|
||||
IAccessibilityInteractionConnection connection, int userId) throws RemoteException {
|
||||
synchronized (mLock) {
|
||||
@@ -521,6 +529,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAccessibilityInteractionConnection(IWindow window) {
|
||||
synchronized (mLock) {
|
||||
mSecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked(
|
||||
@@ -570,6 +579,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerUiTestAutomationService(IBinder owner,
|
||||
IAccessibilityServiceClient serviceClient,
|
||||
AccessibilityServiceInfo accessibilityServiceInfo) {
|
||||
@@ -612,6 +622,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient) {
|
||||
synchronized (mLock) {
|
||||
UserState userState = getCurrentUserStateLocked();
|
||||
@@ -630,6 +641,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void temporaryEnableAccessibilityStateUntilKeyguardRemoved(
|
||||
ComponentName service, boolean touchExplorationEnabled) {
|
||||
mSecurityPolicy.enforceCallingPermission(
|
||||
@@ -662,6 +674,29 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder getWindowToken(int windowId) {
|
||||
mSecurityPolicy.enforceCallingPermission(
|
||||
Manifest.permission.RETRIEVE_WINDOW_TOKEN,
|
||||
GET_WINDOW_TOKEN);
|
||||
synchronized (mLock) {
|
||||
final int resolvedUserId = mSecurityPolicy
|
||||
.resolveCallingUserIdEnforcingPermissionsLocked(
|
||||
UserHandle.getCallingUserId());
|
||||
if (resolvedUserId != mCurrentUserId) {
|
||||
return null;
|
||||
}
|
||||
if (mSecurityPolicy.findWindowById(windowId) == null) {
|
||||
return null;
|
||||
}
|
||||
IBinder token = mGlobalWindowTokens.get(windowId);
|
||||
if (token != null) {
|
||||
return token;
|
||||
}
|
||||
return getCurrentUserStateLocked().mWindowTokens.get(windowId);
|
||||
}
|
||||
}
|
||||
|
||||
boolean onGesture(int gestureId) {
|
||||
synchronized (mLock) {
|
||||
boolean handled = notifyGestureLocked(gestureId, false);
|
||||
@@ -689,7 +724,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
* @param outBounds The output to which to write the focus bounds.
|
||||
* @return Whether accessibility focus was found and the bounds are populated.
|
||||
*/
|
||||
// TODO: (multi-display) Make sure this works for multiple displays.
|
||||
// TODO: (multi-display) Make sure this works for multiple displays.
|
||||
boolean getAccessibilityFocusBoundsInActiveWindow(Rect outBounds) {
|
||||
// Instead of keeping track of accessibility focus events per
|
||||
// window to be able to find the focus in the active window,
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.util.ArraySet;
|
||||
import android.util.TimeUtils;
|
||||
import android.view.IWindowId;
|
||||
|
||||
import android.view.WindowContentFrameStats;
|
||||
import com.android.internal.app.IBatteryStats;
|
||||
import com.android.internal.policy.PolicyManager;
|
||||
import com.android.internal.policy.impl.PhoneWindowManager;
|
||||
@@ -626,6 +627,8 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
|
||||
private final PointerEventDispatcher mPointerEventDispatcher;
|
||||
|
||||
private WindowContentFrameStats mTempWindowRenderStats;
|
||||
|
||||
final class DragInputEventReceiver extends InputEventReceiver {
|
||||
public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
|
||||
super(inputChannel, looper);
|
||||
@@ -10264,6 +10267,51 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
return mSafeMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearWindowContentFrameStats(IBinder token) {
|
||||
if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
|
||||
"clearWindowContentFrameStats()")) {
|
||||
throw new SecurityException("Requires FRAME_STATS permission");
|
||||
}
|
||||
synchronized (mWindowMap) {
|
||||
WindowState windowState = mWindowMap.get(token);
|
||||
if (windowState == null) {
|
||||
return false;
|
||||
}
|
||||
SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl;
|
||||
if (surfaceControl == null) {
|
||||
return false;
|
||||
}
|
||||
return surfaceControl.clearContentFrameStats();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindowContentFrameStats getWindowContentFrameStats(IBinder token) {
|
||||
if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
|
||||
"getWindowContentFrameStats()")) {
|
||||
throw new SecurityException("Requires FRAME_STATS permission");
|
||||
}
|
||||
synchronized (mWindowMap) {
|
||||
WindowState windowState = mWindowMap.get(token);
|
||||
if (windowState == null) {
|
||||
return null;
|
||||
}
|
||||
SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl;
|
||||
if (surfaceControl == null) {
|
||||
return null;
|
||||
}
|
||||
if (mTempWindowRenderStats == null) {
|
||||
mTempWindowRenderStats = new WindowContentFrameStats();
|
||||
}
|
||||
WindowContentFrameStats stats = mTempWindowRenderStats;
|
||||
if (!surfaceControl.getContentFrameStats(stats)) {
|
||||
return null;
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
}
|
||||
|
||||
void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
|
||||
pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
|
||||
mPolicy.dump(" ", pw, args);
|
||||
|
||||
@@ -23,22 +23,11 @@ import com.android.internal.view.IInputMethodClient;
|
||||
import android.content.res.CompatibilityInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.IRemoteCallback;
|
||||
import android.os.RemoteException;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.Display;
|
||||
import android.view.Gravity;
|
||||
import android.view.IApplicationToken;
|
||||
import android.view.IInputFilter;
|
||||
import android.view.IOnKeyguardExitResult;
|
||||
import android.view.IRotationWatcher;
|
||||
import android.view.IWindowManager;
|
||||
import android.view.IWindowSession;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Basic implementation of {@link IWindowManager} so that {@link Display} (and
|
||||
@@ -462,4 +451,16 @@ public class IWindowManagerImpl implements IWindowManager {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearWindowContentRenderStats(IBinder token) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindowContentFrameStats getWindowContentRenderStats(IBinder token) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user