diff options
Diffstat (limited to 'core/java/android')
30 files changed, 476 insertions, 266 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 1b4ee2e..e8ab109 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -2075,6 +2075,9 @@ public class Activity extends ContextThemeWrapper "by the window decor. Do not request Window.FEATURE_ACTION_BAR and set " + "android:windowActionBar to false in your theme to use a Toolbar instead."); } + // Clear out the MenuInflater to make sure that it is valid for the new Action Bar + mMenuInflater = null; + ToolbarActionBar tbab = new ToolbarActionBar(toolbar, getTitle(), this); mActionBar = tbab; mWindow.setCallback(tbab.getWrappedWindowCallback()); diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java index 87e2f9a..a1bb40c 100644 --- a/core/java/android/app/admin/DeviceAdminReceiver.java +++ b/core/java/android/app/admin/DeviceAdminReceiver.java @@ -19,6 +19,7 @@ package android.app.admin; import android.accounts.AccountManager; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.SystemApi; import android.app.Service; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -227,14 +228,15 @@ public class DeviceAdminReceiver extends BroadcastReceiver { "android.app.action.PROFILE_PROVISIONING_COMPLETE"; /** + * @hide * Broadcast Action: This broadcast is sent to indicate that the system is ready for the device * initializer to perform user setup tasks. This is only applicable to devices managed by a * device owner app. * * <p>The broadcast will be limited to the {@link DeviceAdminReceiver} component specified in - * the {@link DevicePolicyManager#EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME} field - * of the original intent or NFC bump that started the provisioning process. You will generally - * handle this in {@link DeviceAdminReceiver#onReadyForUserInitialization}. + * the device initializer field of the original intent or NFC bump that started the provisioning + * process. You will generally handle this in + * {@link DeviceAdminReceiver#onReadyForUserInitialization}. * * <p>Input: Nothing.</p> * <p>Output: Nothing</p> @@ -435,23 +437,22 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * Called during provisioning of a managed device to allow the device initializer to perform * user setup steps. Only device initializers should override this method. * - * <p> Called when the DeviceAdminReceiver receives a - * {@link #ACTION_READY_FOR_USER_INITIALIZATION} broadcast. As a prerequisite for the execution - * of this callback the {@link DeviceAdminReceiver} has - * to declare an intent filter for {@link #ACTION_READY_FOR_USER_INITIALIZATION}. Only the - * component specified in the - * {@link DevicePolicyManager#EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME} field of the + * <p> Called when the DeviceAdminReceiver receives an + * android.app.action.ACTION_READY_FOR_USER_INITIALIZATION broadcast. As a prerequisite for the + * execution of this callback the {@link DeviceAdminReceiver} has + * to declare an intent filter for android.app.action.ACTION_READY_FOR_USER_INITIALIZATION. Only + * the component specified in the device initializer component name field of the * original intent or NFC bump that started the provisioning process will receive this callback. * * <p>It is not assumed that the device initializer is finished when it returns from - * this call, as it may do additional setup asynchronously. The device initializer must call - * {@link DevicePolicyManager#setUserEnabled(ComponentName admin)} when it has finished any - * additional setup (such as adding an account by using the {@link AccountManager}) in order for - * the user to be functional. + * this call, as it may do additional setup asynchronously. The device initializer must enable + * the current user when it has finished any additional setup (such as adding an account by + * using the {@link AccountManager}) in order for the user to be functional. * * @param context The running context as per {@link #onReceive}. * @param intent The received intent as per {@link #onReceive}. */ + @SystemApi public void onReadyForUserInitialization(Context context, Intent intent) { } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index b9862ca..125708a 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -468,6 +468,7 @@ public class DevicePolicyManager { "android.app.extra.PROVISIONING_SKIP_ENCRYPTION"; /** + * @hide * On devices managed by a device owner app, a {@link ComponentName} extra indicating the * component of the application that is temporarily granted device owner privileges during * device initialization and profile owner privileges during secondary user initialization. @@ -483,6 +484,7 @@ public class DevicePolicyManager { = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME"; /** + * @hide * A String extra holding an http url that specifies the download location of the device * initializer package. When not provided it is assumed that the device initializer package is * already installed. @@ -494,6 +496,7 @@ public class DevicePolicyManager { = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION"; /** + * @hide * An int extra holding a minimum required version code for the device initializer package. * If the initializer is already installed on the device, it will only be re-downloaded from * {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION} if the version of @@ -506,6 +509,7 @@ public class DevicePolicyManager { = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_MINIMUM_VERSION_CODE"; /** + * @hide * A String extra holding a http cookie header which should be used in the http request to the * url specified in {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}. * @@ -516,6 +520,7 @@ public class DevicePolicyManager { = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER"; /** + * @hide * A String extra holding the URL-safe base64 encoded SHA-256 checksum of the file at download * location specified in * {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}. @@ -532,6 +537,7 @@ public class DevicePolicyManager { = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM"; /** + * @hide * A String extra holding the URL-safe base64 encoded SHA-256 checksum of any signature of the * android package archive at the download location specified in {@link * #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}. @@ -611,11 +617,6 @@ public class DevicePolicyManager { * {@link #MIME_TYPE_PROVISIONING_NFC}: * <ul> * <li>{@link #EXTRA_PROVISIONING_SKIP_ENCRYPTION}, optional</li> - * <li>{@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME}, optional</li> - * <li>{@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}, optional</li> - * <li>{@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER}, optional</li> - * <li>{@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM}, optional</li> - * <li>{@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_MINIMUM_VERSION_CODE}, optional</li> * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME}. * Replaces {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}. The value of the property * should be converted to a String via @@ -2756,6 +2757,7 @@ public class DevicePolicyManager { } /** + * @hide * Sets the given component as the device initializer. The package must already be installed and * set as an active device administrator, and there must not be an existing device initializer, * for this call to succeed. This method can only be called by an app holding the @@ -2784,6 +2786,7 @@ public class DevicePolicyManager { } /** + * @hide * Used to determine if a particular package has been registered as the device initializer. * * @param packageName the package name of the app, to compare with the registered device @@ -2802,6 +2805,7 @@ public class DevicePolicyManager { } /** + * @hide * Removes the device initializer, so that it will not be invoked on user initialization for any * subsequently created users. This method can be called by either the device owner or device * initializer itself. The caller must be an active administrator. @@ -2856,6 +2860,7 @@ public class DevicePolicyManager { /** + * @hide * Sets the enabled state of the user. A user should be enabled only once it is ready to * be used. * diff --git a/core/java/android/content/AbstractThreadedSyncAdapter.java b/core/java/android/content/AbstractThreadedSyncAdapter.java index 809f900..d4dee5b 100644 --- a/core/java/android/content/AbstractThreadedSyncAdapter.java +++ b/core/java/android/content/AbstractThreadedSyncAdapter.java @@ -28,13 +28,26 @@ import java.util.concurrent.atomic.AtomicInteger; /** * An abstract implementation of a SyncAdapter that spawns a thread to invoke a sync operation. - * If a sync operation is already in progress when a startSync() request is received then an error - * will be returned to the new request and the existing request will be allowed to continue. - * When a startSync() is received and there is no sync operation in progress then a thread - * will be started to run the operation and {@link #onPerformSync} will be invoked on that thread. - * If a cancelSync() is received that matches an existing sync operation then the thread - * that is running that sync operation will be interrupted, which will indicate to the thread - * that the sync has been canceled. + * If a sync operation is already in progress when a sync request is received, an error will be + * returned to the new request and the existing request will be allowed to continue. + * However if there is no sync in progress then a thread will be spawned and {@link #onPerformSync} + * will be invoked on that thread. + * <p> + * Syncs can be cancelled at any time by the framework. For example a sync that was not + * user-initiated and lasts longer than 30 minutes will be considered timed-out and cancelled. + * Similarly the framework will attempt to determine whether or not an adapter is making progress + * by monitoring its network activity over the course of a minute. If the network traffic over this + * window is close enough to zero the sync will be cancelled. You can also request the sync be + * cancelled via {@link ContentResolver#cancelSync(Account, String)} or + * {@link ContentResolver#cancelSync(SyncRequest)}. + * <p> + * A sync is cancelled by issuing a {@link Thread#interrupt()} on the syncing thread. <strong>Either + * your code in {@link #onPerformSync(Account, Bundle, String, ContentProviderClient, SyncResult)} + * must check {@link Thread#interrupted()}, or you you must override one of + * {@link #onSyncCanceled(Thread)}/{@link #onSyncCanceled()}</strong> (depending on whether or not + * your adapter supports syncing of multiple accounts in parallel). If your adapter does not + * respect the cancel issued by the framework you run the risk of your app's entire process being + * killed. * <p> * In order to be a sync adapter one must extend this class, provide implementations for the * abstract methods and write a service that returns the result of {@link #getSyncAdapterBinder()} diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 0c07bc3..2dbcde9 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -282,6 +282,10 @@ interface IPackageManager { */ byte[] getPreferredActivityBackup(int userId); void restorePreferredActivities(in byte[] backup, int userId); + byte[] getDefaultAppsBackup(int userId); + void restoreDefaultApps(in byte[] backup, int userId); + byte[] getIntentFilterVerificationBackup(int userId); + void restoreIntentFilterVerification(in byte[] backup, int userId); /** * Report the set of 'Home' activity candidates, plus (if any) which of them diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java index 5c21c8e..e9ec771 100644 --- a/core/java/android/content/pm/LauncherApps.java +++ b/core/java/android/content/pm/LauncherApps.java @@ -294,7 +294,7 @@ public class LauncherApps { */ public void registerCallback(Callback callback, Handler handler) { synchronized (this) { - if (callback != null && !mCallbacks.contains(callback)) { + if (callback != null && findCallbackLocked(callback) < 0) { boolean addedFirstCallback = mCallbacks.size() == 0; addCallbackLocked(callback, handler); if (addedFirstCallback) { @@ -325,17 +325,25 @@ public class LauncherApps { } } - private void removeCallbackLocked(Callback callback) { + /** @return position in mCallbacks for callback or -1 if not present. */ + private int findCallbackLocked(Callback callback) { if (callback == null) { throw new IllegalArgumentException("Callback cannot be null"); } final int size = mCallbacks.size(); for (int i = 0; i < size; ++i) { if (mCallbacks.get(i).mCallback == callback) { - mCallbacks.remove(i); - return; + return i; } } + return -1; + } + + private void removeCallbackLocked(Callback callback) { + int pos = findCallbackLocked(callback); + if (pos >= 0) { + mCallbacks.remove(pos); + } } private void addCallbackLocked(Callback callback, Handler handler) { diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index 27d14b3..261ce72 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -2679,9 +2679,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * <p>Camera devices will come in three flavors: LEGACY, LIMITED and FULL.</p> * <p>A FULL device will support below capabilities:</p> * <ul> - * <li>30fps operation at maximum resolution (== sensor resolution) is preferred, more than - * 20fps is required, for at least uncompressed YUV - * output. ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains BURST_CAPTURE)</li> + * <li>BURST_CAPTURE capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains BURST_CAPTURE)</li> * <li>Per frame control ({@link CameraCharacteristics#SYNC_MAX_LATENCY android.sync.maxLatency} <code>==</code> PER_FRAME_CONTROL)</li> * <li>Manual sensor control ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains MANUAL_SENSOR)</li> * <li>Manual post-processing control ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains @@ -2689,7 +2687,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * <li>Arbitrary cropping region ({@link CameraCharacteristics#SCALER_CROPPING_TYPE android.scaler.croppingType} <code>==</code> FREEFORM)</li> * <li>At least 3 processed (but not stalling) format output streams * ({@link CameraCharacteristics#REQUEST_MAX_NUM_OUTPUT_PROC android.request.maxNumOutputProc} <code>>=</code> 3)</li> - * <li>The required stream configuration defined in android.scaler.availableStreamConfigurations</li> + * <li>The required stream configurations defined in android.scaler.availableStreamConfigurations</li> * <li>The required exposure time range defined in {@link CameraCharacteristics#SENSOR_INFO_EXPOSURE_TIME_RANGE android.sensor.info.exposureTimeRange}</li> * <li>The required maxFrameDuration defined in {@link CameraCharacteristics#SENSOR_INFO_MAX_FRAME_DURATION android.sensor.info.maxFrameDuration}</li> * </ul> @@ -2709,23 +2707,11 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * post-processing, arbitrary cropping regions, and has relaxed performance constraints.</p> * <p>Each higher level supports everything the lower level supports * in this order: FULL <code>></code> LIMITED <code>></code> LEGACY.</p> - * <p>A HIGH_RESOLUTION device is equivalent to a FULL device, except that:</p> - * <ul> - * <li>At least one output resolution of 8 megapixels or higher in uncompressed YUV is - * supported at <code>>=</code> 20 fps.</li> - * <li>Maximum-size (sensor resolution) uncompressed YUV is supported at <code>>=</code> 10 - * fps.</li> - * <li>For devices that list the RAW capability and support either RAW10 or RAW12 output, - * maximum-resolution RAW10 or RAW12 capture will operate at least at the rate of - * maximum-resolution YUV capture, and at least one supported output resolution of - * 8 megapixels or higher in RAW10 or RAW12 is supported <code>>=</code> 20 fps.</li> - * </ul> * <p><b>Possible values:</b> * <ul> * <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED}</li> * <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}</li> * <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY}</li> - * <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_HIGH_RESOLUTION HIGH_RESOLUTION}</li> * </ul></p> * <p>This key is available on all devices.</p> * @@ -2743,7 +2729,6 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * @see #INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED * @see #INFO_SUPPORTED_HARDWARE_LEVEL_FULL * @see #INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY - * @see #INFO_SUPPORTED_HARDWARE_LEVEL_HIGH_RESOLUTION */ @PublicKey public static final Key<Integer> INFO_SUPPORTED_HARDWARE_LEVEL = diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java index c656fb8..5a80585 100644 --- a/core/java/android/hardware/camera2/CameraMetadata.java +++ b/core/java/android/hardware/camera2/CameraMetadata.java @@ -531,37 +531,32 @@ public abstract class CameraMetadata<TKey> { public static final int REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS = 5; /** - * <p>The camera device supports capturing maximum-resolution - * images at >= 20 frames per second, in at least the - * uncompressed YUV format, when post-processing settings - * are set to FAST.</p> - * <p>More specifically, this means that a size matching the - * camera device's active array size is listed as a - * supported size for the YUV_420_888 format in - * {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap}, the minimum frame - * duration for that format and size is <= 1/20 s, and - * the {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES android.control.aeAvailableTargetFpsRanges} entry - * lists at least one FPS range where the minimum FPS is</p> - * <blockquote> - * <p>= 1 / minimumFrameDuration for the maximum-size - * YUV_420_888 format.</p> - * </blockquote> - * <p>In addition, the {@link CameraCharacteristics#SYNC_MAX_LATENCY android.sync.maxLatency} field is - * guaranted to have a value between 0 and 4, inclusive. - * {@link CameraCharacteristics#CONTROL_AE_LOCK_AVAILABLE android.control.aeLockAvailable} and - * {@link CameraCharacteristics#CONTROL_AWB_LOCK_AVAILABLE android.control.awbLockAvailable} are also guaranteed - * to be <code>true</code> so burst capture with these two locks ON - * yields consistent image output.</p> - * <p>On a camera device that reports the HIGH_RESOLUTION hardware - * level, meaning the device supports very large capture sizes, - * BURST_CAPTURE means that at least 8-megapixel images can be - * captured at <code>>=</code> 20 fps, and maximum-resolution images can be - * captured at <code>>=</code> 10 fps.</p> + * <p>The camera device supports capturing high-resolution images at >= 20 frames per + * second, in at least the uncompressed YUV format, when post-processing settings are set + * to FAST. Additionally, maximum-resolution images can be captured at >= 10 frames + * per second. Here, 'high resolution' means at least 8 megapixels, or the maximum + * resolution of the device, whichever is smaller.</p> + * <p>More specifically, this means that a size matching the camera device's active array + * size is listed as a supported size for the {@link android.graphics.ImageFormat#YUV_420_888 } format in either {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputSizes } or {@link android.hardware.camera2.params.StreamConfigurationMap#getHighResolutionOutputSizes }, + * with a minimum frame duration for that format and size of either <= 1/20 s, or + * <= 1/10 s, respectively; and the {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES android.control.aeAvailableTargetFpsRanges} entry + * lists at least one FPS range where the minimum FPS is >= 1 / minimumFrameDuration + * for the maximum-size YUV_420_888 format. If that maximum size is listed in {@link android.hardware.camera2.params.StreamConfigurationMap#getHighResolutionOutputSizes }, + * then the list of resolutions for YUV_420_888 from {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputSizes } contains at + * least one resolution >= 8 megapixels, with a minimum frame duration of <= 1/20 + * s.</p> + * <p>If the device supports the {@link android.graphics.ImageFormat#RAW10 }, {@link android.graphics.ImageFormat#RAW12 }, then those can also be captured at the same rate + * as the maximum-size YUV_420_888 resolution is.</p> + * <p>If the device supports the PRIVATE_REPROCESSING capability, then the same guarantees + * as for the YUV_420_888 format also apply to the {@link android.graphics.ImageFormat#PRIVATE } format.</p> + * <p>In addition, the {@link CameraCharacteristics#SYNC_MAX_LATENCY android.sync.maxLatency} field is guaranted to have a value between 0 + * and 4, inclusive. {@link CameraCharacteristics#CONTROL_AE_LOCK_AVAILABLE android.control.aeLockAvailable} and {@link CameraCharacteristics#CONTROL_AWB_LOCK_AVAILABLE android.control.awbLockAvailable} + * are also guaranteed to be <code>true</code> so burst capture with these two locks ON yields + * consistent image output.</p> * * @see CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES * @see CameraCharacteristics#CONTROL_AE_LOCK_AVAILABLE * @see CameraCharacteristics#CONTROL_AWB_LOCK_AVAILABLE - * @see CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP * @see CameraCharacteristics#SYNC_MAX_LATENCY * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES */ @@ -954,13 +949,6 @@ public abstract class CameraMetadata<TKey> { */ public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY = 2; - /** - * <p>This camera device is capable of supporting advanced imaging applications at full rate, - * and additional high-resolution outputs at lower rates.</p> - * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL - */ - public static final int INFO_SUPPORTED_HARDWARE_LEVEL_HIGH_RESOLUTION = 3; - // // Enumeration values for CameraCharacteristics#SYNC_MAX_LATENCY // diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index 9fa6687..e405ba6 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -398,7 +398,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> @Override public int hashCode() { - return HashCodeHelpers.hashCode(mSettings, mSurfaceSet, mUserTag); + return HashCodeHelpers.hashCodeGeneric(mSettings, mSurfaceSet, mUserTag); } public static final Parcelable.Creator<CaptureRequest> CREATOR = diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java index 10dd8ae..7e50fd9 100644 --- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java +++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java @@ -842,11 +842,19 @@ public class CameraMetadataNative implements Parcelable { CameraCharacteristics.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS); ReprocessFormatsMap inputOutputFormatsMap = getBase( CameraCharacteristics.SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP); - + int[] capabilities = getBase(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES); + boolean listHighResolution = false; + for (int capability : capabilities) { + if (capability == CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE) { + listHighResolution = true; + break; + } + } return new StreamConfigurationMap( configurations, minFrameDurations, stallDurations, depthConfigurations, depthMinFrameDurations, depthStallDurations, - highSpeedVideoConfigurations, inputOutputFormatsMap); + highSpeedVideoConfigurations, inputOutputFormatsMap, + listHighResolution); } private <T> Integer getMaxRegions(Key<T> key) { diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java index 2fb3203..e786707 100644 --- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java +++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java @@ -605,6 +605,14 @@ public class LegacyCameraDevice implements AutoCloseable { return LegacyExceptionUtils.throwOnError(nativeDetectSurfaceType(surface)); } + /** + * Query the surface for its currently configured dataspace + */ + public static int detectSurfaceDataspace(Surface surface) throws BufferQueueAbandonedException { + checkNotNull(surface); + return LegacyExceptionUtils.throwOnError(nativeDetectSurfaceDataspace(surface)); + } + static void configureSurface(Surface surface, int width, int height, int pixelFormat) throws BufferQueueAbandonedException { checkNotNull(surface); @@ -702,6 +710,8 @@ public class LegacyCameraDevice implements AutoCloseable { private static native int nativeDetectSurfaceType(Surface surface); + private static native int nativeDetectSurfaceDataspace(Surface surface); + private static native int nativeDetectSurfaceDimens(Surface surface, /*out*/int[/*2*/] dimens); diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java index c6ea488..0935564 100644 --- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java +++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java @@ -22,12 +22,13 @@ import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.utils.HashCodeHelpers; +import android.hardware.camera2.utils.SurfaceUtils; import android.hardware.camera2.legacy.LegacyCameraDevice; import android.hardware.camera2.legacy.LegacyMetadataMapper; -import android.hardware.camera2.legacy.LegacyExceptionUtils.BufferQueueAbandonedException; import android.view.Surface; import android.util.Range; import android.util.Size; +import android.util.SparseIntArray; import java.util.Arrays; import java.util.HashMap; @@ -79,7 +80,8 @@ public final class StreamConfigurationMap { * @param stallDurations a non-{@code null} array of {@link StreamConfigurationDuration} * @param highSpeedVideoConfigurations an array of {@link HighSpeedVideoConfiguration}, null if * camera device does not support high speed video recording - * + * @param listHighResolution a flag indicating whether the device supports BURST_CAPTURE + * and thus needs a separate list of slow high-resolution output sizes * @throws NullPointerException if any of the arguments except highSpeedVideoConfigurations * were {@code null} or any subelements were {@code null} * @@ -93,10 +95,12 @@ public final class StreamConfigurationMap { StreamConfigurationDuration[] depthMinFrameDurations, StreamConfigurationDuration[] depthStallDurations, HighSpeedVideoConfiguration[] highSpeedVideoConfigurations, - ReprocessFormatsMap inputOutputFormatsMap) { + ReprocessFormatsMap inputOutputFormatsMap, + boolean listHighResolution) { mConfigurations = checkArrayElementsNotNull(configurations, "configurations"); mMinFrameDurations = checkArrayElementsNotNull(minFrameDurations, "minFrameDurations"); mStallDurations = checkArrayElementsNotNull(stallDurations, "stallDurations"); + mListHighResolution = listHighResolution; if (depthConfigurations == null) { mDepthConfigurations = new StreamConfiguration[0]; @@ -120,15 +124,27 @@ public final class StreamConfigurationMap { // For each format, track how many sizes there are available to configure for (StreamConfiguration config : configurations) { - HashMap<Integer, Integer> map = config.isOutput() ? mOutputFormats : mInputFormats; - - Integer count = map.get(config.getFormat()); - - if (count == null) { - count = 0; + int fmt = config.getFormat(); + SparseIntArray map = null; + if (config.isOutput()) { + mAllOutputFormats.put(fmt, mAllOutputFormats.get(fmt) + 1); + long duration = 0; + if (mListHighResolution) { + for (StreamConfigurationDuration configurationDuration : mMinFrameDurations) { + if (configurationDuration.getFormat() == fmt && + configurationDuration.getWidth() == config.getSize().getWidth() && + configurationDuration.getHeight() == config.getSize().getHeight()) { + duration = configurationDuration.getDuration(); + break; + } + } + } + map = duration <= DURATION_20FPS_NS ? + mOutputFormats : mHighResOutputFormats; + } else { + map = mInputFormats; } - - map.put(config.getFormat(), count + 1); + map.put(fmt, map.get(fmt) + 1); } // For each depth format, track how many sizes there are available to configure @@ -138,16 +154,11 @@ public final class StreamConfigurationMap { continue; } - Integer count = mDepthOutputFormats.get(config.getFormat()); - - if (count == null) { - count = 0; - } - - mDepthOutputFormats.put(config.getFormat(), count + 1); + mDepthOutputFormats.put(config.getFormat(), + mDepthOutputFormats.get(config.getFormat()) + 1); } - if (!mOutputFormats.containsKey(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)) { + if (mOutputFormats.indexOfKey(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) < 0) { throw new AssertionError( "At least one stream configuration for IMPLEMENTATION_DEFINED must exist"); } @@ -241,7 +252,7 @@ public final class StreamConfigurationMap { * @return a non-empty array of sizes, or {@code null} if the format was not available. */ public Size[] getInputSizes(final int format) { - return getPublicFormatSizes(format, /*output*/false); + return getPublicFormatSizes(format, /*output*/false, /*highRes*/false); } /** @@ -274,9 +285,9 @@ public final class StreamConfigurationMap { int internalFormat = imageFormatToInternal(format); int dataspace = imageFormatToDataspace(format); if (dataspace == HAL_DATASPACE_DEPTH) { - return mDepthOutputFormats.containsKey(internalFormat); + return mDepthOutputFormats.indexOfKey(internalFormat) >= 0; } else { - return getFormatsMap(/*output*/true).containsKey(internalFormat); + return getFormatsMap(/*output*/true).indexOfKey(internalFormat) >= 0; } } @@ -378,27 +389,24 @@ public final class StreamConfigurationMap { public boolean isOutputSupportedFor(Surface surface) { checkNotNull(surface, "surface must not be null"); - Size surfaceSize; - int surfaceFormat = -1; - try { - surfaceSize = LegacyCameraDevice.getSurfaceSize(surface); - surfaceFormat = LegacyCameraDevice.detectSurfaceType(surface); - } catch(BufferQueueAbandonedException e) { - throw new IllegalArgumentException("Abandoned surface", e); - } + Size surfaceSize = SurfaceUtils.getSurfaceSize(surface); + int surfaceFormat = SurfaceUtils.getSurfaceFormat(surface); + int surfaceDataspace = SurfaceUtils.getSurfaceDataspace(surface); // See if consumer is flexible. - boolean isFlexible = LegacyCameraDevice.isFlexibleConsumer(surface); + boolean isFlexible = SurfaceUtils.isFlexibleConsumer(surface); // Override RGB formats to IMPLEMENTATION_DEFINED, b/9487482 if ((surfaceFormat >= LegacyMetadataMapper.HAL_PIXEL_FORMAT_RGBA_8888 && surfaceFormat <= LegacyMetadataMapper.HAL_PIXEL_FORMAT_BGRA_8888)) { - surfaceFormat = LegacyMetadataMapper.HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; + surfaceFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; } - for (StreamConfiguration config : mConfigurations) { + StreamConfiguration[] configs = + surfaceDataspace != HAL_DATASPACE_DEPTH ? mConfigurations : mDepthConfigurations; + for (StreamConfiguration config : configs) { if (config.getFormat() == surfaceFormat && config.isOutput()) { - // Mathing format, either need exact size match, or a flexible consumer + // Matching format, either need exact size match, or a flexible consumer // and a size no bigger than MAX_DIMEN_FOR_ROUNDING if (config.getSize().equals(surfaceSize)) { return true; @@ -414,12 +422,12 @@ public final class StreamConfigurationMap { /** * Get a list of sizes compatible with {@code klass} to use as an output. * - * <p>Since some of the supported classes may support additional formats beyond + * <p>Some of the supported classes may support additional formats beyond * {@link ImageFormat#PRIVATE}; this function only returns * sizes for {@link ImageFormat#PRIVATE}. For example, {@link android.media.ImageReader} * supports {@link ImageFormat#YUV_420_888} and {@link ImageFormat#PRIVATE}, this method will * only return the sizes for {@link ImageFormat#PRIVATE} for {@link android.media.ImageReader} - * class .</p> + * class.</p> * * <p>If a well-defined format such as {@code NV21} is required, use * {@link #getOutputSizes(int)} instead.</p> @@ -444,7 +452,7 @@ public final class StreamConfigurationMap { } return getInternalFormatSizes(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, - HAL_DATASPACE_UNKNOWN,/*output*/true); + HAL_DATASPACE_UNKNOWN,/*output*/true, /*highRes*/false); } /** @@ -453,6 +461,14 @@ public final class StreamConfigurationMap { * <p>The {@code format} should be a supported format (one of the formats returned by * {@link #getOutputFormats}).</p> * + * As of API level 23, the {@link #getHighResolutionOutputSizes} method can be used on devices + * that support the + * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE BURST_CAPTURE} + * capability to get a list of high-resolution output sizes that cannot operate at the preferred + * 20fps rate. This means that for some supported formats, this method will return an empty + * list, if all the supported resolutions operate at below 20fps. For devices that do not + * support the BURST_CAPTURE capability, all output resolutions are listed through this method. + * * @param format an image format from {@link ImageFormat} or {@link PixelFormat} * @return * an array of supported sizes, @@ -463,7 +479,7 @@ public final class StreamConfigurationMap { * @see #getOutputFormats */ public Size[] getOutputSizes(int format) { - return getPublicFormatSizes(format, /*output*/true); + return getPublicFormatSizes(format, /*output*/true, /*highRes*/ false); } /** @@ -616,6 +632,32 @@ public final class StreamConfigurationMap { } /** + * Get a list of supported high resolution sizes, which cannot operate at full BURST_CAPTURE + * rate. + * + * <p>This includes all output sizes that cannot meet the 20 fps frame rate requirements for the + * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE BURST_CAPTURE} + * capability. This does not include the stall duration, so for example, a JPEG or RAW16 output + * resolution with a large stall duration but a minimum frame duration that's above 20 fps will + * still be listed in the regular {@link #getOutputSizes} list. All the sizes on this list are + * still guaranteed to operate at a rate of at least 10 fps, not including stall duration.</p> + * + * <p>For a device that does not support the BURST_CAPTURE capability, this list will be + * {@code null}, since resolutions in the {@link #getOutputSizes} list are already not + * guaranteed to meet >= 20 fps rate requirements. For a device that does support the + * BURST_CAPTURE capability, this list may be empty, if all supported resolutions meet the 20 + * fps requirement.</p> + * + * @return an array of supported slower high-resolution sizes, or {@code null} if the + * BURST_CAPTURE capability is not supported + */ + public Size[] getHighResolutionOutputSizes(int format) { + if (!mListHighResolution) return null; + + return getPublicFormatSizes(format, /*output*/true, /*highRes*/ true); + } + + /** * Get the minimum {@link CaptureRequest#SENSOR_FRAME_DURATION frame duration} * for the format/size combination (in nanoseconds). * @@ -867,6 +909,7 @@ public final class StreamConfigurationMap { return Arrays.equals(mConfigurations, other.mConfigurations) && Arrays.equals(mMinFrameDurations, other.mMinFrameDurations) && Arrays.equals(mStallDurations, other.mStallDurations) && + Arrays.equals(mDepthConfigurations, other.mDepthConfigurations) && Arrays.equals(mHighSpeedVideoConfigurations, other.mHighSpeedVideoConfigurations); } @@ -879,18 +922,31 @@ public final class StreamConfigurationMap { @Override public int hashCode() { // XX: do we care about order? - return HashCodeHelpers.hashCode( + return HashCodeHelpers.hashCodeGeneric( mConfigurations, mMinFrameDurations, - mStallDurations, mHighSpeedVideoConfigurations); + mStallDurations, + mDepthConfigurations, mHighSpeedVideoConfigurations); } // Check that the argument is supported by #getOutputFormats or #getInputFormats private int checkArgumentFormatSupported(int format, boolean output) { checkArgumentFormat(format); - int[] formats = output ? getOutputFormats() : getInputFormats(); - for (int i = 0; i < formats.length; ++i) { - if (format == formats[i]) { + int internalFormat = imageFormatToInternal(format); + int internalDataspace = imageFormatToDataspace(format); + + if (output) { + if (internalDataspace == HAL_DATASPACE_DEPTH) { + if (mDepthOutputFormats.indexOfKey(internalFormat) >= 0) { + return format; + } + } else { + if (mAllOutputFormats.indexOfKey(internalFormat) >= 0) { + return format; + } + } + } else { + if (mInputFormats.indexOfKey(internalFormat) >= 0) { return format; } } @@ -1175,7 +1231,7 @@ public final class StreamConfigurationMap { return formats; } - private Size[] getPublicFormatSizes(int format, boolean output) { + private Size[] getPublicFormatSizes(int format, boolean output, boolean highRes) { try { checkArgumentFormatSupported(format, output); } catch (IllegalArgumentException e) { @@ -1185,36 +1241,57 @@ public final class StreamConfigurationMap { int internalFormat = imageFormatToInternal(format); int dataspace = imageFormatToDataspace(format); - return getInternalFormatSizes(internalFormat, dataspace, output); + return getInternalFormatSizes(internalFormat, dataspace, output, highRes); } - private Size[] getInternalFormatSizes(int format, int dataspace, boolean output) { - - HashMap<Integer, Integer> formatsMap = - (dataspace == HAL_DATASPACE_DEPTH) ? mDepthOutputFormats : getFormatsMap(output); - - Integer sizesCount = formatsMap.get(format); - if (sizesCount == null) { + private Size[] getInternalFormatSizes(int format, int dataspace, + boolean output, boolean highRes) { + SparseIntArray formatsMap = + !output ? mInputFormats : + dataspace == HAL_DATASPACE_DEPTH ? mDepthOutputFormats : + highRes ? mHighResOutputFormats : + mOutputFormats; + + int sizesCount = formatsMap.get(format); + if ( ((!output || dataspace == HAL_DATASPACE_DEPTH) && sizesCount == 0) || + (output && dataspace != HAL_DATASPACE_DEPTH && mAllOutputFormats.get(format) == 0)) { + // Only throw if this is really not supported at all throw new IllegalArgumentException("format not available"); } - int len = sizesCount; - Size[] sizes = new Size[len]; + Size[] sizes = new Size[sizesCount]; int sizeIndex = 0; StreamConfiguration[] configurations = (dataspace == HAL_DATASPACE_DEPTH) ? mDepthConfigurations : mConfigurations; - for (StreamConfiguration config : configurations) { - if (config.getFormat() == format && config.isOutput() == output) { + int fmt = config.getFormat(); + if (fmt == format && config.isOutput() == output) { + if (output) { + // Filter slow high-res output formats; include for + // highRes, remove for !highRes + long duration = 0; + for (int i = 0; i < mMinFrameDurations.length; i++) { + StreamConfigurationDuration d = mMinFrameDurations[i]; + if (d.getFormat() == fmt && + d.getWidth() == config.getSize().getWidth() && + d.getHeight() == config.getSize().getHeight()) { + duration = d.getDuration(); + break; + } + } + if (highRes != (duration > DURATION_20FPS_NS)) { + continue; + } + } sizes[sizeIndex++] = config.getSize(); } } - if (sizeIndex != len) { + if (sizeIndex != sizesCount) { throw new AssertionError( - "Too few sizes (expected " + len + ", actual " + sizeIndex + ")"); + "Too few sizes (expected " + sizesCount + ", actual " + sizeIndex + ")"); } return sizes; @@ -1226,14 +1303,16 @@ public final class StreamConfigurationMap { int i = 0; - for (int format : getFormatsMap(output).keySet()) { + SparseIntArray map = getFormatsMap(output); + for (int j = 0; j < map.size(); j++) { + int format = map.keyAt(j); if (format != HAL_PIXEL_FORMAT_RAW_OPAQUE) { formats[i++] = imageFormatToPublic(format); } } if (output) { - for (int format : mDepthOutputFormats.keySet()) { - formats[i++] = depthFormatToPublic(format); + for (int j = 0; j < mDepthOutputFormats.size(); j++) { + formats[i++] = depthFormatToPublic(mDepthOutputFormats.keyAt(j)); } } if (formats.length != i) { @@ -1244,14 +1323,14 @@ public final class StreamConfigurationMap { } /** Get the format -> size count map for either output or input formats */ - private HashMap<Integer, Integer> getFormatsMap(boolean output) { - return output ? mOutputFormats : mInputFormats; + private SparseIntArray getFormatsMap(boolean output) { + return output ? mAllOutputFormats : mInputFormats; } private long getInternalFormatDuration(int format, int dataspace, Size size, int duration) { // assume format is already checked, since its internal - if (!arrayContains(getInternalFormatSizes(format, dataspace, /*output*/true), size)) { + if (!isSupportedInternalConfiguration(format, dataspace, size)) { throw new IllegalArgumentException("size was not supported"); } @@ -1289,10 +1368,9 @@ public final class StreamConfigurationMap { /** Count the number of publicly-visible output formats */ private int getPublicFormatCount(boolean output) { - HashMap<Integer, Integer> formatsMap = getFormatsMap(output); - + SparseIntArray formatsMap = getFormatsMap(output); int size = formatsMap.size(); - if (formatsMap.containsKey(HAL_PIXEL_FORMAT_RAW_OPAQUE)) { + if (formatsMap.indexOfKey(HAL_PIXEL_FORMAT_RAW_OPAQUE) >= 0) { size -= 1; } if (output) { @@ -1316,6 +1394,21 @@ public final class StreamConfigurationMap { return false; } + private boolean isSupportedInternalConfiguration(int format, int dataspace, + Size size) { + StreamConfiguration[] configurations = + (dataspace == HAL_DATASPACE_DEPTH) ? mDepthConfigurations : mConfigurations; + + for (int i = 0; i < configurations.length; i++) { + if (configurations[i].getFormat() == format && + configurations[i].getSize().equals(size)) { + return true; + } + } + + return false; + } + /** * Return this {@link StreamConfigurationMap} as a string representation. * @@ -1351,6 +1444,8 @@ public final class StreamConfigurationMap { StringBuilder sb = new StringBuilder("StreamConfiguration("); appendOutputsString(sb); sb.append(", "); + appendHighResOutputsString(sb); + sb.append(", "); appendInputsString(sb); sb.append(", "); appendValidOutputFormatsForInputString(sb); @@ -1381,6 +1476,27 @@ public final class StreamConfigurationMap { sb.append(")"); } + private void appendHighResOutputsString(StringBuilder sb) { + sb.append("HighResolutionOutputs("); + int[] formats = getOutputFormats(); + for (int format : formats) { + Size[] sizes = getHighResolutionOutputSizes(format); + if (sizes == null) continue; + for (Size size : sizes) { + long minFrameDuration = getOutputMinFrameDuration(format, size); + long stallDuration = getOutputStallDuration(format, size); + sb.append(String.format("[w:%d, h:%d, format:%s(%d), min_duration:%d, " + + "stall:%d], ", size.getWidth(), size.getHeight(), formatToString(format), + format, minFrameDuration, stallDuration)); + } + } + // Remove the pending ", " + if (sb.charAt(sb.length() - 1) == ' ') { + sb.delete(sb.length() - 2, sb.length()); + } + sb.append(")"); + } + private void appendInputsString(StringBuilder sb) { sb.append("Inputs("); int[] formats = getInputFormats(); @@ -1479,15 +1595,21 @@ public final class StreamConfigurationMap { } // from system/core/include/system/graphics.h + private static final int HAL_PIXEL_FORMAT_RAW16 = 0x20; private static final int HAL_PIXEL_FORMAT_BLOB = 0x21; private static final int HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 0x22; + private static final int HAL_PIXEL_FORMAT_YCbCr_420_888 = 0x23; private static final int HAL_PIXEL_FORMAT_RAW_OPAQUE = 0x24; + private static final int HAL_PIXEL_FORMAT_RAW10 = 0x25; + private static final int HAL_PIXEL_FORMAT_RAW12 = 0x26; private static final int HAL_PIXEL_FORMAT_Y16 = 0x20363159; + private static final int HAL_DATASPACE_UNKNOWN = 0x0; private static final int HAL_DATASPACE_JFIF = 0x101; private static final int HAL_DATASPACE_DEPTH = 0x1000; + private static final long DURATION_20FPS_NS = 50000000L; /** * @see #getDurations(int, int) */ @@ -1505,15 +1627,20 @@ public final class StreamConfigurationMap { private final HighSpeedVideoConfiguration[] mHighSpeedVideoConfigurations; private final ReprocessFormatsMap mInputOutputFormatsMap; - /** ImageFormat -> num output sizes mapping */ - private final HashMap</*ImageFormat*/Integer, /*Count*/Integer> mOutputFormats = - new HashMap<Integer, Integer>(); - /** ImageFormat -> num input sizes mapping */ - private final HashMap</*ImageFormat*/Integer, /*Count*/Integer> mInputFormats = - new HashMap<Integer, Integer>(); - /** ImageFormat -> num depth output sizes mapping */ - private final HashMap</*ImageFormat*/Integer, /*Count*/Integer> mDepthOutputFormats = - new HashMap<Integer, Integer>(); + private final boolean mListHighResolution; + + /** internal format -> num output sizes mapping, not including slow high-res sizes, for + * non-depth dataspaces */ + private final SparseIntArray mOutputFormats = new SparseIntArray(); + /** internal format -> num output sizes mapping for slow high-res sizes, for non-depth + * dataspaces */ + private final SparseIntArray mHighResOutputFormats = new SparseIntArray(); + /** internal format -> num output sizes mapping for all non-depth dataspaces */ + private final SparseIntArray mAllOutputFormats = new SparseIntArray(); + /** internal format -> num input sizes mapping, for input reprocessing formats */ + private final SparseIntArray mInputFormats = new SparseIntArray(); + /** internal format -> num depth output sizes mapping, for HAL_DATASPACE_DEPTH */ + private final SparseIntArray mDepthOutputFormats = new SparseIntArray(); /** High speed video Size -> FPS range count mapping*/ private final HashMap</*HighSpeedVideoSize*/Size, /*Count*/Integer> mHighSpeedVideoSizeMap = new HashMap<Size, Integer>(); @@ -1522,4 +1649,3 @@ public final class StreamConfigurationMap { mHighSpeedVideoFpsRangeMap = new HashMap<Range<Integer>, Integer>(); } - diff --git a/core/java/android/hardware/camera2/params/TonemapCurve.java b/core/java/android/hardware/camera2/params/TonemapCurve.java index 398a7e9..2d7bbaa 100644 --- a/core/java/android/hardware/camera2/params/TonemapCurve.java +++ b/core/java/android/hardware/camera2/params/TonemapCurve.java @@ -277,7 +277,7 @@ public final class TonemapCurve { return mHashCode; } - mHashCode = HashCodeHelpers.hashCode(mRed, mGreen, mBlue); + mHashCode = HashCodeHelpers.hashCodeGeneric(mRed, mGreen, mBlue); mHashCalculated = true; return mHashCode; diff --git a/core/java/android/hardware/camera2/utils/HashCodeHelpers.java b/core/java/android/hardware/camera2/utils/HashCodeHelpers.java index 7b4aa09..731da8b 100644 --- a/core/java/android/hardware/camera2/utils/HashCodeHelpers.java +++ b/core/java/android/hardware/camera2/utils/HashCodeHelpers.java @@ -30,7 +30,7 @@ public final class HashCodeHelpers { * * @return the numeric hash code */ - public static int hashCode(int[] array) { + public static int hashCode(int... array) { if (array == null) { return 0; } @@ -60,7 +60,7 @@ public final class HashCodeHelpers { * * @return the numeric hash code */ - public static int hashCode(float[] array) { + public static int hashCode(float... array) { if (array == null) { return 0; } @@ -83,7 +83,7 @@ public final class HashCodeHelpers { * * @return the numeric hash code */ - public static <T> int hashCode(T[] array) { + public static <T> int hashCodeGeneric(T... array) { if (array == null) { return 0; } @@ -97,56 +97,4 @@ public final class HashCodeHelpers { return h; } - public static <T> int hashCode(T a) { - return (a == null) ? 0 : a.hashCode(); - } - - public static <T> int hashCode(T a, T b) { - int h = hashCode(a); - - int x = (b == null) ? 0 : b.hashCode(); - h = ((h << 5) - h) ^ x; // (h * 31) XOR x - - return h; - } - - public static <T> int hashCode(T a, T b, T c) { - int h = hashCode(a, b); - - int x = (c == null) ? 0 : c.hashCode(); - h = ((h << 5) - h) ^ x; // (h * 31) XOR x - - return h; - } - - public static <T> int hashCode(T a, T b, T c, T d) { - int h = hashCode(a, b, c); - - int x = (d == null) ? 0 : d.hashCode(); - h = ((h << 5) - h) ^ x; // (h * 31) XOR x - - return h; - } - - public static int hashCode(int x) { - return hashCode(new int[] { x } ); - } - - public static int hashCode(int x, int y) { - return hashCode(new int[] { x, y } ); - } - - public static int hashCode(int x, int y, int z) { - return hashCode(new int[] { x, y, z } ); - } - - public static int hashCode(int x, int y, int z, int w) { - return hashCode(new int[] { x, y, z, w } ); - } - - public static int hashCode(int x, int y, int z, int w, int t) { - return hashCode(new int[] { x, y, z, w, t } ); - } - - } diff --git a/core/java/android/hardware/camera2/utils/SurfaceUtils.java b/core/java/android/hardware/camera2/utils/SurfaceUtils.java index 40005a5..064b21a 100644 --- a/core/java/android/hardware/camera2/utils/SurfaceUtils.java +++ b/core/java/android/hardware/camera2/utils/SurfaceUtils.java @@ -79,4 +79,30 @@ public class SurfaceUtils { throw new IllegalArgumentException("Surface was abandoned", e); } } + + /** + * Get the Surface dataspace. + * + * @param surface The surface to be queried for dataspace. + * @return dataspace of the surface. + * + * @throws IllegalArgumentException if the surface is already abandoned. + */ + public static int getSurfaceDataspace(Surface surface) { + try { + return LegacyCameraDevice.detectSurfaceDataspace(surface); + } catch (BufferQueueAbandonedException e) { + throw new IllegalArgumentException("Surface was abandoned", e); + } + } + + /** + * Return true is the consumer is one of the consumers that can accept + * producer overrides of the default dimensions and format. + * + */ + public static boolean isFlexibleConsumer(Surface output) { + return LegacyCameraDevice.isFlexibleConsumer(output); + } + } diff --git a/core/java/android/inputmethodservice/ExtractEditText.java b/core/java/android/inputmethodservice/ExtractEditText.java index f965f54..8bc2876 100644 --- a/core/java/android/inputmethodservice/ExtractEditText.java +++ b/core/java/android/inputmethodservice/ExtractEditText.java @@ -165,6 +165,14 @@ public class ExtractEditText extends EditText { } /** + * @hide + */ + @Override + public boolean isInExtractedMode() { + return true; + } + + /** * {@inheritDoc} * @hide */ diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 593f804..7fda30a 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -142,9 +142,9 @@ public abstract class BatteryStats implements Parcelable { public static final int CAMERA_TURNED_ON = 17; /** - * A constant indicating a doze wake lock timer. + * A constant indicating a draw wake lock timer. */ - public static final int WAKE_TYPE_DOZE = 18; + public static final int WAKE_TYPE_DRAW = 18; /** * Include all of the data in the stats, including previously saved data. @@ -3839,7 +3839,7 @@ public abstract class BatteryStats implements Parcelable { final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats(); long totalFullWakelock = 0, totalPartialWakelock = 0, totalWindowWakelock = 0; - long totalDozeWakelock = 0; + long totalDrawWakelock = 0; int countWakelock = 0; for (int iw=wakelocks.size()-1; iw>=0; iw--) { final Uid.Wakelock wl = wakelocks.valueAt(iw); @@ -3854,8 +3854,8 @@ public abstract class BatteryStats implements Parcelable { "partial", which, linePrefix); linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime, "window", which, linePrefix); - linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_DOZE), rawRealtime, - "doze", which, linePrefix); + linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_DRAW), rawRealtime, + "draw", which, linePrefix); sb.append(" realtime"); pw.println(sb.toString()); uidActivity = true; @@ -3867,7 +3867,7 @@ public abstract class BatteryStats implements Parcelable { rawRealtime, which); totalWindowWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime, which); - totalDozeWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_DOZE), + totalDrawWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_DRAW), rawRealtime, which); } if (countWakelock > 1) { @@ -3898,13 +3898,13 @@ public abstract class BatteryStats implements Parcelable { formatTimeMs(sb, totalWindowWakelock); sb.append("window"); } - if (totalDozeWakelock != 0) { + if (totalDrawWakelock != 0) { if (needComma) { sb.append(","); } needComma = true; - formatTimeMs(sb, totalDozeWakelock); - sb.append("doze"); + formatTimeMs(sb, totalDrawWakelock); + sb.append("draw"); } sb.append(" realtime"); pw.println(sb.toString()); diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 00350ec..9770941 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -449,6 +449,22 @@ public class UserManager { public static final String DISALLOW_RECORD_AUDIO = "no_record_audio"; /** + * This user restriction has an effect only in a managed profile. + * If set: + * Intent filters of activities in the parent profile with action + * {@link android.content.Intent#ACTION_VIEW}, + * category {@link android.content.Intent#CATEGORY_BROWSABLE}, scheme http or https, and which + * define a host can handle intents from the managed profile. + * The default value is <code>false</code>. + * + * <p/>Key for user restrictions. + * <p/>Type: Boolean + * @see #setUserRestrictions(Bundle) + * @see #getUserRestrictions() + */ + public static final String ALLOW_PARENT_APP_LINKING = "allow_parent_app_linking"; + + /** * Application restriction key that is used to indicate the pending arrival * of real restrictions for the app. * diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java index 8d11527..e33baa9 100644 --- a/core/java/android/os/storage/VolumeInfo.java +++ b/core/java/android/os/storage/VolumeInfo.java @@ -137,6 +137,7 @@ public class VolumeInfo implements Parcelable { public final String id; public final int type; public final DiskInfo disk; + public final String partGuid; public int mountFlags = 0; public int mountUserId = -1; public int state = STATE_UNMOUNTED; @@ -149,10 +150,11 @@ public class VolumeInfo implements Parcelable { /** Framework state */ public final int mtpIndex; - public VolumeInfo(String id, int type, DiskInfo disk, int mtpIndex) { + public VolumeInfo(String id, int type, DiskInfo disk, String partGuid, int mtpIndex) { this.id = Preconditions.checkNotNull(id); this.type = type; this.disk = disk; + this.partGuid = partGuid; this.mtpIndex = mtpIndex; } @@ -164,6 +166,7 @@ public class VolumeInfo implements Parcelable { } else { disk = null; } + partGuid = parcel.readString(); mountFlags = parcel.readInt(); mountUserId = parcel.readInt(); state = parcel.readInt(); @@ -385,6 +388,7 @@ public class VolumeInfo implements Parcelable { pw.increaseIndent(); pw.printPair("type", DebugUtils.valueToString(getClass(), "TYPE_", type)); pw.printPair("diskId", getDiskId()); + pw.printPair("partGuid", partGuid); pw.printPair("mountFlags", DebugUtils.flagsToString(getClass(), "MOUNT_FLAG_", mountFlags)); pw.printPair("mountUserId", mountUserId); pw.printPair("state", DebugUtils.valueToString(getClass(), "STATE_", state)); @@ -453,6 +457,7 @@ public class VolumeInfo implements Parcelable { } else { parcel.writeInt(0); } + parcel.writeString(partGuid); parcel.writeInt(mountFlags); parcel.writeInt(mountUserId); parcel.writeInt(state); diff --git a/core/java/android/os/storage/VolumeRecord.java b/core/java/android/os/storage/VolumeRecord.java index 096e2dd..cb16305 100644 --- a/core/java/android/os/storage/VolumeRecord.java +++ b/core/java/android/os/storage/VolumeRecord.java @@ -39,6 +39,7 @@ public class VolumeRecord implements Parcelable { public final int type; public final String fsUuid; + public String partGuid; public String nickname; public int userFlags; @@ -50,6 +51,7 @@ public class VolumeRecord implements Parcelable { public VolumeRecord(Parcel parcel) { type = parcel.readInt(); fsUuid = parcel.readString(); + partGuid = parcel.readString(); nickname = parcel.readString(); userFlags = parcel.readInt(); } @@ -79,6 +81,8 @@ public class VolumeRecord implements Parcelable { pw.increaseIndent(); pw.printPair("type", DebugUtils.valueToString(VolumeInfo.class, "TYPE_", type)); pw.printPair("fsUuid", fsUuid); + pw.printPair("partGuid", partGuid); + pw.println(); pw.printPair("nickname", nickname); pw.printPair("userFlags", DebugUtils.flagsToString(VolumeRecord.class, "USER_FLAG_", userFlags)); @@ -133,6 +137,7 @@ public class VolumeRecord implements Parcelable { public void writeToParcel(Parcel parcel, int flags) { parcel.writeInt(type); parcel.writeString(fsUuid); + parcel.writeString(partGuid); parcel.writeString(nickname); parcel.writeInt(userFlags); } diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java index d51aa79..d8f7158 100644 --- a/core/java/android/text/TextUtils.java +++ b/core/java/android/text/TextUtils.java @@ -465,6 +465,11 @@ public class TextUtils { return false; } + /** {@hide} */ + public static String nullIfEmpty(@Nullable String str) { + return isEmpty(str) ? null : str; + } + /** * Returns the length that the specified CharSequence would have if * spaces and control characters were trimmed from the start and end, diff --git a/core/java/android/util/Range.java b/core/java/android/util/Range.java index 211d01a..5524506 100644 --- a/core/java/android/util/Range.java +++ b/core/java/android/util/Range.java @@ -350,7 +350,7 @@ public final class Range<T extends Comparable<? super T>> { */ @Override public int hashCode() { - return HashCodeHelpers.hashCode(mLower, mUpper); + return HashCodeHelpers.hashCodeGeneric(mLower, mUpper); } private final T mLower; diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java index 52a12f3..3c21981 100644 --- a/core/java/android/view/DisplayListCanvas.java +++ b/core/java/android/view/DisplayListCanvas.java @@ -323,10 +323,4 @@ public class DisplayListCanvas extends Canvas { } private static native void nDrawRects(long renderer, long region, long paint); - - @Override - public void drawPicture(Picture picture) { - picture.endRecording(); - // TODO: Implement rendering - } } diff --git a/core/java/android/view/accessibility/CaptioningManager.java b/core/java/android/view/accessibility/CaptioningManager.java index 410d39c..14f0b0a 100644 --- a/core/java/android/view/accessibility/CaptioningManager.java +++ b/core/java/android/view/accessibility/CaptioningManager.java @@ -266,11 +266,19 @@ public class CaptioningManager { * background colors, edge properties, and typeface. */ public static final class CaptionStyle { - /** Packed value for a color of 'none' and a cached opacity of 100%. */ + /** + * Packed value for a color of 'none' and a cached opacity of 100%. + * + * @hide + */ private static final int COLOR_NONE_OPAQUE = 0x000000FF; - /** Packed value for an unspecified color and opacity. */ - private static final int COLOR_UNSPECIFIED = 0x000001FF; + /** + * Packed value for a color of 'default' and opacity of 100%. + * + * @hide + */ + public static final int COLOR_UNSPECIFIED = 0x00FFFFFF; private static final CaptionStyle WHITE_ON_BLACK; private static final CaptionStyle BLACK_ON_WHITE; @@ -350,11 +358,11 @@ public class CaptioningManager { private CaptionStyle(int foregroundColor, int backgroundColor, int edgeType, int edgeColor, int windowColor, String rawTypeface) { - mHasForegroundColor = foregroundColor != COLOR_UNSPECIFIED; - mHasBackgroundColor = backgroundColor != COLOR_UNSPECIFIED; + mHasForegroundColor = hasColor(foregroundColor); + mHasBackgroundColor = hasColor(backgroundColor); mHasEdgeType = edgeType != EDGE_TYPE_UNSPECIFIED; - mHasEdgeColor = edgeColor != COLOR_UNSPECIFIED; - mHasWindowColor = windowColor != COLOR_UNSPECIFIED; + mHasEdgeColor = hasColor(edgeColor); + mHasWindowColor = hasColor(windowColor); // Always use valid colors, even when no override is specified, to // ensure backwards compatibility with apps targeting KitKat MR2. @@ -368,6 +376,20 @@ public class CaptioningManager { } /** + * Returns whether a packed color indicates a non-default value. + * + * @param packedColor the packed color value + * @return {@code true} if a non-default value is specified + * @hide + */ + public static boolean hasColor(int packedColor) { + // Matches the color packing code from Settings. "Default" packed + // colors are indicated by zero alpha and non-zero red/blue. The + // cached alpha value used by Settings is stored in green. + return (packedColor >>> 24) != 0 || (packedColor & 0xFFFF00) == 0; + } + + /** * Applies a caption style, overriding any properties that are specified * in the overlay caption. * diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java index 2f5c9e2..de8ccc1 100644 --- a/core/java/android/webkit/WebViewClient.java +++ b/core/java/android/webkit/WebViewClient.java @@ -298,14 +298,27 @@ public class WebViewClient { * Notify the host application to handle a SSL client certificate * request. The host application is responsible for showing the UI * if desired and providing the keys. There are three ways to - * respond: proceed(), cancel() or ignore(). Webview remembers the - * response if proceed() or cancel() is called and does not - * call onReceivedClientCertRequest() again for the same host and port - * pair. Webview does not remember the response if ignore() is called. + * respond: proceed(), cancel() or ignore(). Webview stores the response + * in memory (for the life of the application) if proceed() or cancel() is + * called and does not call onReceivedClientCertRequest() again for the + * same host and port pair. Webview does not store the response if ignore() + * is called. * * This method is called on the UI thread. During the callback, the * connection is suspended. * + * For most use cases, the application program should implement the + * {@link android.security.KeyChainAliasCallback} interface and pass it to + * {@link android.security.KeyChain#choosePrivateKeyAlias} to start an + * activity for the user to choose the proper alias. The keychain activity will + * provide the alias through the callback method in the implemented interface. Next + * the application should create an async task to call + * {@link android.security.KeyChain#getPrivateKey} to receive the key. + * + * An example implementation of client certificates can be seen at + * <A href="https://android.googlesource.com/platform/packages/apps/Browser/+/android-5.1.1_r1/src/com/android/browser/Tab.java"> + * AOSP Browser</a> + * * The default behavior is to cancel, returning no client certificate. * * @param view The WebView that is initiating the callback diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 9ca59f1..e050bda 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -623,7 +623,7 @@ public class Editor { // One is the true focus lost where suggestions pop-up (if any) should be dismissed, and the // other is an side effect of showing the suggestions pop-up itself. We use isShowingUp() // to distinguish one from the other. - if (mSuggestionsPopupWindow != null && ((mTextView instanceof ExtractEditText) || + if (mSuggestionsPopupWindow != null && ((mTextView.isInExtractedMode()) || !mSuggestionsPopupWindow.isShowingUp())) { // Should be done before hide insertion point controller since it triggers a show of it mSuggestionsPopupWindow.hide(); @@ -640,7 +640,7 @@ public class Editor { mTextView.removeAdjacentSuggestionSpans(end); if (mTextView.isTextEditable() && mTextView.isSuggestionsEnabled() && - !(mTextView instanceof ExtractEditText)) { + !(mTextView.isInExtractedMode())) { if (mSpellChecker == null && createSpellChecker) { mSpellChecker = new SpellChecker(mTextView); } @@ -1063,7 +1063,7 @@ public class Editor { // ExtractEditText clears focus, which gives focus to the ExtractEditText. // This special case ensure that we keep current selection in that case. // It would be better to know why the DecorView does not have focus at that time. - if (((mTextView instanceof ExtractEditText) || mSelectionMoved) && + if (((mTextView.isInExtractedMode()) || mSelectionMoved) && selStart >= 0 && selEnd >= 0) { /* * Someone intentionally set the selection, so let them @@ -1099,7 +1099,7 @@ public class Editor { // Don't leave us in the middle of a batch edit. mTextView.onEndBatchEdit(); - if (mTextView instanceof ExtractEditText) { + if (mTextView.isInExtractedMode()) { // terminateTextSelectionMode removes selection, which we want to keep when // ExtractEditText goes out of focus. final int selStart = mTextView.getSelectionStart(); @@ -1825,7 +1825,7 @@ public class Editor { } private boolean extractedTextModeWillBeStarted() { - if (!(mTextView instanceof ExtractEditText)) { + if (!(mTextView.isInExtractedMode())) { final InputMethodManager imm = InputMethodManager.peekInstance(); return imm != null && imm.isFullscreenMode(); } @@ -4657,7 +4657,9 @@ public class Editor { mEndHandle.showAtLocation(endOffset); // No longer the first dragging motion, reset. - startSelectionActionMode(); + if (!(mTextView.isInExtractedMode())) { + startSelectionActionMode(); + } mDragAcceleratorActive = false; mStartOffset = -1; mSwitchedLines = false; diff --git a/core/java/android/widget/OverScroller.java b/core/java/android/widget/OverScroller.java index 451e493..98bfd7d 100644 --- a/core/java/android/widget/OverScroller.java +++ b/core/java/android/widget/OverScroller.java @@ -731,7 +731,7 @@ public class OverScroller { // mStartTime has been set mFinished = false; mState = CUBIC; - mStart = start; + mCurrentPosition = mStart = start; mFinal = end; final int delta = start - end; mDeceleration = getDeceleration(delta); @@ -797,7 +797,9 @@ public class OverScroller { private void fitOnBounceCurve(int start, int end, int velocity) { // Simulate a bounce that started from edge final float durationToApex = - velocity / mDeceleration; - final float distanceToApex = velocity * velocity / 2.0f / Math.abs(mDeceleration); + // The float cast below is necessary to avoid integer overflow. + final float velocitySquared = (float) velocity * velocity; + final float distanceToApex = velocitySquared / 2.0f / Math.abs(mDeceleration); final float distanceToEdge = Math.abs(end - start); final float totalDuration = (float) Math.sqrt( 2.0 * (distanceToApex + distanceToEdge) / Math.abs(mDeceleration)); @@ -848,12 +850,14 @@ public class OverScroller { private void onEdgeReached() { // mStart, mVelocity and mStartTime were adjusted to their values when edge was reached. - float distance = mVelocity * mVelocity / (2.0f * Math.abs(mDeceleration)); + // The float cast below is necessary to avoid integer overflow. + final float velocitySquared = (float) mVelocity * mVelocity; + float distance = velocitySquared / (2.0f * Math.abs(mDeceleration)); final float sign = Math.signum(mVelocity); if (distance > mOver) { // Default deceleration is not sufficient to slow us down before boundary - mDeceleration = - sign * mVelocity * mVelocity / (2.0f * mOver); + mDeceleration = - sign * velocitySquared / (2.0f * mOver); distance = mOver; } diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java index affc5da..339038e 100644 --- a/core/java/android/widget/RelativeLayout.java +++ b/core/java/android/widget/RelativeLayout.java @@ -522,7 +522,7 @@ public class RelativeLayout extends ViewGroup { View baselineView = null; LayoutParams baselineParams = null; for (int i = 0; i < count; i++) { - final View child = getChildAt(i); + final View child = views[i]; if (child.getVisibility() != GONE) { final LayoutParams childParams = (LayoutParams) child.getLayoutParams(); if (baselineView == null || baselineParams == null @@ -548,9 +548,9 @@ public class RelativeLayout extends ViewGroup { if (offsetHorizontalAxis) { for (int i = 0; i < count; i++) { - View child = getChildAt(i); + final View child = views[i]; if (child.getVisibility() != GONE) { - LayoutParams params = (LayoutParams) child.getLayoutParams(); + final LayoutParams params = (LayoutParams) child.getLayoutParams(); final int[] rules = params.getRules(layoutDirection); if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_HORIZONTAL] != 0) { centerHorizontal(child, params, width); @@ -578,9 +578,9 @@ public class RelativeLayout extends ViewGroup { if (offsetVerticalAxis) { for (int i = 0; i < count; i++) { - View child = getChildAt(i); + final View child = views[i]; if (child.getVisibility() != GONE) { - LayoutParams params = (LayoutParams) child.getLayoutParams(); + final LayoutParams params = (LayoutParams) child.getLayoutParams(); final int[] rules = params.getRules(layoutDirection); if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_VERTICAL] != 0) { centerVertical(child, params, height); @@ -607,9 +607,9 @@ public class RelativeLayout extends ViewGroup { final int verticalOffset = contentBounds.top - top; if (horizontalOffset != 0 || verticalOffset != 0) { for (int i = 0; i < count; i++) { - View child = getChildAt(i); + final View child = views[i]; if (child.getVisibility() != GONE && child != ignore) { - LayoutParams params = (LayoutParams) child.getLayoutParams(); + final LayoutParams params = (LayoutParams) child.getLayoutParams(); if (horizontalGravity) { params.mLeft += horizontalOffset; params.mRight += horizontalOffset; @@ -626,9 +626,9 @@ public class RelativeLayout extends ViewGroup { if (isLayoutRtl()) { final int offsetWidth = myWidth - width; for (int i = 0; i < count; i++) { - View child = getChildAt(i); + final View child = views[i]; if (child.getVisibility() != GONE) { - LayoutParams params = (LayoutParams) child.getLayoutParams(); + final LayoutParams params = (LayoutParams) child.getLayoutParams(); params.mLeft -= offsetWidth; params.mRight -= offsetWidth; } diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java index fdabe91..6abd129 100644 --- a/core/java/android/widget/Spinner.java +++ b/core/java/android/widget/Spinner.java @@ -711,9 +711,7 @@ public class Spinner extends AbsSpinner implements OnClickListener { lp = generateDefaultLayoutParams(); } - if (addChild) { - addViewInLayout(child, 0, lp); - } + addViewInLayout(child, 0, lp); child.setSelected(hasFocus()); if (mDisableChildrenWhenDisabled) { @@ -743,6 +741,10 @@ public class Spinner extends AbsSpinner implements OnClickListener { childRight = childLeft + width; child.layout(childLeft, childTop, childRight, childBottom); + + if (!addChild) { + removeViewInLayout(child); + } } @Override diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index c538dc2..f733eab 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -8637,6 +8637,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** + * @return true if this TextView is specialized for showing and interacting with the extracted + * text in a full-screen input method. + * @hide + */ + public boolean isInExtractedMode() { + return false; + } + + /** * This is a temporary method. Future versions may support multi-locale text. * Caveat: This method may not return the latest spell checker locale, but this should be * acceptable and it's more important to make this method asynchronous. |
