diff options
Diffstat (limited to 'core')
88 files changed, 1520 insertions, 793 deletions
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java index 9156eeb..7c13dbe 100644 --- a/core/java/android/animation/AnimatorSet.java +++ b/core/java/android/animation/AnimatorSet.java @@ -504,6 +504,10 @@ public final class AnimatorSet extends Animator { mStarted = true; mPaused = false; + for (Node node : mNodes) { + node.animation.setAllowRunningAsynchronously(false); + } + if (mDuration >= 0) { // If the duration was set on this AnimatorSet, pass it along to all child animations for (Node node : mNodes) { diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 3e03893..9486a72 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -2656,17 +2656,24 @@ public class ActivityManager { /** * Start an activity in this task. Brings the task to the foreground. If this task - * is not currently active (that is, its id < 0), then the activity being started - * needs to be started as a new task and the Intent's ComponentName must match the - * base ComponenentName of the recent task entry. Otherwise, the activity being - * started must <b>not</b> be launched as a new task -- not through explicit intent - * flags nor implicitly as the singleTask or singleInstance launch modes. + * is not currently active (that is, its id < 0), then a new activity for the given + * Intent will be launched as the root of the task and the task brought to the + * foreground. Otherwise, if this task is currently active and the Intent does not specify + * an activity to launch in a new task, then a new activity for the given Intent will + * be launched on top of the task and the task brought to the foreground. If this + * task is currently active and the Intent specifies {@link Intent#FLAG_ACTIVITY_NEW_TASK} + * or would otherwise be launched in to a new task, then the activity not launched but + * this task be brought to the foreground and a new intent delivered to the top + * activity if appropriate. * - * <p>See {@link Activity#startActivity(android.content.Intent, android.os.Bundle) - * Activity.startActivity} for more information.</p> + * <p>In other words, you generally want to use an Intent here that does not specify + * {@link Intent#FLAG_ACTIVITY_NEW_TASK} or {@link Intent#FLAG_ACTIVITY_NEW_DOCUMENT}, + * and let the system do the right thing.</p> * * @param intent The Intent describing the new activity to be launched on the task. * @param options Optional launch options. + * + * @see Activity#startActivity(android.content.Intent, android.os.Bundle) */ public void startActivity(Context context, Intent intent, Bundle options) { ActivityThread thread = ActivityThread.currentActivityThread(); diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 1f7e450..394b183 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -509,8 +509,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM case ACTIVITY_PAUSED_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); - PersistableBundle persistentState = data.readPersistableBundle(); - activityPaused(token, persistentState); + activityPaused(token); reply.writeNoException(); return true; } @@ -2829,13 +2828,12 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); reply.recycle(); } - public void activityPaused(IBinder token, PersistableBundle persistentState) throws RemoteException + public void activityPaused(IBinder token) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(token); - data.writePersistableBundle(persistentState); mRemote.transact(ACTIVITY_PAUSED_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index 9dd4605..ffffb6c 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -84,13 +84,13 @@ public class ActivityOptions { * Initial width of the animation. * @hide */ - public static final String KEY_ANIM_START_WIDTH = "android:animStartWidth"; + public static final String KEY_ANIM_WIDTH = "android:animWidth"; /** * Initial height of the animation. * @hide */ - public static final String KEY_ANIM_START_HEIGHT = "android:animStartHeight"; + public static final String KEY_ANIM_HEIGHT = "android:animHeight"; /** * Callback for when animation is started. @@ -140,8 +140,8 @@ public class ActivityOptions { private Bitmap mThumbnail; private int mStartX; private int mStartY; - private int mStartWidth; - private int mStartHeight; + private int mWidth; + private int mHeight; private IRemoteCallback mAnimationStartedListener; private ResultReceiver mTransitionReceiver; private boolean mIsReturning; @@ -238,13 +238,13 @@ public class ActivityOptions { * defines the coordinate space for <var>startX</var> and <var>startY</var>. * @param startX The x starting location of the new activity, relative to <var>source</var>. * @param startY The y starting location of the activity, relative to <var>source</var>. - * @param startWidth The initial width of the new activity. - * @param startHeight The initial height of the new activity. + * @param width The initial width of the new activity. + * @param height The initial height of the new activity. * @return Returns a new ActivityOptions object that you can use to * supply these options as the options Bundle when starting an activity. */ public static ActivityOptions makeScaleUpAnimation(View source, - int startX, int startY, int startWidth, int startHeight) { + int startX, int startY, int width, int height) { ActivityOptions opts = new ActivityOptions(); opts.mPackageName = source.getContext().getPackageName(); opts.mAnimationType = ANIM_SCALE_UP; @@ -252,8 +252,8 @@ public class ActivityOptions { source.getLocationOnScreen(pts); opts.mStartX = pts[0] + startX; opts.mStartY = pts[1] + startY; - opts.mStartWidth = startWidth; - opts.mStartHeight = startHeight; + opts.mWidth = width; + opts.mHeight = height; return opts; } @@ -359,9 +359,10 @@ public class ActivityOptions { * @hide */ public static ActivityOptions makeThumbnailAspectScaleUpAnimation(View source, - Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) { - return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY, listener, - true); + Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight, + OnAnimationStartedListener listener) { + return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY, + targetWidth, targetHeight, listener, true); } /** @@ -382,13 +383,15 @@ public class ActivityOptions { * @hide */ public static ActivityOptions makeThumbnailAspectScaleDownAnimation(View source, - Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) { - return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY, listener, - false); + Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight, + OnAnimationStartedListener listener) { + return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY, + targetWidth, targetHeight, listener, false); } private static ActivityOptions makeAspectScaledThumbnailAnimation(View source, Bitmap thumbnail, - int startX, int startY, OnAnimationStartedListener listener, boolean scaleUp) { + int startX, int startY, int targetWidth, int targetHeight, + OnAnimationStartedListener listener, boolean scaleUp) { ActivityOptions opts = new ActivityOptions(); opts.mPackageName = source.getContext().getPackageName(); opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_ASPECT_SCALE_UP : @@ -398,6 +401,8 @@ public class ActivityOptions { source.getLocationOnScreen(pts); opts.mStartX = pts[0] + startX; opts.mStartY = pts[1] + startY; + opts.mWidth = targetWidth; + opts.mHeight = targetHeight; opts.setOnAnimationStartedListener(source.getHandler(), listener); return opts; } @@ -543,8 +548,8 @@ public class ActivityOptions { case ANIM_SCALE_UP: mStartX = opts.getInt(KEY_ANIM_START_X, 0); mStartY = opts.getInt(KEY_ANIM_START_Y, 0); - mStartWidth = opts.getInt(KEY_ANIM_START_WIDTH, 0); - mStartHeight = opts.getInt(KEY_ANIM_START_HEIGHT, 0); + mWidth = opts.getInt(KEY_ANIM_WIDTH, 0); + mHeight = opts.getInt(KEY_ANIM_HEIGHT, 0); break; case ANIM_THUMBNAIL_SCALE_UP: @@ -554,6 +559,8 @@ public class ActivityOptions { mThumbnail = (Bitmap) opts.getParcelable(KEY_ANIM_THUMBNAIL); mStartX = opts.getInt(KEY_ANIM_START_X, 0); mStartY = opts.getInt(KEY_ANIM_START_Y, 0); + mWidth = opts.getInt(KEY_ANIM_WIDTH, 0); + mHeight = opts.getInt(KEY_ANIM_HEIGHT, 0); mAnimationStartedListener = IRemoteCallback.Stub.asInterface( opts.getBinder(KEY_ANIM_START_LISTENER)); break; @@ -605,13 +612,13 @@ public class ActivityOptions { } /** @hide */ - public int getStartWidth() { - return mStartWidth; + public int getWidth() { + return mWidth; } /** @hide */ - public int getStartHeight() { - return mStartHeight; + public int getHeight() { + return mHeight; } /** @hide */ @@ -690,8 +697,8 @@ public class ActivityOptions { case ANIM_SCALE_UP: mStartX = otherOptions.mStartX; mStartY = otherOptions.mStartY; - mStartWidth = otherOptions.mStartWidth; - mStartHeight = otherOptions.mStartHeight; + mWidth = otherOptions.mWidth; + mHeight = otherOptions.mHeight; if (mAnimationStartedListener != null) { try { mAnimationStartedListener.sendResult(null); @@ -707,6 +714,8 @@ public class ActivityOptions { mThumbnail = otherOptions.mThumbnail; mStartX = otherOptions.mStartX; mStartY = otherOptions.mStartY; + mWidth = otherOptions.mWidth; + mHeight = otherOptions.mHeight; if (mAnimationStartedListener != null) { try { mAnimationStartedListener.sendResult(null); @@ -755,8 +764,8 @@ public class ActivityOptions { case ANIM_SCALE_UP: b.putInt(KEY_ANIM_START_X, mStartX); b.putInt(KEY_ANIM_START_Y, mStartY); - b.putInt(KEY_ANIM_START_WIDTH, mStartWidth); - b.putInt(KEY_ANIM_START_HEIGHT, mStartHeight); + b.putInt(KEY_ANIM_WIDTH, mWidth); + b.putInt(KEY_ANIM_HEIGHT, mHeight); break; case ANIM_THUMBNAIL_SCALE_UP: case ANIM_THUMBNAIL_SCALE_DOWN: @@ -765,6 +774,8 @@ public class ActivityOptions { b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail); b.putInt(KEY_ANIM_START_X, mStartX); b.putInt(KEY_ANIM_START_Y, mStartY); + b.putInt(KEY_ANIM_WIDTH, mWidth); + b.putInt(KEY_ANIM_HEIGHT, mHeight); b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener != null ? mAnimationStartedListener.asBinder() : null); break; diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 4f2a3bc..3a39900 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -563,11 +563,11 @@ public final class ActivityThread { } public final void schedulePauseActivity(IBinder token, boolean finished, - boolean userLeaving, int configChanges) { + boolean userLeaving, int configChanges, boolean dontReport) { sendMessage( finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY, token, - (userLeaving ? 1 : 0), + (userLeaving ? 1 : 0) | (dontReport ? 2 : 0), configChanges); } @@ -1283,13 +1283,15 @@ public final class ActivityThread { } break; case PAUSE_ACTIVITY: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause"); - handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2); + handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2, + (msg.arg1&2) != 0); maybeSnapshot(); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; case PAUSE_ACTIVITY_FINISHING: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause"); - handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2); + handlePauseActivity((IBinder)msg.obj, true, (msg.arg1&1) != 0, msg.arg2, + (msg.arg1&1) != 0); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; case STOP_ACTIVITY_SHOW: @@ -3142,7 +3144,7 @@ public final class ActivityThread { } private void handlePauseActivity(IBinder token, boolean finished, - boolean userLeaving, int configChanges) { + boolean userLeaving, int configChanges, boolean dontReport) { ActivityClientRecord r = mActivities.get(token); if (r != null) { //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r); @@ -3159,9 +3161,11 @@ public final class ActivityThread { } // Tell the activity manager we have paused. - try { - ActivityManagerNative.getDefault().activityPaused(token, r.persistentState); - } catch (RemoteException ex) { + if (!dontReport) { + try { + ActivityManagerNative.getDefault().activityPaused(token); + } catch (RemoteException ex) { + } } mSomeActivitiesChanged = true; } @@ -4283,6 +4287,8 @@ public final class ActivityThread { AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } + Message.updateCheckRecycle(data.appInfo.targetSdkVersion); + /* * Before spawning a new process, reset the time zone to be the system time zone. * This needs to be done because the system time zone could have changed after the diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 8b755cc..404268c 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -1693,7 +1693,7 @@ final class ApplicationPackageManager extends PackageManager { if (dr == null) { dr = itemInfo.loadDefaultIcon(this); } - return getUserBadgedDrawableForDensity(dr, new UserHandle(mContext.getUserId()), null, 0); + return getUserBadgedIcon(dr, new UserHandle(mContext.getUserId())); } private Drawable getBadgedDrawable(Drawable drawable, Drawable badgeDrawable, @@ -1759,7 +1759,7 @@ final class ApplicationPackageManager extends PackageManager { } private UserInfo getUserIfProfile(int userHandle) { - List<UserInfo> userProfiles = mUserManager.getProfiles(UserHandle.myUserId()); + List<UserInfo> userProfiles = getUserManager().getProfiles(UserHandle.myUserId()); for (UserInfo user : userProfiles) { if (user.id == userHandle) { return user; diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java index 63e8707..0123e16 100644 --- a/core/java/android/app/ApplicationThreadNative.java +++ b/core/java/android/app/ApplicationThreadNative.java @@ -78,7 +78,8 @@ public abstract class ApplicationThreadNative extends Binder boolean finished = data.readInt() != 0; boolean userLeaving = data.readInt() != 0; int configChanges = data.readInt(); - schedulePauseActivity(b, finished, userLeaving, configChanges); + boolean dontReport = data.readInt() != 0; + schedulePauseActivity(b, finished, userLeaving, configChanges, dontReport); return true; } @@ -689,13 +690,14 @@ class ApplicationThreadProxy implements IApplicationThread { } public final void schedulePauseActivity(IBinder token, boolean finished, - boolean userLeaving, int configChanges) throws RemoteException { + boolean userLeaving, int configChanges, boolean dontReport) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeStrongBinder(token); data.writeInt(finished ? 1 : 0); data.writeInt(userLeaving ? 1 :0); data.writeInt(configChanges); + data.writeInt(dontReport ? 1 : 0); mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 91a0aed..cc5c643 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -2121,7 +2121,9 @@ class ContextImpl extends Context { public Context createPackageContextAsUser(String packageName, int flags, UserHandle user) throws NameNotFoundException { final boolean restricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED; - if (packageName.equals("system") || packageName.equals("android")) { + if ((packageName.equals("system") || packageName.equals("android")) + && user.getIdentifier() == UserHandle.getUserId( + mPackageInfo.getApplicationInfo().uid)) { return new ContextImpl(this, mMainThread, mPackageInfo, mActivityToken, user, restricted, mDisplay, mOverrideConfiguration); } diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 99428e8..9483680 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -111,7 +111,7 @@ public interface IActivityManager extends IInterface { public void activityResumed(IBinder token) throws RemoteException; public void activityIdle(IBinder token, Configuration config, boolean stopProfiling) throws RemoteException; - public void activityPaused(IBinder token, PersistableBundle persistentState) throws RemoteException; + public void activityPaused(IBinder token) throws RemoteException; public void activityStopped(IBinder token, Bundle state, PersistableBundle persistentState, CharSequence description) throws RemoteException; public void activitySlept(IBinder token) throws RemoteException; diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java index a7546d9..f53075c 100644 --- a/core/java/android/app/IApplicationThread.java +++ b/core/java/android/app/IApplicationThread.java @@ -49,7 +49,7 @@ import java.util.Map; */ public interface IApplicationThread extends IInterface { void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving, - int configChanges) throws RemoteException; + int configChanges, boolean dontReport) throws RemoteException; void scheduleStopActivity(IBinder token, boolean showWindow, int configChanges) throws RemoteException; void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException; diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java index e055237..cc9aed8 100644 --- a/core/java/android/app/KeyguardManager.java +++ b/core/java/android/app/KeyguardManager.java @@ -56,13 +56,6 @@ public class KeyguardManager { public static final String EXTRA_DESCRIPTION = "android.app.extra.DESCRIPTION"; /** - * @removed - */ - public Intent getConfirmDeviceCredentialIntent(CharSequence title, CharSequence description) { - return createConfirmDeviceCredentialIntent(title, description); - } - - /** * Get an intent to prompt the user to confirm credentials (pin, pattern or password) * for the current user of the device. The caller is expected to launch this activity using * {@link android.app.Activity#startActivityForResult(Intent, int)} and check for diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 112fc82..926a348 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -441,13 +441,13 @@ public class DevicePolicyManager { * Flag used by {@link #addCrossProfileIntentFilter} to allow access of certain intents from a * managed profile to its parent. */ - public static int FLAG_PARENT_CAN_ACCESS_MANAGED = 0x0001; + public static final int FLAG_PARENT_CAN_ACCESS_MANAGED = 0x0001; /** * Flag used by {@link #addCrossProfileIntentFilter} to allow access of certain intents from the * parent to its managed profile. */ - public static int FLAG_MANAGED_CAN_ACCESS_PARENT = 0x0002; + public static final int FLAG_MANAGED_CAN_ACCESS_PARENT = 0x0002; /** * Return true if the given administrator component is currently diff --git a/core/java/android/bluetooth/le/AdvertiseData.java b/core/java/android/bluetooth/le/AdvertiseData.java index c7bfae9..ff0db9a 100644 --- a/core/java/android/bluetooth/le/AdvertiseData.java +++ b/core/java/android/bluetooth/le/AdvertiseData.java @@ -119,8 +119,8 @@ public final class AdvertiseData implements Parcelable { } AdvertiseData other = (AdvertiseData) obj; return Objects.equals(mServiceUuids, other.mServiceUuids) && - Utils.equals(mManufacturerSpecificData, other.mManufacturerSpecificData) && - Utils.equals(mServiceData, other.mServiceData) && + BluetoothLeUtils.equals(mManufacturerSpecificData, other.mManufacturerSpecificData) && + BluetoothLeUtils.equals(mServiceData, other.mServiceData) && mIncludeDeviceName == other.mIncludeDeviceName && mIncludeTxPowerLevel == other.mIncludeTxPowerLevel; } @@ -128,8 +128,8 @@ public final class AdvertiseData implements Parcelable { @Override public String toString() { return "AdvertiseData [mServiceUuids=" + mServiceUuids + ", mManufacturerSpecificData=" - + Utils.toString(mManufacturerSpecificData) + ", mServiceData=" - + Utils.toString(mServiceData) + + BluetoothLeUtils.toString(mManufacturerSpecificData) + ", mServiceData=" + + BluetoothLeUtils.toString(mServiceData) + ", mIncludeTxPowerLevel=" + mIncludeTxPowerLevel + ", mIncludeDeviceName=" + mIncludeDeviceName + "]"; } diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java index 3568f26..d468508 100644 --- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java +++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java @@ -107,7 +107,7 @@ public final class BluetoothLeAdvertiser { AdvertiseData advertiseData, AdvertiseData scanResponse, final AdvertiseCallback callback) { synchronized (mLeAdvertisers) { - checkAdapterState(); + BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter); if (callback == null) { throw new IllegalArgumentException("callback cannot be null"); } @@ -150,7 +150,7 @@ public final class BluetoothLeAdvertiser { */ public void stopAdvertising(final AdvertiseCallback callback) { synchronized (mLeAdvertisers) { - checkAdapterState(); + BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter); if (callback == null) { throw new IllegalArgumentException("callback cannot be null"); } @@ -265,9 +265,18 @@ public final class BluetoothLeAdvertiser { } if (mClientIf > 0 && mIsAdvertising) { mLeAdvertisers.put(mAdvertiseCallback, this); - } else { + } else if (mClientIf <= 0) { + // Post internal error if registration failed. postStartFailure(mAdvertiseCallback, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR); + } else { + // Unregister application if it's already registered but advertise failed. + try { + mBluetoothGatt.unregisterClient(mClientIf); + mClientIf = -1; + } catch (RemoteException e) { + Log.e(TAG, "remote exception when unregistering", e); + } } } } @@ -342,13 +351,6 @@ public final class BluetoothLeAdvertiser { } } - // TODO: move this api to a common util class. - private void checkAdapterState() { - if (mBluetoothAdapter.getState() != mBluetoothAdapter.STATE_ON) { - throw new IllegalStateException("BT Adapter is not turned ON"); - } - } - private void postStartFailure(final AdvertiseCallback callback, final int error) { mHandler.post(new Runnable() { @Override diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java index e1d4bbd2..a57c3ca 100644 --- a/core/java/android/bluetooth/le/BluetoothLeScanner.java +++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java @@ -80,11 +80,10 @@ public final class BluetoothLeScanner { * @throws IllegalArgumentException If {@code callback} is null. */ public void startScan(final ScanCallback callback) { - checkAdapterState(); if (callback == null) { throw new IllegalArgumentException("callback is null"); } - this.startScan(null, new ScanSettings.Builder().build(), callback); + startScan(null, new ScanSettings.Builder().build(), callback); } /** @@ -104,7 +103,7 @@ public final class BluetoothLeScanner { private void startScan(List<ScanFilter> filters, ScanSettings settings, final ScanCallback callback, List<List<ResultStorageDescriptor>> resultStorages) { - checkAdapterState(); + BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter); if (settings == null || callback == null) { throw new IllegalArgumentException("settings or callback is null"); } @@ -142,7 +141,7 @@ public final class BluetoothLeScanner { * @param callback */ public void stopScan(ScanCallback callback) { - checkAdapterState(); + BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter); synchronized (mLeScanClients) { BleScanCallbackWrapper wrapper = mLeScanClients.remove(callback); if (wrapper == null) { @@ -162,7 +161,7 @@ public final class BluetoothLeScanner { * used to start scan. */ public void flushPendingScanResults(ScanCallback callback) { - checkAdapterState(); + BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter); if (callback == null) { throw new IllegalArgumentException("callback cannot be null!"); } @@ -373,13 +372,6 @@ public final class BluetoothLeScanner { } } - // TODO: move this api to a common util class. - private void checkAdapterState() { - if (mBluetoothAdapter.getState() != mBluetoothAdapter.STATE_ON) { - throw new IllegalStateException("BT Adapter is not turned ON"); - } - } - private void postCallbackError(final ScanCallback callback, final int errorCode) { mHandler.post(new Runnable() { @Override diff --git a/core/java/android/bluetooth/le/Utils.java b/core/java/android/bluetooth/le/BluetoothLeUtils.java index ccdae69..4916bd9 100644 --- a/core/java/android/bluetooth/le/Utils.java +++ b/core/java/android/bluetooth/le/BluetoothLeUtils.java @@ -16,6 +16,7 @@ package android.bluetooth.le; +import android.bluetooth.BluetoothAdapter; import android.util.SparseArray; import java.util.Arrays; @@ -29,7 +30,7 @@ import java.util.Set; * * @hide */ -public class Utils { +public class BluetoothLeUtils { /** * Returns a string composed from a {@link SparseArray}. @@ -123,4 +124,17 @@ public class Utils { } return true; } + + /** + * Ensure Bluetooth is turned on. + * + * @throws IllegalStateException If {@code adapter} is null or Bluetooth state is not + * {@link BluetoothAdapter#STATE_ON}. + */ + static void checkAdapterStateOn(BluetoothAdapter adapter) { + if (adapter == null || adapter.getState() != BluetoothAdapter.STATE_ON) { + throw new IllegalStateException("BT Adapter is not turned ON"); + } + } + } diff --git a/core/java/android/bluetooth/le/ScanRecord.java b/core/java/android/bluetooth/le/ScanRecord.java index 2f3d06f..f802e8d 100644 --- a/core/java/android/bluetooth/le/ScanRecord.java +++ b/core/java/android/bluetooth/le/ScanRecord.java @@ -268,8 +268,8 @@ public final class ScanRecord { @Override public String toString() { return "ScanRecord [mAdvertiseFlags=" + mAdvertiseFlags + ", mServiceUuids=" + mServiceUuids - + ", mManufacturerSpecificData=" + Utils.toString(mManufacturerSpecificData) - + ", mServiceData=" + Utils.toString(mServiceData) + + ", mManufacturerSpecificData=" + BluetoothLeUtils.toString(mManufacturerSpecificData) + + ", mServiceData=" + BluetoothLeUtils.toString(mServiceData) + ", mTxPowerLevel=" + mTxPowerLevel + ", mDeviceName=" + mDeviceName + "]"; } diff --git a/core/java/android/content/IRestrictionsManager.aidl b/core/java/android/content/IRestrictionsManager.aidl index 495ac2e..db9146f 100644 --- a/core/java/android/content/IRestrictionsManager.aidl +++ b/core/java/android/content/IRestrictionsManager.aidl @@ -30,5 +30,5 @@ interface IRestrictionsManager { void requestPermission(in String packageName, in String requestType, in String requestId, in PersistableBundle requestData); void notifyPermissionResponse(in String packageName, in PersistableBundle response); - Intent getLocalApprovalIntent(); + Intent createLocalApprovalIntent(); } diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 51a58d1..ff9f6ab 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -1213,6 +1213,13 @@ public class Intent implements Parcelable, Cloneable { = "android.intent.extra.ASSIST_CONTEXT"; /** + * An optional field on {@link #ACTION_ASSIST} suggesting that the user will likely use a + * keyboard as the primary input device for assistance. + */ + public static final String EXTRA_ASSIST_INPUT_HINT_KEYBOARD = + "android.intent.extra.ASSIST_INPUT_HINT_KEYBOARD"; + + /** * Activity Action: List all available applications * <p>Input: Nothing. * <p>Output: nothing. diff --git a/core/java/android/content/RestrictionsManager.java b/core/java/android/content/RestrictionsManager.java index 849df55..21a6a0d 100644 --- a/core/java/android/content/RestrictionsManager.java +++ b/core/java/android/content/RestrictionsManager.java @@ -155,7 +155,7 @@ public class RestrictionsManager { * The intent must contain {@link #EXTRA_REQUEST_BUNDLE} as an extra and the bundle must * contain at least {@link #REQUEST_KEY_MESSAGE} for the activity to display. * <p> - * @see #getLocalApprovalIntent() + * @see #createLocalApprovalIntent() */ public static final String ACTION_REQUEST_LOCAL_APPROVAL = "android.content.action.REQUEST_LOCAL_APPROVAL"; @@ -473,10 +473,10 @@ public class RestrictionsManager { } } - public Intent getLocalApprovalIntent() { + public Intent createLocalApprovalIntent() { try { if (mService != null) { - return mService.getLocalApprovalIntent(); + return mService.createLocalApprovalIntent(); } } catch (RemoteException re) { Log.w(TAG, "Couldn't reach service"); diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index dbf49c5..8d3126d 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -255,16 +255,22 @@ public class ActivityInfo extends ComponentInfo * Bit in {@link #flags}: If set, a task rooted at this activity will have its * baseIntent replaced by the activity immediately above this. Each activity may further * relinquish its identity to the activity above it using this flag. Set from the - * android.R.attr#relinquishTaskIdentity attribute. + * {@link android.R.attr#relinquishTaskIdentity} attribute. */ public static final int FLAG_RELINQUISH_TASK_IDENTITY = 0x1000; /** * Bit in {@link #flags} indicating that tasks started with this activity are to be * removed from the recent list of tasks when the last activity in the task is finished. - * {@link android.R.attr#autoRemoveFromRecents} + * Corresponds to {@link android.R.attr#autoRemoveFromRecents} */ public static final int FLAG_AUTO_REMOVE_FROM_RECENTS = 0x2000; /** + * Bit in {@link #flags} indicating that this activity can start is creation/resume + * while the previous activity is still pausing. Corresponds to + * {@link android.R.attr#resumeWhilePausing} + */ + public static final int FLAG_RESUME_WHILE_PAUSING = 0x4000; + /** * @hide Bit in {@link #flags}: If set, this component will only be seen * by the primary user. Only works with broadcast receivers. Set from the * android.R.attr#primaryUserOnly attribute. diff --git a/core/java/android/content/pm/IPackageInstallerCallback.aidl b/core/java/android/content/pm/IPackageInstallerCallback.aidl index fe98ee7..974eb1e 100644 --- a/core/java/android/content/pm/IPackageInstallerCallback.aidl +++ b/core/java/android/content/pm/IPackageInstallerCallback.aidl @@ -20,8 +20,7 @@ package android.content.pm; oneway interface IPackageInstallerCallback { void onSessionCreated(int sessionId); void onSessionBadgingChanged(int sessionId); - void onSessionOpened(int sessionId); + void onSessionActiveChanged(int sessionId, boolean active); void onSessionProgressChanged(int sessionId, float progress); - void onSessionClosed(int sessionId); void onSessionFinished(int sessionId, boolean success); } diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 7c34a65..06d4c4a 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -285,6 +285,9 @@ public class PackageInstaller { * * @throws IOException if parameters were unsatisfiable, such as lack of * disk space or unavailable media. + * @throws SecurityException when installation services are unavailable, + * such as when called from a restricted user. + * @throws IllegalArgumentException when {@link SessionParams} is invalid. * @return positive, non-zero unique ID that represents the created session. * This ID remains consistent across device reboots until the * session is finalized. IDs are not reused during a given boot. @@ -303,10 +306,18 @@ public class PackageInstaller { /** * Open an existing session to actively perform work. To succeed, the caller * must be the owner of the install session. + * + * @throws IOException if parameters were unsatisfiable, such as lack of + * disk space or unavailable media. + * @throws SecurityException when the caller does not own the session, or + * the session is invalid. */ - public @NonNull Session openSession(int sessionId) { + public @NonNull Session openSession(int sessionId) throws IOException { try { return new Session(mInstaller.openSession(sessionId)); + } catch (RuntimeException e) { + ExceptionUtils.maybeUnwrapIOException(e); + throw e; } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -316,6 +327,9 @@ public class PackageInstaller { * Update the icon representing the app being installed in a specific * session. This should be roughly * {@link ActivityManager#getLauncherLargeIconSize()} in both dimensions. + * + * @throws SecurityException when the caller does not own the session, or + * the session is invalid. */ public void updateSessionAppIcon(int sessionId, @Nullable Bitmap appIcon) { try { @@ -328,6 +342,9 @@ public class PackageInstaller { /** * Update the label representing the app being installed in a specific * session. + * + * @throws SecurityException when the caller does not own the session, or + * the session is invalid. */ public void updateSessionAppLabel(int sessionId, @Nullable CharSequence appLabel) { try { @@ -338,6 +355,15 @@ public class PackageInstaller { } } + /** + * Completely abandon the given session, destroying all staged data and + * rendering it invalid. Abandoned sessions will be reported to + * {@link SessionCallback} listeners as failures. This is equivalent to + * opening the session and calling {@link Session#abandon()}. + * + * @throws SecurityException when the caller does not own the session, or + * the session is invalid. + */ public void abandonSession(int sessionId) { try { mInstaller.abandonSession(sessionId); @@ -347,7 +373,11 @@ public class PackageInstaller { } /** - * Return details for a specific session. + * Return details for a specific session. No special permissions are + * required to retrieve these details. + * + * @return details for the requested session, or {@code null} if the session + * does not exist. */ public @Nullable SessionInfo getSessionInfo(int sessionId) { try { @@ -358,12 +388,12 @@ public class PackageInstaller { } /** - * Return list of all active install sessions, regardless of the installer. + * Return list of all known install sessions, regardless of the installer. */ public @NonNull List<SessionInfo> getAllSessions() { final ApplicationInfo info = mContext.getApplicationInfo(); if ("com.google.android.googlequicksearchbox".equals(info.packageName) - && info.versionCode <= 300400070) { + && info.versionCode <= 300400110) { Log.d(TAG, "Ignoring callback request from old prebuilt"); return Collections.EMPTY_LIST; } @@ -376,7 +406,7 @@ public class PackageInstaller { } /** - * Return list of all install sessions owned by the calling app. + * Return list of all known install sessions owned by the calling app. */ public @NonNull List<SessionInfo> getMySessions() { try { @@ -436,27 +466,32 @@ public class PackageInstaller { public abstract void onBadgingChanged(int sessionId); /** - * Session has been opened. A session is usually opened when the - * installer is actively writing data. + * Active state for session has been changed. + * <p> + * A session is considered active whenever there is ongoing forward + * progress being made, such as the installer holding an open + * {@link Session} instance while streaming data into place, or the + * system optimizing code as the result of + * {@link Session#commit(IntentSender)}. + * <p> + * If the installer closes the {@link Session} without committing, the + * session is considered inactive until the installer opens the session + * again. */ - public abstract void onOpened(int sessionId); + public abstract void onActiveChanged(int sessionId, boolean active); /** * Progress for given session has been updated. * <p> * Note that this progress may not directly correspond to the value - * reported by {@link PackageInstaller.Session#setProgress(float)}, as - * the system may carve out a portion of the overall progress to - * represent its own internal installation work. + * reported by + * {@link PackageInstaller.Session#setStagingProgress(float)}, as the + * system may carve out a portion of the overall progress to represent + * its own internal installation work. */ public abstract void onProgressChanged(int sessionId, float progress); /** - * Session has been closed. - */ - public abstract void onClosed(int sessionId); - - /** * Session has completely finished, either with success or failure. */ public abstract void onFinished(int sessionId, boolean success); @@ -467,10 +502,9 @@ public class PackageInstaller { Handler.Callback { private static final int MSG_SESSION_CREATED = 1; private static final int MSG_SESSION_BADGING_CHANGED = 2; - private static final int MSG_SESSION_OPENED = 3; + private static final int MSG_SESSION_ACTIVE_CHANGED = 3; private static final int MSG_SESSION_PROGRESS_CHANGED = 4; - private static final int MSG_SESSION_CLOSED = 5; - private static final int MSG_SESSION_FINISHED = 6; + private static final int MSG_SESSION_FINISHED = 5; final SessionCallback mCallback; final Handler mHandler; @@ -482,24 +516,23 @@ public class PackageInstaller { @Override public boolean handleMessage(Message msg) { + final int sessionId = msg.arg1; switch (msg.what) { case MSG_SESSION_CREATED: - mCallback.onCreated(msg.arg1); + mCallback.onCreated(sessionId); return true; case MSG_SESSION_BADGING_CHANGED: - mCallback.onBadgingChanged(msg.arg1); + mCallback.onBadgingChanged(sessionId); return true; - case MSG_SESSION_OPENED: - mCallback.onOpened(msg.arg1); + case MSG_SESSION_ACTIVE_CHANGED: + final boolean active = msg.arg2 != 0; + mCallback.onActiveChanged(sessionId, active); return true; case MSG_SESSION_PROGRESS_CHANGED: - mCallback.onProgressChanged(msg.arg1, (float) msg.obj); - return true; - case MSG_SESSION_CLOSED: - mCallback.onClosed(msg.arg1); + mCallback.onProgressChanged(sessionId, (float) msg.obj); return true; case MSG_SESSION_FINISHED: - mCallback.onFinished(msg.arg1, msg.arg2 != 0); + mCallback.onFinished(sessionId, msg.arg2 != 0); return true; } return false; @@ -516,8 +549,9 @@ public class PackageInstaller { } @Override - public void onSessionOpened(int sessionId) { - mHandler.obtainMessage(MSG_SESSION_OPENED, sessionId, 0).sendToTarget(); + public void onSessionActiveChanged(int sessionId, boolean active) { + mHandler.obtainMessage(MSG_SESSION_ACTIVE_CHANGED, sessionId, active ? 1 : 0) + .sendToTarget(); } @Override @@ -527,11 +561,6 @@ public class PackageInstaller { } @Override - public void onSessionClosed(int sessionId) { - mHandler.obtainMessage(MSG_SESSION_CLOSED, sessionId, 0).sendToTarget(); - } - - @Override public void onSessionFinished(int sessionId, boolean success) { mHandler.obtainMessage(MSG_SESSION_FINISHED, sessionId, success ? 1 : 0) .sendToTarget(); @@ -545,7 +574,8 @@ public class PackageInstaller { } /** - * Register to watch for session lifecycle events. + * Register to watch for session lifecycle events. No special permissions + * are required to watch for these events. */ public void registerSessionCallback(@NonNull SessionCallback callback) { registerSessionCallback(callback, new Handler()); @@ -558,7 +588,8 @@ public class PackageInstaller { } /** - * Register to watch for session lifecycle events. + * Register to watch for session lifecycle events. No special permissions + * are required to watch for these events. * * @param handler to dispatch callback events through, otherwise uses * calling thread. @@ -567,7 +598,7 @@ public class PackageInstaller { // TODO: remove this temporary guard once we have new prebuilts final ApplicationInfo info = mContext.getApplicationInfo(); if ("com.google.android.googlequicksearchbox".equals(info.packageName) - && info.versionCode <= 300400070) { + && info.versionCode <= 300400110) { Log.d(TAG, "Ignoring callback request from old prebuilt"); return; } @@ -591,7 +622,7 @@ public class PackageInstaller { } /** - * Unregister an existing callback. + * Unregister a previously registered callback. */ public void unregisterSessionCallback(@NonNull SessionCallback callback) { synchronized (mDelegates) { @@ -629,10 +660,22 @@ public class PackageInstaller { mSession = session; } + /** {@hide} */ + @Deprecated + public void setProgress(float progress) { + setStagingProgress(progress); + } + /** - * Set current progress. Valid values are anywhere between 0 and 1. + * Set current progress of staging this session. Valid values are + * anywhere between 0 and 1. + * <p> + * Note that this progress may not directly correspond to the value + * reported by {@link SessionCallback#onProgressChanged(int, float)}, as + * the system may carve out a portion of the overall progress to + * represent its own internal installation work. */ - public void setProgress(float progress) { + public void setStagingProgress(float progress) { try { mSession.setClientProgress(progress); } catch (RemoteException e) { @@ -672,6 +715,12 @@ public class PackageInstaller { * start at the beginning of the file. * @param lengthBytes total size of the file being written, used to * preallocate the underlying disk space, or -1 if unknown. + * The system may clear various caches as needed to allocate + * this space. + * @throws IOException if trouble opening the file for writing, such as + * lack of disk space or unavailable media. + * @throws SecurityException if called after the session has been + * committed or abandoned. */ public @NonNull OutputStream openWrite(@NonNull String name, long offsetBytes, long lengthBytes) throws IOException { @@ -705,6 +754,9 @@ public class PackageInstaller { * <p> * This returns all names which have been previously written through * {@link #openWrite(String, long, long)} as part of this session. + * + * @throws SecurityException if called after the session has been + * committed or abandoned. */ public @NonNull String[] getNames() throws IOException { try { @@ -724,6 +776,9 @@ public class PackageInstaller { * through {@link #openWrite(String, long, long)} as part of this * session. For example, this stream may be used to calculate a * {@link MessageDigest} of a written APK before committing. + * + * @throws SecurityException if called after the session has been + * committed or abandoned. */ public @NonNull InputStream openRead(@NonNull String name) throws IOException { try { @@ -745,6 +800,9 @@ public class PackageInstaller { * Once this method is called, no additional mutations may be performed * on the session. If the device reboots before the session has been * finalized, you may commit the session again. + * + * @throws SecurityException if streams opened through + * {@link #openWrite(String, long, long)} are still open. */ public void commit(@NonNull IntentSender statusReceiver) { try { @@ -769,7 +827,9 @@ public class PackageInstaller { /** * Completely abandon this session, destroying all staged data and - * rendering it invalid. + * rendering it invalid. Abandoned sessions will be reported to + * {@link SessionCallback} listeners as failures. This is equivalent to + * opening the session and calling {@link Session#abandon()}. */ public void abandon() { try { @@ -923,6 +983,18 @@ public class PackageInstaller { } /** {@hide} */ + public void setInstallFlagsInternal() { + installFlags |= PackageManager.INSTALL_INTERNAL; + installFlags &= ~PackageManager.INSTALL_EXTERNAL; + } + + /** {@hide} */ + public void setInstallFlagsExternal() { + installFlags |= PackageManager.INSTALL_EXTERNAL; + installFlags &= ~PackageManager.INSTALL_INTERNAL; + } + + /** {@hide} */ public void dump(IndentingPrintWriter pw) { pw.printPair("mode", mode); pw.printHexPair("installFlags", installFlags); @@ -986,7 +1058,7 @@ public class PackageInstaller { /** {@hide} */ public boolean sealed; /** {@hide} */ - public boolean open; + public boolean active; /** {@hide} */ public int mode; @@ -1010,7 +1082,7 @@ public class PackageInstaller { resolvedBaseCodePath = source.readString(); progress = source.readFloat(); sealed = source.readInt() != 0; - open = source.readInt() != 0; + active = source.readInt() != 0; mode = source.readInt(); sizeBytes = source.readLong(); @@ -1036,20 +1108,37 @@ public class PackageInstaller { /** * Return current overall progress of this session, between 0 and 1. * <p> - * Note that this progress may not directly correspond to the value reported - * by {@link PackageInstaller.Session#setProgress(float)}, as the system may - * carve out a portion of the overall progress to represent its own internal - * installation work. + * Note that this progress may not directly correspond to the value + * reported by + * {@link PackageInstaller.Session#setStagingProgress(float)}, as the + * system may carve out a portion of the overall progress to represent + * its own internal installation work. */ public float getProgress() { return progress; } /** - * Return if this session is currently open. + * Return if this session is currently active. + * <p> + * A session is considered active whenever there is ongoing forward + * progress being made, such as the installer holding an open + * {@link Session} instance while streaming data into place, or the + * system optimizing code as the result of + * {@link Session#commit(IntentSender)}. + * <p> + * If the installer closes the {@link Session} without committing, the + * session is considered inactive until the installer opens the session + * again. */ + public boolean isActive() { + return active; + } + + /** {@hide} */ + @Deprecated public boolean isOpen() { - return open; + return isActive(); } /** @@ -1105,7 +1194,7 @@ public class PackageInstaller { dest.writeString(resolvedBaseCodePath); dest.writeFloat(progress); dest.writeInt(sealed ? 1 : 0); - dest.writeInt(open ? 1 : 0); + dest.writeInt(active ? 1 : 0); dest.writeInt(mode); dest.writeLong(sizeBytes); diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index e87adda..748fca2 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -976,6 +976,14 @@ public abstract class PackageManager { /** * Feature for {@link #getSystemAvailableFeatures} and + * {@link #hasSystemFeature}: The device includes at least one form of audio + * output, such as speakers, audio jack or streaming over bluetooth + */ + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output"; + + /** + * Feature for {@link #getSystemAvailableFeatures} and * {@link #hasSystemFeature}: The device is capable of communicating with * other devices via Bluetooth. */ diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 6d40dcf..e0fd532 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -3110,6 +3110,12 @@ public class PackageParser { false)) { a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY; } + + if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestActivity_resumeWhilePausing, + false)) { + a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING; + } } else { a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE; a.info.configChanges = 0; diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java index 2684e6c..e578822 100644 --- a/core/java/android/content/res/AssetManager.java +++ b/core/java/android/content/res/AssetManager.java @@ -773,6 +773,7 @@ public final class AssetManager implements AutoCloseable { private native final String[] getArrayStringResource(int arrayRes); private native final int[] getArrayStringInfo(int arrayRes); /*package*/ native final int[] getArrayIntResource(int arrayRes); + /*package*/ native final int[] getStyleAttributes(int themeRes); private native final void init(boolean isSystem); private native final void destroy(); diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 31813c1..cabe228 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -1572,6 +1572,16 @@ public class Resources { } /** + * Gets all of the attribute ids associated with this {@link Theme}. For debugging only. + * + * @return The int array containing attribute ids associated with this {@link Theme}. + * @hide + */ + public int[] getAllAttributes() { + return mAssets.getStyleAttributes(getAppliedStyleResId()); + } + + /** * Returns the resources to which this theme belongs. * * @return Resources to which this theme belongs. diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java index b52a0c5..f514e42 100644 --- a/core/java/android/hardware/Sensor.java +++ b/core/java/android/hardware/Sensor.java @@ -737,12 +737,11 @@ public final class Sensor { } /** - * This value is defined only for continuous mode sensors. It is the delay between two - * sensor events corresponding to the lowest frequency that this sensor supports. When - * lower frequencies are requested through registerListener() the events will be generated - * at this frequency instead. It can be used to estimate when the batch FIFO may be full. - * Older devices may set this value to zero. Ignore this value in case it is negative - * or zero. + * This value is defined only for continuous and on-change sensors. It is the delay between two + * sensor events corresponding to the lowest frequency that this sensor supports. When lower + * frequencies are requested through registerListener() the events will be generated at this + * frequency instead. It can be used to estimate when the batch FIFO may be full. Older devices + * may set this value to zero. Ignore this value in case it is negative or zero. * * @return The max delay for this sensor in microseconds. */ diff --git a/core/java/android/hardware/camera2/CameraAccessException.java b/core/java/android/hardware/camera2/CameraAccessException.java index ca71e81..91ef6ca 100644 --- a/core/java/android/hardware/camera2/CameraAccessException.java +++ b/core/java/android/hardware/camera2/CameraAccessException.java @@ -61,7 +61,7 @@ public class CameraAccessException extends AndroidException { * * <p>The camera has failed to open or has failed at a later time * as a result of some non-user interaction. Refer to - * {@link CameraDevice.StateListener#onError} for the exact + * {@link CameraDevice.StateCallback#onError} for the exact * nature of the error.</p> * * <p>No further calls to the camera will succeed. Clean up diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java index fc2141f..29e42ea 100644 --- a/core/java/android/hardware/camera2/CameraCaptureSession.java +++ b/core/java/android/hardware/camera2/CameraCaptureSession.java @@ -32,18 +32,18 @@ import java.util.List; * sending images to the desired targets. Therefore the setup is done asynchronously, and * {@link CameraDevice#createCaptureSession createCaptureSession} will send the ready-to-use * CameraCaptureSession to the provided listener's - * {@link CameraCaptureSession.StateListener#onConfigured onConfigured} callback. If configuration + * {@link CameraCaptureSession.StateCallback#onConfigured onConfigured} callback. If configuration * cannot be completed, then the - * {@link CameraCaptureSession.StateListener#onConfigureFailed onConfigureFailed} is called, and the + * {@link CameraCaptureSession.StateCallback#onConfigureFailed onConfigureFailed} is called, and the * session will not become active.</p> *<!-- * <p>Any capture requests (repeating or non-repeating) submitted before the session is ready will * be queued up and will begin capture once the session becomes ready. In case the session cannot be - * configured and {@link StateListener#onConfigureFailed onConfigureFailed} is called, all queued + * configured and {@link StateCallback#onConfigureFailed onConfigureFailed} is called, all queued * capture requests are discarded.</p> *--> * <p>If a new session is created by the camera device, then the previous session is closed, and its - * associated {@link StateListener#onClosed onClosed} callback will be invoked. All + * associated {@link StateCallback#onClosed onClosed} callback will be invoked. All * of the session methods will throw an IllegalStateException if called once the session is * closed.</p> * @@ -86,7 +86,7 @@ public abstract class CameraCaptureSession implements AutoCloseable { * looper}. * * @return int A unique capture sequence ID used by - * {@link CaptureListener#onCaptureSequenceCompleted}. + * {@link CaptureCallback#onCaptureSequenceCompleted}. * * @throws CameraAccessException if the camera device is no longer connected or has * encountered a fatal error @@ -103,7 +103,7 @@ public abstract class CameraCaptureSession implements AutoCloseable { * @see #setRepeatingBurst * @see #abortCaptures */ - public abstract int capture(CaptureRequest request, CaptureListener listener, Handler handler) + public abstract int capture(CaptureRequest request, CaptureCallback listener, Handler handler) throws CameraAccessException; /** @@ -131,7 +131,7 @@ public abstract class CameraCaptureSession implements AutoCloseable { * looper}. * * @return int A unique capture sequence ID used by - * {@link CaptureListener#onCaptureSequenceCompleted}. + * {@link CaptureCallback#onCaptureSequenceCompleted}. * * @throws CameraAccessException if the camera device is no longer connected or has * encountered a fatal error @@ -147,7 +147,7 @@ public abstract class CameraCaptureSession implements AutoCloseable { * @see #setRepeatingBurst * @see #abortCaptures */ - public abstract int captureBurst(List<CaptureRequest> requests, CaptureListener listener, + public abstract int captureBurst(List<CaptureRequest> requests, CaptureCallback listener, Handler handler) throws CameraAccessException; /** @@ -185,7 +185,7 @@ public abstract class CameraCaptureSession implements AutoCloseable { * looper}. * * @return int A unique capture sequence ID used by - * {@link CaptureListener#onCaptureSequenceCompleted}. + * {@link CaptureCallback#onCaptureSequenceCompleted}. * * @throws CameraAccessException if the camera device is no longer connected or has * encountered a fatal error @@ -203,7 +203,7 @@ public abstract class CameraCaptureSession implements AutoCloseable { * @see #stopRepeating * @see #abortCaptures */ - public abstract int setRepeatingRequest(CaptureRequest request, CaptureListener listener, + public abstract int setRepeatingRequest(CaptureRequest request, CaptureCallback listener, Handler handler) throws CameraAccessException; /** @@ -245,7 +245,7 @@ public abstract class CameraCaptureSession implements AutoCloseable { * looper}. * * @return int A unique capture sequence ID used by - * {@link CaptureListener#onCaptureSequenceCompleted}. + * {@link CaptureCallback#onCaptureSequenceCompleted}. * * @throws CameraAccessException if the camera device is no longer connected or has * encountered a fatal error @@ -263,7 +263,7 @@ public abstract class CameraCaptureSession implements AutoCloseable { * @see #stopRepeating * @see #abortCaptures */ - public abstract int setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener, + public abstract int setRepeatingBurst(List<CaptureRequest> requests, CaptureCallback listener, Handler handler) throws CameraAccessException; /** @@ -274,7 +274,7 @@ public abstract class CameraCaptureSession implements AutoCloseable { * * <p>Any currently in-flight captures will still complete, as will any burst that is * mid-capture. To ensure that the device has finished processing all of its capture requests - * and is in ready state, wait for the {@link StateListener#onReady} callback after + * and is in ready state, wait for the {@link StateCallback#onReady} callback after * calling this method.</p> * * @throws CameraAccessException if the camera device is no longer connected or has @@ -285,7 +285,7 @@ public abstract class CameraCaptureSession implements AutoCloseable { * * @see #setRepeatingRequest * @see #setRepeatingBurst - * @see StateListener#onIdle + * @see StateCallback#onIdle */ public abstract void stopRepeating() throws CameraAccessException; @@ -293,15 +293,15 @@ public abstract class CameraCaptureSession implements AutoCloseable { * Discard all captures currently pending and in-progress as fast as possible. * * <p>The camera device will discard all of its current work as fast as possible. Some in-flight - * captures may complete successfully and call {@link CaptureListener#onCaptureCompleted}, while - * others will trigger their {@link CaptureListener#onCaptureFailed} callbacks. If a repeating + * captures may complete successfully and call {@link CaptureCallback#onCaptureCompleted}, while + * others will trigger their {@link CaptureCallback#onCaptureFailed} callbacks. If a repeating * request or a repeating burst is set, it will be cleared.</p> * * <p>This method is the fastest way to switch the camera device to a new session with * {@link CameraDevice#createCaptureSession}, at the cost of discarding in-progress work. It * must be called before the new session is created. Once all pending requests are either - * completed or thrown away, the {@link StateListener#onReady} callback will be called, - * if the session has not been closed. Otherwise, the {@link StateListener#onClosed} + * completed or thrown away, the {@link StateCallback#onReady} callback will be called, + * if the session has not been closed. Otherwise, the {@link StateCallback#onClosed} * callback will be fired when a new session is created by the camera device.</p> * * <p>Cancelling will introduce at least a brief pause in the stream of data from the camera @@ -332,7 +332,7 @@ public abstract class CameraCaptureSession implements AutoCloseable { * * <p>Note that creating a new capture session with {@link CameraDevice#createCaptureSession} * will close any existing capture session automatically, and call the older session listener's - * {@link StateListener#onClosed} callback. Using {@link CameraDevice#createCaptureSession} + * {@link StateCallback#onClosed} callback. Using {@link CameraDevice#createCaptureSession} * directly without closing is the recommended approach for quickly switching to a new session, * since unchanged target outputs can be reused more efficiently.</p> * @@ -340,7 +340,7 @@ public abstract class CameraCaptureSession implements AutoCloseable { * repeating requests or bursts are stopped (as if {@link #stopRepeating()} was called). * However, any in-progress capture requests submitted to the session will be completed as * normal; once all captures have completed and the session has been torn down, - * {@link StateListener#onClosed} will be called.</p> + * {@link StateCallback#onClosed} will be called.</p> * * <p>Closing a session is idempotent; closing more than once has no effect.</p> */ @@ -348,10 +348,10 @@ public abstract class CameraCaptureSession implements AutoCloseable { public abstract void close(); /** - * A listener for tracking the state of a camera capture session. + * A callback object for receiving updates about the state of a camera capture session. * */ - public static abstract class StateListener { + public static abstract class StateCallback { /** * This method is called when the camera device has finished configuring itself, and the @@ -439,10 +439,17 @@ public abstract class CameraCaptureSession implements AutoCloseable { } /** - * <p>A listener for tracking the progress of a {@link CaptureRequest} - * submitted to the camera device.</p> + * Temporary for migrating to Callback naming + * @hide + */ + public static abstract class StateListener extends StateCallback { + } + + /** + * <p>A callback object for tracking the progress of a {@link CaptureRequest} submitted to the + * camera device.</p> * - * <p>This listener is called when a request triggers a capture to start, + * <p>This callback is invoked when a request triggers a capture to start, * and when the capture is complete. In case on an error capturing an image, * the error method is triggered instead of the completion method.</p> * @@ -451,7 +458,7 @@ public abstract class CameraCaptureSession implements AutoCloseable { * @see #setRepeatingRequest * @see #setRepeatingBurst */ - public static abstract class CaptureListener { + public static abstract class CaptureCallback { /** * This constant is used to indicate that no images were captured for @@ -625,7 +632,7 @@ public abstract class CameraCaptureSession implements AutoCloseable { } /** - * This method is called independently of the others in CaptureListener, + * This method is called independently of the others in CaptureCallback, * when a capture sequence finishes and all {@link CaptureResult} * or {@link CaptureFailure} for it have been returned via this listener. * @@ -655,7 +662,7 @@ public abstract class CameraCaptureSession implements AutoCloseable { } /** - * This method is called independently of the others in CaptureListener, + * This method is called independently of the others in CaptureCallback, * when a capture sequence aborts before any {@link CaptureResult} * or {@link CaptureFailure} for it have been returned via this listener. * @@ -684,4 +691,11 @@ public abstract class CameraCaptureSession implements AutoCloseable { } } + /** + * Temporary for migrating to Callback naming + * @hide + */ + public static abstract class CaptureListener extends CaptureCallback { + } + } diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java index 097b430..0bb742c 100644 --- a/core/java/android/hardware/camera2/CameraDevice.java +++ b/core/java/android/hardware/camera2/CameraDevice.java @@ -199,8 +199,8 @@ public abstract class CameraDevice implements AutoCloseable { * <p>It can take several hundred milliseconds for the session's configuration to complete, * since camera hardware may need to be powered on or reconfigured. Once the configuration is * complete and the session is ready to actually capture data, the provided - * {@link CameraCaptureSession.StateListener}'s - * {@link CameraCaptureSession.StateListener#onConfigured} callback will be called.</p> + * {@link CameraCaptureSession.StateCallback}'s + * {@link CameraCaptureSession.StateCallback#onConfigured} callback will be called.</p> * * <p>If a prior CameraCaptureSession already exists when a new one is created, the previous * session is closed. Any in-progress capture requests made on the prior session will be @@ -340,12 +340,12 @@ public abstract class CameraDevice implements AutoCloseable { * * @param outputs The new set of Surfaces that should be made available as * targets for captured image data. - * @param listener The listener to notify about the status of the new capture session. - * @param handler The handler on which the listener should be invoked, or {@code null} to use + * @param callback The callback to notify about the status of the new capture session. + * @param handler The handler on which the callback should be invoked, or {@code null} to use * the current thread's {@link android.os.Looper looper}. * * @throws IllegalArgumentException if the set of output Surfaces do not meet the requirements, - * the listener is null, or the handler is null but the current + * the callback is null, or the handler is null but the current * thread has no looper. * @throws CameraAccessException if the camera device is no longer connected or has * encountered a fatal error @@ -357,7 +357,7 @@ public abstract class CameraDevice implements AutoCloseable { * @see StreamConfigurationMap#getOutputSizes(Class) */ public abstract void createCaptureSession(List<Surface> outputs, - CameraCaptureSession.StateListener listener, Handler handler) + CameraCaptureSession.StateCallback callback, Handler handler) throws CameraAccessException; /** @@ -393,10 +393,10 @@ public abstract class CameraDevice implements AutoCloseable { * * <p>Immediately after this call, all calls to the camera device or active session interface * will throw a {@link IllegalStateException}, except for calls to close(). Once the device has - * fully shut down, the {@link StateListener#onClosed} callback will be called, and the camera + * fully shut down, the {@link StateCallback#onClosed} callback will be called, and the camera * is free to be re-opened.</p> * - * <p>Immediately after this call, besides the final {@link StateListener#onClosed} calls, no + * <p>Immediately after this call, besides the final {@link StateCallback#onClosed} calls, no * further callbacks from the device or the active session will occur, and any remaining * submitted capture requests will be discarded, as if * {@link CameraCaptureSession#abortCaptures} had been called, except that no success or failure @@ -407,24 +407,24 @@ public abstract class CameraDevice implements AutoCloseable { public abstract void close(); /** - * A listener for notifications about the state of a camera - * device. + * A callback objects for receiving updates about the state of a camera device. * - * <p>A listener must be provided to the {@link CameraManager#openCamera} - * method to open a camera device.</p> + * <p>A callback instance must be provided to the {@link CameraManager#openCamera} method to + * open a camera device.</p> * - * <p>These events include notifications about the device completing startup ( + * <p>These state updates include notifications about the device completing startup ( * allowing for {@link #createCaptureSession} to be called), about device * disconnection or closure, and about unexpected device errors.</p> * * <p>Events about the progress of specific {@link CaptureRequest CaptureRequests} are provided - * through a {@link CameraCaptureSession.CaptureListener} given to the + * through a {@link CameraCaptureSession.CaptureCallback} given to the * {@link CameraCaptureSession#capture}, {@link CameraCaptureSession#captureBurst}, - * {@link CameraCaptureSession#setRepeatingRequest}, or {@link CameraCaptureSession#setRepeatingBurst} methods. + * {@link CameraCaptureSession#setRepeatingRequest}, or + * {@link CameraCaptureSession#setRepeatingBurst} methods. * * @see CameraManager#openCamera */ - public static abstract class StateListener { + public static abstract class StateCallback { /** * An error code that can be reported by {@link #onError} * indicating that the camera device is in use already. @@ -530,7 +530,7 @@ public abstract class CameraDevice implements AutoCloseable { * of a removable camera device; or the camera being needed for a * higher-priority use case.</p> * - * <p>There may still be capture listener callbacks that are called + * <p>There may still be capture callbacks that are invoked * after this method is called, or new image buffers that are delivered * to active outputs.</p> * @@ -539,7 +539,7 @@ public abstract class CameraDevice implements AutoCloseable { * * <p>You should clean up the camera with {@link CameraDevice#close} after * this happens, as it is not recoverable until opening the camera again - * after it becomes {@link CameraManager.AvailabilityListener#onCameraAvailable available}. + * after it becomes {@link CameraManager.AvailabilityCallback#onCameraAvailable available}. * </p> * * @param camera the device that has been disconnected @@ -558,7 +558,7 @@ public abstract class CameraDevice implements AutoCloseable { * {@link CameraAccessException#CAMERA_ERROR CAMERA_ERROR} reason. * </p> * - * <p>There may still be capture completion or camera stream listeners + * <p>There may still be capture completion or camera stream callbacks * that will be called after this error is received.</p> * * <p>You should clean up the camera with {@link CameraDevice#close} after @@ -566,7 +566,7 @@ public abstract class CameraDevice implements AutoCloseable { * * @param camera The device reporting the error * @param error The error code, one of the - * {@code StateListener.ERROR_*} values. + * {@code StateCallback.ERROR_*} values. * * @see #ERROR_CAMERA_DEVICE * @see #ERROR_CAMERA_SERVICE @@ -577,6 +577,13 @@ public abstract class CameraDevice implements AutoCloseable { } /** + * Temporary for migrating to Callback naming + * @hide + */ + public static abstract class StateListener extends StateCallback { + } + + /** * To be inherited by android.hardware.camera2.* code only. * @hide */ diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java index a4a1559..9a9e4c2 100644 --- a/core/java/android/hardware/camera2/CameraManager.java +++ b/core/java/android/hardware/camera2/CameraManager.java @@ -69,8 +69,8 @@ public final class CameraManager { private ArrayList<String> mDeviceIdList; - private final ArrayMap<AvailabilityListener, Handler> mListenerMap = - new ArrayMap<AvailabilityListener, Handler>(); + private final ArrayMap<AvailabilityCallback, Handler> mCallbackMap = + new ArrayMap<AvailabilityCallback, Handler>(); private final Context mContext; private final Object mLock = new Object(); @@ -108,19 +108,19 @@ public final class CameraManager { } /** - * Register a listener to be notified about camera device availability. + * Register a callback to be notified about camera device availability. * - * <p>Registering the same listener again will replace the handler with the + * <p>Registering the same callback again will replace the handler with the * new one provided.</p> * - * <p>The first time a listener is registered, it is immediately called + * <p>The first time a callback is registered, it is immediately called * with the availability status of all currently known camera devices.</p> * - * @param listener The new listener to send camera availability notices to - * @param handler The handler on which the listener should be invoked, or + * @param callback the new callback to send camera availability notices to + * @param handler The handler on which the callback should be invoked, or * {@code null} to use the current thread's {@link android.os.Looper looper}. */ - public void addAvailabilityListener(AvailabilityListener listener, Handler handler) { + public void registerAvailabilityCallback(AvailabilityCallback callback, Handler handler) { if (handler == null) { Looper looper = Looper.myLooper(); if (looper == null) { @@ -131,25 +131,25 @@ public final class CameraManager { } synchronized (mLock) { - Handler oldHandler = mListenerMap.put(listener, handler); - // For new listeners, provide initial availability information + Handler oldHandler = mCallbackMap.put(callback, handler); + // For new callbacks, provide initial availability information if (oldHandler == null) { - mServiceListener.updateListenerLocked(listener, handler); + mServiceListener.updateCallbackLocked(callback, handler); } } } /** - * Remove a previously-added listener; the listener will no longer receive - * connection and disconnection callbacks. + * Remove a previously-added callback; the callback will no longer receive connection and + * disconnection callbacks. * - * <p>Removing a listener that isn't registered has no effect.</p> + * <p>Removing a callback that isn't registered has no effect.</p> * - * @param listener The listener to remove from the notification list + * @param callback The callback to remove from the notification list */ - public void removeAvailabilityListener(AvailabilityListener listener) { + public void unregisterAvailabilityCallback(AvailabilityCallback callback) { synchronized (mLock) { - mListenerMap.remove(listener); + mCallbackMap.remove(callback); } } @@ -228,8 +228,8 @@ public final class CameraManager { * Helper for openning a connection to a camera with the given ID. * * @param cameraId The unique identifier of the camera device to open - * @param listener The listener for the camera. Must not be null. - * @param handler The handler to call the listener on. Must not be null. + * @param callback The callback for the camera. Must not be null. + * @param handler The handler to invoke the callback on. Must not be null. * * @throws CameraAccessException if the camera is disabled by device policy, * or too many camera devices are already open, or the cameraId does not match @@ -237,14 +237,14 @@ public final class CameraManager { * * @throws SecurityException if the application does not have permission to * access the camera - * @throws IllegalArgumentException if listener or handler is null. + * @throws IllegalArgumentException if callback or handler is null. * @return A handle to the newly-created camera device. * * @see #getCameraIdList * @see android.app.admin.DevicePolicyManager#setCameraDisabled */ private CameraDevice openCameraDeviceUserAsync(String cameraId, - CameraDevice.StateListener listener, Handler handler) + CameraDevice.StateCallback callback, Handler handler) throws CameraAccessException { CameraCharacteristics characteristics = getCameraCharacteristics(cameraId); CameraDevice device = null; @@ -257,7 +257,7 @@ public final class CameraManager { android.hardware.camera2.impl.CameraDeviceImpl deviceImpl = new android.hardware.camera2.impl.CameraDeviceImpl( cameraId, - listener, + callback, handler, characteristics); @@ -313,7 +313,7 @@ public final class CameraManager { throw ce.asChecked(); } - // TODO: factor out listener to be non-nested, then move setter to constructor + // TODO: factor out callback to be non-nested, then move setter to constructor // For now, calling setRemoteDevice will fire initial // onOpened/onUnconfigured callbacks. deviceImpl.setRemoteDevice(cameraUser); @@ -337,7 +337,7 @@ public final class CameraManager { * is disconnected between the calls to {@link #getCameraIdList} and * {@link #openCamera}.</p> * - * <p>Once the camera is successfully opened, {@link CameraDevice.StateListener#onOpened} will + * <p>Once the camera is successfully opened, {@link CameraDevice.StateCallback#onOpened} will * be invoked with the newly opened {@link CameraDevice}. The camera device can then be set up * for operation by calling {@link CameraDevice#createCaptureSession} and * {@link CameraDevice#createCaptureRequest}</p> @@ -345,31 +345,31 @@ public final class CameraManager { * <!-- * <p>Since the camera device will be opened asynchronously, any asynchronous operations done * on the returned CameraDevice instance will be queued up until the device startup has - * completed and the listener's {@link CameraDevice.StateListener#onOpened onOpened} method is + * completed and the callback's {@link CameraDevice.StateCallback#onOpened onOpened} method is * called. The pending operations are then processed in order.</p> * --> * <p>If the camera becomes disconnected during initialization * after this function call returns, - * {@link CameraDevice.StateListener#onDisconnected} with a + * {@link CameraDevice.StateCallback#onDisconnected} with a * {@link CameraDevice} in the disconnected state (and - * {@link CameraDevice.StateListener#onOpened} will be skipped).</p> + * {@link CameraDevice.StateCallback#onOpened} will be skipped).</p> * - * <p>If opening the camera device fails, then the device listener's - * {@link CameraDevice.StateListener#onError onError} method will be called, and subsequent + * <p>If opening the camera device fails, then the device callback's + * {@link CameraDevice.StateCallback#onError onError} method will be called, and subsequent * calls on the camera device will throw a {@link CameraAccessException}.</p> * * @param cameraId * The unique identifier of the camera device to open - * @param listener - * The listener which is invoked once the camera is opened + * @param callback + * The callback which is invoked once the camera is opened * @param handler - * The handler on which the listener should be invoked, or + * The handler on which the callback should be invoked, or * {@code null} to use the current thread's {@link android.os.Looper looper}. * * @throws CameraAccessException if the camera is disabled by device policy, * or the camera has become or was disconnected. * - * @throws IllegalArgumentException if cameraId or the listener was null, + * @throws IllegalArgumentException if cameraId or the callback was null, * or the cameraId does not match any currently or previously available * camera device. * @@ -379,14 +379,14 @@ public final class CameraManager { * @see #getCameraIdList * @see android.app.admin.DevicePolicyManager#setCameraDisabled */ - public void openCamera(String cameraId, final CameraDevice.StateListener listener, + public void openCamera(String cameraId, final CameraDevice.StateCallback callback, Handler handler) throws CameraAccessException { if (cameraId == null) { throw new IllegalArgumentException("cameraId was null"); - } else if (listener == null) { - throw new IllegalArgumentException("listener was null"); + } else if (callback == null) { + throw new IllegalArgumentException("callback was null"); } else if (handler == null) { if (Looper.myLooper() != null) { handler = new Handler(); @@ -396,11 +396,11 @@ public final class CameraManager { } } - openCameraDeviceUserAsync(cameraId, listener, handler); + openCameraDeviceUserAsync(cameraId, callback, handler); } /** - * A listener for camera devices becoming available or + * A callback for camera devices becoming available or * unavailable to open. * * <p>Cameras become available when they are no longer in use, or when a new @@ -408,13 +408,13 @@ public final class CameraManager { * application or service starts using a camera, or when a removable camera * is disconnected.</p> * - * <p>Extend this listener and pass an instance of the subclass to - * {@link CameraManager#addAvailabilityListener} to be notified of such availability + * <p>Extend this callback and pass an instance of the subclass to + * {@link CameraManager#registerAvailabilityCallback} to be notified of such availability * changes.</p> * - * @see addAvailabilityListener + * @see registerAvailabilityCallback */ - public static abstract class AvailabilityListener { + public static abstract class AvailabilityCallback { /** * A new camera has become available to use. @@ -432,7 +432,7 @@ public final class CameraManager { * * <p>If an application had an active CameraDevice instance for the * now-disconnected camera, that application will receive a - * {@link CameraDevice.StateListener#onDisconnected disconnection error}.</p> + * {@link CameraDevice.StateCallback#onDisconnected disconnection error}.</p> * * <p>The default implementation of this method does nothing.</p> * @@ -444,6 +444,13 @@ public final class CameraManager { } /** + * Temporary for migrating to Callback naming + * @hide + */ + public static abstract class AvailabilityListener extends AvailabilityCallback { + } + + /** * Return or create the list of currently connected camera devices. * * <p>In case of errors connecting to the camera service, will return an empty list.</p> @@ -707,14 +714,14 @@ public final class CameraManager { } } - private void postSingleUpdate(final AvailabilityListener listener, final Handler handler, + private void postSingleUpdate(final AvailabilityCallback callback, final Handler handler, final String id, final int status) { if (isAvailable(status)) { handler.post( new Runnable() { @Override public void run() { - listener.onCameraAvailable(id); + callback.onCameraAvailable(id); } }); } else { @@ -722,7 +729,7 @@ public final class CameraManager { new Runnable() { @Override public void run() { - listener.onCameraUnavailable(id); + callback.onCameraUnavailable(id); } }); } @@ -732,11 +739,11 @@ public final class CameraManager { * Send the state of all known cameras to the provided listener, to initialize * the listener's knowledge of camera state. */ - public void updateListenerLocked(AvailabilityListener listener, Handler handler) { + public void updateCallbackLocked(AvailabilityCallback callback, Handler handler) { for (int i = 0; i < mDeviceStatus.size(); i++) { String id = mDeviceStatus.keyAt(i); Integer status = mDeviceStatus.valueAt(i); - postSingleUpdate(listener, handler, id, status); + postSingleUpdate(callback, handler, id, status); } } @@ -795,12 +802,12 @@ public final class CameraManager { return; } - final int listenerCount = mListenerMap.size(); - for (int i = 0; i < listenerCount; i++) { - Handler handler = mListenerMap.valueAt(i); - final AvailabilityListener listener = mListenerMap.keyAt(i); + final int callbackCount = mCallbackMap.size(); + for (int i = 0; i < callbackCount; i++) { + Handler handler = mCallbackMap.valueAt(i); + final AvailabilityCallback callback = mCallbackMap.keyAt(i); - postSingleUpdate(listener, handler, id, status); + postSingleUpdate(callback, handler, id, status); } } // onStatusChangedLocked diff --git a/core/java/android/hardware/camera2/CaptureFailure.java b/core/java/android/hardware/camera2/CaptureFailure.java index b6d3b08..c168ff1 100644 --- a/core/java/android/hardware/camera2/CaptureFailure.java +++ b/core/java/android/hardware/camera2/CaptureFailure.java @@ -65,12 +65,12 @@ public class CaptureFailure { * Get the request associated with this failed capture. * * <p>Whenever a request is unsuccessfully captured, with - * {@link CameraCaptureSession.CaptureListener#onCaptureFailed}, + * {@link CameraCaptureSession.CaptureCallback#onCaptureFailed}, * the {@code failed capture}'s {@code getRequest()} will return that {@code request}. * </p> * * <p>In particular, - * <code><pre>cameraDevice.capture(someRequest, new CaptureListener() { + * <code><pre>cameraDevice.capture(someRequest, new CaptureCallback() { * {@literal @}Override * void onCaptureFailed(CaptureRequest myRequest, CaptureFailure myFailure) { * assert(myFailure.getRequest.equals(myRequest) == true); @@ -135,7 +135,7 @@ public class CaptureFailure { * * @return int The ID for the sequence of requests that this capture failure is the result of * - * @see CameraDevice.CaptureListener#onCaptureSequenceCompleted + * @see CameraDevice.CaptureCallback#onCaptureSequenceCompleted */ public int getSequenceId() { return mSequenceId; diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index bcdcd62..6d0d505 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -245,7 +245,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <p>This tag is not used for anything by the camera device, but can be * used by an application to easily identify a CaptureRequest when it is * returned by - * {@link CameraCaptureSession.CaptureListener#onCaptureCompleted CaptureListener.onCaptureCompleted} + * {@link CameraCaptureSession.CaptureCallback#onCaptureCompleted CaptureCallback.onCaptureCompleted} * </p> * * @return the last tag Object set on this request, or {@code null} if @@ -435,7 +435,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <p>This tag is not used for anything by the camera device, but can be * used by an application to easily identify a CaptureRequest when it is * returned by - * {@link CameraCaptureSession.CaptureListener#onCaptureCompleted CaptureListener.onCaptureCompleted} + * {@link CameraCaptureSession.CaptureCallback#onCaptureCompleted CaptureCallback.onCaptureCompleted} * * @param tag an arbitrary Object to store with this request * @see CaptureRequest#getTag diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java index f9c4df4..754d83e 100644 --- a/core/java/android/hardware/camera2/CaptureResult.java +++ b/core/java/android/hardware/camera2/CaptureResult.java @@ -268,13 +268,13 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * Get the request associated with this result. * * <p>Whenever a request has been fully or partially captured, with - * {@link CameraCaptureSession.CaptureListener#onCaptureCompleted} or - * {@link CameraCaptureSession.CaptureListener#onCaptureProgressed}, the {@code result}'s + * {@link CameraCaptureSession.CaptureCallback#onCaptureCompleted} or + * {@link CameraCaptureSession.CaptureCallback#onCaptureProgressed}, the {@code result}'s * {@code getRequest()} will return that {@code request}. * </p> * * <p>For example, - * <code><pre>cameraDevice.capture(someRequest, new CaptureListener() { + * <code><pre>cameraDevice.capture(someRequest, new CaptureCallback() { * {@literal @}Override * void onCaptureCompleted(CaptureRequest myRequest, CaptureResult myResult) { * assert(myResult.getRequest.equals(myRequest) == true); @@ -314,8 +314,8 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * * @return int The ID for the sequence of requests that this capture result is a part of * - * @see CameraDevice.CaptureListener#onCaptureSequenceCompleted - * @see CameraDevice.CaptureListener#onCaptureSequenceAborted + * @see CameraDevice.CaptureCallback#onCaptureSequenceCompleted + * @see CameraDevice.CaptureCallback#onCaptureSequenceAborted */ public int getSequenceId() { return mSequenceId; diff --git a/core/java/android/hardware/camera2/TotalCaptureResult.java b/core/java/android/hardware/camera2/TotalCaptureResult.java index 0895fe3..6f7dd78 100644 --- a/core/java/android/hardware/camera2/TotalCaptureResult.java +++ b/core/java/android/hardware/camera2/TotalCaptureResult.java @@ -45,7 +45,7 @@ import java.util.List; * * <p>{@link TotalCaptureResult} objects are immutable.</p> * - * @see CameraDevice.CaptureListener#onCaptureCompleted + * @see CameraDevice.CaptureCallback#onCaptureCompleted */ public final class TotalCaptureResult extends CaptureResult { @@ -88,7 +88,7 @@ public final class TotalCaptureResult extends CaptureResult { * * <p>The list size will be inclusive between {@code 0} and * {@link CameraCharacteristics#REQUEST_PARTIAL_RESULT_COUNT}, with elements in ascending order - * of when {@link CameraCaptureSession.CaptureListener#onCaptureProgressed} was invoked.</p> + * of when {@link CameraCaptureSession.CaptureCallback#onCaptureProgressed} was invoked.</p> * * @return unmodifiable list of partial results */ diff --git a/core/java/android/hardware/camera2/impl/ListenerProxies.java b/core/java/android/hardware/camera2/impl/CallbackProxies.java index f44f9ad..e5ddb7a 100644 --- a/core/java/android/hardware/camera2/impl/ListenerProxies.java +++ b/core/java/android/hardware/camera2/impl/CallbackProxies.java @@ -27,22 +27,22 @@ import android.hardware.camera2.dispatch.MethodNameInvoker; import static com.android.internal.util.Preconditions.*; /** - * Proxy out invocations to the camera2 API listeners into a {@link Dispatchable}. + * Proxy out invocations to the camera2 API callbacks into a {@link Dispatchable}. * * <p>Since abstract classes do not support Java's dynamic {@code Proxy}, we have to * to use our own proxy mechanism.</p> */ -public class ListenerProxies { +public class CallbackProxies { // TODO: replace with codegen - public static class DeviceStateListenerProxy extends CameraDeviceImpl.StateListenerKK { - private final MethodNameInvoker<CameraDeviceImpl.StateListenerKK> mProxy; + public static class DeviceStateCallbackProxy extends CameraDeviceImpl.StateCallbackKK { + private final MethodNameInvoker<CameraDeviceImpl.StateCallbackKK> mProxy; - public DeviceStateListenerProxy( - Dispatchable<CameraDeviceImpl.StateListenerKK> dispatchTarget) { + public DeviceStateCallbackProxy( + Dispatchable<CameraDeviceImpl.StateCallbackKK> dispatchTarget) { dispatchTarget = checkNotNull(dispatchTarget, "dispatchTarget must not be null"); - mProxy = new MethodNameInvoker<>(dispatchTarget, CameraDeviceImpl.StateListenerKK.class); + mProxy = new MethodNameInvoker<>(dispatchTarget, CameraDeviceImpl.StateCallbackKK.class); } @Override @@ -87,13 +87,13 @@ public class ListenerProxies { } @SuppressWarnings("deprecation") - public static class DeviceCaptureListenerProxy extends CameraDeviceImpl.CaptureListener { - private final MethodNameInvoker<CameraDeviceImpl.CaptureListener> mProxy; + public static class DeviceCaptureCallbackProxy extends CameraDeviceImpl.CaptureCallback { + private final MethodNameInvoker<CameraDeviceImpl.CaptureCallback> mProxy; - public DeviceCaptureListenerProxy( - Dispatchable<CameraDeviceImpl.CaptureListener> dispatchTarget) { + public DeviceCaptureCallbackProxy( + Dispatchable<CameraDeviceImpl.CaptureCallback> dispatchTarget) { dispatchTarget = checkNotNull(dispatchTarget, "dispatchTarget must not be null"); - mProxy = new MethodNameInvoker<>(dispatchTarget, CameraDeviceImpl.CaptureListener.class); + mProxy = new MethodNameInvoker<>(dispatchTarget, CameraDeviceImpl.CaptureCallback.class); } @Override @@ -139,15 +139,15 @@ public class ListenerProxies { } } - public static class SessionStateListenerProxy - extends CameraCaptureSession.StateListener { - private final MethodNameInvoker<CameraCaptureSession.StateListener> mProxy; + public static class SessionStateCallbackProxy + extends CameraCaptureSession.StateCallback { + private final MethodNameInvoker<CameraCaptureSession.StateCallback> mProxy; - public SessionStateListenerProxy( - Dispatchable<CameraCaptureSession.StateListener> dispatchTarget) { + public SessionStateCallbackProxy( + Dispatchable<CameraCaptureSession.StateCallback> dispatchTarget) { dispatchTarget = checkNotNull(dispatchTarget, "dispatchTarget must not be null"); mProxy = new MethodNameInvoker<>(dispatchTarget, - CameraCaptureSession.StateListener.class); + CameraCaptureSession.StateCallback.class); } @Override @@ -177,7 +177,7 @@ public class ListenerProxies { } } - private ListenerProxies() { + private CallbackProxies() { throw new AssertionError(); } } diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java index 9ca1fba..843f117 100644 --- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java @@ -45,11 +45,11 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession { /** User-specified set of surfaces used as the configuration outputs */ private final List<Surface> mOutputs; /** - * User-specified state listener, used for outgoing events; calls to this object will be + * User-specified state callback, used for outgoing events; calls to this object will be * automatically {@link Handler#post(Runnable) posted} to {@code mStateHandler}. */ - private final CameraCaptureSession.StateListener mStateListener; - /** User-specified state handler used for outgoing state listener events */ + private final CameraCaptureSession.StateCallback mStateCallback; + /** User-specified state handler used for outgoing state callback events */ private final Handler mStateHandler; /** Internal camera device; used to translate calls into existing deprecated API */ @@ -84,28 +84,28 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession { * (e.g. no pending captures, no repeating requests, no flush).</p> */ CameraCaptureSessionImpl(List<Surface> outputs, - CameraCaptureSession.StateListener listener, Handler stateHandler, + CameraCaptureSession.StateCallback callback, Handler stateHandler, android.hardware.camera2.impl.CameraDeviceImpl deviceImpl, Handler deviceStateHandler, boolean configureSuccess) { if (outputs == null || outputs.isEmpty()) { throw new IllegalArgumentException("outputs must be a non-null, non-empty list"); - } else if (listener == null) { - throw new IllegalArgumentException("listener must not be null"); + } else if (callback == null) { + throw new IllegalArgumentException("callback must not be null"); } // TODO: extra verification of outputs mOutputs = outputs; mStateHandler = checkHandler(stateHandler); - mStateListener = createUserStateListenerProxy(mStateHandler, listener); + mStateCallback = createUserStateCallbackProxy(mStateHandler, callback); mDeviceHandler = checkNotNull(deviceStateHandler, "deviceStateHandler must not be null"); mDeviceImpl = checkNotNull(deviceImpl, "deviceImpl must not be null"); /* - * Use the same handler as the device's StateListener for all the internal coming events + * Use the same handler as the device's StateCallback for all the internal coming events * - * This ensures total ordering between CameraDevice.StateListener and - * CameraDeviceImpl.CaptureListener events. + * This ensures total ordering between CameraDevice.StateCallback and + * CameraDeviceImpl.CaptureCallback events. */ mSequenceDrainer = new TaskDrainer<>(mDeviceHandler, new SequenceDrainListener(), /*name*/"seq"); @@ -119,11 +119,11 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession { // CameraDevice should call configureOutputs and have it finish before constructing us if (configureSuccess) { - mStateListener.onConfigured(this); + mStateCallback.onConfigured(this); if (VERBOSE) Log.v(TAG, "ctor - Created session successfully"); mConfigureSuccess = true; } else { - mStateListener.onConfigureFailed(this); + mStateCallback.onConfigureFailed(this); mClosed = true; // do not fire any other callbacks, do not allow any other work Log.e(TAG, "Failed to create capture session; configuration failed"); mConfigureSuccess = false; @@ -136,7 +136,7 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession { } @Override - public synchronized int capture(CaptureRequest request, CaptureListener listener, + public synchronized int capture(CaptureRequest request, CaptureCallback callback, Handler handler) throws CameraAccessException { if (request == null) { throw new IllegalArgumentException("request must not be null"); @@ -145,19 +145,19 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession { checkNotClosed(); checkLegalToCapture(); - handler = checkHandler(handler, listener); + handler = checkHandler(handler, callback); if (VERBOSE) { - Log.v(TAG, "capture - request " + request + ", listener " + listener + " handler" + + Log.v(TAG, "capture - request " + request + ", callback " + callback + " handler" + " " + handler); } return addPendingSequence(mDeviceImpl.capture(request, - createCaptureListenerProxy(handler, listener), mDeviceHandler)); + createCaptureCallbackProxy(handler, callback), mDeviceHandler)); } @Override - public synchronized int captureBurst(List<CaptureRequest> requests, CaptureListener listener, + public synchronized int captureBurst(List<CaptureRequest> requests, CaptureCallback callback, Handler handler) throws CameraAccessException { if (requests == null) { throw new IllegalArgumentException("requests must not be null"); @@ -168,20 +168,20 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession { checkNotClosed(); checkLegalToCapture(); - handler = checkHandler(handler, listener); + handler = checkHandler(handler, callback); if (VERBOSE) { CaptureRequest[] requestArray = requests.toArray(new CaptureRequest[0]); - Log.v(TAG, "captureBurst - requests " + Arrays.toString(requestArray) + ", listener " + - listener + " handler" + "" + handler); + Log.v(TAG, "captureBurst - requests " + Arrays.toString(requestArray) + ", callback " + + callback + " handler" + "" + handler); } return addPendingSequence(mDeviceImpl.captureBurst(requests, - createCaptureListenerProxy(handler, listener), mDeviceHandler)); + createCaptureCallbackProxy(handler, callback), mDeviceHandler)); } @Override - public synchronized int setRepeatingRequest(CaptureRequest request, CaptureListener listener, + public synchronized int setRepeatingRequest(CaptureRequest request, CaptureCallback callback, Handler handler) throws CameraAccessException { if (request == null) { throw new IllegalArgumentException("request must not be null"); @@ -190,20 +190,20 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession { checkNotClosed(); checkLegalToCapture(); - handler = checkHandler(handler, listener); + handler = checkHandler(handler, callback); if (VERBOSE) { - Log.v(TAG, "setRepeatingRequest - request " + request + ", listener " + listener + + Log.v(TAG, "setRepeatingRequest - request " + request + ", callback " + callback + " handler" + " " + handler); } return addPendingSequence(mDeviceImpl.setRepeatingRequest(request, - createCaptureListenerProxy(handler, listener), mDeviceHandler)); + createCaptureCallbackProxy(handler, callback), mDeviceHandler)); } @Override public synchronized int setRepeatingBurst(List<CaptureRequest> requests, - CaptureListener listener, Handler handler) throws CameraAccessException { + CaptureCallback callback, Handler handler) throws CameraAccessException { if (requests == null) { throw new IllegalArgumentException("requests must not be null"); } else if (requests.isEmpty()) { @@ -213,16 +213,16 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession { checkNotClosed(); checkLegalToCapture(); - handler = checkHandler(handler, listener); + handler = checkHandler(handler, callback); if (VERBOSE) { CaptureRequest[] requestArray = requests.toArray(new CaptureRequest[0]); Log.v(TAG, "setRepeatingBurst - requests " + Arrays.toString(requestArray) + - ", listener " + listener + " handler" + "" + handler); + ", callback " + callback + " handler" + "" + handler); } return addPendingSequence(mDeviceImpl.setRepeatingBurst(requests, - createCaptureListenerProxy(handler, listener), mDeviceHandler)); + createCaptureCallbackProxy(handler, callback), mDeviceHandler)); } @Override @@ -331,8 +331,8 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession { // or just suppress the ISE only and rely onClosed. // Also skip any of the draining work if this is already closed. - // Short-circuit; queue listener immediately and return - mStateListener.onClosed(this); + // Short-circuit; queue callback immediately and return + mStateCallback.onClosed(this); return; } catch (CameraAccessException e) { // OK: close does not throw checked exceptions. @@ -360,30 +360,30 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession { } /** - * Post calls into a CameraCaptureSession.StateListener to the user-specified {@code handler}. + * Post calls into a CameraCaptureSession.StateCallback to the user-specified {@code handler}. */ - private StateListener createUserStateListenerProxy(Handler handler, StateListener listener) { - InvokeDispatcher<StateListener> userListenerSink = new InvokeDispatcher<>(listener); - HandlerDispatcher<StateListener> handlerPassthrough = - new HandlerDispatcher<>(userListenerSink, handler); + private StateCallback createUserStateCallbackProxy(Handler handler, StateCallback callback) { + InvokeDispatcher<StateCallback> userCallbackSink = new InvokeDispatcher<>(callback); + HandlerDispatcher<StateCallback> handlerPassthrough = + new HandlerDispatcher<>(userCallbackSink, handler); - return new ListenerProxies.SessionStateListenerProxy(handlerPassthrough); + return new CallbackProxies.SessionStateCallbackProxy(handlerPassthrough); } /** * Forward callbacks from - * CameraDeviceImpl.CaptureListener to the CameraCaptureSession.CaptureListener. + * CameraDeviceImpl.CaptureCallback to the CameraCaptureSession.CaptureCallback. * * <p>In particular, all calls are automatically split to go both to our own - * internal listener, and to the user-specified listener (by transparently posting + * internal callback, and to the user-specified callback (by transparently posting * to the user-specified handler).</p> * * <p>When a capture sequence finishes, update the pending checked sequences set.</p> */ @SuppressWarnings("deprecation") - private CameraDeviceImpl.CaptureListener createCaptureListenerProxy( - Handler handler, CaptureListener listener) { - CameraDeviceImpl.CaptureListener localListener = new CameraDeviceImpl.CaptureListener() { + private CameraDeviceImpl.CaptureCallback createCaptureCallbackProxy( + Handler handler, CaptureCallback callback) { + CameraDeviceImpl.CaptureCallback localCallback = new CameraDeviceImpl.CaptureCallback() { @Override public void onCaptureSequenceCompleted(CameraDevice camera, int sequenceId, long frameNumber) { @@ -398,43 +398,43 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession { }; /* - * Split the calls from the device listener into local listener and the following chain: + * Split the calls from the device callback into local callback and the following chain: * - replace the first CameraDevice arg with a CameraCaptureSession - * - duck type from device listener to session listener + * - duck type from device callback to session callback * - then forward the call to a handler - * - then finally invoke the destination method on the session listener object + * - then finally invoke the destination method on the session callback object */ - if (listener == null) { - // OK: API allows the user to not specify a listener, and the handler may + if (callback == null) { + // OK: API allows the user to not specify a callback, and the handler may // also be null in that case. Collapse whole dispatch chain to only call the local - // listener - return localListener; + // callback + return localCallback; } - InvokeDispatcher<CameraDeviceImpl.CaptureListener> localSink = - new InvokeDispatcher<>(localListener); + InvokeDispatcher<CameraDeviceImpl.CaptureCallback> localSink = + new InvokeDispatcher<>(localCallback); - InvokeDispatcher<CaptureListener> userListenerSink = - new InvokeDispatcher<>(listener); - HandlerDispatcher<CaptureListener> handlerPassthrough = - new HandlerDispatcher<>(userListenerSink, handler); - DuckTypingDispatcher<CameraDeviceImpl.CaptureListener, CaptureListener> duckToSession - = new DuckTypingDispatcher<>(handlerPassthrough, CaptureListener.class); - ArgumentReplacingDispatcher<CameraDeviceImpl.CaptureListener, CameraCaptureSessionImpl> + InvokeDispatcher<CaptureCallback> userCallbackSink = + new InvokeDispatcher<>(callback); + HandlerDispatcher<CaptureCallback> handlerPassthrough = + new HandlerDispatcher<>(userCallbackSink, handler); + DuckTypingDispatcher<CameraDeviceImpl.CaptureCallback, CaptureCallback> duckToSession + = new DuckTypingDispatcher<>(handlerPassthrough, CaptureCallback.class); + ArgumentReplacingDispatcher<CameraDeviceImpl.CaptureCallback, CameraCaptureSessionImpl> replaceDeviceWithSession = new ArgumentReplacingDispatcher<>(duckToSession, /*argumentIndex*/0, this); - BroadcastDispatcher<CameraDeviceImpl.CaptureListener> broadcaster = - new BroadcastDispatcher<CameraDeviceImpl.CaptureListener>( + BroadcastDispatcher<CameraDeviceImpl.CaptureCallback> broadcaster = + new BroadcastDispatcher<CameraDeviceImpl.CaptureCallback>( replaceDeviceWithSession, localSink); - return new ListenerProxies.DeviceCaptureListenerProxy(broadcaster); + return new CallbackProxies.DeviceCaptureCallbackProxy(broadcaster); } /** * - * Create an internal state listener, to be invoked on the mDeviceHandler + * Create an internal state callback, to be invoked on the mDeviceHandler * * <p>It has a few behaviors: * <ul> @@ -443,10 +443,10 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession { * </ul> * </p> * */ - CameraDeviceImpl.StateListenerKK getDeviceStateListener() { + CameraDeviceImpl.StateCallbackKK getDeviceStateCallback() { final CameraCaptureSession session = this; - return new CameraDeviceImpl.StateListenerKK() { + return new CameraDeviceImpl.StateCallbackKK() { private boolean mBusy = false; private boolean mActive = false; @@ -471,7 +471,7 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession { mIdleDrainer.taskStarted(); mActive = true; - mStateListener.onActive(session); + mStateCallback.onActive(session); } @Override @@ -507,7 +507,7 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession { mBusy = false; mActive = false; - mStateListener.onReady(session); + mStateCallback.onReady(session); } @Override @@ -629,7 +629,7 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession { // Fast path: A new capture session has replaced this one; don't unconfigure. if (mSkipUnconfigure) { - mStateListener.onClosed(CameraCaptureSessionImpl.this); + mStateCallback.onClosed(CameraCaptureSessionImpl.this); return; } @@ -655,7 +655,7 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession { public void onDrained() { synchronized (CameraCaptureSessionImpl.this) { // The device has finished unconfiguring. It's now fully closed. - mStateListener.onClosed(CameraCaptureSessionImpl.this); + mStateCallback.onClosed(CameraCaptureSessionImpl.this); } } } diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java index f5666bf..d454092 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java @@ -64,17 +64,17 @@ public class CameraDeviceImpl extends CameraDevice { private final Object mInterfaceLock = new Object(); private final CameraDeviceCallbacks mCallbacks = new CameraDeviceCallbacks(); - private final StateListener mDeviceListener; - private volatile StateListenerKK mSessionStateListener; + private final StateCallback mDeviceCallback; + private volatile StateCallbackKK mSessionStateCallback; private final Handler mDeviceHandler; private volatile boolean mClosing = false; private boolean mInError = false; private boolean mIdle = true; - /** map request IDs to listener/request data */ - private final SparseArray<CaptureListenerHolder> mCaptureListenerMap = - new SparseArray<CaptureListenerHolder>(); + /** map request IDs to callback/request data */ + private final SparseArray<CaptureCallbackHolder> mCaptureCallbackMap = + new SparseArray<CaptureCallbackHolder>(); private int mRepeatingRequestId = REQUEST_ID_NONE; private final ArrayList<Integer> mRepeatingRequestIdDeletedList = new ArrayList<Integer>(); @@ -106,30 +106,30 @@ public class CameraDeviceImpl extends CameraDevice { private final Runnable mCallOnOpened = new Runnable() { @Override public void run() { - StateListenerKK sessionListener = null; + StateCallbackKK sessionCallback = null; synchronized(mInterfaceLock) { if (mRemoteDevice == null) return; // Camera already closed - sessionListener = mSessionStateListener; + sessionCallback = mSessionStateCallback; } - if (sessionListener != null) { - sessionListener.onOpened(CameraDeviceImpl.this); + if (sessionCallback != null) { + sessionCallback.onOpened(CameraDeviceImpl.this); } - mDeviceListener.onOpened(CameraDeviceImpl.this); + mDeviceCallback.onOpened(CameraDeviceImpl.this); } }; private final Runnable mCallOnUnconfigured = new Runnable() { @Override public void run() { - StateListenerKK sessionListener = null; + StateCallbackKK sessionCallback = null; synchronized(mInterfaceLock) { if (mRemoteDevice == null) return; // Camera already closed - sessionListener = mSessionStateListener; + sessionCallback = mSessionStateCallback; } - if (sessionListener != null) { - sessionListener.onUnconfigured(CameraDeviceImpl.this); + if (sessionCallback != null) { + sessionCallback.onUnconfigured(CameraDeviceImpl.this); } } }; @@ -137,14 +137,14 @@ public class CameraDeviceImpl extends CameraDevice { private final Runnable mCallOnActive = new Runnable() { @Override public void run() { - StateListenerKK sessionListener = null; + StateCallbackKK sessionCallback = null; synchronized(mInterfaceLock) { if (mRemoteDevice == null) return; // Camera already closed - sessionListener = mSessionStateListener; + sessionCallback = mSessionStateCallback; } - if (sessionListener != null) { - sessionListener.onActive(CameraDeviceImpl.this); + if (sessionCallback != null) { + sessionCallback.onActive(CameraDeviceImpl.this); } } }; @@ -152,14 +152,14 @@ public class CameraDeviceImpl extends CameraDevice { private final Runnable mCallOnBusy = new Runnable() { @Override public void run() { - StateListenerKK sessionListener = null; + StateCallbackKK sessionCallback = null; synchronized(mInterfaceLock) { if (mRemoteDevice == null) return; // Camera already closed - sessionListener = mSessionStateListener; + sessionCallback = mSessionStateCallback; } - if (sessionListener != null) { - sessionListener.onBusy(CameraDeviceImpl.this); + if (sessionCallback != null) { + sessionCallback.onBusy(CameraDeviceImpl.this); } } }; @@ -172,14 +172,14 @@ public class CameraDeviceImpl extends CameraDevice { if (mClosedOnce) { throw new AssertionError("Don't post #onClosed more than once"); } - StateListenerKK sessionListener = null; + StateCallbackKK sessionCallback = null; synchronized(mInterfaceLock) { - sessionListener = mSessionStateListener; + sessionCallback = mSessionStateCallback; } - if (sessionListener != null) { - sessionListener.onClosed(CameraDeviceImpl.this); + if (sessionCallback != null) { + sessionCallback.onClosed(CameraDeviceImpl.this); } - mDeviceListener.onClosed(CameraDeviceImpl.this); + mDeviceCallback.onClosed(CameraDeviceImpl.this); mClosedOnce = true; } }; @@ -187,14 +187,14 @@ public class CameraDeviceImpl extends CameraDevice { private final Runnable mCallOnIdle = new Runnable() { @Override public void run() { - StateListenerKK sessionListener = null; + StateCallbackKK sessionCallback = null; synchronized(mInterfaceLock) { if (mRemoteDevice == null) return; // Camera already closed - sessionListener = mSessionStateListener; + sessionCallback = mSessionStateCallback; } - if (sessionListener != null) { - sessionListener.onIdle(CameraDeviceImpl.this); + if (sessionCallback != null) { + sessionCallback.onIdle(CameraDeviceImpl.this); } } }; @@ -202,26 +202,26 @@ public class CameraDeviceImpl extends CameraDevice { private final Runnable mCallOnDisconnected = new Runnable() { @Override public void run() { - StateListenerKK sessionListener = null; + StateCallbackKK sessionCallback = null; synchronized(mInterfaceLock) { if (mRemoteDevice == null) return; // Camera already closed - sessionListener = mSessionStateListener; + sessionCallback = mSessionStateCallback; } - if (sessionListener != null) { - sessionListener.onDisconnected(CameraDeviceImpl.this); + if (sessionCallback != null) { + sessionCallback.onDisconnected(CameraDeviceImpl.this); } - mDeviceListener.onDisconnected(CameraDeviceImpl.this); + mDeviceCallback.onDisconnected(CameraDeviceImpl.this); } }; - public CameraDeviceImpl(String cameraId, StateListener listener, Handler handler, + public CameraDeviceImpl(String cameraId, StateCallback callback, Handler handler, CameraCharacteristics characteristics) { - if (cameraId == null || listener == null || handler == null || characteristics == null) { + if (cameraId == null || callback == null || handler == null || characteristics == null) { throw new IllegalArgumentException("Null argument given"); } mCameraId = cameraId; - mDeviceListener = listener; + mDeviceCallback = callback; mDeviceHandler = handler; mCharacteristics = characteristics; @@ -263,28 +263,28 @@ public class CameraDeviceImpl extends CameraDevice { /** * Call to indicate failed connection to a remote camera device. * - * <p>This places the camera device in the error state and informs the listener. + * <p>This places the camera device in the error state and informs the callback. * Use in place of setRemoteDevice() when startup fails.</p> */ public void setRemoteFailure(final CameraRuntimeException failure) { - int failureCode = StateListener.ERROR_CAMERA_DEVICE; + int failureCode = StateCallback.ERROR_CAMERA_DEVICE; boolean failureIsError = true; switch (failure.getReason()) { case CameraAccessException.CAMERA_IN_USE: - failureCode = StateListener.ERROR_CAMERA_IN_USE; + failureCode = StateCallback.ERROR_CAMERA_IN_USE; break; case CameraAccessException.MAX_CAMERAS_IN_USE: - failureCode = StateListener.ERROR_MAX_CAMERAS_IN_USE; + failureCode = StateCallback.ERROR_MAX_CAMERAS_IN_USE; break; case CameraAccessException.CAMERA_DISABLED: - failureCode = StateListener.ERROR_CAMERA_DISABLED; + failureCode = StateCallback.ERROR_CAMERA_DISABLED; break; case CameraAccessException.CAMERA_DISCONNECTED: failureIsError = false; break; case CameraAccessException.CAMERA_ERROR: - failureCode = StateListener.ERROR_CAMERA_DEVICE; + failureCode = StateCallback.ERROR_CAMERA_DEVICE; break; default: Log.wtf(TAG, "Unknown failure in opening camera device: " + failure.getReason()); @@ -298,9 +298,9 @@ public class CameraDeviceImpl extends CameraDevice { @Override public void run() { if (isError) { - mDeviceListener.onError(CameraDeviceImpl.this, code); + mDeviceCallback.onError(CameraDeviceImpl.this, code); } else { - mDeviceListener.onDisconnected(CameraDeviceImpl.this); + mDeviceCallback.onDisconnected(CameraDeviceImpl.this); } } }); @@ -415,7 +415,7 @@ public class CameraDeviceImpl extends CameraDevice { @Override public void createCaptureSession(List<Surface> outputs, - CameraCaptureSession.StateListener listener, Handler handler) + CameraCaptureSession.StateCallback callback, Handler handler) throws CameraAccessException { synchronized(mInterfaceLock) { if (DEBUG) { @@ -445,7 +445,7 @@ public class CameraDeviceImpl extends CameraDevice { // Fire onConfigured if configureOutputs succeeded, fire onConfigureFailed otherwise. CameraCaptureSessionImpl newSession = - new CameraCaptureSessionImpl(outputs, listener, handler, this, mDeviceHandler, + new CameraCaptureSessionImpl(outputs, callback, handler, this, mDeviceHandler, configureSuccess); // TODO: wait until current session closes, then create the new session @@ -455,16 +455,16 @@ public class CameraDeviceImpl extends CameraDevice { throw pendingException; } - mSessionStateListener = mCurrentSession.getDeviceStateListener(); + mSessionStateCallback = mCurrentSession.getDeviceStateCallback(); } } /** * For use by backwards-compatibility code only. */ - public void setSessionListener(StateListenerKK sessionListener) { + public void setSessionListener(StateCallbackKK sessionCallback) { synchronized(mInterfaceLock) { - mSessionStateListener = sessionListener; + mSessionStateCallback = sessionCallback; } } @@ -492,22 +492,22 @@ public class CameraDeviceImpl extends CameraDevice { } } - public int capture(CaptureRequest request, CaptureListener listener, Handler handler) + public int capture(CaptureRequest request, CaptureCallback callback, Handler handler) throws CameraAccessException { if (DEBUG) { Log.d(TAG, "calling capture"); } List<CaptureRequest> requestList = new ArrayList<CaptureRequest>(); requestList.add(request); - return submitCaptureRequest(requestList, listener, handler, /*streaming*/false); + return submitCaptureRequest(requestList, callback, handler, /*streaming*/false); } - public int captureBurst(List<CaptureRequest> requests, CaptureListener listener, + public int captureBurst(List<CaptureRequest> requests, CaptureCallback callback, Handler handler) throws CameraAccessException { if (requests == null || requests.isEmpty()) { throw new IllegalArgumentException("At least one request must be given"); } - return submitCaptureRequest(requests, listener, handler, /*streaming*/false); + return submitCaptureRequest(requests, callback, handler, /*streaming*/false); } /** @@ -527,12 +527,12 @@ public class CameraDeviceImpl extends CameraDevice { final int requestId, final long lastFrameNumber) { // lastFrameNumber being equal to NO_FRAMES_CAPTURED means that the request // was never sent to HAL. Should trigger onCaptureSequenceAborted immediately. - if (lastFrameNumber == CaptureListener.NO_FRAMES_CAPTURED) { - final CaptureListenerHolder holder; - int index = mCaptureListenerMap.indexOfKey(requestId); - holder = (index >= 0) ? mCaptureListenerMap.valueAt(index) : null; + if (lastFrameNumber == CaptureCallback.NO_FRAMES_CAPTURED) { + final CaptureCallbackHolder holder; + int index = mCaptureCallbackMap.indexOfKey(requestId); + holder = (index >= 0) ? mCaptureCallbackMap.valueAt(index) : null; if (holder != null) { - mCaptureListenerMap.removeAt(index); + mCaptureCallbackMap.removeAt(index); if (DEBUG) { Log.v(TAG, String.format( "remove holder for requestId %d, " @@ -560,7 +560,7 @@ public class CameraDeviceImpl extends CameraDevice { || lastFrameNumber > Integer.MAX_VALUE) { throw new AssertionError(lastFrameNumber + " cannot be cast to int"); } - holder.getListener().onCaptureSequenceAborted( + holder.getCallback().onCaptureSequenceAborted( CameraDeviceImpl.this, requestId); } @@ -569,7 +569,7 @@ public class CameraDeviceImpl extends CameraDevice { holder.getHandler().post(resultDispatch); } else { Log.w(TAG, String.format( - "did not register listener to request %d", + "did not register callback to request %d", requestId)); } } else { @@ -579,12 +579,12 @@ public class CameraDeviceImpl extends CameraDevice { } } - private int submitCaptureRequest(List<CaptureRequest> requestList, CaptureListener listener, + private int submitCaptureRequest(List<CaptureRequest> requestList, CaptureCallback callback, Handler handler, boolean repeating) throws CameraAccessException { // Need a valid handler, or current thread needs to have a looper, if - // listener is valid - handler = checkHandler(handler, listener); + // callback is valid + handler = checkHandler(handler, callback); // Make sure that there all requests have at least 1 surface; all surfaces are non-null for (CaptureRequest request : requestList) { @@ -622,8 +622,8 @@ public class CameraDeviceImpl extends CameraDevice { return -1; } - if (listener != null) { - mCaptureListenerMap.put(requestId, new CaptureListenerHolder(listener, + if (callback != null) { + mCaptureCallbackMap.put(requestId, new CaptureCallbackHolder(callback, requestList, handler, repeating)); } else { if (DEBUG) { @@ -652,19 +652,19 @@ public class CameraDeviceImpl extends CameraDevice { } } - public int setRepeatingRequest(CaptureRequest request, CaptureListener listener, + public int setRepeatingRequest(CaptureRequest request, CaptureCallback callback, Handler handler) throws CameraAccessException { List<CaptureRequest> requestList = new ArrayList<CaptureRequest>(); requestList.add(request); - return submitCaptureRequest(requestList, listener, handler, /*streaming*/true); + return submitCaptureRequest(requestList, callback, handler, /*streaming*/true); } - public int setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener, + public int setRepeatingBurst(List<CaptureRequest> requests, CaptureCallback callback, Handler handler) throws CameraAccessException { if (requests == null || requests.isEmpty()) { throw new IllegalArgumentException("At least one request must be given"); } - return submitCaptureRequest(requests, listener, handler, /*streaming*/true); + return submitCaptureRequest(requests, callback, handler, /*streaming*/true); } public void stopRepeating() throws CameraAccessException { @@ -677,7 +677,7 @@ public class CameraDeviceImpl extends CameraDevice { mRepeatingRequestId = REQUEST_ID_NONE; // Queue for deletion after in-flight requests finish - if (mCaptureListenerMap.get(requestId) != null) { + if (mCaptureCallbackMap.get(requestId) != null) { mRepeatingRequestIdDeletedList.add(requestId); } @@ -782,11 +782,11 @@ public class CameraDeviceImpl extends CameraDevice { } /** - * <p>A listener for tracking the progress of a {@link CaptureRequest} + * <p>A callback for tracking the progress of a {@link CaptureRequest} * submitted to the camera device.</p> * */ - public static abstract class CaptureListener { + public static abstract class CaptureCallback { /** * This constant is used to indicate that no images were captured for @@ -848,9 +848,9 @@ public class CameraDeviceImpl extends CameraDevice { } /** - * This method is called independently of the others in CaptureListener, + * This method is called independently of the others in CaptureCallback, * when a capture sequence finishes and all {@link CaptureResult} - * or {@link CaptureFailure} for it have been returned via this listener. + * or {@link CaptureFailure} for it have been returned via this callback. */ public void onCaptureSequenceCompleted(CameraDevice camera, int sequenceId, long frameNumber) { @@ -858,9 +858,9 @@ public class CameraDeviceImpl extends CameraDevice { } /** - * This method is called independently of the others in CaptureListener, + * This method is called independently of the others in CaptureCallback, * when a capture sequence aborts before any {@link CaptureResult} - * or {@link CaptureFailure} for it have been returned via this listener. + * or {@link CaptureFailure} for it have been returned via this callback. */ public void onCaptureSequenceAborted(CameraDevice camera, int sequenceId) { @@ -869,10 +869,10 @@ public class CameraDeviceImpl extends CameraDevice { } /** - * A listener for notifications about the state of a camera device, adding in the callbacks that + * A callback for notifications about the state of a camera device, adding in the callbacks that * were part of the earlier KK API design, but now only used internally. */ - public static abstract class StateListenerKK extends StateListener { + public static abstract class StateCallbackKK extends StateCallback { /** * The method called when a camera device has no outputs configured. * @@ -908,31 +908,31 @@ public class CameraDeviceImpl extends CameraDevice { } } - static class CaptureListenerHolder { + static class CaptureCallbackHolder { private final boolean mRepeating; - private final CaptureListener mListener; + private final CaptureCallback mCallback; private final List<CaptureRequest> mRequestList; private final Handler mHandler; - CaptureListenerHolder(CaptureListener listener, List<CaptureRequest> requestList, + CaptureCallbackHolder(CaptureCallback callback, List<CaptureRequest> requestList, Handler handler, boolean repeating) { - if (listener == null || handler == null) { + if (callback == null || handler == null) { throw new UnsupportedOperationException( - "Must have a valid handler and a valid listener"); + "Must have a valid handler and a valid callback"); } mRepeating = repeating; mHandler = handler; mRequestList = new ArrayList<CaptureRequest>(requestList); - mListener = listener; + mCallback = callback; } public boolean isRepeating() { return mRepeating; } - public CaptureListener getListener() { - return mListener; + public CaptureCallback getCallback() { + return mCallback; } public CaptureRequest getRequest(int subsequenceId) { @@ -1071,20 +1071,20 @@ public class CameraDeviceImpl extends CameraDevice { final SimpleEntry<Long, Integer> frameNumberRequestPair = iter.next(); if (frameNumberRequestPair.getKey() <= completedFrameNumber) { - // remove request from mCaptureListenerMap + // remove request from mCaptureCallbackMap final int requestId = frameNumberRequestPair.getValue(); - final CaptureListenerHolder holder; + final CaptureCallbackHolder holder; synchronized(mInterfaceLock) { if (mRemoteDevice == null) { Log.w(TAG, "Camera closed while checking sequences"); return; } - int index = mCaptureListenerMap.indexOfKey(requestId); - holder = (index >= 0) ? mCaptureListenerMap.valueAt(index) + int index = mCaptureCallbackMap.indexOfKey(requestId); + holder = (index >= 0) ? mCaptureCallbackMap.valueAt(index) : null; if (holder != null) { - mCaptureListenerMap.removeAt(index); + mCaptureCallbackMap.removeAt(index); if (DEBUG) { Log.v(TAG, String.format( "remove holder for requestId %d, " @@ -1114,7 +1114,7 @@ public class CameraDeviceImpl extends CameraDevice { throw new AssertionError(lastFrameNumber + " cannot be cast to int"); } - holder.getListener().onCaptureSequenceCompleted( + holder.getCallback().onCaptureSequenceCompleted( CameraDeviceImpl.this, requestId, lastFrameNumber); @@ -1146,13 +1146,13 @@ public class CameraDeviceImpl extends CameraDevice { /** * Camera has encountered a device-level error - * Matches CameraDevice.StateListener#ERROR_CAMERA_DEVICE + * Matches CameraDevice.StateCallback#ERROR_CAMERA_DEVICE */ static final int ERROR_CAMERA_DEVICE = 1; /** * Camera has encountered a service-level error - * Matches CameraDevice.StateListener#ERROR_CAMERA_SERVICE + * Matches CameraDevice.StateCallback#ERROR_CAMERA_SERVICE */ static final int ERROR_CAMERA_SERVICE = 2; @@ -1204,7 +1204,7 @@ public class CameraDeviceImpl extends CameraDevice { @Override public void run() { if (!CameraDeviceImpl.this.isClosed()) { - mDeviceListener.onError(CameraDeviceImpl.this, errorCode); + mDeviceCallback.onError(CameraDeviceImpl.this, errorCode); } } }; @@ -1240,13 +1240,13 @@ public class CameraDeviceImpl extends CameraDevice { if (DEBUG) { Log.d(TAG, "Capture started for id " + requestId); } - final CaptureListenerHolder holder; + final CaptureCallbackHolder holder; synchronized(mInterfaceLock) { if (mRemoteDevice == null) return; // Camera already closed - // Get the listener for this frame ID, if there is one - holder = CameraDeviceImpl.this.mCaptureListenerMap.get(requestId); + // Get the callback for this frame ID, if there is one + holder = CameraDeviceImpl.this.mCaptureCallbackMap.get(requestId); if (holder == null) { return; @@ -1260,7 +1260,7 @@ public class CameraDeviceImpl extends CameraDevice { @Override public void run() { if (!CameraDeviceImpl.this.isClosed()) { - holder.getListener().onCaptureStarted( + holder.getCallback().onCaptureStarted( CameraDeviceImpl.this, holder.getRequest(resultExtras.getSubsequenceId()), timestamp); @@ -1290,13 +1290,13 @@ public class CameraDeviceImpl extends CameraDevice { result.set(CameraCharacteristics.LENS_INFO_SHADING_MAP_SIZE, getCharacteristics().get(CameraCharacteristics.LENS_INFO_SHADING_MAP_SIZE)); - final CaptureListenerHolder holder = - CameraDeviceImpl.this.mCaptureListenerMap.get(requestId); + final CaptureCallbackHolder holder = + CameraDeviceImpl.this.mCaptureCallbackMap.get(requestId); boolean isPartialResult = (resultExtras.getPartialResultCount() < mTotalPartialCount); - // Check if we have a listener for this + // Check if we have a callback for this if (holder == null) { if (DEBUG) { Log.d(TAG, @@ -1336,7 +1336,7 @@ public class CameraDeviceImpl extends CameraDevice { @Override public void run() { if (!CameraDeviceImpl.this.isClosed()){ - holder.getListener().onCaptureProgressed( + holder.getCallback().onCaptureProgressed( CameraDeviceImpl.this, request, resultAsCapture); @@ -1357,7 +1357,7 @@ public class CameraDeviceImpl extends CameraDevice { @Override public void run() { if (!CameraDeviceImpl.this.isClosed()){ - holder.getListener().onCaptureCompleted( + holder.getCallback().onCaptureCompleted( CameraDeviceImpl.this, request, resultAsCapture); @@ -1388,8 +1388,8 @@ public class CameraDeviceImpl extends CameraDevice { final int requestId = resultExtras.getRequestId(); final int subsequenceId = resultExtras.getSubsequenceId(); final long frameNumber = resultExtras.getFrameNumber(); - final CaptureListenerHolder holder = - CameraDeviceImpl.this.mCaptureListenerMap.get(requestId); + final CaptureCallbackHolder holder = + CameraDeviceImpl.this.mCaptureCallbackMap.get(requestId); final CaptureRequest request = holder.getRequest(subsequenceId); @@ -1420,7 +1420,7 @@ public class CameraDeviceImpl extends CameraDevice { @Override public void run() { if (!CameraDeviceImpl.this.isClosed()){ - holder.getListener().onCaptureFailed( + holder.getCallback().onCaptureFailed( CameraDeviceImpl.this, request, failure); @@ -1460,12 +1460,12 @@ public class CameraDeviceImpl extends CameraDevice { } /** - * Default handler management, conditional on there being a listener. + * Default handler management, conditional on there being a callback. * - * <p>If the listener isn't null, check the handler, otherwise pass it through.</p> + * <p>If the callback isn't null, check the handler, otherwise pass it through.</p> */ - static <T> Handler checkHandler(Handler handler, T listener) { - if (listener != null) { + static <T> Handler checkHandler(Handler handler, T callback) { + if (callback != null) { return checkHandler(handler); } return handler; diff --git a/core/java/android/hardware/camera2/legacy/GLThreadManager.java b/core/java/android/hardware/camera2/legacy/GLThreadManager.java index 06521cf..2c584ef 100644 --- a/core/java/android/hardware/camera2/legacy/GLThreadManager.java +++ b/core/java/android/hardware/camera2/legacy/GLThreadManager.java @@ -121,9 +121,10 @@ public class GLThreadManager { * Create a new GL thread and renderer. * * @param cameraId the camera id for this thread. + * @param facing direction the camera is facing. */ - public GLThreadManager(int cameraId) { - mTextureRenderer = new SurfaceTextureRenderer(); + public GLThreadManager(int cameraId, int facing) { + mTextureRenderer = new SurfaceTextureRenderer(facing); TAG = String.format("CameraDeviceGLThread-%d", cameraId); mGLHandlerThread = new RequestHandlerThread(TAG, mGLHandlerCb); } diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java index eb8debb..e6ff17b 100644 --- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java +++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java @@ -399,7 +399,7 @@ public class RequestThreadManager { // TODO: Detect and optimize single-output paths here to skip stream teeing. if (mGLThreadManager == null) { - mGLThreadManager = new GLThreadManager(mCameraId); + mGLThreadManager = new GLThreadManager(mCameraId, facing); mGLThreadManager.start(); } mGLThreadManager.waitUntilStarted(); diff --git a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java index b1b0f9b..a35883c 100644 --- a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java +++ b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java @@ -18,6 +18,7 @@ package android.hardware.camera2.legacy; import android.graphics.ImageFormat; import android.graphics.RectF; import android.graphics.SurfaceTexture; +import android.hardware.camera2.CameraCharacteristics; import android.os.Environment; import android.opengl.EGL14; import android.opengl.EGLConfig; @@ -80,7 +81,18 @@ public class SurfaceTextureRenderer { private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES; private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0; private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3; - private final float[] mTriangleVerticesData = { + + // Sampling is mirrored across the vertical axis to undo horizontal flip from the front camera + private static final float[] sFrontCameraTriangleVertices = { + // X, Y, Z, U, V + -1.0f, -1.0f, 0, 1.f, 0.f, + 1.0f, -1.0f, 0, 0.f, 0.f, + -1.0f, 1.0f, 0, 1.f, 1.f, + 1.0f, 1.0f, 0, 0.f, 1.f, + }; + + // Sampling is 1:1 for a straight copy for the back camera + private static final float[] sBackCameraTriangleVertices = { // X, Y, Z, U, V -1.0f, -1.0f, 0, 0.f, 0.f, 1.0f, -1.0f, 0, 1.f, 0.f, @@ -135,10 +147,16 @@ public class SurfaceTextureRenderer { private PerfMeasurement mPerfMeasurer = null; private static final String LEGACY_PERF_PROPERTY = "persist.camera.legacy_perf"; - public SurfaceTextureRenderer() { - mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length * - FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer(); - mTriangleVertices.put(mTriangleVerticesData).position(0); + public SurfaceTextureRenderer(int facing) { + if (facing == CameraCharacteristics.LENS_FACING_BACK) { + mTriangleVertices = ByteBuffer.allocateDirect(sBackCameraTriangleVertices.length * + FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer(); + mTriangleVertices.put(sBackCameraTriangleVertices).position(0); + } else { + mTriangleVertices = ByteBuffer.allocateDirect(sFrontCameraTriangleVertices.length * + FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer(); + mTriangleVertices.put(sFrontCameraTriangleVertices).position(0); + } Matrix.setIdentityM(mSTMatrix, 0); } diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java index 7a49eb5..7390e2b 100644 --- a/core/java/android/hardware/soundtrigger/SoundTrigger.java +++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java @@ -480,7 +480,7 @@ public class SoundTrigger { int capturePreambleMs = in.readInt(); boolean triggerInData = in.readByte() == 1; AudioFormat captureFormat = null; - if (triggerInData) { + if (in.readByte() == 1) { int sampleRate = in.readInt(); int encoding = in.readInt(); int channelMask = in.readInt(); @@ -508,7 +508,8 @@ public class SoundTrigger { dest.writeInt(captureSession); dest.writeInt(captureDelayMs); dest.writeInt(capturePreambleMs); - if (triggerInData && (captureFormat != null)) { + dest.writeByte((byte) (triggerInData ? 1 : 0)); + if (captureFormat != null) { dest.writeByte((byte)1); dest.writeInt(captureFormat.getSampleRate()); dest.writeInt(captureFormat.getEncoding()); diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index fe9f79b..461469c 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -1667,7 +1667,7 @@ public abstract class BatteryStats implements Parcelable { */ public abstract long[] getChargeStepDurationsArray(); - public abstract Map<String, ? extends LongCounter> getWakeupReasonStats(); + public abstract Map<String, ? extends Timer> getWakeupReasonStats(); public abstract Map<String, ? extends Timer> getKernelWakelockStats(); @@ -2045,11 +2045,15 @@ public abstract class BatteryStats implements Parcelable { sb.toString()); } } - Map<String, ? extends LongCounter> wakeupReasons = getWakeupReasonStats(); + Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats(); if (wakeupReasons.size() > 0) { - for (Map.Entry<String, ? extends LongCounter> ent : wakeupReasons.entrySet()) { + for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) { + // Not doing the regular wake lock formatting to remain compatible + // with the old checkin format. + long totalTimeMicros = ent.getValue().getTotalTimeLocked(rawRealtime, which); + int count = ent.getValue().getCountLocked(which); dumpLine(pw, 0 /* uid */, category, WAKEUP_REASON_DATA, - "\"" + ent.getKey() + "\"", ent.getValue().getCountLocked(which)); + "\"" + ent.getKey() + "\"", (totalTimeMicros + 500) / 1000, count); } } } @@ -2921,14 +2925,14 @@ public abstract class BatteryStats implements Parcelable { pw.println(); } - Map<String, ? extends LongCounter> wakeupReasons = getWakeupReasonStats(); + Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats(); if (wakeupReasons.size() > 0) { pw.print(prefix); pw.println(" All wakeup reasons:"); final ArrayList<TimerEntry> reasons = new ArrayList<TimerEntry>(); - for (Map.Entry<String, ? extends LongCounter> ent : wakeupReasons.entrySet()) { - BatteryStats.LongCounter counter = ent.getValue(); - reasons.add(new TimerEntry(ent.getKey(), 0, null, - ent.getValue().getCountLocked(which))); + for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) { + Timer timer = ent.getValue(); + reasons.add(new TimerEntry(ent.getKey(), 0, timer, + timer.getCountLocked(which))); } Collections.sort(reasons, timerComparator); for (int i=0; i<reasons.size(); i++) { @@ -2938,9 +2942,8 @@ public abstract class BatteryStats implements Parcelable { sb.append(prefix); sb.append(" Wakeup reason "); sb.append(timer.mName); - sb.append(": "); - formatTimeMs(sb, timer.mTime); - sb.append("realtime"); + printWakeLock(sb, timer.mTimer, rawRealtime, null, which, ": "); + sb.append(" realtime"); pw.println(sb.toString()); } pw.println(); @@ -3138,7 +3141,7 @@ public abstract class BatteryStats implements Parcelable { } Map<String, ? extends Timer> jobs = u.getJobStats(); - if (syncs.size() > 0) { + if (jobs.size() > 0) { for (Map.Entry<String, ? extends Timer> ent : jobs.entrySet()) { Timer timer = ent.getValue(); // Convert from microseconds to milliseconds with rounding @@ -3952,7 +3955,7 @@ public abstract class BatteryStats implements Parcelable { prepareForDumpLocked(); dumpLine(pw, 0 /* uid */, "i" /* category */, VERSION_DATA, - "10", getParcelVersion(), getStartPlatformVersion(), getEndPlatformVersion()); + "11", getParcelVersion(), getStartPlatformVersion(), getEndPlatformVersion()); long now = getHistoryBaseTime() + SystemClock.elapsedRealtime(); diff --git a/core/java/android/os/FileBridge.java b/core/java/android/os/FileBridge.java index 022a106..0acf24b 100644 --- a/core/java/android/os/FileBridge.java +++ b/core/java/android/os/FileBridge.java @@ -75,6 +75,13 @@ public class FileBridge extends Thread { return mClosed; } + public void forceClose() { + IoUtils.closeQuietly(mTarget); + IoUtils.closeQuietly(mServer); + IoUtils.closeQuietly(mClient); + mClosed = true; + } + public void setTargetFile(FileDescriptor target) { mTarget = target; } @@ -89,7 +96,6 @@ public class FileBridge extends Thread { try { while (IoBridge.read(mServer, temp, 0, MSG_LENGTH) == MSG_LENGTH) { final int cmd = Memory.peekInt(temp, 0, ByteOrder.BIG_ENDIAN); - if (cmd == CMD_WRITE) { // Shuttle data into local file int len = Memory.peekInt(temp, 4, ByteOrder.BIG_ENDIAN); @@ -118,15 +124,10 @@ public class FileBridge extends Thread { } } - } catch (ErrnoException e) { - Log.wtf(TAG, "Failed during bridge", e); - } catch (IOException e) { + } catch (ErrnoException | IOException e) { Log.wtf(TAG, "Failed during bridge", e); } finally { - IoUtils.closeQuietly(mTarget); - IoUtils.closeQuietly(mServer); - IoUtils.closeQuietly(mClient); - mClosed = true; + forceClose(); } } @@ -151,6 +152,7 @@ public class FileBridge extends Thread { writeCommandAndBlock(CMD_CLOSE, "close()"); } finally { IoBridge.closeAndSignalBlockedThreads(mClient); + IoUtils.closeQuietly(mClientPfd); } } diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java index 1a5811c..b6b70cc 100644 --- a/core/java/android/os/Message.java +++ b/core/java/android/os/Message.java @@ -113,6 +113,8 @@ public final class Message implements Parcelable { private static final int MAX_POOL_SIZE = 50; + private static boolean gCheckRecycle = true; + /** * Return a new Message instance from the global pool. Allows us to * avoid allocating new objects in many cases. @@ -256,6 +258,13 @@ public final class Message implements Parcelable { return m; } + /** @hide */ + public static void updateCheckRecycle(int targetSdkVersion) { + if (targetSdkVersion < Build.VERSION_CODES.L) { + gCheckRecycle = false; + } + } + /** * Return a Message instance to the global pool. * <p> @@ -266,8 +275,11 @@ public final class Message implements Parcelable { */ public void recycle() { if (isInUse()) { - throw new IllegalStateException("This message cannot be recycled because it " - + "is still in use."); + if (gCheckRecycle) { + throw new IllegalStateException("This message cannot be recycled because it " + + "is still in use."); + } + return; } recycleUnchecked(); } diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java index 9361286..bf8ac65 100644 --- a/core/java/android/print/PrintManager.java +++ b/core/java/android/print/PrintManager.java @@ -535,7 +535,7 @@ public final class PrintManager { destroyed = isDestroyedLocked(); } - if (destroyed) { + if (destroyed && observer != null) { try { observer.onDestroy(); } catch (RemoteException re) { diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl index 8ca9b6c..e6bf6ba 100644 --- a/core/java/android/service/notification/INotificationListener.aidl +++ b/core/java/android/service/notification/INotificationListener.aidl @@ -16,6 +16,7 @@ package android.service.notification; +import android.service.notification.IStatusBarNotificationHolder; import android.service.notification.StatusBarNotification; import android.service.notification.NotificationRankingUpdate; @@ -23,9 +24,9 @@ import android.service.notification.NotificationRankingUpdate; oneway interface INotificationListener { void onListenerConnected(in NotificationRankingUpdate update); - void onNotificationPosted(in StatusBarNotification notification, + void onNotificationPosted(in IStatusBarNotificationHolder notificationHolder, in NotificationRankingUpdate update); - void onNotificationRemoved(in StatusBarNotification notification, + void onNotificationRemoved(in IStatusBarNotificationHolder notificationHolder, in NotificationRankingUpdate update); void onNotificationRankingUpdate(in NotificationRankingUpdate update); void onListenerHintsChanged(int hints); diff --git a/core/java/android/service/notification/IStatusBarNotificationHolder.aidl b/core/java/android/service/notification/IStatusBarNotificationHolder.aidl new file mode 100644 index 0000000..fd6b59e --- /dev/null +++ b/core/java/android/service/notification/IStatusBarNotificationHolder.aidl @@ -0,0 +1,24 @@ +/** + * 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.service.notification; + +import android.service.notification.StatusBarNotification; + +/** @hide */ +interface IStatusBarNotificationHolder { + StatusBarNotification get(); +} diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java index 2ca8098..d744070 100644 --- a/core/java/android/service/notification/NotificationListenerService.java +++ b/core/java/android/service/notification/NotificationListenerService.java @@ -603,8 +603,15 @@ public abstract class NotificationListenerService extends Service { private class INotificationListenerWrapper extends INotificationListener.Stub { @Override - public void onNotificationPosted(StatusBarNotification sbn, + public void onNotificationPosted(IStatusBarNotificationHolder sbnHolder, NotificationRankingUpdate update) { + StatusBarNotification sbn; + try { + sbn = sbnHolder.get(); + } catch (RemoteException e) { + Log.w(TAG, "onNotificationPosted: Error receiving StatusBarNotification", e); + return; + } Notification.Builder.rebuild(getContext(), sbn.getNotification()); // protect subclass from concurrent modifications of (@link mNotificationKeys}. @@ -618,8 +625,15 @@ public abstract class NotificationListenerService extends Service { } } @Override - public void onNotificationRemoved(StatusBarNotification sbn, + public void onNotificationRemoved(IStatusBarNotificationHolder sbnHolder, NotificationRankingUpdate update) { + StatusBarNotification sbn; + try { + sbn = sbnHolder.get(); + } catch (RemoteException e) { + Log.w(TAG, "onNotificationRemoved: Error receiving StatusBarNotification", e); + return; + } // protect subclass from concurrent modifications of (@link mNotificationKeys}. synchronized (mWrapper) { applyUpdate(update); diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java index 7245975..a4b6e92 100644 --- a/core/java/android/speech/tts/TextToSpeech.java +++ b/core/java/android/speech/tts/TextToSpeech.java @@ -578,7 +578,7 @@ public class TextToSpeech { * * @deprecated Starting from API level 20, to select network synthesis, call * ({@link TextToSpeech#getVoices()}, find a suitable network voice - * ({@link Voice#getRequiresNetworkConnection()}) and pass it + * ({@link Voice#isNetworkConnectionRequired()}) and pass it * to {@link TextToSpeech#setVoice(Voice)}). */ @Deprecated @@ -596,7 +596,7 @@ public class TextToSpeech { * @deprecated Starting from API level 20, to select embedded synthesis, call * ({@link TextToSpeech#getVoices()}, find a suitable embedded voice - * ({@link Voice#getRequiresNetworkConnection()}) and pass it + * ({@link Voice#isNetworkConnectionRequired()}) and pass it * to {@link TextToSpeech#setVoice(Voice)}). */ @Deprecated @@ -957,20 +957,18 @@ public class TextToSpeech { * * @param text * The string of text. Example: <code>"south_south_east"</code> - * @param filename - * The full path to the sound file (for example: - * "/sdcard/mysounds/hello.wav") + * @param file + * File object pointing to the sound file. * * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. */ - public int addSpeech(CharSequence text, String filename) { + public int addSpeech(CharSequence text, File file) { synchronized (mStartLock) { - mUtterances.put(text, Uri.parse(filename)); + mUtterances.put(text, Uri.fromFile(file)); return SUCCESS; } } - /** * Adds a mapping between a string of text and a sound resource in a * package. Use this to add custom earcons. @@ -1017,7 +1015,11 @@ public class TextToSpeech { * "/sdcard/mysounds/tick.wav") * * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. + * + * @deprecated As of API level 20, replaced by + * {@link #addEarcon(String, File)}. */ + @Deprecated public int addEarcon(String earcon, String filename) { synchronized(mStartLock) { mEarcons.put(earcon, Uri.parse(filename)); @@ -1025,6 +1027,27 @@ public class TextToSpeech { } } + /** + * Adds a mapping between a string of text and a sound file. + * Use this to add custom earcons. + * + * @see #playEarcon(String, int, HashMap) + * + * @param earcon + * The name of the earcon. + * Example: <code>"[tick]"</code> + * @param file + * File object pointing to the sound file. + * + * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. + */ + public int addEarcon(String earcon, File file) { + synchronized(mStartLock) { + mEarcons.put(earcon, Uri.fromFile(file)); + return SUCCESS; + } + } + private Uri makeResourceUri(String packageName, int resourceId) { return new Uri.Builder() .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) @@ -1061,7 +1084,7 @@ public class TextToSpeech { */ public int speak(final CharSequence text, final int queueMode, - final HashMap<String, String> params, + final Bundle params, final String utteranceId) { return runAction(new Action<Integer>() { @Override @@ -1103,11 +1126,11 @@ public class TextToSpeech { * * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the speak operation. * @deprecated As of API level 20, replaced by - * {@link #speak(CharSequence, int, HashMap, String)}. + * {@link #speak(CharSequence, int, Bundle, String)}. */ @Deprecated public int speak(final String text, final int queueMode, final HashMap<String, String> params) { - return speak(text, queueMode, params, + return speak(text, queueMode, convertParamsHashMaptoBundle(params), params == null ? null : params.get(Engine.KEY_PARAM_UTTERANCE_ID)); } @@ -1135,7 +1158,7 @@ public class TextToSpeech { * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playEarcon operation. */ public int playEarcon(final String earcon, final int queueMode, - final HashMap<String, String> params, final String utteranceId) { + final Bundle params, final String utteranceId) { return runAction(new Action<Integer>() { @Override public Integer run(ITextToSpeechService service) throws RemoteException { @@ -1173,12 +1196,12 @@ public class TextToSpeech { * * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playEarcon operation. * @deprecated As of API level 20, replaced by - * {@link #playEarcon(String, int, HashMap, String)}. + * {@link #playEarcon(String, int, Bundle, String)}. */ @Deprecated public int playEarcon(final String earcon, final int queueMode, final HashMap<String, String> params) { - return playEarcon(earcon, queueMode, params, + return playEarcon(earcon, queueMode, convertParamsHashMaptoBundle(params), params == null ? null : params.get(Engine.KEY_PARAM_UTTERANCE_ID)); } @@ -1757,22 +1780,20 @@ public class TextToSpeech { * must be prefixed by the name of the engine they are intended for. For example * the keys "com.svox.pico_foo" and "com.svox.pico:bar" will be passed to the * engine named "com.svox.pico" if it is being used. - * @param filename Absolute file filename to write the generated audio data to.It should be - * something like "/sdcard/myappsounds/mysound.wav". + * @param file File to write the generated audio data to. * @param utteranceId An unique identifier for this request. * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the synthesizeToFile operation. */ - public int synthesizeToFile(final CharSequence text, final HashMap<String, String> params, - final String filename, final String utteranceId) { + public int synthesizeToFile(final CharSequence text, final Bundle params, + final File file, final String utteranceId) { return runAction(new Action<Integer>() { @Override public Integer run(ITextToSpeechService service) throws RemoteException { ParcelFileDescriptor fileDescriptor; int returnValue; try { - File file = new File(filename); if(file.exists() && !file.canWrite()) { - Log.e(TAG, "Can't write to " + filename); + Log.e(TAG, "Can't write to " + file); return ERROR; } fileDescriptor = ParcelFileDescriptor.open(file, @@ -1784,10 +1805,10 @@ public class TextToSpeech { fileDescriptor.close(); return returnValue; } catch (FileNotFoundException e) { - Log.e(TAG, "Opening file " + filename + " failed", e); + Log.e(TAG, "Opening file " + file + " failed", e); return ERROR; } catch (IOException e) { - Log.e(TAG, "Closing file " + filename + " failed", e); + Log.e(TAG, "Closing file " + file + " failed", e); return ERROR; } } @@ -1817,16 +1838,18 @@ public class TextToSpeech { * * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the synthesizeToFile operation. * @deprecated As of API level 20, replaced by - * {@link #synthesizeToFile(CharSequence, HashMap, String, String)}. + * {@link #synthesizeToFile(CharSequence, Bundle, File, String)}. */ + @Deprecated public int synthesizeToFile(final String text, final HashMap<String, String> params, final String filename) { - return synthesizeToFile(text, params, filename, params.get(Engine.KEY_PARAM_UTTERANCE_ID)); + return synthesizeToFile(text, convertParamsHashMaptoBundle(params), + new File(filename), params.get(Engine.KEY_PARAM_UTTERANCE_ID)); } - private Bundle getParams(HashMap<String, String> params) { + private Bundle convertParamsHashMaptoBundle(HashMap<String, String> params) { if (params != null && !params.isEmpty()) { - Bundle bundle = new Bundle(mParams); + Bundle bundle = new Bundle(); copyIntParam(bundle, params, Engine.KEY_PARAM_STREAM); copyIntParam(bundle, params, Engine.KEY_PARAM_SESSION_ID); copyStringParam(bundle, params, Engine.KEY_PARAM_UTTERANCE_ID); @@ -1852,11 +1875,85 @@ public class TextToSpeech { } return bundle; + } + return null; + } + + private Bundle getParams(Bundle params) { + if (params != null && !params.isEmpty()) { + Bundle bundle = new Bundle(mParams); + bundle.putAll(params); + + verifyIntegerBundleParam(bundle, Engine.KEY_PARAM_STREAM); + verifyIntegerBundleParam(bundle, Engine.KEY_PARAM_SESSION_ID); + verifyStringBundleParam(bundle, Engine.KEY_PARAM_UTTERANCE_ID); + verifyFloatBundleParam(bundle, Engine.KEY_PARAM_VOLUME); + verifyFloatBundleParam(bundle, Engine.KEY_PARAM_PAN); + + // Copy feature strings defined by the framework. + verifyBooleanBundleParam(bundle, Engine.KEY_FEATURE_NETWORK_SYNTHESIS); + verifyBooleanBundleParam(bundle, Engine.KEY_FEATURE_EMBEDDED_SYNTHESIS); + verifyIntegerBundleParam(bundle, Engine.KEY_FEATURE_NETWORK_TIMEOUT_MS); + verifyIntegerBundleParam(bundle, Engine.KEY_FEATURE_NETWORK_RETRIES_COUNT); + + return bundle; } else { return mParams; } } + private static boolean verifyIntegerBundleParam(Bundle bundle, String key) { + if (bundle.containsKey(key)) { + if (!(bundle.get(key) instanceof Integer || + bundle.get(key) instanceof Long)) { + bundle.remove(key); + Log.w(TAG, "Synthesis request paramter " + key + " containst value " + + " with invalid type. Should be an Integer or a Long"); + return false; + } + } + return true; + } + + private static boolean verifyStringBundleParam(Bundle bundle, String key) { + if (bundle.containsKey(key)) { + if (!(bundle.get(key) instanceof String)) { + bundle.remove(key); + Log.w(TAG, "Synthesis request paramter " + key + " containst value " + + " with invalid type. Should be a String"); + return false; + } + } + return true; + } + + private static boolean verifyBooleanBundleParam(Bundle bundle, String key) { + if (bundle.containsKey(key)) { + if (!(bundle.get(key) instanceof Boolean || + bundle.get(key) instanceof String)) { + bundle.remove(key); + Log.w(TAG, "Synthesis request paramter " + key + " containst value " + + " with invalid type. Should be a Boolean or String"); + return false; + } + } + return true; + } + + + private static boolean verifyFloatBundleParam(Bundle bundle, String key) { + if (bundle.containsKey(key)) { + if (!(bundle.get(key) instanceof Float || + bundle.get(key) instanceof Double)) { + bundle.remove(key); + Log.w(TAG, "Synthesis request paramter " + key + " containst value " + + " with invalid type. Should be a Float or a Double"); + return false; + } + } + return true; + } + private void copyStringParam(Bundle bundle, HashMap<String, String> params, String key) { String value = params.get(key); if (value != null) { diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java index 4fea109..d00a433 100644 --- a/core/java/android/speech/tts/TextToSpeechService.java +++ b/core/java/android/speech/tts/TextToSpeechService.java @@ -84,7 +84,7 @@ import java.util.Set; * the following methods: * <ul> * <li>{@link #onGetVoices()}</li> - * <li>{@link #isValidVoiceName(String)}</li> + * <li>{@link #onIsValidVoiceName(String)}</li> * <li>{@link #onLoadVoice(String)}</li> * <li>{@link #onGetDefaultVoiceNameFor(String, String, String)}</li> * </ul> @@ -278,7 +278,7 @@ public abstract class TextToSpeechService extends Service { * * @return A list of voices supported. */ - protected List<Voice> onGetVoices() { + public List<Voice> onGetVoices() { // Enumerate all locales and check if they are available ArrayList<Voice> voices = new ArrayList<Voice>(); for (Locale locale : Locale.getAvailableLocales()) { @@ -335,7 +335,7 @@ public abstract class TextToSpeechService extends Service { } Locale properLocale = TtsEngines.normalizeTTSLocale(iso3Locale); String voiceName = properLocale.toLanguageTag(); - if (isValidVoiceName(voiceName) == TextToSpeech.SUCCESS) { + if (onIsValidVoiceName(voiceName) == TextToSpeech.SUCCESS) { return voiceName; } else { return null; @@ -357,7 +357,7 @@ public abstract class TextToSpeechService extends Service { * @param voiceName Name of the voice. * @return {@link TextToSpeech#ERROR} or {@link TextToSpeech#SUCCESS}. */ - protected int onLoadVoice(String voiceName) { + public int onLoadVoice(String voiceName) { Locale locale = Locale.forLanguageTag(voiceName); if (locale == null) { return TextToSpeech.ERROR; @@ -388,7 +388,7 @@ public abstract class TextToSpeechService extends Service { * @param voiceName Name of the voice. * @return {@link TextToSpeech#ERROR} or {@link TextToSpeech#SUCCESS}. */ - protected int isValidVoiceName(String voiceName) { + public int onIsValidVoiceName(String voiceName) { Locale locale = Locale.forLanguageTag(voiceName); if (locale == null) { return TextToSpeech.ERROR; @@ -1275,7 +1275,7 @@ public abstract class TextToSpeechService extends Service { if (!checkNonNull(voiceName)) { return TextToSpeech.ERROR; } - int retVal = isValidVoiceName(voiceName); + int retVal = onIsValidVoiceName(voiceName); if (retVal == TextToSpeech.SUCCESS) { SpeechItem item = new LoadVoiceItem(caller, Binder.getCallingUid(), diff --git a/core/java/android/speech/tts/Voice.java b/core/java/android/speech/tts/Voice.java index a97141c..a1fa51d 100644 --- a/core/java/android/speech/tts/Voice.java +++ b/core/java/android/speech/tts/Voice.java @@ -162,7 +162,7 @@ public class Voice implements Parcelable { /** * @return Does the Voice require a network connection to work. */ - public boolean getRequiresNetworkConnection() { + public boolean isNetworkConnectionRequired() { return mRequiresNetworkConnection; } diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java index 0d1b568..40bb6ec 100644 --- a/core/java/android/transition/Transition.java +++ b/core/java/android/transition/Transition.java @@ -1417,9 +1417,9 @@ public abstract class Transition implements Cloneable { } capturePropagationValues(values); if (start) { - addViewValues(mStartValues, view, values); + addViewValues(mStartValues, view, values, true); } else { - addViewValues(mEndValues, view, values); + addViewValues(mEndValues, view, values, true); } } } @@ -1460,7 +1460,7 @@ public abstract class Transition implements Cloneable { } static void addViewValues(TransitionValuesMaps transitionValuesMaps, - View view, TransitionValues transitionValues) { + View view, TransitionValues transitionValues, boolean setTransientState) { transitionValuesMaps.viewValues.put(view, transitionValues); int id = view.getId(); if (id >= 0) { @@ -1489,11 +1489,15 @@ public abstract class Transition implements Cloneable { // Duplicate item IDs: cannot match by item ID. View alreadyMatched = transitionValuesMaps.itemIdValues.get(itemId); if (alreadyMatched != null) { - alreadyMatched.setHasTransientState(false); + if (setTransientState) { + alreadyMatched.setHasTransientState(false); + } transitionValuesMaps.itemIdValues.put(itemId, null); } } else { - view.setHasTransientState(true); + if (setTransientState) { + view.setHasTransientState(true); + } transitionValuesMaps.itemIdValues.put(itemId, view); } } @@ -1560,9 +1564,9 @@ public abstract class Transition implements Cloneable { } capturePropagationValues(values); if (start) { - addViewValues(mStartValues, view, values); + addViewValues(mStartValues, view, values, true); } else { - addViewValues(mEndValues, view, values); + addViewValues(mEndValues, view, values, true); } } if (view instanceof ViewGroup) { diff --git a/core/java/android/transition/TransitionSet.java b/core/java/android/transition/TransitionSet.java index f6499ae..56db674 100644 --- a/core/java/android/transition/TransitionSet.java +++ b/core/java/android/transition/TransitionSet.java @@ -408,7 +408,7 @@ public class TransitionSet extends Transition { for (int i = 0; i < numValues; i++) { View view = values.viewValues.keyAt(i); if (isValidTarget(view)) { - addViewValues(included, view, values.viewValues.valueAt(i)); + addViewValues(included, view, values.viewValues.valueAt(i), false); } } return included; diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java index 0b02552..d648ca6 100644 --- a/core/java/android/transition/Visibility.java +++ b/core/java/android/transition/Visibility.java @@ -358,12 +358,16 @@ public abstract class Visibility extends Transition { overlayView = startView; } else if (startView.getParent() instanceof View) { View startParent = (View) startView.getParent(); - if (!isValidTarget(startParent)) { - if (startView.isAttachedToWindow()) { - overlayView = copyViewImage(startView); - } else { - overlayView = startView; - } + VisibilityInfo parentVisibilityInfo = null; + TransitionValues endParentValues = getMatchedTransitionValues(startParent, + true); + if (endParentValues != null) { + TransitionValues startParentValues = getTransitionValues(startParent, true); + parentVisibilityInfo = + getVisibilityChangeInfo(startParentValues, endParentValues); + } + if (parentVisibilityInfo == null || !parentVisibilityInfo.visibilityChange) { + overlayView = copyViewImage(startView); } else if (startParent.getParent() == null) { int id = startParent.getId(); if (id != View.NO_ID && sceneRoot.findViewById(id) != null diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 5d6d998..6aa86c7 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -94,7 +94,8 @@ interface IWindowManager void overridePendingAppTransitionThumb(in Bitmap srcThumb, int startX, int startY, IRemoteCallback startedCallback, boolean scaleUp); void overridePendingAppTransitionAspectScaledThumb(in Bitmap srcThumb, int startX, - int startY, IRemoteCallback startedCallback, boolean scaleUp); + int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback, + boolean scaleUp); void executeAppTransition(); void setAppStartingWindow(IBinder token, String pkg, int theme, in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java index 9dc9766..47f72a8 100644 --- a/core/java/android/view/RenderNode.java +++ b/core/java/android/view/RenderNode.java @@ -367,6 +367,10 @@ public class RenderNode { throw new IllegalArgumentException("Unrecognized outline?"); } + public boolean hasShadow() { + return nHasShadow(mNativeRenderNode); + } + /** * Enables or disables clipping to the outline. * @@ -861,6 +865,7 @@ public class RenderNode { float alpha); private static native boolean nSetOutlineEmpty(long renderNode); private static native boolean nSetOutlineNone(long renderNode); + private static native boolean nHasShadow(long renderNode); private static native boolean nSetClipToOutline(long renderNode, boolean clipToOutline); private static native boolean nSetRevealClip(long renderNode, boolean shouldClip, float x, float y, float radius); diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java index fa4a13a..debf45d 100644 --- a/core/java/android/view/RenderNodeAnimator.java +++ b/core/java/android/view/RenderNodeAnimator.java @@ -453,6 +453,12 @@ public class RenderNodeAnimator extends Animator { throw new IllegalStateException("Cannot clone this animator"); } + @Override + public void setAllowRunningAsynchronously(boolean mayRunAsync) { + checkMutable(); + nSetAllowRunningAsync(mNativePtr.get(), mayRunAsync); + } + private static native long nCreateAnimator(int property, float finalValue); private static native long nCreateCanvasPropertyFloatAnimator( long canvasProperty, float finalValue); @@ -466,6 +472,7 @@ public class RenderNodeAnimator extends Animator { private static native long nGetDuration(long nativePtr); private static native void nSetStartDelay(long nativePtr, long startDelay); private static native void nSetInterpolator(long animPtr, long interpolatorPtr); + private static native void nSetAllowRunningAsync(long animPtr, boolean mayRunAsync); private static native void nStart(long animPtr, RenderNodeAnimator finishListener); private static native void nEnd(long animPtr); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 92ad4e8..770e78c 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -10224,6 +10224,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * * @return true if the content in this view might overlap, false otherwise. */ + @ViewDebug.ExportedProperty(category = "drawing") public boolean hasOverlappingRendering() { return true; } @@ -10926,6 +10927,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidateViewProperty(false, false); } + /** + * HierarchyViewer only + * + * @hide + */ + @ViewDebug.ExportedProperty(category = "drawing") + public boolean hasShadow() { + return mRenderNode.hasShadow(); + } + + /** @hide */ public void setRevealClip(boolean shouldClip, float x, float y, float radius) { mRenderNode.setRevealClip(shouldClip, x, y, radius); diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index 6c66eb0..a94f973 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -26,6 +26,7 @@ import android.os.Handler; import android.os.RemoteException; import android.util.DisplayMetrics; import android.util.Log; +import android.util.TypedValue; import java.io.BufferedOutputStream; import java.io.BufferedWriter; @@ -315,6 +316,7 @@ public class ViewDebug { private static final String REMOTE_COMMAND_CAPTURE = "CAPTURE"; private static final String REMOTE_COMMAND_DUMP = "DUMP"; + private static final String REMOTE_COMMAND_DUMP_THEME = "DUMP_THEME"; private static final String REMOTE_COMMAND_INVALIDATE = "INVALIDATE"; private static final String REMOTE_COMMAND_REQUEST_LAYOUT = "REQUEST_LAYOUT"; private static final String REMOTE_PROFILE = "PROFILE"; @@ -430,6 +432,8 @@ public class ViewDebug { if (REMOTE_COMMAND_DUMP.equalsIgnoreCase(command)) { dump(view, false, true, clientStream); + } else if (REMOTE_COMMAND_DUMP_THEME.equalsIgnoreCase(command)) { + dumpTheme(view, clientStream); } else if (REMOTE_COMMAND_CAPTURE_LAYERS.equalsIgnoreCase(command)) { captureLayers(view, new DataOutputStream(clientStream)); } else { @@ -820,6 +824,64 @@ public class ViewDebug { } } + /** + * Dumps the theme attributes from the given View. + * @hide + */ + public static void dumpTheme(View view, OutputStream clientStream) throws IOException { + BufferedWriter out = null; + try { + out = new BufferedWriter(new OutputStreamWriter(clientStream, "utf-8"), 32 * 1024); + String[] attributes = getStyleAttributesDump(view.getContext().getResources(), + view.getContext().getTheme()); + if (attributes != null) { + for (int i = 0; i < attributes.length; i += 2) { + if (attributes[i] != null) { + out.write(attributes[i] + "\n"); + out.write(attributes[i + 1] + "\n"); + } + } + } + out.write("DONE."); + out.newLine(); + } catch (Exception e) { + android.util.Log.w("View", "Problem dumping View Theme:", e); + } finally { + if (out != null) { + out.close(); + } + } + } + + /** + * Gets the style attributes from the {@link Resources.Theme}. For debugging only. + * + * @param resources Resources to resolve attributes from. + * @param theme Theme to dump. + * @return a String array containing pairs of adjacent Theme attribute data: name followed by + * its value. + * + * @hide + */ + private static String[] getStyleAttributesDump(Resources resources, Resources.Theme theme) { + TypedValue outValue = new TypedValue(); + String nullString = "null"; + int i = 0; + int[] attributes = theme.getAllAttributes(); + String[] data = new String[attributes.length * 2]; + for (int attributeId : attributes) { + try { + data[i] = resources.getResourceName(attributeId); + data[i + 1] = theme.resolveAttribute(attributeId, outValue, true) ? + outValue.coerceToString().toString() : nullString; + i += 2; + } catch (Resources.NotFoundException e) { + // ignore resources we can't resolve + } + } + return data; + } + private static View findView(ViewGroup group, String className, int hashCode) { if (isRequestedView(group, className, hashCode)) { return group; diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 974fe4e..c1e66de 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -3301,6 +3301,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * @return True if the group's children will be clipped to their bounds, * false otherwise. */ + @ViewDebug.ExportedProperty(category = "drawing") public boolean getClipChildren() { return ((mGroupFlags & FLAG_CLIP_CHILDREN) != 0); } @@ -3349,6 +3350,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * * @attr ref android.R.styleable#ViewGroup_clipToPadding */ + @ViewDebug.ExportedProperty(category = "drawing") public boolean getClipToPadding() { return hasBooleanFlag(FLAG_CLIP_TO_PADDING); } @@ -5722,6 +5724,28 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } @Override + public void drawableHotspotChanged(float x, float y) { + super.drawableHotspotChanged(x, y); + + if ((mGroupFlags & FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE) != 0) { + if ((mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) != 0) { + throw new IllegalStateException("addStateFromChildren cannot be enabled if a" + + " child has duplicateParentState set to true"); + } + + final View[] children = mChildren; + final int count = mChildrenCount; + + for (int i = 0; i < count; i++) { + final View child = children[i]; + if ((child.mViewFlags & DUPLICATE_PARENT_STATE) != 0) { + child.drawableHotspotChanged(x, y); + } + } + } + } + + @Override protected int[] onCreateDrawableState(int extraSpace) { if ((mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) == 0) { return super.onCreateDrawableState(extraSpace); diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index b7b12a8..2ed125d 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -770,7 +770,8 @@ public interface WindowManagerPolicy { public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags); /** - * Called from the input reader thread before a motion is enqueued when the screen is off. + * Called from the input reader thread before a motion is enqueued when the device is in a + * non-interactive state. * * <p>There are some actions that need to be handled here because they * affect the power state of the device, for example, waking on motions. @@ -780,7 +781,7 @@ public interface WindowManagerPolicy { * * @return Actions flags: may be {@link #ACTION_PASS_TO_USER}. */ - public int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags); + public int interceptMotionBeforeQueueingNonInteractive(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/inputmethod/CursorAnchorInfo.java b/core/java/android/view/inputmethod/CursorAnchorInfo.java index fe0f5b9..600fffe 100644 --- a/core/java/android/view/inputmethod/CursorAnchorInfo.java +++ b/core/java/android/view/inputmethod/CursorAnchorInfo.java @@ -35,9 +35,21 @@ import java.util.Objects; * actually inserted.</p> */ public final class CursorAnchorInfo implements Parcelable { + /** + * The index of the first character of the selected text (inclusive). {@code -1} when there is + * no text selection. + */ private final int mSelectionStart; + /** + * The index of the first character of the selected text (exclusive). {@code -1} when there is + * no text selection. + */ private final int mSelectionEnd; + /** + * The index of the first character of the composing text (inclusive). {@code -1} when there is + * no composing text. + */ private final int mComposingTextStart; /** * The text, tracked as a composing region. @@ -82,7 +94,7 @@ public final class CursorAnchorInfo implements Parcelable { * Java chars, in the local coordinates that will be transformed with the transformation matrix * when rendered on the screen. */ - private final SparseRectFArray mCharacterRects; + private final SparseRectFArray mCharacterBoundsArray; /** * Transformation matrix that is applied to any positional information of this class to @@ -91,18 +103,24 @@ public final class CursorAnchorInfo implements Parcelable { private final Matrix mMatrix; /** - * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterRectFlags(int)}: the + * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterBoundsFlags(int)}: the * insertion marker or character bounds have at least one visible region. */ public static final int FLAG_HAS_VISIBLE_REGION = 0x01; /** - * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterRectFlags(int)}: the + * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterBoundsFlags(int)}: the * insertion marker or character bounds have at least one invisible (clipped) region. */ public static final int FLAG_HAS_INVISIBLE_REGION = 0x02; /** + * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterBoundsFlags(int)}: the + * insertion marker or character bounds is placed at right-to-left (RTL) character. + */ + public static final int FLAG_IS_RTL = 0x04; + + /** * @removed */ public static final int CHARACTER_RECT_TYPE_MASK = 0x0f; @@ -144,7 +162,7 @@ public final class CursorAnchorInfo implements Parcelable { mInsertionMarkerTop = source.readFloat(); mInsertionMarkerBaseline = source.readFloat(); mInsertionMarkerBottom = source.readFloat(); - mCharacterRects = source.readParcelable(SparseRectFArray.class.getClassLoader()); + mCharacterBoundsArray = source.readParcelable(SparseRectFArray.class.getClassLoader()); mMatrix = new Matrix(); mMatrix.setValues(source.createFloatArray()); } @@ -166,7 +184,7 @@ public final class CursorAnchorInfo implements Parcelable { dest.writeFloat(mInsertionMarkerTop); dest.writeFloat(mInsertionMarkerBaseline); dest.writeFloat(mInsertionMarkerBottom); - dest.writeParcelable(mCharacterRects, flags); + dest.writeParcelable(mCharacterBoundsArray, flags); final float[] matrixArray = new float[9]; mMatrix.getValues(matrixArray); dest.writeFloatArray(matrixArray); @@ -174,7 +192,6 @@ public final class CursorAnchorInfo implements Parcelable { @Override public int hashCode(){ - // TODO: Improve the hash function. final float floatHash = mInsertionMarkerHorizontal + mInsertionMarkerTop + mInsertionMarkerBaseline + mInsertionMarkerBottom; int hash = floatHash > 0 ? (int) floatHash : (int)(-floatHash); @@ -185,7 +202,7 @@ public final class CursorAnchorInfo implements Parcelable { hash *= 31; hash += Objects.hashCode(mComposingText); hash *= 31; - hash += Objects.hashCode(mCharacterRects); + hash += Objects.hashCode(mCharacterBoundsArray); hash *= 31; hash += Objects.hashCode(mMatrix); return hash; @@ -231,7 +248,7 @@ public final class CursorAnchorInfo implements Parcelable { || !areSameFloatImpl(mInsertionMarkerBottom, that.mInsertionMarkerBottom)) { return false; } - if (!Objects.equals(mCharacterRects, that.mCharacterRects)) { + if (!Objects.equals(mCharacterBoundsArray, that.mCharacterBoundsArray)) { return false; } if (!Objects.equals(mMatrix, that.mMatrix)) { @@ -250,7 +267,7 @@ public final class CursorAnchorInfo implements Parcelable { + " mInsertionMarkerTop=" + mInsertionMarkerTop + " mInsertionMarkerBaseline=" + mInsertionMarkerBaseline + " mInsertionMarkerBottom=" + mInsertionMarkerBottom - + " mCharacterRects=" + Objects.toString(mCharacterRects) + + " mCharacterBoundsArray=" + Objects.toString(mCharacterBoundsArray) + " mMatrix=" + Objects.toString(mMatrix) + "}"; } @@ -259,6 +276,19 @@ public final class CursorAnchorInfo implements Parcelable { * Builder for {@link CursorAnchorInfo}. This class is not designed to be thread-safe. */ public static final class Builder { + private int mSelectionStart = -1; + private int mSelectionEnd = -1; + private int mComposingTextStart = -1; + private CharSequence mComposingText = null; + private float mInsertionMarkerHorizontal = Float.NaN; + private float mInsertionMarkerTop = Float.NaN; + private float mInsertionMarkerBaseline = Float.NaN; + private float mInsertionMarkerBottom = Float.NaN; + private int mInsertionMarkerFlags = 0; + private SparseRectFArrayBuilder mCharacterBoundsArrayBuilder = null; + private final Matrix mMatrix = new Matrix(Matrix.IDENTITY_MATRIX); + private boolean mMatrixInitialized = false; + /** * Sets the text range of the selection. Calling this can be skipped if there is no * selection. @@ -268,8 +298,6 @@ public final class CursorAnchorInfo implements Parcelable { mSelectionEnd = newEnd; return this; } - private int mSelectionStart = -1; - private int mSelectionEnd = -1; /** * Sets the text range of the composing text. Calling this can be skipped if there is @@ -288,8 +316,6 @@ public final class CursorAnchorInfo implements Parcelable { } return this; } - private int mComposingTextStart = -1; - private CharSequence mComposingText = null; /** * @removed @@ -335,11 +361,33 @@ public final class CursorAnchorInfo implements Parcelable { mInsertionMarkerFlags = flags; return this; } - private float mInsertionMarkerHorizontal = Float.NaN; - private float mInsertionMarkerTop = Float.NaN; - private float mInsertionMarkerBaseline = Float.NaN; - private float mInsertionMarkerBottom = Float.NaN; - private int mInsertionMarkerFlags = 0; + + /** + * Adds the bounding box of the character specified with the index. + * + * @param index index of the character in Java chars units. Must be specified in + * ascending order across successive calls. + * @param left x coordinate of the left edge of the character in local coordinates. + * @param top y coordinate of the top edge of the character in local coordinates. + * @param right x coordinate of the right edge of the character in local coordinates. + * @param bottom y coordinate of the bottom edge of the character in local coordinates. + * @param flags flags for this character bounds. See {@link #FLAG_HAS_VISIBLE_REGION}, + * {@link #FLAG_HAS_INVISIBLE_REGION} and {@link #FLAG_IS_RTL}. These flags must be + * specified when necessary. + * @throws IllegalArgumentException If the index is a negative value, or not greater than + * all of the previously called indices. + */ + public Builder addCharacterBounds(final int index, final float left, final float top, + final float right, final float bottom, final int flags) { + if (index < 0) { + throw new IllegalArgumentException("index must not be a negative integer."); + } + if (mCharacterBoundsArrayBuilder == null) { + mCharacterBoundsArrayBuilder = new SparseRectFArrayBuilder(); + } + mCharacterBoundsArrayBuilder.append(index, left, top, right, bottom, flags); + return this; + } /** * Adds the bounding box of the character specified with the index. @@ -358,21 +406,25 @@ public final class CursorAnchorInfo implements Parcelable { * example. * @throws IllegalArgumentException If the index is a negative value, or not greater than * all of the previously called indices. + * @removed */ public Builder addCharacterRect(final int index, final float leadingEdgeX, final float leadingEdgeY, final float trailingEdgeX, final float trailingEdgeY, final int flags) { - if (index < 0) { - throw new IllegalArgumentException("index must not be a negative integer."); - } - if (mCharacterRectBuilder == null) { - mCharacterRectBuilder = new SparseRectFArrayBuilder(); + final int newFlags; + final float left; + final float right; + if (leadingEdgeX <= trailingEdgeX) { + newFlags = flags; + left = leadingEdgeX; + right = trailingEdgeX; + } else { + newFlags = flags | FLAG_IS_RTL; + left = trailingEdgeX; + right = leadingEdgeX; } - mCharacterRectBuilder.append(index, leadingEdgeX, leadingEdgeY, trailingEdgeX, - trailingEdgeY, flags); - return this; + return addCharacterBounds(index, left, leadingEdgeY, right, trailingEdgeY, newFlags); } - private SparseRectFArrayBuilder mCharacterRectBuilder = null; /** * Sets the matrix that transforms local coordinates into screen coordinates. @@ -384,8 +436,6 @@ public final class CursorAnchorInfo implements Parcelable { mMatrixInitialized = true; return this; } - private final Matrix mMatrix = new Matrix(Matrix.IDENTITY_MATRIX); - private boolean mMatrixInitialized = false; /** * @return {@link CursorAnchorInfo} using parameters in this {@link Builder}. @@ -394,13 +444,15 @@ public final class CursorAnchorInfo implements Parcelable { */ public CursorAnchorInfo build() { if (!mMatrixInitialized) { - // Coordinate transformation matrix is mandatory when positional parameters are - // specified. - if ((mCharacterRectBuilder != null && !mCharacterRectBuilder.isEmpty()) || - !Float.isNaN(mInsertionMarkerHorizontal) || - !Float.isNaN(mInsertionMarkerTop) || - !Float.isNaN(mInsertionMarkerBaseline) || - !Float.isNaN(mInsertionMarkerBottom)) { + // Coordinate transformation matrix is mandatory when at least one positional + // parameter is specified. + final boolean hasCharacterBounds = (mCharacterBoundsArrayBuilder != null + && !mCharacterBoundsArrayBuilder.isEmpty()); + if (hasCharacterBounds + || !Float.isNaN(mInsertionMarkerHorizontal) + || !Float.isNaN(mInsertionMarkerTop) + || !Float.isNaN(mInsertionMarkerBaseline) + || !Float.isNaN(mInsertionMarkerBottom)) { throw new IllegalArgumentException("Coordinate transformation matrix is " + "required when positional parameters are specified."); } @@ -424,8 +476,8 @@ public final class CursorAnchorInfo implements Parcelable { mInsertionMarkerBottom = Float.NaN; mMatrix.set(Matrix.IDENTITY_MATRIX); mMatrixInitialized = false; - if (mCharacterRectBuilder != null) { - mCharacterRectBuilder.reset(); + if (mCharacterBoundsArrayBuilder != null) { + mCharacterBoundsArrayBuilder.reset(); } } } @@ -440,8 +492,8 @@ public final class CursorAnchorInfo implements Parcelable { mInsertionMarkerTop = builder.mInsertionMarkerTop; mInsertionMarkerBaseline = builder.mInsertionMarkerBaseline; mInsertionMarkerBottom = builder.mInsertionMarkerBottom; - mCharacterRects = builder.mCharacterRectBuilder != null ? - builder.mCharacterRectBuilder.build() : null; + mCharacterBoundsArray = builder.mCharacterBoundsArrayBuilder != null ? + builder.mCharacterBoundsArrayBuilder.build() : null; mMatrix = new Matrix(builder.mMatrix); } @@ -539,6 +591,19 @@ public final class CursorAnchorInfo implements Parcelable { /** * Returns a new instance of {@link RectF} that indicates the location of the character * specified with the index. + * @param index index of the character in a Java chars. + * @return the character bounds in local coordinates as a new instance of {@link RectF}. + */ + public RectF getCharacterBounds(final int index) { + if (mCharacterBoundsArray == null) { + return null; + } + return mCharacterBoundsArray.get(index); + } + + /** + * Returns a new instance of {@link RectF} that indicates the location of the character + * specified with the index. * <p> * Note that coordinates are not necessarily contiguous or even monotonous, especially when * RTL text and LTR text are mixed. @@ -549,28 +614,32 @@ public final class CursorAnchorInfo implements Parcelable { * the location. Note that the {@code left} field can be greater than the {@code right} field * if the character is in RTL text. Returns {@code null} if no location information is * available. + * @removed */ - // TODO: Prepare a document about the expected behavior for surrogate pairs, combining - // characters, and non-graphical chars. public RectF getCharacterRect(final int index) { - if (mCharacterRects == null) { - return null; + return getCharacterBounds(index); + } + + /** + * Returns the flags associated with the character bounds specified with the index. + * @param index index of the character in a Java chars. + * @return {@code 0} if no flag is specified. + */ + public int getCharacterBoundsFlags(final int index) { + if (mCharacterBoundsArray == null) { + return 0; } - return mCharacterRects.get(index); + return mCharacterBoundsArray.getFlags(index, 0); } /** * Returns the flags associated with the character rect specified with the index. * @param index index of the character in a Java chars. * @return {@code 0} if no flag is specified. + * @removed */ - // TODO: Prepare a document about the expected behavior for surrogate pairs, combining - // characters, and non-graphical chars. public int getCharacterRectFlags(final int index) { - if (mCharacterRects == null) { - return 0; - } - return mCharacterRects.getFlags(index, 0); + return getCharacterBoundsFlags(index); } /** diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java index 2729bd0..d77f0b2 100644 --- a/core/java/android/widget/DatePicker.java +++ b/core/java/android/widget/DatePicker.java @@ -125,6 +125,7 @@ public class DatePicker extends FrameLayout { final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePicker, defStyleAttr, defStyleRes); final int mode = a.getInt(R.styleable.DatePicker_datePickerMode, MODE_SPINNER); + final int firstDayOfWeek = a.getInt(R.styleable.DatePicker_firstDayOfWeek, 0); a.recycle(); switch (mode) { @@ -136,6 +137,10 @@ public class DatePicker extends FrameLayout { mDelegate = createSpinnerUIDelegate(context, attrs, defStyleAttr, defStyleRes); break; } + + if (firstDayOfWeek != 0) { + setFirstDayOfWeek(firstDayOfWeek); + } } private DatePickerDelegate createSpinnerUIDelegate(Context context, AttributeSet attrs, @@ -300,6 +305,47 @@ public class DatePicker extends FrameLayout { } /** + * Sets the first day of week. + * + * @param firstDayOfWeek The first day of the week conforming to the + * {@link CalendarView} APIs. + * @see Calendar#SUNDAY + * @see Calendar#MONDAY + * @see Calendar#TUESDAY + * @see Calendar#WEDNESDAY + * @see Calendar#THURSDAY + * @see Calendar#FRIDAY + * @see Calendar#SATURDAY + * + * @attr ref android.R.styleable#DatePicker_firstDayOfWeek + */ + public void setFirstDayOfWeek(int firstDayOfWeek) { + if (firstDayOfWeek < Calendar.SUNDAY || firstDayOfWeek > Calendar.SATURDAY) { + throw new IllegalArgumentException("firstDayOfWeek must be between 1 and 7"); + } + mDelegate.setFirstDayOfWeek(firstDayOfWeek); + } + + /** + * Gets the first day of week. + * + * @return The first day of the week conforming to the {@link CalendarView} + * APIs. + * @see Calendar#SUNDAY + * @see Calendar#MONDAY + * @see Calendar#TUESDAY + * @see Calendar#WEDNESDAY + * @see Calendar#THURSDAY + * @see Calendar#FRIDAY + * @see Calendar#SATURDAY + * + * @attr ref android.R.styleable#DatePicker_firstDayOfWeek + */ + public int getFirstDayOfWeek() { + return mDelegate.getFirstDayOfWeek(); + } + + /** * Gets whether the {@link CalendarView} is shown. * * @return True if the calendar view is shown. @@ -315,7 +361,7 @@ public class DatePicker extends FrameLayout { * @return The calendar view. * @see #getCalendarViewShown() */ - public CalendarView getCalendarView () { + public CalendarView getCalendarView() { return mDelegate.getCalendarView(); } @@ -382,6 +428,9 @@ public class DatePicker extends FrameLayout { int getMonth(); int getDayOfMonth(); + void setFirstDayOfWeek(int firstDayOfWeek); + int getFirstDayOfWeek(); + void setMinDate(long minDate); Calendar getMinDate(); @@ -699,6 +748,16 @@ public class DatePicker extends FrameLayout { } @Override + public void setFirstDayOfWeek(int firstDayOfWeek) { + mCalendarView.setFirstDayOfWeek(firstDayOfWeek); + } + + @Override + public int getFirstDayOfWeek() { + return mCalendarView.getFirstDayOfWeek(); + } + + @Override public void setMinDate(long minDate) { mTempDate.setTimeInMillis(minDate); if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR) diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java index eed49bf..b962962 100644 --- a/core/java/android/widget/DatePickerCalendarDelegate.java +++ b/core/java/android/widget/DatePickerCalendarDelegate.java @@ -49,6 +49,7 @@ import java.util.Locale; */ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate implements View.OnClickListener, DatePickerController { + private static final int USE_LOCALE = 0; private static final int UNINITIALIZED = -1; private static final int MONTH_AND_DAY_VIEW = 0; @@ -99,6 +100,8 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i private Calendar mMinDate; private Calendar mMaxDate; + private int mFirstDayOfWeek = USE_LOCALE; + private HashSet<OnDateChangedListener> mListeners = new HashSet<OnDateChangedListener>(); public DatePickerCalendarDelegate(DatePicker delegator, Context context, AttributeSet attrs, @@ -438,7 +441,15 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i } @Override + public void setFirstDayOfWeek(int firstDayOfWeek) { + mFirstDayOfWeek = firstDayOfWeek; + } + + @Override public int getFirstDayOfWeek() { + if (mFirstDayOfWeek != USE_LOCALE) { + return mFirstDayOfWeek; + } return mCurrentDate.getFirstDayOfWeek(); } diff --git a/core/java/android/widget/DatePickerController.java b/core/java/android/widget/DatePickerController.java index 6a074da..059709d 100644 --- a/core/java/android/widget/DatePickerController.java +++ b/core/java/android/widget/DatePickerController.java @@ -35,6 +35,7 @@ interface DatePickerController { Calendar getSelectedDay(); + void setFirstDayOfWeek(int firstDayOfWeek); int getFirstDayOfWeek(); int getMinYear(); diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 22138d0..3f168e8 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -3060,47 +3060,69 @@ public class Editor { final CharSequence composingText = text.subSequence(composingTextStart, composingTextEnd); builder.setComposingText(composingTextStart, composingText); - } - // TODO: Optimize this loop by caching the result. - for (int offset = composingTextStart; offset < composingTextEnd; offset++) { - if (offset < 0) { - continue; - } - final boolean isRtl = layout.isRtlCharAt(offset); - final int line = layout.getLineForOffset(offset); - final int nextCharIndex = offset + 1; - final float localLeadingEdgeX = layout.getPrimaryHorizontal(offset); - final float localTrailingEdgeX; - if (nextCharIndex != layout.getLineEnd(line)) { - localTrailingEdgeX = layout.getPrimaryHorizontal(nextCharIndex); - } else if (isRtl) { - localTrailingEdgeX = layout.getLineLeft(line); - } else { - localTrailingEdgeX = layout.getLineRight(line); - } - final float leadingEdgeX = localLeadingEdgeX - + viewportToContentHorizontalOffset; - final float trailingEdgeX = localTrailingEdgeX - + viewportToContentHorizontalOffset; - final float top = layout.getLineTop(line) + viewportToContentVerticalOffset; - final float bottom = layout.getLineBottom(line) - + viewportToContentVerticalOffset; - // TODO: Check right-top and left-bottom as well. - final boolean isLeadingEdgeTopVisible = isPositionVisible(leadingEdgeX, top); - final boolean isTrailingEdgeBottomVisible = - isPositionVisible(trailingEdgeX, bottom); - int characterRectFlags = 0; - if (isLeadingEdgeTopVisible || isTrailingEdgeBottomVisible) { - characterRectFlags |= CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION; - } - if (!isLeadingEdgeTopVisible || !isTrailingEdgeBottomVisible) { - characterRectFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION; + + final int minLine = layout.getLineForOffset(composingTextStart); + final int maxLine = layout.getLineForOffset(composingTextEnd - 1); + for (int line = minLine; line <= maxLine; ++line) { + final int lineStart = layout.getLineStart(line); + final int lineEnd = layout.getLineEnd(line); + final int offsetStart = Math.max(lineStart, composingTextStart); + final int offsetEnd = Math.min(lineEnd, composingTextEnd); + final boolean ltrLine = + layout.getParagraphDirection(line) == Layout.DIR_LEFT_TO_RIGHT; + final float[] widths = new float[offsetEnd - offsetStart]; + layout.getPaint().getTextWidths(text, offsetStart, offsetEnd, widths); + final float top = layout.getLineTop(line); + final float bottom = layout.getLineBottom(line); + for (int offset = offsetStart; offset < offsetEnd; ++offset) { + final float charWidth = widths[offset - offsetStart]; + final boolean isRtl = layout.isRtlCharAt(offset); + final float primary = layout.getPrimaryHorizontal(offset); + final float secondary = layout.getSecondaryHorizontal(offset); + // TODO: This doesn't work perfectly for text with custom styles and + // TAB chars. + final float left; + final float right; + if (ltrLine) { + if (isRtl) { + left = secondary - charWidth; + right = secondary; + } else { + left = primary; + right = primary + charWidth; + } + } else { + if (!isRtl) { + left = secondary; + right = secondary + charWidth; + } else { + left = primary - charWidth; + right = primary; + } + } + // TODO: Check top-right and bottom-left as well. + final float localLeft = left + viewportToContentHorizontalOffset; + final float localRight = right + viewportToContentHorizontalOffset; + final float localTop = top + viewportToContentVerticalOffset; + final float localBottom = bottom + viewportToContentVerticalOffset; + final boolean isTopLeftVisible = isPositionVisible(localLeft, localTop); + final boolean isBottomRightVisible = + isPositionVisible(localRight, localBottom); + int characterBoundsFlags = 0; + if (isTopLeftVisible || isBottomRightVisible) { + characterBoundsFlags |= CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION; + } + if (!isTopLeftVisible || !isTopLeftVisible) { + characterBoundsFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION; + } + if (isRtl) { + characterBoundsFlags |= CursorAnchorInfo.FLAG_IS_RTL; + } + // Here offset is the index in Java chars. + builder.addCharacterBounds(offset, localLeft, localTop, localRight, + localBottom, characterBoundsFlags); + } } - // Here offset is the index in Java chars. - // TODO: We must have a well-defined specification. For example, how - // surrogate pairs and composition letters are handled must be documented. - builder.addCharacterRect(offset, leadingEdgeX, top, trailingEdgeX, bottom, - characterRectFlags); } } @@ -3127,6 +3149,9 @@ public class Editor { if (!isTopVisible || !isBottomVisible) { insertionMarkerFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION; } + if (layout.isRtlCharAt(offset)) { + insertionMarkerFlags |= CursorAnchorInfo.FLAG_IS_RTL; + } builder.setInsertionMarkerLocation(insertionMarkerX, insertionMarkerTop, insertionMarkerBaseline, insertionMarkerBottom, insertionMarkerFlags); } diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java index c17f4ee..7bdb4be 100644 --- a/core/java/com/android/internal/content/PackageHelper.java +++ b/core/java/com/android/internal/content/PackageHelper.java @@ -390,7 +390,10 @@ public class PackageHelper { if (!emulated && (checkBoth || prefer == RECOMMEND_INSTALL_EXTERNAL)) { final File target = new UserEnvironment(UserHandle.USER_OWNER) .getExternalStorageDirectory(); - fitsOnExternal = (sizeBytes <= storage.getStorageBytesUntilLow(target)); + // External is only an option when size is known + if (sizeBytes > 0) { + fitsOnExternal = (sizeBytes <= storage.getStorageBytesUntilLow(target)); + } } if (prefer == RECOMMEND_INSTALL_INTERNAL) { diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 69cdbff..45a9dde 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -94,7 +94,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 113 + (USE_OLD_HISTORY ? 1000 : 0); + private static final int VERSION = 114 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS = 2000; @@ -385,10 +385,9 @@ public final class BatteryStatsImpl extends BatteryStats { String mLastWakeupReason = null; long mLastWakeupUptimeMs = 0; - private final HashMap<String, LongSamplingCounter> mWakeupReasonStats = - new HashMap<String, LongSamplingCounter>(); + private final HashMap<String, SamplingTimer> mWakeupReasonStats = new HashMap<>(); - public Map<String, ? extends LongCounter> getWakeupReasonStats() { + public Map<String, ? extends Timer> getWakeupReasonStats() { return mWakeupReasonStats; } @@ -1131,6 +1130,10 @@ public final class BatteryStatsImpl extends BatteryStats { mCurrentReportedCount = count; } + public void addCurrentReportedCount(int delta) { + updateCurrentReportedCount(mCurrentReportedCount + delta); + } + public void updateCurrentReportedTotalTime(long totalTime) { if (mTimeBaseRunning && mUnpluggedReportedTotalTime == 0) { // Updating the reported value for the first time. @@ -1141,6 +1144,10 @@ public final class BatteryStatsImpl extends BatteryStats { mCurrentReportedTotalTime = totalTime; } + public void addCurrentReportedTotalTime(long delta) { + updateCurrentReportedTotalTime(mCurrentReportedTotalTime + delta); + } + public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) { super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime); if (mTrackingReportedValues) { @@ -1688,13 +1695,13 @@ public final class BatteryStatsImpl extends BatteryStats { * Get the wakeup reason counter, and create a new one if one * doesn't already exist. */ - public LongSamplingCounter getWakeupReasonCounterLocked(String name) { - LongSamplingCounter counter = mWakeupReasonStats.get(name); - if (counter == null) { - counter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase); - mWakeupReasonStats.put(name, counter); + public SamplingTimer getWakeupReasonTimerLocked(String name) { + SamplingTimer timer = mWakeupReasonStats.get(name); + if (timer == null) { + timer = new SamplingTimer(mOnBatteryTimeBase, true); + mWakeupReasonStats.put(name, timer); } - return counter; + return timer; } private final Map<String, KernelWakelockStats> readKernelWakelockStats() { @@ -2753,8 +2760,9 @@ public final class BatteryStatsImpl extends BatteryStats { void aggregateLastWakeupUptimeLocked(long uptimeMs) { if (mLastWakeupReason != null) { long deltaUptime = uptimeMs - mLastWakeupUptimeMs; - LongSamplingCounter timer = getWakeupReasonCounterLocked(mLastWakeupReason); - timer.addCountLocked(deltaUptime); + SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason); + timer.addCurrentReportedCount(1); + timer.addCurrentReportedTotalTime(deltaUptime * 1000); // time is in microseconds mLastWakeupReason = null; } } @@ -2762,7 +2770,7 @@ public final class BatteryStatsImpl extends BatteryStats { public void noteWakeupReasonLocked(String reason) { final long elapsedRealtime = SystemClock.elapsedRealtime(); final long uptime = SystemClock.uptimeMillis(); - if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason reason \"" + reason +"\": " + if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": " + Integer.toHexString(mHistoryCur.states)); aggregateLastWakeupUptimeLocked(uptime); mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag; @@ -6193,7 +6201,7 @@ public final class BatteryStatsImpl extends BatteryStats { } public void noteStartJobLocked(String name, long elapsedRealtimeMs) { - StopwatchTimer t = mJobStats.stopObject(name); + StopwatchTimer t = mJobStats.startObject(name); if (t != null) { t.startRunningLocked(elapsedRealtimeMs); } @@ -6636,8 +6644,8 @@ public final class BatteryStatsImpl extends BatteryStats { } if (mWakeupReasonStats.size() > 0) { - for (LongSamplingCounter timer : mWakeupReasonStats.values()) { - mOnBatteryScreenOffTimeBase.remove(timer); + for (SamplingTimer timer : mWakeupReasonStats.values()) { + mOnBatteryTimeBase.remove(timer); } mWakeupReasonStats.clear(); } @@ -7848,7 +7856,7 @@ public final class BatteryStatsImpl extends BatteryStats { for (int iwr = 0; iwr < NWR; iwr++) { if (in.readInt() != 0) { String reasonName = in.readString(); - getWakeupReasonCounterLocked(reasonName).readSummaryFromParcelLocked(in); + getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in); } } @@ -8122,12 +8130,12 @@ public final class BatteryStatsImpl extends BatteryStats { } out.writeInt(mWakeupReasonStats.size()); - for (Map.Entry<String, LongSamplingCounter> ent : mWakeupReasonStats.entrySet()) { - LongSamplingCounter counter = ent.getValue(); - if (counter != null) { + for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) { + SamplingTimer timer = ent.getValue(); + if (timer != null) { out.writeInt(1); out.writeString(ent.getKey()); - counter.writeSummaryFromParcelLocked(out); + timer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); } else { out.writeInt(0); } @@ -8438,7 +8446,7 @@ public final class BatteryStatsImpl extends BatteryStats { for (int ikw = 0; ikw < NKW; ikw++) { if (in.readInt() != 0) { String wakelockName = in.readString(); - SamplingTimer kwlt = new SamplingTimer(mOnBatteryTimeBase, in); + SamplingTimer kwlt = new SamplingTimer(mOnBatteryScreenOffTimeBase, in); mKernelWakelockStats.put(wakelockName, kwlt); } } @@ -8448,9 +8456,8 @@ public final class BatteryStatsImpl extends BatteryStats { for (int iwr = 0; iwr < NWR; iwr++) { if (in.readInt() != 0) { String reasonName = in.readString(); - LongSamplingCounter counter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase, - in); - mWakeupReasonStats.put(reasonName, counter); + SamplingTimer timer = new SamplingTimer(mOnBatteryTimeBase, in); + mWakeupReasonStats.put(reasonName, timer); } } @@ -8585,12 +8592,12 @@ public final class BatteryStatsImpl extends BatteryStats { } } out.writeInt(mWakeupReasonStats.size()); - for (Map.Entry<String, LongSamplingCounter> ent : mWakeupReasonStats.entrySet()) { - LongSamplingCounter counter = ent.getValue(); - if (counter != null) { + for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) { + SamplingTimer timer = ent.getValue(); + if (timer != null) { out.writeInt(1); out.writeString(ent.getKey()); - counter.writeToParcel(out); + timer.writeToParcel(out, uSecRealtime); } else { out.writeInt(0); } diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java index 7db70ba..45d790b 100644 --- a/core/java/com/android/internal/util/XmlUtils.java +++ b/core/java/com/android/internal/util/XmlUtils.java @@ -1440,6 +1440,16 @@ public class XmlUtils { return Boolean.parseBoolean(value); } + public static boolean readBooleanAttribute(XmlPullParser in, String name, + boolean defaultValue) { + final String value = in.getAttributeValue(null, name); + if (value == null) { + return defaultValue; + } else { + return Boolean.parseBoolean(value); + } + } + public static void writeBooleanAttribute(XmlSerializer out, String name, boolean value) throws IOException { out.attribute(null, name, Boolean.toString(value)); diff --git a/core/jni/android_hardware_SoundTrigger.cpp b/core/jni/android_hardware_SoundTrigger.cpp index f0d7a35..7b33bc2 100644 --- a/core/jni/android_hardware_SoundTrigger.cpp +++ b/core/jni/android_hardware_SoundTrigger.cpp @@ -211,7 +211,7 @@ void JNISoundTriggerCallback::onRecognitionEvent(struct sound_trigger_recognitio } jobject jAudioFormat = NULL; - if (event->trigger_in_data) { + if (event->trigger_in_data || event->capture_available) { jAudioFormat = env->NewObject(gAudioFormatClass, gAudioFormatCstor, audioFormatFromNative(event->audio_config.format), diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp index 5faf03d..396f3ec 100644 --- a/core/jni/android_util_AssetManager.cpp +++ b/core/jni/android_util_AssetManager.cpp @@ -1888,6 +1888,37 @@ static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, j return array; } +static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz, + jint styleId) +{ + AssetManager* am = assetManagerForJavaObject(env, clazz); + if (am == NULL) { + return NULL; + } + const ResTable& res(am->getResources()); + + const ResTable::bag_entry* startOfBag; + const ssize_t N = res.lockBag(styleId, &startOfBag); + if (N < 0) { + return NULL; + } + + jintArray array = env->NewIntArray(N); + if (array == NULL) { + res.unlockBag(startOfBag); + return NULL; + } + + Res_value value; + const ResTable::bag_entry* bag = startOfBag; + for (size_t i=0; ((ssize_t)i)<N; i++, bag++) { + int resourceId = bag->map.name.ident; + env->SetIntArrayRegion(array, i, 1, &resourceId); + } + res.unlockBag(startOfBag); + return array; +} + static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem) { if (isSystem) { @@ -2038,6 +2069,8 @@ static JNINativeMethod gAssetManagerMethods[] = { (void*) android_content_AssetManager_getArrayStringInfo }, { "getArrayIntResource","(I)[I", (void*) android_content_AssetManager_getArrayIntResource }, + { "getStyleAttributes","(I)[I", + (void*) android_content_AssetManager_getStyleAttributes }, // Bookkeeping. { "init", "(Z)V", diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp index 949f4ff..050037e 100644 --- a/core/jni/android_view_RenderNode.cpp +++ b/core/jni/android_view_RenderNode.cpp @@ -173,6 +173,12 @@ static jboolean android_view_RenderNode_setOutlineNone(JNIEnv* env, return true; } +static jboolean android_view_RenderNode_hasShadow(JNIEnv* env, + jobject clazz, jlong renderNodePtr) { + RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); + return renderNode->stagingProperties().hasShadow(); +} + static jboolean android_view_RenderNode_setClipToOutline(JNIEnv* env, jobject clazz, jlong renderNodePtr, jboolean clipToOutline) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); @@ -491,6 +497,7 @@ static JNINativeMethod gMethods[] = { { "nSetOutlineConvexPath", "(JJF)Z", (void*) android_view_RenderNode_setOutlineConvexPath }, { "nSetOutlineEmpty", "(J)Z", (void*) android_view_RenderNode_setOutlineEmpty }, { "nSetOutlineNone", "(J)Z", (void*) android_view_RenderNode_setOutlineNone }, + { "nHasShadow", "(J)Z", (void*) android_view_RenderNode_hasShadow }, { "nSetClipToOutline", "(JZ)Z", (void*) android_view_RenderNode_setClipToOutline }, { "nSetRevealClip", "(JZFFF)Z", (void*) android_view_RenderNode_setRevealClip }, diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp index 85c2a09..84b7913 100644 --- a/core/jni/android_view_RenderNodeAnimator.cpp +++ b/core/jni/android_view_RenderNodeAnimator.cpp @@ -159,6 +159,11 @@ static void setInterpolator(JNIEnv* env, jobject clazz, jlong animatorPtr, jlong animator->setInterpolator(interpolator); } +static void setAllowRunningAsync(JNIEnv* env, jobject clazz, jlong animatorPtr, jboolean mayRunAsync) { + BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); + animator->setAllowRunningAsync(mayRunAsync); +} + static void start(JNIEnv* env, jobject clazz, jlong animatorPtr, jobject finishListener) { BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); if (finishListener) { @@ -191,6 +196,7 @@ static JNINativeMethod gMethods[] = { { "nGetDuration", "(J)J", (void*) getDuration }, { "nSetStartDelay", "(JJ)V", (void*) setStartDelay }, { "nSetInterpolator", "(JJ)V", (void*) setInterpolator }, + { "nSetAllowRunningAsync", "(JZ)V", (void*) setAllowRunningAsync }, { "nStart", "(JLandroid/view/RenderNodeAnimator;)V", (void*) start }, { "nEnd", "(J)V", (void*) end }, #endif diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp index 7e6d335..a8edb77 100644 --- a/core/jni/android_view_ThreadedRenderer.cpp +++ b/core/jni/android_view_ThreadedRenderer.cpp @@ -158,9 +158,11 @@ public: // Marks the start of a frame, which will update the frame time and move all // next frame animations into the current frame - virtual void startFrame() { - mRootNode->doAttachAnimatingNodes(this); - AnimationContext::startFrame(); + virtual void startFrame(TreeInfo::TraversalMode mode) { + if (mode == TreeInfo::MODE_FULL) { + mRootNode->doAttachAnimatingNodes(this); + } + AnimationContext::startFrame(mode); } // Runs any animations still left in mCurrentFrameAnimations diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 7c5233c..72dd930 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -182,11 +182,11 @@ <protected-broadcast android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" /> <protected-broadcast android:name="android.intent.action.HEADSET_PLUG" /> - <protected-broadcast android:name="android.intent.action.ANALOG_AUDIO_DOCK_PLUG" /> - <protected-broadcast android:name="android.intent.action.DIGITAL_AUDIO_DOCK_PLUG" /> - <protected-broadcast android:name="android.intent.action.HDMI_AUDIO_PLUG" /> - <protected-broadcast android:name="android.intent.action.USB_AUDIO_ACCESSORY_PLUG" /> - <protected-broadcast android:name="android.intent.action.USB_AUDIO_DEVICE_PLUG" /> + <protected-broadcast android:name="android.media.action.ANALOG_AUDIO_DOCK_PLUG" /> + <protected-broadcast android:name="android.media.action.DIGITAL_AUDIO_DOCK_PLUG" /> + <protected-broadcast android:name="android.media.action.HDMI_AUDIO_PLUG" /> + <protected-broadcast android:name="android.media.action.USB_AUDIO_ACCESSORY_PLUG" /> + <protected-broadcast android:name="android.media.action.USB_AUDIO_DEVICE_PLUG" /> <protected-broadcast android:name="android.media.AUDIO_BECOMING_NOISY" /> <protected-broadcast android:name="android.media.RINGER_MODE_CHANGED" /> diff --git a/core/res/res/values-mcc310-mnc260/config.xml b/core/res/res/values-mcc310-mnc260/config.xml index 2f9394a..f8fff3b 100644 --- a/core/res/res/values-mcc310-mnc260/config.xml +++ b/core/res/res/values-mcc310-mnc260/config.xml @@ -25,6 +25,11 @@ --> <integer name="config_mobile_mtu">1440</integer> + <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of + carrier provisioning. If false: hard disabled. If true: then depends on carrier + provisioning, availability etc --> + <bool name="config_carrier_volte_vt_available">true</bool> + <!-- Values for GPS configuration (T-Mobile) --> <string-array translatable="false" name="config_gpsParameters"> <item>CAPABILITEIS=0x33</item> diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml index cd5d55b..57ecd31 100644 --- a/core/res/res/values-mcc311-mnc480/config.xml +++ b/core/res/res/values-mcc311-mnc480/config.xml @@ -38,10 +38,10 @@ be disabled) but individual Features can be disabled using ImsConfig.setFeatureValue() --> <bool name="imsServiceAllowTurnOff">false</bool> - <!-- Flag specifying whether VoLTE & VT should be allowed on device: independent of the + <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of carrier provisioning. If false: hard disabled. If true: then depends on carrier provisioning, availability etc --> - <bool name="config_mobile_allow_volte_vt">false</bool> + <bool name="config_carrier_volte_vt_available">false</bool> <bool name="config_auto_attach_data_on_creation">false</bool> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index d1cc1fd..cf4064f 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -4341,6 +4341,8 @@ <attr name="minDate" format="string" /> <!-- The maximal date shown by this calendar view in mm/dd/yyyy format. --> <attr name="maxDate" format="string" /> + <!-- The first day of week according to {@link java.util.Calendar}. --> + <attr name="firstDayOfWeek" /> <!-- @hide The layout of the date picker. --> <attr name="internalLayout" format="reference" /> <!-- @hide The layout of the legacy DatePicker. --> diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index e905a3a..10c2518 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -939,7 +939,7 @@ {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK Intent.FLAG_ACTIVITY_MULTIPLE_TASK}. If the value of documentLaunchModes is <code>never</code> then any use of -.........{@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT + {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT Intent.FLAG_ACTIVITY_NEW_DOCUMENT} to launch this activity will be ignored. --> <attr name="documentLaunchMode"> <!-- The default mode, which will create a new task only when @@ -994,6 +994,15 @@ TaskDescription to change labels, colors and icons in the recent task list. --> <attr name="relinquishTaskIdentity" format="boolean" /> + <!-- Indicate that it is okay for this activity be resumed while the previous + activity is in the process of pausing, without waiting for the previous pause + to complete. Use this with caution: your activity can not acquire any exclusive + resources (such as opening the camera or recording audio) when it launches, or it + may conflict with the previous activity and fail. + + <p>The default value of this attribute is <code>false</code>. --> + <attr name="resumeWhilePausing" format="boolean" /> + <!-- The <code>manifest</code> tag is the root of an <code>AndroidManifest.xml</code> file, describing the contents of an Android package (.apk) file. One @@ -1678,6 +1687,7 @@ <attr name="maxRecents" /> <attr name="autoRemoveFromRecents" /> <attr name="relinquishTaskIdentity" /> + <attr name="resumeWhilePausing" /> </declare-styleable> <!-- The <code>activity-alias</code> tag declares a new diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml index d8e14a0..939cbf1 100644 --- a/core/res/res/values/colors_material.xml +++ b/core/res/res/values/colors_material.xml @@ -19,8 +19,8 @@ <color name="background_material_dark">#ff212121</color> <color name="background_material_light">#fffafafa</color> - <color name="ripple_material_light">#20444444</color> - <color name="ripple_material_dark">#20ffffff</color> + <color name="ripple_material_light">#40000000</color> + <color name="ripple_material_dark">#40ffffff</color> <color name="button_material_dark">#ff5a595b</color> <color name="button_material_light">#ffd6d7d7</color> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index b63b91d..f3b3077 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -771,6 +771,9 @@ specified --> <string name="default_wallpaper_component" translatable="false">@null</string> + <!-- Component name of the built in wallpaper used to display bitmap wallpapers. This must not be null. --> + <string name="image_wallpaper_component" translatable="false">com.android.systemui/com.android.systemui.ImageWallpaper</string> + <!-- True if WallpaperService is enabled --> <bool name="config_enableWallpaperService">true</bool> @@ -1671,10 +1674,13 @@ be disabled) but individual Features can be disabled using ImsConfig.setFeatureValue() --> <bool name="imsServiceAllowTurnOff">true</bool> - <!-- Flag specifying whether VoLTE & VT should be allowed on device: independent of the + <!-- Flag specifying whether VoLTE & VT is availasble on device --> + <bool name="config_device_volte_vt_available">false</bool> + + <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of carrier provisioning. If false: hard disabled. If true: then depends on carrier provisioning, availability etc --> - <bool name="config_mobile_allow_volte_vt">true</bool> + <bool name="config_carrier_volte_vt_available">false</bool> <bool name="config_networkSamplingWakesDevice">true</bool> @@ -1695,9 +1701,13 @@ and adds page info " x/y". This config is used to set which carrier doesn't support EMS and whether page info should be added at the beginning or the end. We use tag 'prefix' for position beginning and 'suffix' for position end. - Examples: <item>311480;prefix</item> <item>310260;suffix</item> + And use gid to distinguish different carriers which using same mcc and mnc. + Examples: <item>simOperatorNumber;position;gid(optional)</item>> --> - <string-array translatable="false" name="no_ems_support_sim_operators" /> + <string-array translatable="false" name="no_ems_support_sim_operators"> + <!-- VZW --> + <item>20404;suffix;BAE0000000000000</item> + </string-array> <bool name="config_auto_attach_data_on_creation">true</bool> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index a4c3474..5b047f7 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2266,7 +2266,7 @@ <public type="attr" name="windowReenterTransition" /> <public type="attr" name="windowSharedElementReturnTransition" /> <public type="attr" name="windowSharedElementReenterTransition" /> - <public type="attr" name="__removed1" /> + <public type="attr" name="resumeWhilePausing" /> <public type="attr" name="datePickerMode"/> <public type="attr" name="timePickerMode"/> <public type="attr" name="inset" /> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 1b0f9c4..01e6e76 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1634,6 +1634,7 @@ <java-symbol type="string" name="hardware" /> <java-symbol type="string" name="heavy_weight_notification" /> <java-symbol type="string" name="heavy_weight_notification_detail" /> + <java-symbol type="string" name="image_wallpaper_component" /> <java-symbol type="string" name="input_method_binding_label" /> <java-symbol type="string" name="launch_warning_original" /> <java-symbol type="string" name="launch_warning_replace" /> @@ -1969,7 +1970,8 @@ <java-symbol type="attr" name="preferenceFragmentStyle" /> <java-symbol type="bool" name="skipHoldBeforeMerge" /> <java-symbol type="bool" name="imsServiceAllowTurnOff" /> - <java-symbol type="bool" name="config_mobile_allow_volte_vt" /> + <java-symbol type="bool" name="config_device_volte_vt_available" /> + <java-symbol type="bool" name="config_carrier_volte_vt_available" /> <java-symbol type="bool" name="useImsAlwaysForEmergencyCall" /> <java-symbol type="attr" name="touchscreenBlocksFocus" /> <java-symbol type="layout" name="resolver_list_with_default" /> diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java index a3c5351..77e1c53 100644 --- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java +++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java @@ -54,7 +54,7 @@ public class ConnectivityManagerTestBase extends InstrumentationTestCase { protected static final int WAIT_FOR_SCAN_RESULT = 10 * 1000; //10 seconds protected static final int WIFI_SCAN_TIMEOUT = 50 * 1000; // 50 seconds protected static final int SHORT_TIMEOUT = 5 * 1000; // 5 seconds - protected static final long LONG_TIMEOUT = 50 * 1000; // 50 seconds + protected static final long LONG_TIMEOUT = 2 * 60 * 1000; // 2 minutes protected static final long WIFI_CONNECTION_TIMEOUT = 5 * 60 * 1000; // 5 minutes // 2 minutes timer between wifi stop and start protected static final long WIFI_STOP_START_INTERVAL = 2 * 60 * 1000; // 2 minutes diff --git a/core/tests/inputmethodtests/run_core_inputmethod_test.sh b/core/tests/inputmethodtests/run_core_inputmethod_test.sh index ed8b7f7..a11e49b 100755 --- a/core/tests/inputmethodtests/run_core_inputmethod_test.sh +++ b/core/tests/inputmethodtests/run_core_inputmethod_test.sh @@ -15,7 +15,7 @@ fi if [[ $rebuild == true ]]; then make -j4 FrameworksCoreInputMethodTests - TESTAPP=${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreInputMethodTests.apk + TESTAPP=${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreInputMethodTests/FrameworksCoreInputMethodTests.apk COMMAND="adb install -r $TESTAPP" echo $COMMAND $COMMAND diff --git a/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java b/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java index cc4a7c4..b6a03d9 100644 --- a/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java +++ b/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java @@ -26,14 +26,12 @@ import android.view.inputmethod.CursorAnchorInfo.Builder; import java.util.Objects; -import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_FULLY_VISIBLE; -import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_INVISIBLE; -import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_NOT_FEASIBLE; -import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE; -import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_UNSPECIFIED; +import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION; +import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION; +import static android.view.inputmethod.CursorAnchorInfo.FLAG_IS_RTL; public class CursorAnchorInfoTest extends InstrumentationTestCase { - private static final RectF[] MANY_RECTS = new RectF[] { + private static final RectF[] MANY_BOUNDS = new RectF[] { new RectF(101.0f, 201.0f, 301.0f, 401.0f), new RectF(102.0f, 202.0f, 302.0f, 402.0f), new RectF(103.0f, 203.0f, 303.0f, 403.0f), @@ -55,25 +53,25 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { new RectF(119.0f, 219.0f, 319.0f, 419.0f), }; private static final int[] MANY_FLAGS_ARRAY = new int[] { - CHARACTER_RECT_TYPE_FULLY_VISIBLE, - CHARACTER_RECT_TYPE_INVISIBLE, - CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE, - CHARACTER_RECT_TYPE_FULLY_VISIBLE, - CHARACTER_RECT_TYPE_FULLY_VISIBLE, - CHARACTER_RECT_TYPE_FULLY_VISIBLE, - CHARACTER_RECT_TYPE_NOT_FEASIBLE, - CHARACTER_RECT_TYPE_FULLY_VISIBLE, - CHARACTER_RECT_TYPE_FULLY_VISIBLE, - CHARACTER_RECT_TYPE_FULLY_VISIBLE, - CHARACTER_RECT_TYPE_FULLY_VISIBLE, - CHARACTER_RECT_TYPE_FULLY_VISIBLE, - CHARACTER_RECT_TYPE_FULLY_VISIBLE, - CHARACTER_RECT_TYPE_FULLY_VISIBLE, - CHARACTER_RECT_TYPE_FULLY_VISIBLE, - CHARACTER_RECT_TYPE_FULLY_VISIBLE, - CHARACTER_RECT_TYPE_FULLY_VISIBLE, - CHARACTER_RECT_TYPE_NOT_FEASIBLE, - CHARACTER_RECT_TYPE_NOT_FEASIBLE, + FLAG_HAS_INVISIBLE_REGION, + FLAG_HAS_INVISIBLE_REGION | FLAG_HAS_VISIBLE_REGION, + FLAG_HAS_VISIBLE_REGION, + FLAG_HAS_VISIBLE_REGION, + FLAG_HAS_VISIBLE_REGION, + FLAG_HAS_VISIBLE_REGION, + FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL, + FLAG_HAS_INVISIBLE_REGION | FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL, + FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL, + FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL, + FLAG_HAS_VISIBLE_REGION, + FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL, + FLAG_HAS_VISIBLE_REGION, + FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL, + FLAG_HAS_VISIBLE_REGION, + FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL, + FLAG_HAS_VISIBLE_REGION, + FLAG_HAS_INVISIBLE_REGION, + FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL, }; @SmallTest @@ -82,11 +80,13 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { final int SELECTION_END = 40; final int COMPOSING_TEXT_START = 32; final String COMPOSING_TEXT = "test"; - final boolean INSERTION_MARKER_CLIPPED = true; + final int INSERTION_MARKER_FLAGS = + FLAG_HAS_VISIBLE_REGION | FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL; final float INSERTION_MARKER_HORIZONTAL = 10.5f; final float INSERTION_MARKER_TOP = 100.1f; final float INSERTION_MARKER_BASELINE = 110.4f; final float INSERTION_MARKER_BOTOM = 111.0f; + Matrix TRANSFORM_MATRIX = new Matrix(Matrix.IDENTITY_MATRIX); TRANSFORM_MATRIX.setScale(10.0f, 20.0f); @@ -94,13 +94,13 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { builder.setSelectionRange(SELECTION_START, SELECTION_END) .setComposingText(COMPOSING_TEXT_START, COMPOSING_TEXT) .setInsertionMarkerLocation(INSERTION_MARKER_HORIZONTAL, INSERTION_MARKER_TOP, - INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM, - INSERTION_MARKER_CLIPPED) + INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM, INSERTION_MARKER_FLAGS) .setMatrix(TRANSFORM_MATRIX); - for (int i = 0; i < MANY_RECTS.length; i++) { - final RectF rect = MANY_RECTS[i]; + for (int i = 0; i < MANY_BOUNDS.length; i++) { + final RectF bounds = MANY_BOUNDS[i]; final int flags = MANY_FLAGS_ARRAY[i]; - builder.addCharacterRect(i, rect.left, rect.top, rect.right, rect.bottom, flags); + builder.addCharacterBounds(i, bounds.left, bounds.top, bounds.right, bounds.bottom, + flags); } final CursorAnchorInfo info = builder.build(); @@ -108,26 +108,24 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { assertEquals(SELECTION_END, info.getSelectionEnd()); assertEquals(COMPOSING_TEXT_START, info.getComposingTextStart()); assertTrue(TextUtils.equals(COMPOSING_TEXT, info.getComposingText())); - assertTrue(info.isInsertionMarkerClipped()); + assertEquals(INSERTION_MARKER_FLAGS, info.getInsertionMarkerFlags()); assertEquals(INSERTION_MARKER_HORIZONTAL, info.getInsertionMarkerHorizontal()); assertEquals(INSERTION_MARKER_TOP, info.getInsertionMarkerTop()); assertEquals(INSERTION_MARKER_BASELINE, info.getInsertionMarkerBaseline()); assertEquals(INSERTION_MARKER_BOTOM, info.getInsertionMarkerBottom()); assertEquals(TRANSFORM_MATRIX, info.getMatrix()); - for (int i = 0; i < MANY_RECTS.length; i++) { - final RectF expectedRect = MANY_RECTS[i]; - assertEquals(expectedRect, info.getCharacterRect(i)); + for (int i = 0; i < MANY_BOUNDS.length; i++) { + final RectF expectedBounds = MANY_BOUNDS[i]; + assertEquals(expectedBounds, info.getCharacterRect(i)); } assertNull(info.getCharacterRect(-1)); - assertNull(info.getCharacterRect(MANY_RECTS.length + 1)); + assertNull(info.getCharacterRect(MANY_BOUNDS.length + 1)); for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) { final int expectedFlags = MANY_FLAGS_ARRAY[i]; assertEquals(expectedFlags, info.getCharacterRectFlags(i)); } - assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED, - info.getCharacterRectFlags(-1)); - assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED, - info.getCharacterRectFlags(MANY_RECTS.length + 1)); + assertEquals(0, info.getCharacterRectFlags(-1)); + assertEquals(0, info.getCharacterRectFlags(MANY_BOUNDS.length + 1)); // Make sure that the builder can reproduce the same object. final CursorAnchorInfo info2 = builder.build(); @@ -135,25 +133,24 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { assertEquals(SELECTION_END, info2.getSelectionEnd()); assertEquals(COMPOSING_TEXT_START, info2.getComposingTextStart()); assertTrue(TextUtils.equals(COMPOSING_TEXT, info2.getComposingText())); - assertTrue(info2.isInsertionMarkerClipped()); + assertEquals(INSERTION_MARKER_FLAGS, info2.getInsertionMarkerFlags()); assertEquals(INSERTION_MARKER_HORIZONTAL, info2.getInsertionMarkerHorizontal()); assertEquals(INSERTION_MARKER_TOP, info2.getInsertionMarkerTop()); assertEquals(INSERTION_MARKER_BASELINE, info2.getInsertionMarkerBaseline()); assertEquals(INSERTION_MARKER_BOTOM, info2.getInsertionMarkerBottom()); assertEquals(TRANSFORM_MATRIX, info2.getMatrix()); - for (int i = 0; i < MANY_RECTS.length; i++) { - final RectF expectedRect = MANY_RECTS[i]; - assertEquals(expectedRect, info2.getCharacterRect(i)); + for (int i = 0; i < MANY_BOUNDS.length; i++) { + final RectF expectedBounds = MANY_BOUNDS[i]; + assertEquals(expectedBounds, info2.getCharacterRect(i)); } assertNull(info2.getCharacterRect(-1)); - assertNull(info2.getCharacterRect(MANY_RECTS.length + 1)); + assertNull(info2.getCharacterRect(MANY_BOUNDS.length + 1)); for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) { final int expectedFlags = MANY_FLAGS_ARRAY[i]; assertEquals(expectedFlags, info2.getCharacterRectFlags(i)); } - assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED, info2.getCharacterRectFlags(-1)); - assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED, - info2.getCharacterRectFlags(MANY_RECTS.length + 1)); + assertEquals(0, info2.getCharacterRectFlags(-1)); + assertEquals(0, info2.getCharacterRectFlags(MANY_BOUNDS.length + 1)); assertEquals(info, info2); assertEquals(info.hashCode(), info2.hashCode()); @@ -163,25 +160,24 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { assertEquals(SELECTION_END, info3.getSelectionEnd()); assertEquals(COMPOSING_TEXT_START, info3.getComposingTextStart()); assertTrue(TextUtils.equals(COMPOSING_TEXT, info3.getComposingText())); - assertTrue(info3.isInsertionMarkerClipped()); + assertEquals(INSERTION_MARKER_FLAGS, info3.getInsertionMarkerFlags()); assertEquals(INSERTION_MARKER_HORIZONTAL, info3.getInsertionMarkerHorizontal()); assertEquals(INSERTION_MARKER_TOP, info3.getInsertionMarkerTop()); assertEquals(INSERTION_MARKER_BASELINE, info3.getInsertionMarkerBaseline()); assertEquals(INSERTION_MARKER_BOTOM, info3.getInsertionMarkerBottom()); assertEquals(TRANSFORM_MATRIX, info3.getMatrix()); - for (int i = 0; i < MANY_RECTS.length; i++) { - final RectF expectedRect = MANY_RECTS[i]; - assertEquals(expectedRect, info3.getCharacterRect(i)); + for (int i = 0; i < MANY_BOUNDS.length; i++) { + final RectF expectedBounds = MANY_BOUNDS[i]; + assertEquals(expectedBounds, info3.getCharacterRect(i)); } assertNull(info3.getCharacterRect(-1)); - assertNull(info3.getCharacterRect(MANY_RECTS.length + 1)); + assertNull(info3.getCharacterRect(MANY_BOUNDS.length + 1)); for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) { final int expectedFlags = MANY_FLAGS_ARRAY[i]; assertEquals(expectedFlags, info3.getCharacterRectFlags(i)); } - assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED, info3.getCharacterRectFlags(-1)); - assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED, - info3.getCharacterRectFlags(MANY_RECTS.length + 1)); + assertEquals(0, info3.getCharacterRectFlags(-1)); + assertEquals(0, info3.getCharacterRectFlags(MANY_BOUNDS.length + 1)); assertEquals(info.hashCode(), info3.hashCode()); builder.reset(); @@ -190,7 +186,7 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { assertEquals(-1, uninitializedInfo.getSelectionEnd()); assertEquals(-1, uninitializedInfo.getComposingTextStart()); assertNull(uninitializedInfo.getComposingText()); - assertFalse(uninitializedInfo.isInsertionMarkerClipped()); + assertEquals(0, uninitializedInfo.getInsertionMarkerFlags()); assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerHorizontal()); assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerTop()); assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerBaseline()); @@ -218,7 +214,7 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { final int SELECTION_END1 = 7; final String COMPOSING_TEXT1 = "0123456789"; final int COMPOSING_TEXT_START1 = 0; - final boolean INSERTION_MARKER_CLIPPED1 = true; + final int INSERTION_MARKER_FLAGS1 = FLAG_HAS_VISIBLE_REGION; final float INSERTION_MARKER_HORIZONTAL1 = 10.5f; final float INSERTION_MARKER_TOP1 = 100.1f; final float INSERTION_MARKER_BASELINE1 = 110.4f; @@ -227,7 +223,8 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { final int SELECTION_END2 = 8; final String COMPOSING_TEXT2 = "9876543210"; final int COMPOSING_TEXT_START2 = 3; - final boolean INSERTION_MARKER_CLIPPED2 = false; + final int INSERTION_MARKER_FLAGS2 = + FLAG_HAS_VISIBLE_REGION | FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL; final float INSERTION_MARKER_HORIZONTAL2 = 14.5f; final float INSERTION_MARKER_TOP2 = 200.1f; final float INSERTION_MARKER_BASELINE2 = 210.4f; @@ -265,10 +262,10 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { assertEquals( new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( Float.NaN, Float.NaN, Float.NaN, Float.NaN, - INSERTION_MARKER_CLIPPED1).build(), + INSERTION_MARKER_FLAGS1).build(), new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( Float.NaN, Float.NaN, Float.NaN, Float.NaN, - INSERTION_MARKER_CLIPPED1).build()); + INSERTION_MARKER_FLAGS1).build()); // Check Matrix. assertEquals( @@ -290,74 +287,74 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_CLIPPED1).build(), + INSERTION_MARKER_FLAGS1).build(), new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_CLIPPED1).build()); + INSERTION_MARKER_FLAGS1).build()); assertNotEquals( new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( Float.NaN, INSERTION_MARKER_TOP1, INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_CLIPPED1).build(), + INSERTION_MARKER_FLAGS1).build(), new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_CLIPPED1).build()); + INSERTION_MARKER_FLAGS1).build()); assertNotEquals( new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_CLIPPED1).build(), + INSERTION_MARKER_FLAGS1).build(), new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL2, INSERTION_MARKER_TOP1, INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_CLIPPED1).build()); + INSERTION_MARKER_FLAGS1).build()); assertNotEquals( new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_CLIPPED1).build(), + INSERTION_MARKER_FLAGS1).build(), new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP2, INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_CLIPPED1).build()); + INSERTION_MARKER_FLAGS1).build()); assertNotEquals( new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_CLIPPED1).build(), + INSERTION_MARKER_FLAGS1).build(), new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, INSERTION_MARKER_BASELINE2, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_CLIPPED1).build()); + INSERTION_MARKER_FLAGS1).build()); assertNotEquals( new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_CLIPPED1).build(), + INSERTION_MARKER_FLAGS1).build(), new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL2, INSERTION_MARKER_TOP1, INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_CLIPPED1).build()); + INSERTION_MARKER_FLAGS1).build()); assertNotEquals( new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_CLIPPED1).build(), + INSERTION_MARKER_FLAGS1).build(), new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM2, - INSERTION_MARKER_CLIPPED1).build()); + INSERTION_MARKER_FLAGS1).build()); assertNotEquals( new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_CLIPPED1).build(), + INSERTION_MARKER_FLAGS1).build(), new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_CLIPPED2).build()); + INSERTION_MARKER_FLAGS2).build()); } @SmallTest @@ -394,7 +391,7 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { final int SELECTION_END = 40; final int COMPOSING_TEXT_START = 32; final String COMPOSING_TEXT = "test"; - final boolean INSERTION_MARKER_CLIPPED = true; + final int INSERTION_MARKER_FLAGS = FLAG_HAS_VISIBLE_REGION; final float INSERTION_MARKER_HORIZONTAL = 10.5f; final float INSERTION_MARKER_TOP = 100.1f; final float INSERTION_MARKER_BASELINE = 110.4f; @@ -416,7 +413,7 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { } builder.setInsertionMarkerLocation(INSERTION_MARKER_HORIZONTAL, INSERTION_MARKER_TOP, - INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM, INSERTION_MARKER_CLIPPED); + INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM, INSERTION_MARKER_FLAGS); try { // Coordinate transformation matrix is required if no positional information is // specified. @@ -438,19 +435,10 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { } @SmallTest - public void testBuilderAddCharacterRect() throws Exception { + public void testBuilderAddCharacterBounds() throws Exception { // A negative index should be rejected. try { - new Builder().addCharacterRect(-1, 0.0f, 0.0f, 0.0f, 0.0f, - CHARACTER_RECT_TYPE_FULLY_VISIBLE); - assertTrue(false); - } catch (IllegalArgumentException ex) { - } - - // CHARACTER_RECT_TYPE_UNSPECIFIED is not allowed. - try { - new Builder().addCharacterRect(0, 0.0f, 0.0f, 0.0f, 0.0f, - CHARACTER_RECT_TYPE_UNSPECIFIED); + new Builder().addCharacterBounds(-1, 0.0f, 0.0f, 0.0f, 0.0f, FLAG_HAS_VISIBLE_REGION); assertTrue(false); } catch (IllegalArgumentException ex) { } |
