diff options
Diffstat (limited to 'core/java/android')
61 files changed, 1832 insertions, 330 deletions
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java index b01d92c..2620c44 100644 --- a/core/java/android/accessibilityservice/AccessibilityService.java +++ b/core/java/android/accessibilityservice/AccessibilityService.java @@ -526,6 +526,31 @@ public abstract class AccessibilityService extends Service { } /** + * Find the view that has the specified focus type. The search is performed + * across all windows. + * <p> + * <strong>Note:</strong> In order to access the windows your service has + * to declare the capability to retrieve window content by setting the + * {@link android.R.styleable#AccessibilityService_canRetrieveWindowContent} + * property in its meta-data. For details refer to {@link #SERVICE_META_DATA}. + * Also the service has to opt-in to retrieve the interactive windows by + * setting the {@link AccessibilityServiceInfo#FLAG_RETRIEVE_INTERACTIVE_WINDOWS} + * flag.Otherwise, the search will be performed only in the active window. + * </p> + * + * @param focus The focus to find. One of {@link AccessibilityNodeInfo#FOCUS_INPUT} or + * {@link AccessibilityNodeInfo#FOCUS_ACCESSIBILITY}. + * @return The node info of the focused view or null. + * + * @see AccessibilityNodeInfo#FOCUS_INPUT + * @see AccessibilityNodeInfo#FOCUS_ACCESSIBILITY + */ + public AccessibilityNodeInfo findFocus(int focus) { + return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId, + AccessibilityNodeInfo.ANY_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID, focus); + } + + /** * Gets the an {@link AccessibilityServiceInfo} describing this * {@link AccessibilityService}. This method is useful if one wants * to change some of the dynamically configurable properties at diff --git a/core/java/android/app/IUiAutomationConnection.aidl b/core/java/android/app/IUiAutomationConnection.aidl index 09bf829..347de97 100644 --- a/core/java/android/app/IUiAutomationConnection.aidl +++ b/core/java/android/app/IUiAutomationConnection.aidl @@ -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(); } diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 36d2635..fe629f6 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -1311,6 +1311,7 @@ public class Notification implements Parcelable private Notification mPublicVersion = null; private boolean mQuantumTheme; private final LegacyNotificationUtil mLegacyNotificationUtil; + private ArrayList<String> mPeople; /** * Constructs a new Builder with the defaults: @@ -1338,6 +1339,7 @@ public class Notification implements Parcelable mWhen = System.currentTimeMillis(); mAudioStreamType = STREAM_DEFAULT; mPriority = PRIORITY_DEFAULT; + mPeople = new ArrayList<String>(); // TODO: Decide on targetSdk from calling app whether to use quantum theme. mQuantumTheme = true; @@ -1723,6 +1725,16 @@ public class Notification implements Parcelable } /** + * Add a person that is relevant to this notification. + * + * @see Notification#EXTRA_PEOPLE + */ + public Builder addPerson(String handle) { + mPeople.add(handle); + return this; + } + + /** * Merge additional metadata into this notification. * * <p>Values within the Bundle will replace existing extras values in this Builder. @@ -2149,6 +2161,9 @@ public class Notification implements Parcelable if (mLargeIcon != null) { extras.putParcelable(EXTRA_LARGE_ICON, mLargeIcon); } + if (!mPeople.isEmpty()) { + extras.putStringArray(EXTRA_PEOPLE, mPeople.toArray(new String[mPeople.size()])); + } } /** diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java index 354a19f..9405325 100644 --- a/core/java/android/app/UiAutomation.java +++ b/core/java/android/app/UiAutomation.java @@ -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; @@ -295,6 +297,28 @@ public final class UiAutomation { } /** + * Find the view that has the specified focus type. The search is performed + * across all windows. + * <p> + * <strong>Note:</strong> In order to access the windows you have to opt-in + * to retrieve the interactive windows by setting the + * {@link AccessibilityServiceInfo#FLAG_RETRIEVE_INTERACTIVE_WINDOWS} flag. + * Otherwise, the search will be performed only in the active window. + * </p> + * + * @param focus The focus to find. One of {@link AccessibilityNodeInfo#FOCUS_INPUT} or + * {@link AccessibilityNodeInfo#FOCUS_ACCESSIBILITY}. + * @return The node info of the focused view or null. + * + * @see AccessibilityNodeInfo#FOCUS_INPUT + * @see AccessibilityNodeInfo#FOCUS_ACCESSIBILITY + */ + public AccessibilityNodeInfo findFocus(int focus) { + return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId, + AccessibilityNodeInfo.ANY_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID, focus); + } + + /** * Gets the an {@link AccessibilityServiceInfo} describing this UiAutomation. * This method is useful if one wants to change some of the dynamically * configurable properties at runtime. @@ -674,6 +698,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: { diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java index 91b0d7c..fa40286 100644 --- a/core/java/android/app/UiAutomationConnection.java +++ b/core/java/android/app/UiAutomationConnection.java @@ -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(); @@ -144,6 +150,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) { if (isConnectedLocked()) { diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 30c84f6..725f808 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -1534,10 +1534,10 @@ public class DevicePolicyManager { /** * @hide */ - public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing) { + public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing, int userHandle) { if (mService != null) { try { - mService.setActiveAdmin(policyReceiver, refreshing, UserHandle.myUserId()); + mService.setActiveAdmin(policyReceiver, refreshing, userHandle); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1545,6 +1545,13 @@ public class DevicePolicyManager { } /** + * @hide + */ + public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing) { + setActiveAdmin(policyReceiver, refreshing, UserHandle.myUserId()); + } + + /** * Returns the DeviceAdminInfo as defined by the administrator's package info & meta-data * @hide */ @@ -1749,8 +1756,26 @@ public class DevicePolicyManager { } /** + * Sets the enabled state of the profile. A profile should be enabled only once it is ready to + * be used. Only the profile owner can call this. + * + * @see #isPRofileOwnerApp + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + */ + public void setProfileEnabled(ComponentName admin) { + if (mService != null) { + try { + mService.setProfileEnabled(admin); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } + + /** * Used to determine if a particular package is registered as the Profile Owner for the - * current user. A profile owner is a special device admin that has additional priviledges + * current user. A profile owner is a special device admin that has additional privileges * within the managed profile. * * @param packageName The package name of the app to compare with the registered profile owner. diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 8119585..e4b2adc 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -107,6 +107,7 @@ interface IDevicePolicyManager { boolean setProfileOwner(String packageName, String ownerName, int userHandle); String getProfileOwner(int userHandle); String getProfileOwnerName(int userHandle); + void setProfileEnabled(in ComponentName who); boolean installCaCert(in byte[] certBuffer); void uninstallCaCert(in byte[] certBuffer); diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java index 101b721..ff3af7c 100644 --- a/core/java/android/bluetooth/BluetoothGatt.java +++ b/core/java/android/bluetooth/BluetoothGatt.java @@ -50,6 +50,7 @@ public final class BluetoothGatt implements BluetoothProfile { private boolean mAutoConnect; private int mConnState; private final Object mStateLock = new Object(); + private Boolean mDeviceBusy = false; private static final int CONN_STATE_IDLE = 0; private static final int CONN_STATE_CONNECTING = 1; @@ -166,6 +167,10 @@ public final class BluetoothGatt implements BluetoothProfile { mConnState = CONN_STATE_IDLE; } } + + synchronized(mDeviceBusy) { + mDeviceBusy = false; + } } /** @@ -301,6 +306,11 @@ public final class BluetoothGatt implements BluetoothProfile { if (!address.equals(mDevice.getAddress())) { return; } + + synchronized(mDeviceBusy) { + mDeviceBusy = false; + } + if ((status == GATT_INSUFFICIENT_AUTHENTICATION || status == GATT_INSUFFICIENT_ENCRYPTION) && mAuthRetry == false) { @@ -348,6 +358,11 @@ public final class BluetoothGatt implements BluetoothProfile { if (!address.equals(mDevice.getAddress())) { return; } + + synchronized(mDeviceBusy) { + mDeviceBusy = false; + } + BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(), srvcInstId, srvcType); if (service == null) return; @@ -425,6 +440,11 @@ public final class BluetoothGatt implements BluetoothProfile { if (!address.equals(mDevice.getAddress())) { return; } + + synchronized(mDeviceBusy) { + mDeviceBusy = false; + } + BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(), srvcInstId, srvcType); if (service == null) return; @@ -474,6 +494,11 @@ public final class BluetoothGatt implements BluetoothProfile { if (!address.equals(mDevice.getAddress())) { return; } + + synchronized(mDeviceBusy) { + mDeviceBusy = false; + } + BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(), srvcInstId, srvcType); if (service == null) return; @@ -519,6 +544,11 @@ public final class BluetoothGatt implements BluetoothProfile { if (!address.equals(mDevice.getAddress())) { return; } + + synchronized(mDeviceBusy) { + mDeviceBusy = false; + } + try { mCallback.onReliableWriteCompleted(BluetoothGatt.this, status); } catch (Exception ex) { @@ -851,6 +881,11 @@ public final class BluetoothGatt implements BluetoothProfile { BluetoothDevice device = service.getDevice(); if (device == null) return false; + synchronized(mDeviceBusy) { + if (mDeviceBusy) return false; + mDeviceBusy = true; + } + try { mService.readCharacteristic(mClientIf, device.getAddress(), service.getType(), service.getInstanceId(), @@ -858,6 +893,7 @@ public final class BluetoothGatt implements BluetoothProfile { new ParcelUuid(characteristic.getUuid()), AUTHENTICATION_NONE); } catch (RemoteException e) { Log.e(TAG,"",e); + mDeviceBusy = false; return false; } @@ -890,6 +926,11 @@ public final class BluetoothGatt implements BluetoothProfile { BluetoothDevice device = service.getDevice(); if (device == null) return false; + synchronized(mDeviceBusy) { + if (mDeviceBusy) return false; + mDeviceBusy = true; + } + try { mService.writeCharacteristic(mClientIf, device.getAddress(), service.getType(), service.getInstanceId(), @@ -899,6 +940,7 @@ public final class BluetoothGatt implements BluetoothProfile { characteristic.getValue()); } catch (RemoteException e) { Log.e(TAG,"",e); + mDeviceBusy = false; return false; } @@ -930,6 +972,11 @@ public final class BluetoothGatt implements BluetoothProfile { BluetoothDevice device = service.getDevice(); if (device == null) return false; + synchronized(mDeviceBusy) { + if (mDeviceBusy) return false; + mDeviceBusy = true; + } + try { mService.readDescriptor(mClientIf, device.getAddress(), service.getType(), service.getInstanceId(), new ParcelUuid(service.getUuid()), @@ -938,6 +985,7 @@ public final class BluetoothGatt implements BluetoothProfile { AUTHENTICATION_NONE); } catch (RemoteException e) { Log.e(TAG,"",e); + mDeviceBusy = false; return false; } @@ -968,6 +1016,11 @@ public final class BluetoothGatt implements BluetoothProfile { BluetoothDevice device = service.getDevice(); if (device == null) return false; + synchronized(mDeviceBusy) { + if (mDeviceBusy) return false; + mDeviceBusy = true; + } + try { mService.writeDescriptor(mClientIf, device.getAddress(), service.getType(), service.getInstanceId(), new ParcelUuid(service.getUuid()), @@ -977,6 +1030,7 @@ public final class BluetoothGatt implements BluetoothProfile { descriptor.getValue()); } catch (RemoteException e) { Log.e(TAG,"",e); + mDeviceBusy = false; return false; } @@ -1034,10 +1088,16 @@ public final class BluetoothGatt implements BluetoothProfile { if (DBG) Log.d(TAG, "executeReliableWrite() - device: " + mDevice.getAddress()); if (mService == null || mClientIf == 0) return false; + synchronized(mDeviceBusy) { + if (mDeviceBusy) return false; + mDeviceBusy = true; + } + try { mService.endReliableWrite(mClientIf, mDevice.getAddress(), true); } catch (RemoteException e) { Log.e(TAG,"",e); + mDeviceBusy = false; return false; } diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 9881428..a7d5606 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -1417,15 +1417,38 @@ public class Intent implements Parcelable, Cloneable { // Standard intent broadcast actions (see action variable). /** - * Broadcast Action: Sent after the screen turns off. + * Broadcast Action: Sent when the device goes to sleep and becomes non-interactive. + * <p> + * For historical reasons, the name of this broadcast action refers to the power + * state of the screen but it is actually sent in response to changes in the + * overall interactive state of the device. + * </p><p> + * This broadcast is sent when the device becomes non-interactive which may have + * nothing to do with the screen turning off. To determine the + * actual state of the screen, use {@link android.view.Display#getState}. + * </p><p> + * See {@link android.os.PowerManager#isInteractive} for details. + * </p> * * <p class="note">This is a protected intent that can only be sent * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF"; + /** - * Broadcast Action: Sent after the screen turns on. + * Broadcast Action: Sent when the device wakes up and becomes interactive. + * <p> + * For historical reasons, the name of this broadcast action refers to the power + * state of the screen but it is actually sent in response to changes in the + * overall interactive state of the device. + * </p><p> + * This broadcast is sent when the device becomes interactive which may have + * nothing to do with the screen turning on. To determine the + * actual state of the screen, use {@link android.view.Display#getState}. + * </p><p> + * See {@link android.os.PowerManager#isInteractive} for details. + * </p> * * <p class="note">This is a protected intent that can only be sent * by the system. diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 5d02ae9..0d1b262 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -447,6 +447,15 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public String nativeLibraryDir; /** + * The ABI that this application requires, This is inferred from the ABIs + * of the native JNI libraries the application bundles. Will be {@code null} + * if this application does not require any particular ABI. + * + * {@hide} + */ + public String requiredCpuAbi; + + /** * The kernel user-ID that has been assigned to this application; * currently this is not a unique ID (multiple applications can have * the same uid). @@ -583,6 +592,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { sourceDir = orig.sourceDir; publicSourceDir = orig.publicSourceDir; nativeLibraryDir = orig.nativeLibraryDir; + requiredCpuAbi = orig.requiredCpuAbi; resourceDirs = orig.resourceDirs; seinfo = orig.seinfo; sharedLibraryFiles = orig.sharedLibraryFiles; @@ -624,6 +634,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { dest.writeString(sourceDir); dest.writeString(publicSourceDir); dest.writeString(nativeLibraryDir); + dest.writeString(requiredCpuAbi); dest.writeStringArray(resourceDirs); dest.writeString(seinfo); dest.writeStringArray(sharedLibraryFiles); @@ -664,6 +675,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { sourceDir = source.readString(); publicSourceDir = source.readString(); nativeLibraryDir = source.readString(); + requiredCpuAbi = source.readString(); resourceDirs = source.readStringArray(); seinfo = source.readString(); sharedLibraryFiles = source.readStringArray(); diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 3300e9d..d24a472 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -698,6 +698,25 @@ public abstract class PackageManager { public static final int INSTALL_FAILED_DUPLICATE_PERMISSION = -112; /** + * Installation failed return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} + * if the system failed to install the package because its packaged native code did not + * match any of the ABIs supported by the system. + * + * @hide + */ + public static final int INSTALL_FAILED_NO_MATCHING_ABIS = -113; + + /** + * Internal return code for NativeLibraryHelper methods to indicate that the package + * being processed did not contain any native code. This is placed here only so that + * it can belong to the same value space as the other install failure codes. + * + * @hide + */ + public static final int NO_NATIVE_LIBRARIES = -114; + + /** * Flag parameter for {@link #deletePackage} to indicate that you don't want to delete the * package's data directory. * diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java index 1e34498..9b1bc53 100644 --- a/core/java/android/hardware/camera2/CameraMetadata.java +++ b/core/java/android/hardware/camera2/CameraMetadata.java @@ -940,6 +940,17 @@ public abstract class CameraMetadata { */ public static final int CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG = 5; + /** + * <p>This request is for manual capture use case where + * the applications want to directly control the capture parameters + * (e.g. {@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime}, {@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity} etc.).</p> + * + * @see CaptureRequest#SENSOR_EXPOSURE_TIME + * @see CaptureRequest#SENSOR_SENSITIVITY + * @see CaptureRequest#CONTROL_CAPTURE_INTENT + */ + public static final int CONTROL_CAPTURE_INTENT_MANUAL = 6; + // // Enumeration values for CaptureRequest#CONTROL_EFFECT_MODE // diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index 7656505..c4e342c 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -714,16 +714,21 @@ public final class CaptureRequest extends CameraMetadata implements Parcelable { * auto-focus, auto-white balance) routines about the purpose * of this capture, to help the camera device to decide optimal 3A * strategy.</p> - * <p>This control is only effective if <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF</code> - * and any 3A routine is active.</p> + * <p>This control (except for MANUAL) is only effective if + * <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF</code> and any 3A routine is active.</p> + * <p>ZERO_SHUTTER_LAG must be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} + * contains ZSL. MANUAL must be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} + * contains MANUAL_SENSOR.</p> * * @see CaptureRequest#CONTROL_MODE + * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES * @see #CONTROL_CAPTURE_INTENT_CUSTOM * @see #CONTROL_CAPTURE_INTENT_PREVIEW * @see #CONTROL_CAPTURE_INTENT_STILL_CAPTURE * @see #CONTROL_CAPTURE_INTENT_VIDEO_RECORD * @see #CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT * @see #CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG + * @see #CONTROL_CAPTURE_INTENT_MANUAL */ public static final Key<Integer> CONTROL_CAPTURE_INTENT = new Key<Integer>("android.control.captureIntent", int.class); diff --git a/core/java/android/hardware/camera2/CaptureResultExtras.aidl b/core/java/android/hardware/camera2/CaptureResultExtras.aidl new file mode 100644 index 0000000..6587f02 --- /dev/null +++ b/core/java/android/hardware/camera2/CaptureResultExtras.aidl @@ -0,0 +1,20 @@ +/* + * 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.hardware.camera2; + +/** @hide */ +parcelable CaptureResultExtras; diff --git a/core/java/android/hardware/camera2/CaptureResultExtras.java b/core/java/android/hardware/camera2/CaptureResultExtras.java new file mode 100644 index 0000000..e5c2c1c --- /dev/null +++ b/core/java/android/hardware/camera2/CaptureResultExtras.java @@ -0,0 +1,90 @@ +/* + * 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.hardware.camera2; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * @hide + */ +public class CaptureResultExtras implements Parcelable { + private int requestId; + private int subsequenceId; + private int afTriggerId; + private int precaptureTriggerId; + private long frameNumber; + + public static final Parcelable.Creator<CaptureResultExtras> CREATOR = + new Parcelable.Creator<CaptureResultExtras>() { + @Override + public CaptureResultExtras createFromParcel(Parcel in) { + return new CaptureResultExtras(in); + } + + @Override + public CaptureResultExtras[] newArray(int size) { + return new CaptureResultExtras[size]; + } + }; + + private CaptureResultExtras(Parcel in) { + readFromParcel(in); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(requestId); + dest.writeInt(subsequenceId); + dest.writeInt(afTriggerId); + dest.writeInt(precaptureTriggerId); + dest.writeLong(frameNumber); + } + + public void readFromParcel(Parcel in) { + requestId = in.readInt(); + subsequenceId = in.readInt(); + afTriggerId = in.readInt(); + precaptureTriggerId = in.readInt(); + frameNumber = in.readLong(); + } + + public int getRequestId() { + return requestId; + } + + public int getSubsequenceId() { + return subsequenceId; + } + + public int getAfTriggerId() { + return afTriggerId; + } + + public int getPrecaptureTriggerId() { + return precaptureTriggerId; + } + + public long getFrameNumber() { + return frameNumber; + } + +} diff --git a/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl b/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl index 02a73d66..a14d38b 100644 --- a/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl +++ b/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl @@ -17,6 +17,7 @@ package android.hardware.camera2; import android.hardware.camera2.impl.CameraMetadataNative; +import android.hardware.camera2.CaptureResultExtras; /** @hide */ interface ICameraDeviceCallbacks @@ -25,8 +26,9 @@ interface ICameraDeviceCallbacks * Keep up-to-date with frameworks/av/include/camera/camera2/ICameraDeviceCallbacks.h */ - oneway void onCameraError(int errorCode); + oneway void onCameraError(int errorCode, in CaptureResultExtras resultExtras); oneway void onCameraIdle(); - oneway void onCaptureStarted(int requestId, long timestamp); - oneway void onResultReceived(int requestId, in CameraMetadataNative result); + oneway void onCaptureStarted(in CaptureResultExtras resultExtras, long timestamp); + oneway void onResultReceived(in CameraMetadataNative result, + in CaptureResultExtras resultExtras); } diff --git a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl index 1936963..d77f3d1 100644 --- a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl +++ b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl @@ -20,6 +20,8 @@ import android.view.Surface; import android.hardware.camera2.impl.CameraMetadataNative; import android.hardware.camera2.CaptureRequest; +import android.hardware.camera2.LongParcelable; + /** @hide */ interface ICameraDeviceUser { @@ -31,9 +33,13 @@ interface ICameraDeviceUser // ints here are status_t // non-negative value is the requestId. negative value is status_t - int submitRequest(in CaptureRequest request, boolean streaming); + int submitRequest(in CaptureRequest request, boolean streaming, + out LongParcelable lastFrameNumber); + + int submitRequestList(in List<CaptureRequest> requestList, boolean streaming, + out LongParcelable lastFrameNumber); - int cancelRequest(int requestId); + int cancelRequest(int requestId, out LongParcelable lastFrameNumber); int deleteStream(int streamId); @@ -46,5 +52,5 @@ interface ICameraDeviceUser int waitUntilIdle(); - int flush(); + int flush(out LongParcelable lastFrameNumber); } diff --git a/core/java/android/hardware/camera2/LongParcelable.aidl b/core/java/android/hardware/camera2/LongParcelable.aidl new file mode 100644 index 0000000..7d7e51b --- /dev/null +++ b/core/java/android/hardware/camera2/LongParcelable.aidl @@ -0,0 +1,20 @@ +/* + * 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.hardware.camera2; + +/** @hide */ +parcelable LongParcelable;
\ No newline at end of file diff --git a/core/java/android/hardware/camera2/LongParcelable.java b/core/java/android/hardware/camera2/LongParcelable.java new file mode 100644 index 0000000..97b0631 --- /dev/null +++ b/core/java/android/hardware/camera2/LongParcelable.java @@ -0,0 +1,74 @@ +/* + * 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.hardware.camera2; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * @hide + */ +public class LongParcelable implements Parcelable { + private long number; + + public LongParcelable() { + this.number = 0; + } + + public LongParcelable(long number) { + this.number = number; + } + + public static final Parcelable.Creator<LongParcelable> CREATOR = + new Parcelable.Creator<LongParcelable>() { + @Override + public LongParcelable createFromParcel(Parcel in) { + return new LongParcelable(in); + } + + @Override + public LongParcelable[] newArray(int size) { + return new LongParcelable[size]; + } + }; + + private LongParcelable(Parcel in) { + readFromParcel(in); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeLong(number); + } + + public void readFromParcel(Parcel in) { + number = in.readLong(); + } + + public long getNumber() { + return number; + } + + public void setNumber(long number) { + this.number = number; + } + +} diff --git a/core/java/android/hardware/camera2/impl/CameraDevice.java b/core/java/android/hardware/camera2/impl/CameraDevice.java index ecc461e..cd44b51 100644 --- a/core/java/android/hardware/camera2/impl/CameraDevice.java +++ b/core/java/android/hardware/camera2/impl/CameraDevice.java @@ -21,8 +21,10 @@ import static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE; import android.hardware.camera2.CameraAccessException; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.CaptureResult; +import android.hardware.camera2.CaptureResultExtras; import android.hardware.camera2.ICameraDeviceCallbacks; import android.hardware.camera2.ICameraDeviceUser; +import android.hardware.camera2.LongParcelable; import android.hardware.camera2.utils.CameraBinderDecorator; import android.hardware.camera2.utils.CameraRuntimeException; import android.os.Handler; @@ -33,10 +35,12 @@ import android.util.Log; import android.util.SparseArray; import android.view.Surface; +import java.util.AbstractMap.SimpleEntry; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.TreeSet; /** * HAL2.1+ implementation of CameraDevice. Use CameraManager#open to instantiate @@ -69,10 +73,24 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { private final String mCameraId; + /** + * A list tracking request and its expected last frame. + * Updated when calling ICameraDeviceUser methods. + */ + private final List<SimpleEntry</*frameNumber*/Long, /*requestId*/Integer>> + mFrameNumberRequestPairs = new ArrayList<SimpleEntry<Long, Integer>>(); + + /** + * An object tracking received frame numbers. + * Updated when receiving callbacks from ICameraDeviceCallbacks. + */ + private final FrameNumberTracker mFrameNumberTracker = new FrameNumberTracker(); + // Runnables for all state transitions, except error, which needs the // error code argument private final Runnable mCallOnOpened = new Runnable() { + @Override public void run() { if (!CameraDevice.this.isClosed()) { mDeviceListener.onOpened(CameraDevice.this); @@ -81,6 +99,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { }; private final Runnable mCallOnUnconfigured = new Runnable() { + @Override public void run() { if (!CameraDevice.this.isClosed()) { mDeviceListener.onUnconfigured(CameraDevice.this); @@ -89,6 +108,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { }; private final Runnable mCallOnActive = new Runnable() { + @Override public void run() { if (!CameraDevice.this.isClosed()) { mDeviceListener.onActive(CameraDevice.this); @@ -97,6 +117,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { }; private final Runnable mCallOnBusy = new Runnable() { + @Override public void run() { if (!CameraDevice.this.isClosed()) { mDeviceListener.onBusy(CameraDevice.this); @@ -105,12 +126,14 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { }; private final Runnable mCallOnClosed = new Runnable() { + @Override public void run() { mDeviceListener.onClosed(CameraDevice.this); } }; private final Runnable mCallOnIdle = new Runnable() { + @Override public void run() { if (!CameraDevice.this.isClosed()) { mDeviceListener.onIdle(CameraDevice.this); @@ -119,6 +142,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { }; private final Runnable mCallOnDisconnected = new Runnable() { + @Override public void run() { if (!CameraDevice.this.isClosed()) { mDeviceListener.onDisconnected(CameraDevice.this); @@ -249,22 +273,26 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { @Override public int capture(CaptureRequest request, CaptureListener listener, Handler handler) throws CameraAccessException { - return submitCaptureRequest(request, listener, handler, /*streaming*/false); + if (DEBUG) { + Log.d(TAG, "calling capture"); + } + List<CaptureRequest> requestList = new ArrayList<CaptureRequest>(); + requestList.add(request); + return submitCaptureRequest(requestList, listener, handler, /*streaming*/false); } @Override public int captureBurst(List<CaptureRequest> requests, CaptureListener listener, Handler handler) throws CameraAccessException { + // TODO: remove this. Throw IAE if the request is null or empty. Need to update API doc. if (requests.isEmpty()) { Log.w(TAG, "Capture burst request list is empty, do nothing!"); return -1; } - // TODO - throw new UnsupportedOperationException("Burst capture implemented yet"); - + return submitCaptureRequest(requests, listener, handler, /*streaming*/false); } - private int submitCaptureRequest(CaptureRequest request, CaptureListener listener, + private int submitCaptureRequest(List<CaptureRequest> requestList, CaptureListener listener, Handler handler, boolean repeating) throws CameraAccessException { // Need a valid handler, or current thread needs to have a looper, if @@ -281,8 +309,13 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { stopRepeating(); } + LongParcelable lastFrameNumberRef = new LongParcelable(); try { - requestId = mRemoteDevice.submitRequest(request, repeating); + requestId = mRemoteDevice.submitRequestList(requestList, repeating, + /*out*/lastFrameNumberRef); + if (!repeating) { + Log.v(TAG, "last frame number " + lastFrameNumberRef.getNumber()); + } } catch (CameraRuntimeException e) { throw e.asChecked(); } catch (RemoteException e) { @@ -290,12 +323,29 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { return -1; } if (listener != null) { - mCaptureListenerMap.put(requestId, new CaptureListenerHolder(listener, request, - handler, repeating)); + mCaptureListenerMap.put(requestId, new CaptureListenerHolder(listener, + requestList, handler, repeating)); } + long lastFrameNumber = lastFrameNumberRef.getNumber(); + /** + * If it's the first repeating request, then returned lastFrameNumber can be + * negative. Otherwise, it should always be non-negative. + */ + if (((lastFrameNumber < 0) && (requestId > 0)) + || ((lastFrameNumber < 0) && (!repeating))) { + throw new AssertionError(String.format("returned bad frame number %d", + lastFrameNumber)); + } if (repeating) { + if (mRepeatingRequestId != REQUEST_ID_NONE) { + mFrameNumberRequestPairs.add( + new SimpleEntry<Long, Integer>(lastFrameNumber, mRepeatingRequestId)); + } mRepeatingRequestId = requestId; + } else { + mFrameNumberRequestPairs.add( + new SimpleEntry<Long, Integer>(lastFrameNumber, requestId)); } if (mIdle) { @@ -310,18 +360,20 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { @Override public int setRepeatingRequest(CaptureRequest request, CaptureListener listener, Handler handler) throws CameraAccessException { - return submitCaptureRequest(request, listener, handler, /*streaming*/true); + List<CaptureRequest> requestList = new ArrayList<CaptureRequest>(); + requestList.add(request); + return submitCaptureRequest(requestList, listener, handler, /*streaming*/true); } @Override public int setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener, Handler handler) throws CameraAccessException { + // TODO: remove this. Throw IAE if the request is null or empty. Need to update API doc. if (requests.isEmpty()) { Log.w(TAG, "Set Repeating burst request list is empty, do nothing!"); return -1; } - // TODO - throw new UnsupportedOperationException("Burst capture implemented yet"); + return submitCaptureRequest(requests, listener, handler, /*streaming*/true); } @Override @@ -340,7 +392,15 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { } try { - mRemoteDevice.cancelRequest(requestId); + LongParcelable lastFrameNumberRef = new LongParcelable(); + mRemoteDevice.cancelRequest(requestId, /*out*/lastFrameNumberRef); + long lastFrameNumber = lastFrameNumberRef.getNumber(); + if ((lastFrameNumber < 0) && (requestId > 0)) { + throw new AssertionError(String.format("returned bad frame number %d", + lastFrameNumber)); + } + mFrameNumberRequestPairs.add( + new SimpleEntry<Long, Integer>(lastFrameNumber, requestId)); } catch (CameraRuntimeException e) { throw e.asChecked(); } catch (RemoteException e) { @@ -379,7 +439,17 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { mDeviceHandler.post(mCallOnBusy); try { - mRemoteDevice.flush(); + LongParcelable lastFrameNumberRef = new LongParcelable(); + mRemoteDevice.flush(/*out*/lastFrameNumberRef); + if (mRepeatingRequestId != REQUEST_ID_NONE) { + long lastFrameNumber = lastFrameNumberRef.getNumber(); + if (lastFrameNumber < 0) { + Log.e(TAG, String.format("returned bad frame number %d", lastFrameNumber)); + } + mFrameNumberRequestPairs.add( + new SimpleEntry<Long, Integer>(lastFrameNumber, mRepeatingRequestId)); + mRepeatingRequestId = REQUEST_ID_NONE; + } } catch (CameraRuntimeException e) { throw e.asChecked(); } catch (RemoteException e) { @@ -425,18 +495,18 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { private final boolean mRepeating; private final CaptureListener mListener; - private final CaptureRequest mRequest; + private final List<CaptureRequest> mRequestList; private final Handler mHandler; - CaptureListenerHolder(CaptureListener listener, CaptureRequest request, Handler handler, - boolean repeating) { + CaptureListenerHolder(CaptureListener listener, List<CaptureRequest> requestList, + Handler handler, boolean repeating) { if (listener == null || handler == null) { throw new UnsupportedOperationException( "Must have a valid handler and a valid listener"); } mRepeating = repeating; mHandler = handler; - mRequest = request; + mRequestList = new ArrayList<CaptureRequest>(requestList); mListener = listener; } @@ -448,8 +518,24 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { return mListener; } + public CaptureRequest getRequest(int subsequenceId) { + if (subsequenceId >= mRequestList.size()) { + throw new IllegalArgumentException( + String.format( + "Requested subsequenceId %d is larger than request list size %d.", + subsequenceId, mRequestList.size())); + } else { + if (subsequenceId < 0) { + throw new IllegalArgumentException(String.format( + "Requested subsequenceId %d is negative", subsequenceId)); + } else { + return mRequestList.get(subsequenceId); + } + } + } + public CaptureRequest getRequest() { - return mRequest; + return getRequest(0); } public Handler getHandler() { @@ -458,6 +544,105 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { } + /** + * This class tracks the last frame number for submitted requests. + */ + public class FrameNumberTracker { + + private long mCompletedFrameNumber = -1; + private final TreeSet<Long> mFutureErrorSet = new TreeSet<Long>(); + + private void update() { + Iterator<Long> iter = mFutureErrorSet.iterator(); + while (iter.hasNext()) { + long errorFrameNumber = iter.next(); + if (errorFrameNumber == mCompletedFrameNumber + 1) { + mCompletedFrameNumber++; + iter.remove(); + } else { + break; + } + } + } + + /** + * This function is called every time when a result or an error is received. + * @param frameNumber: the frame number corresponding to the result or error + * @param isError: true if it is an error, false if it is not an error + */ + public void updateTracker(long frameNumber, boolean isError) { + if (isError) { + mFutureErrorSet.add(frameNumber); + } else { + /** + * HAL cannot send an OnResultReceived for frame N unless it knows for + * sure that all frames prior to N have either errored out or completed. + * So if the current frame is not an error, then all previous frames + * should have arrived. The following line checks whether this holds. + */ + if (frameNumber != mCompletedFrameNumber + 1) { + throw new AssertionError(String.format( + "result frame number %d comes out of order", + frameNumber)); + } + mCompletedFrameNumber++; + } + update(); + } + + public long getCompletedFrameNumber() { + return mCompletedFrameNumber; + } + + } + + private void checkAndFireSequenceComplete() { + long completedFrameNumber = mFrameNumberTracker.getCompletedFrameNumber(); + Iterator<SimpleEntry<Long, Integer> > iter = mFrameNumberRequestPairs.iterator(); + while (iter.hasNext()) { + final SimpleEntry<Long, Integer> frameNumberRequestPair = iter.next(); + if (frameNumberRequestPair.getKey() <= completedFrameNumber) { + + // remove request from mCaptureListenerMap + final int requestId = frameNumberRequestPair.getValue(); + final CaptureListenerHolder holder; + synchronized (mLock) { + int index = CameraDevice.this.mCaptureListenerMap.indexOfKey(requestId); + holder = (index >= 0) ? CameraDevice.this.mCaptureListenerMap.valueAt(index) + : null; + if (holder != null) { + CameraDevice.this.mCaptureListenerMap.removeAt(index); + } + } + iter.remove(); + + // Call onCaptureSequenceCompleted + if (holder != null) { + Runnable resultDispatch = new Runnable() { + @Override + public void run() { + if (!CameraDevice.this.isClosed()){ + if (DEBUG) { + Log.d(TAG, String.format( + "fire sequence complete for request %d", + requestId)); + } + + holder.getListener().onCaptureSequenceCompleted( + CameraDevice.this, + requestId, + // TODO: this is problematic, crop long to int + frameNumberRequestPair.getKey().intValue()); + } + } + }; + holder.getHandler().post(resultDispatch); + } + + } + } + } + public class CameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub { // @@ -492,7 +677,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { } @Override - public void onCameraError(final int errorCode) { + public void onCameraError(final int errorCode, CaptureResultExtras resultExtras) { Runnable r = null; if (isClosed()) return; @@ -507,6 +692,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { case ERROR_CAMERA_DEVICE: case ERROR_CAMERA_SERVICE: r = new Runnable() { + @Override public void run() { if (!CameraDevice.this.isClosed()) { mDeviceListener.onError(CameraDevice.this, errorCode); @@ -517,6 +703,11 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { } CameraDevice.this.mDeviceHandler.post(r); } + + // Fire onCaptureSequenceCompleted + mFrameNumberTracker.updateTracker(resultExtras.getFrameNumber(), /*error*/true); + checkAndFireSequenceComplete(); + } @Override @@ -535,7 +726,8 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { } @Override - public void onCaptureStarted(int requestId, final long timestamp) { + public void onCaptureStarted(final CaptureResultExtras resultExtras, final long timestamp) { + int requestId = resultExtras.getRequestId(); if (DEBUG) { Log.d(TAG, "Capture started for id " + requestId); } @@ -555,11 +747,12 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { // Dispatch capture start notice holder.getHandler().post( new Runnable() { + @Override public void run() { if (!CameraDevice.this.isClosed()) { holder.getListener().onCaptureStarted( CameraDevice.this, - holder.getRequest(), + holder.getRequest(resultExtras.getSubsequenceId()), timestamp); } } @@ -567,48 +760,18 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { } @Override - public void onResultReceived(int requestId, CameraMetadataNative result) - throws RemoteException { + public void onResultReceived(CameraMetadataNative result, + CaptureResultExtras resultExtras) throws RemoteException { + int requestId = resultExtras.getRequestId(); if (DEBUG) { Log.d(TAG, "Received result for id " + requestId); } - final CaptureListenerHolder holder; + final CaptureListenerHolder holder = + CameraDevice.this.mCaptureListenerMap.get(requestId); Boolean quirkPartial = result.get(CaptureResult.QUIRKS_PARTIAL_RESULT); boolean quirkIsPartialResult = (quirkPartial != null && quirkPartial); - synchronized (mLock) { - // TODO: move this whole map into this class to make it more testable, - // exposing the methods necessary like subscribeToRequest, unsubscribe.. - // TODO: make class static class - - holder = CameraDevice.this.mCaptureListenerMap.get(requestId); - - // Clean up listener once we no longer expect to see it. - if (holder != null && !holder.isRepeating() && !quirkIsPartialResult) { - CameraDevice.this.mCaptureListenerMap.remove(requestId); - } - - // TODO: add 'capture sequence completed' callback to the - // service, and clean up repeating requests there instead. - - // If we received a result for a repeating request and have - // prior repeating requests queued for deletion, remove those - // requests from mCaptureListenerMap. - if (holder != null && holder.isRepeating() && !quirkIsPartialResult - && mRepeatingRequestIdDeletedList.size() > 0) { - Iterator<Integer> iter = mRepeatingRequestIdDeletedList.iterator(); - while (iter.hasNext()) { - int deletedRequestId = iter.next(); - if (deletedRequestId < requestId) { - CameraDevice.this.mCaptureListenerMap.remove(deletedRequestId); - iter.remove(); - } - } - } - - } - // Check if we have a listener for this if (holder == null) { return; @@ -616,7 +779,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { if (isClosed()) return; - final CaptureRequest request = holder.getRequest(); + final CaptureRequest request = holder.getRequest(resultExtras.getSubsequenceId()); final CaptureResult resultAsCapture = new CaptureResult(result, request, requestId); Runnable resultDispatch = null; @@ -651,6 +814,12 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { } holder.getHandler().post(resultDispatch); + + // Fire onCaptureSequenceCompleted + if (!quirkIsPartialResult) { + mFrameNumberTracker.updateTracker(resultExtras.getFrameNumber(), /*error*/false); + checkAndFireSequenceComplete(); + } } } diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java index 03fa1d5..cec90cd 100644 --- a/core/java/android/hardware/display/DisplayManagerInternal.java +++ b/core/java/android/hardware/display/DisplayManagerInternal.java @@ -58,16 +58,6 @@ public abstract class DisplayManagerInternal { public abstract boolean isProximitySensorAvailable(); /** - * Called by the power manager to blank all displays. - */ - public abstract void blankAllDisplaysFromPowerManager(); - - /** - * Called by the power manager to unblank all displays. - */ - public abstract void unblankAllDisplaysFromPowerManager(); - - /** * Returns information about the specified logical display. * * @param displayId The logical display id. @@ -254,12 +244,10 @@ public abstract class DisplayManagerInternal { void onStateChanged(); void onProximityPositive(); void onProximityNegative(); + void onDisplayStateChange(int state); // one of the Display state constants void acquireSuspendBlocker(); void releaseSuspendBlocker(); - - void blankAllDisplays(); - void unblankAllDisplays(); } /** diff --git a/core/java/android/hardware/hdmi/HdmiCecClient.java b/core/java/android/hardware/hdmi/HdmiCecClient.java index 1f382e6..cd86cd8 100644 --- a/core/java/android/hardware/hdmi/HdmiCecClient.java +++ b/core/java/android/hardware/hdmi/HdmiCecClient.java @@ -88,7 +88,7 @@ public final class HdmiCecClient { } /** - * Send <TextViewOn> message. + * Send <Text View On> message. */ public void sendTextViewOn() { try { @@ -99,7 +99,7 @@ public final class HdmiCecClient { } /** - * Send <ImageViewOn> message. + * Send <Image View On> message. */ public void sendImageViewOn() { try { @@ -110,6 +110,20 @@ public final class HdmiCecClient { } /** + * Send <Give Device Power Status> message. + * + * @param address logical address of the device to send the message to, such as + * {@link HdmiCec#ADDR_TV}. + */ + public void sendGiveDevicePowerStatus(int address) { + try { + mService.sendGiveDevicePowerStatus(mBinder, address); + } catch (RemoteException e) { + Log.e(TAG, "sendGiveDevicePowerStatus threw exception ", e); + } + } + + /** * Returns true if the TV or attached display is powered on. * <p> * The result of this method is only meaningful on playback devices (where the device diff --git a/core/java/android/hardware/hdmi/IHdmiCecService.aidl b/core/java/android/hardware/hdmi/IHdmiCecService.aidl index b5df131..ecdd345 100644 --- a/core/java/android/hardware/hdmi/IHdmiCecService.aidl +++ b/core/java/android/hardware/hdmi/IHdmiCecService.aidl @@ -33,6 +33,7 @@ interface IHdmiCecService { void sendInactiveSource(IBinder b); void sendImageViewOn(IBinder b); void sendTextViewOn(IBinder b); + void sendGiveDevicePowerStatus(IBinder b, int address); boolean isTvOn(IBinder b); void sendMessage(IBinder b, in HdmiCecMessage message); } diff --git a/core/java/android/hardware/input/InputManagerInternal.java b/core/java/android/hardware/input/InputManagerInternal.java index 8be94d0..6a392dd 100644 --- a/core/java/android/hardware/input/InputManagerInternal.java +++ b/core/java/android/hardware/input/InputManagerInternal.java @@ -25,12 +25,18 @@ import android.view.InputEvent; * @hide Only for use within the system server. */ public abstract class InputManagerInternal { + public abstract boolean injectInputEvent(InputEvent event, int displayId, int mode); + /** - * Sets information about the displays as needed by the input system. - * The input system should copy this information if required. + * Called by the display manager to set information about the displays as needed + * by the input system. The input system must copy this information to retain it. */ public abstract void setDisplayViewports(DisplayViewport defaultViewport, DisplayViewport externalTouchViewport); - public abstract boolean injectInputEvent(InputEvent event, int displayId, int mode); + /** + * Called by the power manager to tell the input manager whether it should start + * watching for wake events. + */ + public abstract void setInteractive(boolean interactive); } diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index c8051aa..7f1a2e4 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -74,7 +74,14 @@ public class Build { /** A hardware serial number, if available. Alphanumeric only, case-insensitive. */ public static final String SERIAL = getString("ro.serialno"); - + + /** + * A list of ABIs (in priority) order supported by this device. + * + * @hide + */ + public static final String[] SUPPORTED_ABIS = getString("ro.product.cpu.abilist").split(","); + /** Various version strings. */ public static class VERSION { /** diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl index be3c0cc..6c7b08d 100644 --- a/core/java/android/os/IPowerManager.aidl +++ b/core/java/android/os/IPowerManager.aidl @@ -40,8 +40,8 @@ interface IPowerManager void wakeUp(long time); void goToSleep(long time, int reason); void nap(long time); + boolean isInteractive(); - boolean isScreenOn(); void reboot(boolean confirm, String reason, boolean wait); void shutdown(boolean confirm, boolean wait); void crash(String message); diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index a195200..f8d7c3e 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -601,21 +601,64 @@ public final class PowerManager { } /** - * Returns whether the screen is currently on. + * Returns true if the device is in an interactive state. * <p> - * Only indicates whether the screen is on. The screen could be either bright or dim. + * For historical reasons, the name of this method refers to the power state of + * the screen but it actually describes the overall interactive state of + * the device. This method has been replaced by {@link #isInteractive}. * </p><p> - * {@samplecode - * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); - * boolean isScreenOn = pm.isScreenOn(); - * } + * The value returned by this method only indicates whether the device is + * in an interactive state which may have nothing to do with the screen being + * on or off. To determine the actual state of the screen, + * use {@link android.view.Display#getState}. * </p> * - * @return whether the screen is on (bright or dim). + * @return True if the device is in an interactive state. + * + * @deprecated Use {@link #isInteractive} instead. */ + @Deprecated public boolean isScreenOn() { + return isInteractive(); + } + + /** + * Returns true if the device is in an interactive state. + * <p> + * When this method returns true, the device is awake and ready to interact + * with the user (although this is not a guarantee that the user is actively + * interacting with the device just this moment). The main screen is usually + * turned on while in this state. Certain features, such as the proximity + * sensor, may temporarily turn off the screen while still leaving the device in an + * interactive state. Note in particular that the device is still considered + * to be interactive while dreaming (since dreams can be interactive) but not + * when it is dozing or asleep. + * </p><p> + * When this method returns false, the device is dozing or asleep and must + * be awoken before it will become ready to interact with the user again. The + * main screen is usually turned off while in this state. Certain features, + * such as "ambient mode" may cause the main screen to remain on (albeit in a + * low power state) to display system-provided content while the device dozes. + * </p><p> + * The system will send a {@link android.content.Intent#ACTION_SCREEN_ON screen on} + * or {@link android.content.Intent#ACTION_SCREEN_OFF screen off} broadcast + * whenever the interactive state of the device changes. For historical reasons, + * the names of these broadcasts refer to the power state of the screen + * but they are actually sent in response to changes in the overall interactive + * state of the device, as described by this method. + * </p><p> + * Services may use the non-interactive state as a hint to conserve power + * since the user is not present. + * </p> + * + * @return True if the device is in an interactive state. + * + * @see android.content.Intent#ACTION_SCREEN_ON + * @see android.content.Intent#ACTION_SCREEN_OFF + */ + public boolean isInteractive() { try { - return mService.isScreenOn(); + return mService.isInteractive(); } catch (RemoteException e) { return false; } diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 79ff49c..995e396 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -372,7 +372,7 @@ public class Process { for (int i = 0; i < tries; i++) { if (i > 0) { try { - Log.i("Zygote", "Zygote not up yet, sleeping..."); + Log.i(LOG_TAG, "Zygote not up yet, sleeping..."); Thread.sleep(ZYGOTE_RETRY_MILLIS); } catch (InterruptedException ex) { throw new ZygoteStartFailedEx(ex); @@ -466,6 +466,7 @@ public class Process { * @param debugFlags Additional flags. * @param targetSdkVersion The target SDK version for the app. * @param seInfo null-ok SELinux information for the new process. + * @param abi non-null the ABI this app should be started with. * @param zygoteArgs Additional arguments to supply to the zygote process. * * @return An object that describes the result of the attempt to start the process. @@ -479,12 +480,12 @@ public class Process { int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, + String abi, String[] zygoteArgs) { try { return startViaZygote(processClass, niceName, uid, gid, gids, debugFlags, mountExternal, targetSdkVersion, seInfo, - null, /* zygoteAbi TODO: Replace this with the real ABI */ - zygoteArgs); + abi, zygoteArgs); } catch (ZygoteStartFailedEx ex) { Log.e(LOG_TAG, "Starting VM process through Zygote failed"); @@ -702,14 +703,17 @@ public class Process { primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET, getNumTries(primaryZygoteState)); } - // TODO: Revert this temporary change. This is required to test - // and submit this change ahead of the package manager changes - // that supply this abi. - if (abi == null) { + if (primaryZygoteState.matches(abi)) { return primaryZygoteState; } - if (primaryZygoteState.matches(abi)) { + // TODO: Get rid of this. This is a temporary workaround until all the + // compilation related pieces for the dual zygote stack are ready. + // b/3647418. + if (System.getenv("ANDROID_SOCKET_" + SECONDARY_ZYGOTE_SOCKET) == null) { + Log.e(LOG_TAG, "Forcing app to primary zygote, secondary unavailable (ABI= " + abi + ")"); + // Should be : + // throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi); return primaryZygoteState; } diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java index 2ef5b66..939cda9 100644 --- a/core/java/android/os/storage/IMountService.java +++ b/core/java/android/os/storage/IMountService.java @@ -625,12 +625,13 @@ public interface IMountService extends IInterface { return _result; } - public int encryptStorage(String password) throws RemoteException { + public int encryptStorage(int type, String password) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); int _result; try { _data.writeInterfaceToken(DESCRIPTOR); + _data.writeInt(type); _data.writeString(password); mRemote.transact(Stub.TRANSACTION_encryptStorage, _data, _reply, 0); _reply.readException(); @@ -1210,8 +1211,9 @@ public interface IMountService extends IInterface { } case TRANSACTION_encryptStorage: { data.enforceInterface(DESCRIPTOR); + int type = data.readInt(); String password = data.readString(); - int result = encryptStorage(password); + int result = encryptStorage(type, password); reply.writeNoException(); reply.writeInt(result); return true; @@ -1495,7 +1497,7 @@ public interface IMountService extends IInterface { /** * Encrypts storage. */ - public int encryptStorage(String password) throws RemoteException; + public int encryptStorage(int type, String password) throws RemoteException; /** * Changes the encryption password. diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java index 144c909..56d5617 100644 --- a/core/java/android/preference/Preference.java +++ b/core/java/android/preference/Preference.java @@ -533,8 +533,7 @@ public class Preference implements Comparable<Preference> { * @see #onCreateView(ViewGroup) */ protected void onBindView(View view) { - final TextView titleView = (TextView) view.findViewById( - com.android.internal.R.id.title); + final TextView titleView = (TextView) view.findViewById(com.android.internal.R.id.title); if (titleView != null) { final CharSequence title = getTitle(); if (!TextUtils.isEmpty(title)) { @@ -557,7 +556,7 @@ public class Preference implements Comparable<Preference> { } } - ImageView imageView = (ImageView) view.findViewById(com.android.internal.R.id.icon); + final ImageView imageView = (ImageView) view.findViewById(com.android.internal.R.id.icon); if (imageView != null) { if (mIconResId != 0 || mIcon != null) { if (mIcon == null) { @@ -570,6 +569,11 @@ public class Preference implements Comparable<Preference> { imageView.setVisibility(mIcon != null ? View.VISIBLE : View.GONE); } + final View imageFrame = view.findViewById(com.android.internal.R.id.icon_frame); + if (imageFrame != null) { + imageFrame.setVisibility(mIcon != null ? View.VISIBLE : View.GONE); + } + if (mShouldDisableView) { setEnabledStateOnViews(view, isEnabled()); } diff --git a/core/java/android/provider/SearchIndexableData.java b/core/java/android/provider/SearchIndexableData.java index 05285a3..3f88f18 100644 --- a/core/java/android/provider/SearchIndexableData.java +++ b/core/java/android/provider/SearchIndexableData.java @@ -128,4 +128,44 @@ public abstract class SearchIndexableData { locale = Locale.getDefault(); enabled = true; } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("SearchIndexableData[context: "); + sb.append(context); + sb.append(", "); + sb.append("locale: "); + sb.append(locale); + sb.append(", "); + sb.append("enabled: "); + sb.append(enabled); + sb.append(", "); + sb.append("rank: "); + sb.append(rank); + sb.append(", "); + sb.append("key: "); + sb.append(key); + sb.append(", "); + sb.append("className: "); + sb.append(className); + sb.append(", "); + sb.append("packageName: "); + sb.append(packageName); + sb.append(", "); + sb.append("iconResId: "); + sb.append(iconResId); + sb.append(", "); + sb.append("intentAction: "); + sb.append(intentAction); + sb.append(", "); + sb.append("intentTargetPackage: "); + sb.append(intentTargetPackage); + sb.append(", "); + sb.append("intentTargetClass: "); + sb.append(intentTargetClass); + sb.append("]"); + + return sb.toString(); + } } diff --git a/core/java/android/provider/SearchIndexableResource.java b/core/java/android/provider/SearchIndexableResource.java index ba3bd4f..bf33c65 100644 --- a/core/java/android/provider/SearchIndexableResource.java +++ b/core/java/android/provider/SearchIndexableResource.java @@ -62,4 +62,17 @@ public class SearchIndexableResource extends SearchIndexableData { public SearchIndexableResource(Context context) { super(context); } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("SearchIndexableResource["); + sb.append(super.toString()); + sb.append(", "); + sb.append("xmlResId: "); + sb.append(xmlResId); + sb.append("]"); + + return sb.toString(); + } }
\ No newline at end of file diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java index de9eeff..2303d65 100644 --- a/core/java/android/service/dreams/DreamService.java +++ b/core/java/android/service/dreams/DreamService.java @@ -789,10 +789,20 @@ public class DreamService extends Service implements Window.Callback { return; } - // start it up - if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()"); - mStarted = true; - onDreamingStarted(); + // We need to defer calling onDreamingStarted until after onWindowAttached, + // which is posted to the handler by addView, so we post onDreamingStarted + // to the handler also. Need to watch out here in case detach occurs before + // this callback is invoked. + mHandler.post(new Runnable() { + @Override + public void run() { + if (mWindow != null) { + if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()"); + mStarted = true; + onDreamingStarted(); + } + } + }); } private void safelyFinish() { diff --git a/core/java/android/speech/tts/TextToSpeechClient.java b/core/java/android/speech/tts/TextToSpeechClient.java index c6a14f2..10e2073 100644 --- a/core/java/android/speech/tts/TextToSpeechClient.java +++ b/core/java/android/speech/tts/TextToSpeechClient.java @@ -57,7 +57,7 @@ import java.util.concurrent.atomic.AtomicInteger; * successful callback is the client usable. * <p> * After successful connection, the list of all available voices can be obtained - * by calling the {@link TextToSpeechClient#getEngineStatus() method. The client can + * by calling the {@link TextToSpeechClient#getEngineStatus()} method. The client can * choose a voice using some custom heuristic and build a {@link RequestConfig} object * using {@link RequestConfig.Builder}, or can use one of the common heuristics found * in ({@link RequestConfigHelper}. @@ -69,7 +69,7 @@ import java.util.concurrent.atomic.AtomicInteger; * {@link ConnectionCallbacks#onEngineStatusChange} with new set of available voices as argument. * In response, the client HAVE to recreate all {@link RequestConfig} instances in use. */ -public final class TextToSpeechClient { +public class TextToSpeechClient { private static final String TAG = TextToSpeechClient.class.getSimpleName(); private final Object mLock = new Object(); diff --git a/core/java/android/tv/TvInputInfo.java b/core/java/android/tv/TvInputInfo.java index 90625d8..90e4177 100644 --- a/core/java/android/tv/TvInputInfo.java +++ b/core/java/android/tv/TvInputInfo.java @@ -87,6 +87,34 @@ public final class TvInputInfo implements Parcelable { return 0; } + @Override + public int hashCode() { + return mId.hashCode(); + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + + if (!(o instanceof TvInputInfo)) { + return false; + } + + TvInputInfo obj = (TvInputInfo) o; + return mId.equals(obj.mId) + && mService.serviceInfo.packageName.equals(obj.mService.serviceInfo.packageName) + && mService.serviceInfo.name.equals(obj.mService.serviceInfo.name); + } + + @Override + public String toString() { + return "TvInputInfo{id=" + mId + + ", pkg=" + mService.serviceInfo.packageName + + ", service=" + mService.serviceInfo.name + "}"; + } + /** * Used to package this object into a {@link Parcel}. * diff --git a/core/java/android/view/AnimationRenderStats.aidl b/core/java/android/view/AnimationRenderStats.aidl new file mode 100644 index 0000000..4599708 --- /dev/null +++ b/core/java/android/view/AnimationRenderStats.aidl @@ -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; diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index d3f63b4..d7a913d 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -204,6 +204,36 @@ public final class Display { public static final int TYPE_VIRTUAL = 5; /** + * Display state: The display state is unknown. + * + * @see #getState + */ + public static final int STATE_UNKNOWN = 0; + + /** + * Display state: The display is off. + * + * @see #getState + */ + public static final int STATE_OFF = 1; + + /** + * Display state: The display is on. + * + * @see #getState + */ + public static final int STATE_ON = 2; + + /** + * Display state: The display is dozing in a low-power state; it may be showing + * system-provided content while the device is in a non-interactive state. + * + * @see #getState + * @see android.os.PowerManager#isInteractive + */ + public static final int STATE_DOZING = 3; + + /** * Internal method to create a display. * Applications should use {@link android.view.WindowManager#getDefaultDisplay()} * or {@link android.hardware.display.DisplayManager#getDisplay} @@ -630,6 +660,19 @@ public final class Display { } /** + * Gets the state of the display, such as whether it is on or off. + * + * @return The state of the display: one of {@link #STATE_OFF}, {@link #STATE_ON}, + * {@link #STATE_DOZING}, or {@link #STATE_UNKNOWN}. + */ + public int getState() { + synchronized (this) { + updateDisplayInfoLocked(); + return mIsValid ? mDisplayInfo.state : STATE_UNKNOWN; + } + } + + /** * Returns true if the specified UID has access to this display. * @hide */ @@ -720,5 +763,22 @@ public final class Display { return Integer.toString(type); } } -} + /** + * @hide + */ + public static String stateToString(int state) { + switch (state) { + case STATE_UNKNOWN: + return "UNKNOWN"; + case STATE_OFF: + return "OFF"; + case STATE_ON: + return "ON"; + case STATE_DOZING: + return "DOZING"; + default: + return Integer.toString(state); + } + } +} diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java index 7fd7b83..b0fe0fa 100644 --- a/core/java/android/view/DisplayInfo.java +++ b/core/java/android/view/DisplayInfo.java @@ -180,6 +180,11 @@ public final class DisplayInfo implements Parcelable { public float physicalYDpi; /** + * The state of the display, such as {@link android.view.Display#STATE_ON}. + */ + public int state; + + /** * The UID of the application that owns this display, or zero if it is owned by the system. * <p> * If the display is private, then only the owner can use it. @@ -248,6 +253,7 @@ public final class DisplayInfo implements Parcelable { && logicalDensityDpi == other.logicalDensityDpi && physicalXDpi == other.physicalXDpi && physicalYDpi == other.physicalYDpi + && state == other.state && ownerUid == other.ownerUid && Objects.equal(ownerPackageName, other.ownerPackageName); } @@ -280,6 +286,7 @@ public final class DisplayInfo implements Parcelable { logicalDensityDpi = other.logicalDensityDpi; physicalXDpi = other.physicalXDpi; physicalYDpi = other.physicalYDpi; + state = other.state; ownerUid = other.ownerUid; ownerPackageName = other.ownerPackageName; } @@ -307,6 +314,7 @@ public final class DisplayInfo implements Parcelable { logicalDensityDpi = source.readInt(); physicalXDpi = source.readFloat(); physicalYDpi = source.readFloat(); + state = source.readInt(); ownerUid = source.readInt(); ownerPackageName = source.readString(); } @@ -335,6 +343,7 @@ public final class DisplayInfo implements Parcelable { dest.writeInt(logicalDensityDpi); dest.writeFloat(physicalXDpi); dest.writeFloat(physicalYDpi); + dest.writeInt(state); dest.writeInt(ownerUid); dest.writeString(ownerPackageName); } @@ -431,7 +440,7 @@ public final class DisplayInfo implements Parcelable { sb.append(smallestNominalAppHeight); sb.append(", "); sb.append(refreshRate); - sb.append(" fps, rotation"); + sb.append(" fps, rotation "); sb.append(rotation); sb.append(", density "); sb.append(logicalDensityDpi); @@ -446,6 +455,8 @@ public final class DisplayInfo implements Parcelable { if (address != null) { sb.append(", address ").append(address); } + sb.append(", state "); + sb.append(Display.stateToString(state)); if (ownerUid != 0 || ownerPackageName != null) { sb.append(", owner ").append(ownerPackageName); sb.append(" (uid ").append(ownerUid).append(")"); diff --git a/core/java/android/view/FrameStats.java b/core/java/android/view/FrameStats.java new file mode 100644 index 0000000..541b336 --- /dev/null +++ b/core/java/android/view/FrameStats.java @@ -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]; + } +} diff --git a/core/java/android/view/GLRenderer.java b/core/java/android/view/GLRenderer.java index bcdfda6..eba4f7f 100644 --- a/core/java/android/view/GLRenderer.java +++ b/core/java/android/view/GLRenderer.java @@ -1226,11 +1226,6 @@ public class GLRenderer extends HardwareRenderer { } } - void setDisplayListData(long displayList, long newData) { - nSetDisplayListData(displayList, newData); - } - private static native void nSetDisplayListData(long displayList, long newData); - @Override void fence() { // Everything is immediate, so this is a no-op @@ -1322,7 +1317,7 @@ public class GLRenderer extends HardwareRenderer { } Trace.traceBegin(Trace.TRACE_TAG_VIEW, "drawDisplayList"); - nUpdateRenderNodeProperties(displayList.getNativeDisplayList()); + nPrepareTree(displayList.getNativeDisplayList()); try { status |= canvas.drawDisplayList(displayList, mRedrawClip, RenderNode.FLAG_CLIP_CHILDREN); @@ -1481,7 +1476,7 @@ public class GLRenderer extends HardwareRenderer { static native void nDestroyLayer(long layerPtr); - private static native void nUpdateRenderNodeProperties(long displayListPtr); + private static native void nPrepareTree(long displayListPtr); class DrawPerformanceDataProvider extends GraphDataProvider { private final int mGraphType; diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 7d46cab..56d96e1 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -580,8 +580,6 @@ public abstract class HardwareRenderer { mRequested = requested; } - abstract void setDisplayListData(long displayList, long newData); - /** * Blocks until all previously queued work has completed. */ diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 8f542bb..80d5bf2 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -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); } diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index c183f08..c3f429c 100644 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -1166,7 +1166,11 @@ public class KeyEvent extends InputEvent implements Parcelable { /** * This mask is set if the device woke because of this key event. + * + * @deprecated This flag will never be set by the system since the system + * consumes all wake keys itself. */ + @Deprecated public static final int FLAG_WOKE_HERE = 0x1; /** diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java index 78ddf5b..30e4281 100644 --- a/core/java/android/view/RenderNode.java +++ b/core/java/android/view/RenderNode.java @@ -174,12 +174,10 @@ public class RenderNode { public static final int STATUS_DREW = 0x4; private boolean mValid; - private final long mNativeDisplayList; - private HardwareRenderer mRenderer; + private final long mNativeRenderNode; private RenderNode(String name) { - mNativeDisplayList = nCreate(); - nSetDisplayListName(mNativeDisplayList, name); + mNativeRenderNode = nCreate(name); } /** @@ -202,7 +200,7 @@ public class RenderNode { * stored in this display list. * * Calling this method will mark the render node invalid until - * {@link #end(HardwareRenderer, HardwareCanvas)} is called. + * {@link #end(HardwareCanvas)} is called. * Only valid render nodes can be replayed. * * @param width The width of the recording viewport @@ -210,7 +208,7 @@ public class RenderNode { * * @return A canvas to record drawing operations. * - * @see #end(HardwareRenderer, HardwareCanvas) + * @see #end(HardwareCanvas) * @see #isValid() */ public HardwareCanvas start(int width, int height) { @@ -229,21 +227,15 @@ public class RenderNode { * @see #start(int, int) * @see #isValid() */ - public void end(HardwareRenderer renderer, HardwareCanvas endCanvas) { + public void end(HardwareCanvas endCanvas) { if (!(endCanvas instanceof GLES20RecordingCanvas)) { throw new IllegalArgumentException("Passed an invalid canvas to end!"); } GLES20RecordingCanvas canvas = (GLES20RecordingCanvas) endCanvas; canvas.onPostDraw(); - long displayListData = canvas.finishRecording(); - if (renderer != mRenderer) { - // If we are changing renderers first destroy with the old - // renderer, then set with the new one - destroyDisplayListData(); - } - mRenderer = renderer; - setDisplayListData(displayListData); + long renderNodeData = canvas.finishRecording(); + nSetDisplayListData(mNativeRenderNode, renderNodeData); canvas.recycle(); mValid = true; } @@ -258,19 +250,10 @@ public class RenderNode { public void destroyDisplayListData() { if (!mValid) return; - setDisplayListData(0); - mRenderer = null; + nSetDisplayListData(mNativeRenderNode, 0); mValid = false; } - private void setDisplayListData(long newData) { - if (mRenderer != null) { - mRenderer.setDisplayListData(mNativeDisplayList, newData); - } else { - throw new IllegalStateException("Trying to set data without a renderer! data=" + newData); - } - } - /** * Returns whether the RenderNode's display list content is currently usable. * If this returns false, the display list should be re-recorded prior to replaying it. @@ -283,7 +266,7 @@ public class RenderNode { if (!mValid) { throw new IllegalStateException("The display list is not valid."); } - return mNativeDisplayList; + return mNativeRenderNode; } /////////////////////////////////////////////////////////////////////////// @@ -291,15 +274,15 @@ public class RenderNode { /////////////////////////////////////////////////////////////////////////// public boolean hasIdentityMatrix() { - return nHasIdentityMatrix(mNativeDisplayList); + return nHasIdentityMatrix(mNativeRenderNode); } public void getMatrix(@NonNull Matrix outMatrix) { - nGetTransformMatrix(mNativeDisplayList, outMatrix.native_instance); + nGetTransformMatrix(mNativeRenderNode, outMatrix.native_instance); } public void getInverseMatrix(@NonNull Matrix outMatrix) { - nGetInverseTransformMatrix(mNativeDisplayList, outMatrix.native_instance); + nGetInverseTransformMatrix(mNativeRenderNode, outMatrix.native_instance); } /////////////////////////////////////////////////////////////////////////// @@ -316,7 +299,7 @@ public class RenderNode { * @hide */ public void setCaching(boolean caching) { - nSetCaching(mNativeDisplayList, caching); + nSetCaching(mNativeRenderNode, caching); } /** @@ -326,7 +309,7 @@ public class RenderNode { * @param clipToBounds true if the display list should clip to its bounds */ public void setClipToBounds(boolean clipToBounds) { - nSetClipToBounds(mNativeDisplayList, clipToBounds); + nSetClipToBounds(mNativeRenderNode, clipToBounds); } /** @@ -337,7 +320,7 @@ public class RenderNode { * containing volume. */ public void setProjectBackwards(boolean shouldProject) { - nSetProjectBackwards(mNativeDisplayList, shouldProject); + nSetProjectBackwards(mNativeRenderNode, shouldProject); } /** @@ -346,7 +329,7 @@ public class RenderNode { * ProjectBackwards=true directly on top of it. Default value is false. */ public void setProjectionReceiver(boolean shouldRecieve) { - nSetProjectionReceiver(mNativeDisplayList, shouldRecieve); + nSetProjectionReceiver(mNativeRenderNode, shouldRecieve); } /** @@ -357,14 +340,14 @@ public class RenderNode { */ public void setOutline(Outline outline) { if (outline == null) { - nSetOutlineEmpty(mNativeDisplayList); + nSetOutlineEmpty(mNativeRenderNode); } else if (!outline.isValid()) { throw new IllegalArgumentException("Outline must be valid"); } else if (outline.mRect != null) { - nSetOutlineRoundRect(mNativeDisplayList, outline.mRect.left, outline.mRect.top, + nSetOutlineRoundRect(mNativeRenderNode, outline.mRect.left, outline.mRect.top, outline.mRect.right, outline.mRect.bottom, outline.mRadius); } else if (outline.mPath != null) { - nSetOutlineConvexPath(mNativeDisplayList, outline.mPath.mNativePath); + nSetOutlineConvexPath(mNativeRenderNode, outline.mPath.mNativePath); } } @@ -374,7 +357,7 @@ public class RenderNode { * @param clipToOutline true if clipping to the outline. */ public void setClipToOutline(boolean clipToOutline) { - nSetClipToOutline(mNativeDisplayList, clipToOutline); + nSetClipToOutline(mNativeRenderNode, clipToOutline); } /** @@ -382,7 +365,7 @@ public class RenderNode { */ public void setRevealClip(boolean shouldClip, boolean inverseClip, float x, float y, float radius) { - nSetRevealClip(mNativeDisplayList, shouldClip, inverseClip, x, y, radius); + nSetRevealClip(mNativeRenderNode, shouldClip, inverseClip, x, y, radius); } /** @@ -392,7 +375,7 @@ public class RenderNode { * @param matrix A transform matrix to apply to this display list */ public void setStaticMatrix(Matrix matrix) { - nSetStaticMatrix(mNativeDisplayList, matrix.native_instance); + nSetStaticMatrix(mNativeRenderNode, matrix.native_instance); } /** @@ -406,7 +389,7 @@ public class RenderNode { * @hide */ public void setAnimationMatrix(Matrix matrix) { - nSetAnimationMatrix(mNativeDisplayList, + nSetAnimationMatrix(mNativeRenderNode, (matrix != null) ? matrix.native_instance : 0); } @@ -419,7 +402,7 @@ public class RenderNode { * @see #getAlpha() */ public void setAlpha(float alpha) { - nSetAlpha(mNativeDisplayList, alpha); + nSetAlpha(mNativeRenderNode, alpha); } /** @@ -430,7 +413,7 @@ public class RenderNode { * @see #setAlpha(float) */ public float getAlpha() { - return nGetAlpha(mNativeDisplayList); + return nGetAlpha(mNativeRenderNode); } /** @@ -445,7 +428,7 @@ public class RenderNode { * @see #hasOverlappingRendering() */ public void setHasOverlappingRendering(boolean hasOverlappingRendering) { - nSetHasOverlappingRendering(mNativeDisplayList, hasOverlappingRendering); + nSetHasOverlappingRendering(mNativeRenderNode, hasOverlappingRendering); } /** @@ -457,7 +440,7 @@ public class RenderNode { */ public boolean hasOverlappingRendering() { //noinspection SimplifiableIfStatement - return nHasOverlappingRendering(mNativeDisplayList); + return nHasOverlappingRendering(mNativeRenderNode); } /** @@ -469,7 +452,7 @@ public class RenderNode { * @see #getTranslationX() */ public void setTranslationX(float translationX) { - nSetTranslationX(mNativeDisplayList, translationX); + nSetTranslationX(mNativeRenderNode, translationX); } /** @@ -478,7 +461,7 @@ public class RenderNode { * @see #setTranslationX(float) */ public float getTranslationX() { - return nGetTranslationX(mNativeDisplayList); + return nGetTranslationX(mNativeRenderNode); } /** @@ -490,7 +473,7 @@ public class RenderNode { * @see #getTranslationY() */ public void setTranslationY(float translationY) { - nSetTranslationY(mNativeDisplayList, translationY); + nSetTranslationY(mNativeRenderNode, translationY); } /** @@ -499,7 +482,7 @@ public class RenderNode { * @see #setTranslationY(float) */ public float getTranslationY() { - return nGetTranslationY(mNativeDisplayList); + return nGetTranslationY(mNativeRenderNode); } /** @@ -509,7 +492,7 @@ public class RenderNode { * @see #getTranslationZ() */ public void setTranslationZ(float translationZ) { - nSetTranslationZ(mNativeDisplayList, translationZ); + nSetTranslationZ(mNativeRenderNode, translationZ); } /** @@ -518,7 +501,7 @@ public class RenderNode { * @see #setTranslationZ(float) */ public float getTranslationZ() { - return nGetTranslationZ(mNativeDisplayList); + return nGetTranslationZ(mNativeRenderNode); } /** @@ -530,7 +513,7 @@ public class RenderNode { * @see #getRotation() */ public void setRotation(float rotation) { - nSetRotation(mNativeDisplayList, rotation); + nSetRotation(mNativeRenderNode, rotation); } /** @@ -539,7 +522,7 @@ public class RenderNode { * @see #setRotation(float) */ public float getRotation() { - return nGetRotation(mNativeDisplayList); + return nGetRotation(mNativeRenderNode); } /** @@ -551,7 +534,7 @@ public class RenderNode { * @see #getRotationX() */ public void setRotationX(float rotationX) { - nSetRotationX(mNativeDisplayList, rotationX); + nSetRotationX(mNativeRenderNode, rotationX); } /** @@ -560,7 +543,7 @@ public class RenderNode { * @see #setRotationX(float) */ public float getRotationX() { - return nGetRotationX(mNativeDisplayList); + return nGetRotationX(mNativeRenderNode); } /** @@ -572,7 +555,7 @@ public class RenderNode { * @see #getRotationY() */ public void setRotationY(float rotationY) { - nSetRotationY(mNativeDisplayList, rotationY); + nSetRotationY(mNativeRenderNode, rotationY); } /** @@ -581,7 +564,7 @@ public class RenderNode { * @see #setRotationY(float) */ public float getRotationY() { - return nGetRotationY(mNativeDisplayList); + return nGetRotationY(mNativeRenderNode); } /** @@ -593,7 +576,7 @@ public class RenderNode { * @see #getScaleX() */ public void setScaleX(float scaleX) { - nSetScaleX(mNativeDisplayList, scaleX); + nSetScaleX(mNativeRenderNode, scaleX); } /** @@ -602,7 +585,7 @@ public class RenderNode { * @see #setScaleX(float) */ public float getScaleX() { - return nGetScaleX(mNativeDisplayList); + return nGetScaleX(mNativeRenderNode); } /** @@ -614,7 +597,7 @@ public class RenderNode { * @see #getScaleY() */ public void setScaleY(float scaleY) { - nSetScaleY(mNativeDisplayList, scaleY); + nSetScaleY(mNativeRenderNode, scaleY); } /** @@ -623,7 +606,7 @@ public class RenderNode { * @see #setScaleY(float) */ public float getScaleY() { - return nGetScaleY(mNativeDisplayList); + return nGetScaleY(mNativeRenderNode); } /** @@ -635,7 +618,7 @@ public class RenderNode { * @see #getPivotX() */ public void setPivotX(float pivotX) { - nSetPivotX(mNativeDisplayList, pivotX); + nSetPivotX(mNativeRenderNode, pivotX); } /** @@ -644,7 +627,7 @@ public class RenderNode { * @see #setPivotX(float) */ public float getPivotX() { - return nGetPivotX(mNativeDisplayList); + return nGetPivotX(mNativeRenderNode); } /** @@ -656,7 +639,7 @@ public class RenderNode { * @see #getPivotY() */ public void setPivotY(float pivotY) { - nSetPivotY(mNativeDisplayList, pivotY); + nSetPivotY(mNativeRenderNode, pivotY); } /** @@ -665,11 +648,11 @@ public class RenderNode { * @see #setPivotY(float) */ public float getPivotY() { - return nGetPivotY(mNativeDisplayList); + return nGetPivotY(mNativeRenderNode); } public boolean isPivotExplicitlySet() { - return nIsPivotExplicitlySet(mNativeDisplayList); + return nIsPivotExplicitlySet(mNativeRenderNode); } /** @@ -683,7 +666,7 @@ public class RenderNode { * @see #getCameraDistance() */ public void setCameraDistance(float distance) { - nSetCameraDistance(mNativeDisplayList, distance); + nSetCameraDistance(mNativeRenderNode, distance); } /** @@ -692,7 +675,7 @@ public class RenderNode { * @see #setCameraDistance(float) */ public float getCameraDistance() { - return nGetCameraDistance(mNativeDisplayList); + return nGetCameraDistance(mNativeRenderNode); } /** @@ -704,7 +687,7 @@ public class RenderNode { * @see #getLeft() */ public void setLeft(int left) { - nSetLeft(mNativeDisplayList, left); + nSetLeft(mNativeRenderNode, left); } /** @@ -713,7 +696,7 @@ public class RenderNode { * @see #setLeft(int) */ public float getLeft() { - return nGetLeft(mNativeDisplayList); + return nGetLeft(mNativeRenderNode); } /** @@ -725,7 +708,7 @@ public class RenderNode { * @see #getTop() */ public void setTop(int top) { - nSetTop(mNativeDisplayList, top); + nSetTop(mNativeRenderNode, top); } /** @@ -734,7 +717,7 @@ public class RenderNode { * @see #setTop(int) */ public float getTop() { - return nGetTop(mNativeDisplayList); + return nGetTop(mNativeRenderNode); } /** @@ -746,7 +729,7 @@ public class RenderNode { * @see #getRight() */ public void setRight(int right) { - nSetRight(mNativeDisplayList, right); + nSetRight(mNativeRenderNode, right); } /** @@ -755,7 +738,7 @@ public class RenderNode { * @see #setRight(int) */ public float getRight() { - return nGetRight(mNativeDisplayList); + return nGetRight(mNativeRenderNode); } /** @@ -767,7 +750,7 @@ public class RenderNode { * @see #getBottom() */ public void setBottom(int bottom) { - nSetBottom(mNativeDisplayList, bottom); + nSetBottom(mNativeRenderNode, bottom); } /** @@ -776,7 +759,7 @@ public class RenderNode { * @see #setBottom(int) */ public float getBottom() { - return nGetBottom(mNativeDisplayList); + return nGetBottom(mNativeRenderNode); } /** @@ -793,7 +776,7 @@ public class RenderNode { * @see View#setBottom(int) */ public void setLeftTopRightBottom(int left, int top, int right, int bottom) { - nSetLeftTopRightBottom(mNativeDisplayList, left, top, right, bottom); + nSetLeftTopRightBottom(mNativeRenderNode, left, top, right, bottom); } /** @@ -805,7 +788,7 @@ public class RenderNode { * @see View#offsetLeftAndRight(int) */ public void offsetLeftAndRight(float offset) { - nOffsetLeftAndRight(mNativeDisplayList, offset); + nOffsetLeftAndRight(mNativeRenderNode, offset); } /** @@ -817,7 +800,7 @@ public class RenderNode { * @see View#offsetTopAndBottom(int) */ public void offsetTopAndBottom(float offset) { - nOffsetTopAndBottom(mNativeDisplayList, offset); + nOffsetTopAndBottom(mNativeRenderNode, offset); } /** @@ -827,80 +810,80 @@ public class RenderNode { * @hide */ public void output() { - nOutput(mNativeDisplayList); + nOutput(mNativeRenderNode); } /////////////////////////////////////////////////////////////////////////// // Native methods /////////////////////////////////////////////////////////////////////////// - private static native long nCreate(); - private static native void nDestroyDisplayList(long displayList); - private static native void nSetDisplayListName(long displayList, String name); + private static native long nCreate(String name); + private static native void nDestroyRenderNode(long renderNode); + private static native void nSetDisplayListData(long renderNode, long newData); // Matrix - private static native void nGetTransformMatrix(long displayList, long nativeMatrix); - private static native void nGetInverseTransformMatrix(long displayList, long nativeMatrix); - private static native boolean nHasIdentityMatrix(long displayList); + private static native void nGetTransformMatrix(long renderNode, long nativeMatrix); + private static native void nGetInverseTransformMatrix(long renderNode, long nativeMatrix); + private static native boolean nHasIdentityMatrix(long renderNode); // Properties - private static native void nOffsetTopAndBottom(long displayList, float offset); - private static native void nOffsetLeftAndRight(long displayList, float offset); - private static native void nSetLeftTopRightBottom(long displayList, int left, int top, + private static native void nOffsetTopAndBottom(long renderNode, float offset); + private static native void nOffsetLeftAndRight(long renderNode, float offset); + private static native void nSetLeftTopRightBottom(long renderNode, int left, int top, int right, int bottom); - private static native void nSetBottom(long displayList, int bottom); - private static native void nSetRight(long displayList, int right); - private static native void nSetTop(long displayList, int top); - private static native void nSetLeft(long displayList, int left); - private static native void nSetCameraDistance(long displayList, float distance); - private static native void nSetPivotY(long displayList, float pivotY); - private static native void nSetPivotX(long displayList, float pivotX); - private static native void nSetCaching(long displayList, boolean caching); - private static native void nSetClipToBounds(long displayList, boolean clipToBounds); - private static native void nSetProjectBackwards(long displayList, boolean shouldProject); - private static native void nSetProjectionReceiver(long displayList, boolean shouldRecieve); - private static native void nSetOutlineRoundRect(long displayList, int left, int top, + private static native void nSetBottom(long renderNode, int bottom); + private static native void nSetRight(long renderNode, int right); + private static native void nSetTop(long renderNode, int top); + private static native void nSetLeft(long renderNode, int left); + private static native void nSetCameraDistance(long renderNode, float distance); + private static native void nSetPivotY(long renderNode, float pivotY); + private static native void nSetPivotX(long renderNode, float pivotX); + private static native void nSetCaching(long renderNode, boolean caching); + private static native void nSetClipToBounds(long renderNode, boolean clipToBounds); + private static native void nSetProjectBackwards(long renderNode, boolean shouldProject); + private static native void nSetProjectionReceiver(long renderNode, boolean shouldRecieve); + private static native void nSetOutlineRoundRect(long renderNode, int left, int top, int right, int bottom, float radius); - private static native void nSetOutlineConvexPath(long displayList, long nativePath); - private static native void nSetOutlineEmpty(long displayList); - private static native void nSetClipToOutline(long displayList, boolean clipToOutline); - private static native void nSetRevealClip(long displayList, + private static native void nSetOutlineConvexPath(long renderNode, long nativePath); + private static native void nSetOutlineEmpty(long renderNode); + private static native void nSetClipToOutline(long renderNode, boolean clipToOutline); + private static native void nSetRevealClip(long renderNode, boolean shouldClip, boolean inverseClip, float x, float y, float radius); - private static native void nSetAlpha(long displayList, float alpha); - private static native void nSetHasOverlappingRendering(long displayList, + private static native void nSetAlpha(long renderNode, float alpha); + private static native void nSetHasOverlappingRendering(long renderNode, boolean hasOverlappingRendering); - private static native void nSetTranslationX(long displayList, float translationX); - private static native void nSetTranslationY(long displayList, float translationY); - private static native void nSetTranslationZ(long displayList, float translationZ); - private static native void nSetRotation(long displayList, float rotation); - private static native void nSetRotationX(long displayList, float rotationX); - private static native void nSetRotationY(long displayList, float rotationY); - private static native void nSetScaleX(long displayList, float scaleX); - private static native void nSetScaleY(long displayList, float scaleY); - private static native void nSetStaticMatrix(long displayList, long nativeMatrix); - private static native void nSetAnimationMatrix(long displayList, long animationMatrix); - - private static native boolean nHasOverlappingRendering(long displayList); - private static native float nGetAlpha(long displayList); - private static native float nGetLeft(long displayList); - private static native float nGetTop(long displayList); - private static native float nGetRight(long displayList); - private static native float nGetBottom(long displayList); - private static native float nGetCameraDistance(long displayList); - private static native float nGetScaleX(long displayList); - private static native float nGetScaleY(long displayList); - private static native float nGetTranslationX(long displayList); - private static native float nGetTranslationY(long displayList); - private static native float nGetTranslationZ(long displayList); - private static native float nGetRotation(long displayList); - private static native float nGetRotationX(long displayList); - private static native float nGetRotationY(long displayList); - private static native boolean nIsPivotExplicitlySet(long displayList); - private static native float nGetPivotX(long displayList); - private static native float nGetPivotY(long displayList); - private static native void nOutput(long displayList); + private static native void nSetTranslationX(long renderNode, float translationX); + private static native void nSetTranslationY(long renderNode, float translationY); + private static native void nSetTranslationZ(long renderNode, float translationZ); + private static native void nSetRotation(long renderNode, float rotation); + private static native void nSetRotationX(long renderNode, float rotationX); + private static native void nSetRotationY(long renderNode, float rotationY); + private static native void nSetScaleX(long renderNode, float scaleX); + private static native void nSetScaleY(long renderNode, float scaleY); + private static native void nSetStaticMatrix(long renderNode, long nativeMatrix); + private static native void nSetAnimationMatrix(long renderNode, long animationMatrix); + + private static native boolean nHasOverlappingRendering(long renderNode); + private static native float nGetAlpha(long renderNode); + private static native float nGetLeft(long renderNode); + private static native float nGetTop(long renderNode); + private static native float nGetRight(long renderNode); + private static native float nGetBottom(long renderNode); + private static native float nGetCameraDistance(long renderNode); + private static native float nGetScaleX(long renderNode); + private static native float nGetScaleY(long renderNode); + private static native float nGetTranslationX(long renderNode); + private static native float nGetTranslationY(long renderNode); + private static native float nGetTranslationZ(long renderNode); + private static native float nGetRotation(long renderNode); + private static native float nGetRotationX(long renderNode); + private static native float nGetRotationY(long renderNode); + private static native boolean nIsPivotExplicitlySet(long renderNode); + private static native float nGetPivotX(long renderNode); + private static native float nGetPivotY(long renderNode); + private static native void nOutput(long renderNode); /////////////////////////////////////////////////////////////////////////// // Finalization @@ -909,7 +892,7 @@ public class RenderNode { @Override protected void finalize() throws Throwable { try { - nDestroyDisplayList(mNativeDisplayList); + nDestroyRenderNode(mNativeRenderNode); } finally { super.finalize(); } diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 5a8d2c8..2d55a01 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -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. diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index 2e0f509..789b761 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -166,11 +166,6 @@ public class ThreadedRenderer extends HardwareRenderer { } @Override - void setDisplayListData(long displayList, long newData) { - nSetDisplayListData(mNativeProxy, displayList, newData); - } - - @Override void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks, Rect dirty) { attachInfo.mIgnoreDirtyState = true; attachInfo.mDrawingTime = SystemClock.uptimeMillis(); @@ -195,12 +190,12 @@ public class ThreadedRenderer extends HardwareRenderer { @Override void detachFunctor(long functor) { - nDetachFunctor(mNativeProxy, functor); + // no-op, we never attach functors to need to detach them } @Override void attachFunctor(AttachInfo attachInfo, long functor) { - nAttachFunctor(mNativeProxy, functor); + invokeFunctor(functor, true); } @Override @@ -294,8 +289,6 @@ public class ThreadedRenderer extends HardwareRenderer { private static native void nRunWithGlContext(long nativeProxy, Runnable runnable); private static native void nDestroyCanvas(long nativeProxy); - private static native void nAttachFunctor(long nativeProxy, long functor); - private static native void nDetachFunctor(long nativeProxy, long functor); private static native void nInvokeFunctor(long nativeProxy, long functor, boolean waitForCompletion); private static native long nCreateDisplayListLayer(long nativeProxy, int width, int height); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 6c414f6..320140e 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -8790,11 +8790,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, && !pointInView(event.getX(), event.getY()))) { mSendingHoverAccessibilityEvents = false; sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT); - // If the window does not have input focus we take away accessibility - // focus as soon as the user stop hovering over the view. - if (mAttachInfo != null && !mAttachInfo.mHasWindowFocus) { - getViewRootImpl().setAccessibilityFocus(null, null); - } } } @@ -13549,11 +13544,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @return A new or reused DisplayList object. */ private void updateDisplayListIfDirty(@NonNull RenderNode renderNode, boolean isLayer) { - final HardwareRenderer renderer = getHardwareRenderer(); if (renderNode == null) { throw new IllegalArgumentException("RenderNode must not be null"); } - if (renderer == null || !canHaveDisplayList()) { + if (!canHaveDisplayList()) { // can't populate RenderNode, don't try return; } @@ -13627,21 +13621,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } } finally { - renderNode.end(renderer, canvas); + renderNode.end(canvas); renderNode.setCaching(caching); if (isLayer) { renderNode.setLeftTopRightBottom(0, 0, width, height); } else { setDisplayListProperties(renderNode); } - - if (renderer != getHardwareRenderer()) { - Log.w(VIEW_LOG_TAG, "View was detached during a draw() call!"); - // TODO: Should this be elevated to a crash? - // For now have it behaves the same as it previously did, it - // will result in the DisplayListData being destroyed later - // than it could be but oh well... - } } } else if (!isLayer) { mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID; @@ -14913,7 +14899,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, final int height = bounds.height(); final HardwareCanvas canvas = displayList.start(width, height); drawable.draw(canvas); - displayList.end(getHardwareRenderer(), canvas); + displayList.end(canvas); // Set up drawable properties that are view-independent. displayList.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 2d503bf..65ac50d 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1505,7 +1505,7 @@ public final class ViewRootImpl implements ViewParent, com.android.internal.R.integer.config_mediumAnimTime); layerCanvas.restoreToCount(restoreCount); - layerRenderNode.end(mAttachInfo.mHardwareRenderer, layerCanvas); + layerRenderNode.end(layerCanvas); layerRenderNode.setCaching(true); layerRenderNode.setLeftTopRightBottom(0, 0, mWidth, mHeight); mTempRect.set(0, 0, mWidth, mHeight); diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java index b05225b..8eae629 100644 --- a/core/java/android/view/VolumePanel.java +++ b/core/java/android/view/VolumePanel.java @@ -27,6 +27,8 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; import android.media.AudioManager; import android.media.AudioService; import android.media.AudioSystem; @@ -238,6 +240,7 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie cleanUp(); } + @Override public void onDismiss(DialogInterface unused) { mContext.unregisterReceiver(this); cleanUp(); @@ -259,8 +262,8 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie mAudioService = volumeService; // For now, only show master volume if master volume is supported - boolean useMasterVolume = context.getResources().getBoolean( - com.android.internal.R.bool.config_useMasterVolume); + final boolean useMasterVolume = context.getResources().getBoolean( + R.bool.config_useMasterVolume); if (useMasterVolume) { for (int i = 0; i < STREAMS.length; i++) { StreamResources streamRes = STREAMS[i]; @@ -268,10 +271,18 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie } } - LayoutInflater inflater = (LayoutInflater) context - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - View view = mView = inflater.inflate(R.layout.volume_adjust, null); + final TypedArray a = context.obtainStyledAttributes(null, + com.android.internal.R.styleable.AlertDialog, + com.android.internal.R.attr.alertDialogStyle, 0); + final Drawable background = a.getDrawable(R.styleable.AlertDialog_fullBright); + a.recycle(); + + final LayoutInflater inflater = (LayoutInflater) context.getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + mView = inflater.inflate(R.layout.volume_adjust, null); + mView.setBackground(background); mView.setOnTouchListener(new View.OnTouchListener() { + @Override public boolean onTouch(View v, MotionEvent event) { resetTimeout(); return false; @@ -279,10 +290,11 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie }); mPanel = (ViewGroup) mView.findViewById(R.id.visible_panel); mSliderGroup = (ViewGroup) mView.findViewById(R.id.slider_group); - mMoreButton = (ImageView) mView.findViewById(R.id.expand_button); - mDivider = (ImageView) mView.findViewById(R.id.expand_button_divider); + mMoreButton = mView.findViewById(R.id.expand_button); + mDivider = mView.findViewById(R.id.expand_button_divider); mDialog = new Dialog(context, R.style.Theme_Panel_Volume) { + @Override public boolean onTouchEvent(MotionEvent event) { if (isShowing() && event.getAction() == MotionEvent.ACTION_OUTSIDE && sConfirmSafeVolumeDialog == null) { @@ -292,22 +304,25 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie return false; } }; + mDialog.setTitle("Volume control"); // No need to localize mDialog.setContentView(mView); mDialog.setOnDismissListener(new OnDismissListener() { + @Override public void onDismiss(DialogInterface dialog) { mActiveStreamType = -1; mAudioManager.forceVolumeControlStream(mActiveStreamType); } }); + // Change some window properties - Window window = mDialog.getWindow(); + final Window window = mDialog.getWindow(); window.setGravity(Gravity.TOP); - LayoutParams lp = window.getAttributes(); + + final LayoutParams lp = window.getAttributes(); lp.token = null; // Offset from the top - lp.y = mContext.getResources().getDimensionPixelOffset( - com.android.internal.R.dimen.volume_panel_top); + lp.y = mContext.getResources().getDimensionPixelOffset(R.dimen.volume_panel_top); lp.type = LayoutParams.TYPE_VOLUME_OVERLAY; lp.width = LayoutParams.WRAP_CONTENT; lp.height = LayoutParams.WRAP_CONTENT; @@ -320,6 +335,7 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie mVoiceCapable = context.getResources().getBoolean(R.bool.config_voice_capable); mShowCombinedVolumes = !mVoiceCapable && !useMasterVolume; + // If we don't want to show multiple volumes, hide the settings button and divider if (!mShowCombinedVolumes) { mMoreButton.setVisibility(View.GONE); @@ -328,10 +344,10 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie mMoreButton.setOnClickListener(this); } - boolean masterVolumeOnly = context.getResources().getBoolean( - com.android.internal.R.bool.config_useMasterVolume); - boolean masterVolumeKeySounds = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_useVolumeKeySounds); + final boolean masterVolumeOnly = context.getResources().getBoolean( + R.bool.config_useMasterVolume); + final boolean masterVolumeKeySounds = mContext.getResources().getBoolean( + R.bool.config_useVolumeKeySounds); mPlayMasterStreamTones = masterVolumeOnly && masterVolumeKeySounds; @@ -347,7 +363,7 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie final IntentFilter filter = new IntentFilter(); filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); mContext.registerReceiver(new BroadcastReceiver() { - + @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); @@ -400,17 +416,21 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie } private void createSliders() { - LayoutInflater inflater = (LayoutInflater) mContext - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + final Resources res = mContext.getResources(); + final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + mStreamControls = new HashMap<Integer, StreamControl>(STREAMS.length); - Resources res = mContext.getResources(); + for (int i = 0; i < STREAMS.length; i++) { StreamResources streamRes = STREAMS[i]; - int streamType = streamRes.streamType; + + final int streamType = streamRes.streamType; if (mVoiceCapable && streamRes == StreamResources.NotificationStream) { streamRes = StreamResources.RingerStream; } - StreamControl sc = new StreamControl(); + + final StreamControl sc = new StreamControl(); sc.streamType = streamType; sc.group = (ViewGroup) inflater.inflate(R.layout.volume_adjust_item, null); sc.group.setTag(sc); @@ -421,7 +441,7 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie sc.iconMuteRes = streamRes.iconMuteRes; sc.icon.setImageResource(sc.iconRes); sc.seekbarView = (SeekBar) sc.group.findViewById(R.id.seekbar); - int plusOne = (streamType == AudioSystem.STREAM_BLUETOOTH_SCO || + final int plusOne = (streamType == AudioSystem.STREAM_BLUETOOTH_SCO || streamType == AudioSystem.STREAM_VOICE_CALL) ? 1 : 0; sc.seekbarView.setMax(getStreamMaxVolume(streamType) + plusOne); sc.seekbarView.setOnSeekBarChangeListener(this); @@ -433,7 +453,7 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie private void reorderSliders(int activeStreamType) { mSliderGroup.removeAllViews(); - StreamControl active = mStreamControls.get(activeStreamType); + final StreamControl active = mStreamControls.get(activeStreamType); if (active == null) { Log.e("VolumePanel", "Missing stream type! - " + activeStreamType); mActiveStreamType = -1; diff --git a/core/java/android/view/WindowAnimationFrameStats.aidl b/core/java/android/view/WindowAnimationFrameStats.aidl new file mode 100644 index 0000000..77f544b --- /dev/null +++ b/core/java/android/view/WindowAnimationFrameStats.aidl @@ -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; diff --git a/core/java/android/view/WindowAnimationFrameStats.java b/core/java/android/view/WindowAnimationFrameStats.java new file mode 100644 index 0000000..c60b96c --- /dev/null +++ b/core/java/android/view/WindowAnimationFrameStats.java @@ -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]; + } + }; +} diff --git a/core/java/android/view/WindowContentFrameStats.aidl b/core/java/android/view/WindowContentFrameStats.aidl new file mode 100644 index 0000000..aa9c2d6 --- /dev/null +++ b/core/java/android/view/WindowContentFrameStats.aidl @@ -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; diff --git a/core/java/android/view/WindowContentFrameStats.java b/core/java/android/view/WindowContentFrameStats.java new file mode 100644 index 0000000..c6da2fb --- /dev/null +++ b/core/java/android/view/WindowContentFrameStats.java @@ -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]; + } + }; +} diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 53a4c0d0..d5a7d33 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -610,7 +610,10 @@ public interface WindowManager extends ViewManager { * screen is pressed, you will receive this first touch event. Usually * the first touch event is consumed by the system since the user can * not see what they are pressing on. + * + * @deprecated This flag has no effect. */ + @Deprecated public static final int FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040; /** Window flag: as long as this window is visible to the user, keep diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index bd203c8..e68d4c0 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -90,8 +90,7 @@ public interface WindowManagerPolicy { public final static int FLAG_FILTERED = 0x04000000; public final static int FLAG_DISABLE_KEY_REPEAT = 0x08000000; - public final static int FLAG_WOKE_HERE = 0x10000000; - public final static int FLAG_BRIGHT_HERE = 0x20000000; + public final static int FLAG_INTERACTIVE = 0x20000000; public final static int FLAG_PASS_TO_USER = 0x40000000; // Flags used for indicating whether the internal and/or external input devices @@ -744,11 +743,10 @@ public interface WindowManagerPolicy { * because it's the most fragile. * @param event The key event. * @param policyFlags The policy flags associated with the key. - * @param isScreenOn True if the screen is already on * * @return Actions flags: may be {@link #ACTION_PASS_TO_USER}. */ - public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn); + public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags); /** * Called from the input reader thread before a motion is enqueued when the screen is off. @@ -761,7 +759,7 @@ public interface WindowManagerPolicy { * * @return Actions flags: may be {@link #ACTION_PASS_TO_USER}. */ - public int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags); + public int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags); /** * Called from the input dispatcher thread before a key is dispatched to a window. diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java index 4dd8dcb..5b9372d 100644 --- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java +++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java @@ -163,6 +163,19 @@ public final class AccessibilityInteractionClient } /** + * Gets the root {@link AccessibilityNodeInfo} in a given window. + * + * @param connectionId The id of a connection for interacting with the system. + * @param windowId The window id. + * @return The root {@link AccessibilityNodeInfo} if found, null otherwise. + */ + public AccessibilityNodeInfo getRootInWindow(int connectionId, int windowId) { + return findAccessibilityNodeInfoByAccessibilityId(connectionId, windowId, + AccessibilityNodeInfo.ROOT_NODE_ID, false, + AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS); + } + + /** * Gets the info for a window. * * @param connectionId The id of a connection for interacting with the system. diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index a6904f7..9d10930 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -77,6 +77,9 @@ public class AccessibilityNodeInfo implements Parcelable { public static final int ACTIVE_WINDOW_ID = UNDEFINED_ITEM_ID; /** @hide */ + public static final int ANY_WINDOW_ID = -2; + + /** @hide */ public static final int FLAG_PREFETCH_PREDECESSORS = 0x00000001; /** @hide */ diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl index fe3e5c6..b6570cc 100644 --- a/core/java/android/view/accessibility/IAccessibilityManager.aidl +++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl @@ -57,4 +57,6 @@ interface IAccessibilityManager { void temporaryEnableAccessibilityStateUntilKeyguardRemoved(in ComponentName service, boolean touchExplorationEnabled); + + IBinder getWindowToken(int windowId); } diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 81d36a4..85168fd 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -1691,6 +1691,9 @@ public class WebView extends AbsoluteLayout * thread of this WebView. Care is therefore required to maintain thread * safety.</li> * <li> The Java object's fields are not accessible.</li> + * <li> For applications targeted to API level {@link android.os.Build.VERSION_CODES#L} + * and above, methods of injected Java objects are enumerable from + * JavaScript.</li> * </ul> * * @param object the Java object to inject into this WebView's JavaScript diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 14e7951..b0a4e24 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -1338,7 +1338,6 @@ public class Editor { layout.drawBackground(canvas, highlight, highlightPaint, cursorOffsetVertical, firstLine, lastLine); - final HardwareRenderer renderer = mTextView.getHardwareRenderer(); if (layout instanceof DynamicLayout) { if (mTextDisplayLists == null) { @@ -1402,7 +1401,7 @@ public class Editor { // No need to untranslate, previous context is popped after // drawDisplayList } finally { - blockDisplayList.end(renderer, hardwareCanvas); + blockDisplayList.end(hardwareCanvas); // Same as drawDisplayList below, handled by our TextView's parent blockDisplayList.setClipToBounds(false); } diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java index 00b2c13..d6fa05a 100644 --- a/core/java/android/widget/NumberPicker.java +++ b/core/java/android/widget/NumberPicker.java @@ -1991,7 +1991,16 @@ public class NumberPicker extends LinearLayout { , '\u0669', // Extended Arabic-Indic '\u06f0', '\u06f1', '\u06f2', '\u06f3', '\u06f4', '\u06f5', '\u06f6', '\u06f7', '\u06f8' - , '\u06f9' + , '\u06f9', + // Hindi and Marathi (Devanagari script) + '\u0966', '\u0967', '\u0968', '\u0969', '\u096a', '\u096b', '\u096c', '\u096d', '\u096e' + , '\u096f', + // Bengali + '\u09e6', '\u09e7', '\u09e8', '\u09e9', '\u09ea', '\u09eb', '\u09ec', '\u09ed', '\u09ee' + , '\u09ef', + // Kannada + '\u0ce6', '\u0ce7', '\u0ce8', '\u0ce9', '\u0cea', '\u0ceb', '\u0cec', '\u0ced', '\u0cee' + , '\u0cef' }; /** |
