diff options
Diffstat (limited to 'core/java')
20 files changed, 282 insertions, 113 deletions
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index bc54055..3e03893 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -18,12 +18,14 @@ package android.app; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Point; import android.os.BatteryStats; import android.os.IBinder; import android.os.ParcelFileDescriptor; + import com.android.internal.app.ProcessStats; import com.android.internal.os.TransferPipe; import com.android.internal.util.FastPrintWriter; @@ -2464,7 +2466,11 @@ public class ActivityManager { } } - /** @hide */ + /** + * Gets the userId of the current foreground user. Requires system permissions. + * @hide + */ + @SystemApi public static int getCurrentUser() { UserInfo ui; try { diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java index 613e248..ad4a22b 100644 --- a/core/java/android/app/ActivityTransitionState.java +++ b/core/java/android/app/ActivityTransitionState.java @@ -151,6 +151,7 @@ class ActivityTransitionState { mEnterActivityOptions = options; mIsEnterTriggered = false; if (mEnterActivityOptions.isReturning()) { + restoreExitedViews(); int result = mEnterActivityOptions.getResultCode(); if (result != 0) { activity.onActivityReenter(result, mEnterActivityOptions.getResultData()); diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java index 47d3fd6..4126647 100644 --- a/core/java/android/app/EnterTransitionCoordinator.java +++ b/core/java/android/app/EnterTransitionCoordinator.java @@ -170,7 +170,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { private void sendSharedElementDestination() { boolean allReady; - if (allowOverlappingTransitions()) { + if (allowOverlappingTransitions() && getEnterViewsTransition() != null) { allReady = false; } else { allReady = !getDecor().isLayoutRequested(); @@ -466,6 +466,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { Drawable background = getDecor().getBackground(); if (background != null) { background = background.mutate(); + getWindow().setBackgroundDrawable(background); mBackgroundAnimator = ObjectAnimator.ofInt(background, "alpha", 255); mBackgroundAnimator.setDuration(getFadeDuration()); mBackgroundAnimator.addListener(new AnimatorListenerAdapter() { diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java index 3760b96..231c93f 100644 --- a/core/java/android/app/ExitTransitionCoordinator.java +++ b/core/java/android/app/ExitTransitionCoordinator.java @@ -140,7 +140,8 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { if (getDecor() != null) { getDecor().suppressLayout(true); } - if (!mSharedElements.isEmpty() && getSharedElementTransition() != null) { + if (mExitSharedElementBundle != null && !mExitSharedElementBundle.isEmpty() && + !mSharedElements.isEmpty() && getSharedElementTransition() != null) { startTransition(new Runnable() { public void run() { startSharedElementExit(); @@ -259,6 +260,8 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { ViewGroup decor = getDecor(); Drawable background; if (decor != null && (background = decor.getBackground()) != null) { + background = background.mutate(); + getWindow().setBackgroundDrawable(background); mBackgroundAnimator = ObjectAnimator.ofInt(background, "alpha", 0); mBackgroundAnimator.addListener(new AnimatorListenerAdapter() { @Override diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 6cc6fb2..ebeaf34 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -1917,7 +1917,7 @@ public class Notification implements Parcelable mPeople = new ArrayList<String>(); mColorUtil = context.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.L ? - NotificationColorUtil.getInstance() : null; + NotificationColorUtil.getInstance(mContext) : null; } /** @@ -2890,7 +2890,7 @@ public class Notification implements Parcelable } private void processLegacyAction(Action action, RemoteViews button) { - if (!isLegacy() || mColorUtil.isGrayscale(mContext, action.icon)) { + if (!isLegacy() || mColorUtil.isGrayscaleIcon(mContext, action.icon)) { button.setTextViewCompoundDrawablesRelativeColorFilter(R.id.action0, 0, mContext.getResources().getColor(R.color.notification_action_color_filter), PorterDuff.Mode.MULTIPLY); @@ -2909,7 +2909,7 @@ public class Notification implements Parcelable * Apply any necessary background to smallIcons being used in the largeIcon spot. */ private void processSmallIconAsLarge(int largeIconId, RemoteViews contentView) { - if (!isLegacy() || mColorUtil.isGrayscale(mContext, largeIconId)) { + if (!isLegacy() || mColorUtil.isGrayscaleIcon(mContext, largeIconId)) { applyLargeIconBackground(contentView); } } @@ -2920,7 +2920,7 @@ public class Notification implements Parcelable */ // TODO: also check bounds, transparency, that sort of thing. private void processLargeLegacyIcon(Bitmap largeIcon, RemoteViews contentView) { - if (isLegacy() && mColorUtil.isGrayscale(largeIcon)) { + if (isLegacy() && mColorUtil.isGrayscaleIcon(largeIcon)) { applyLargeIconBackground(contentView); } else { removeLargeIconBackground(contentView); @@ -2956,7 +2956,7 @@ public class Notification implements Parcelable */ private void processSmallRightIcon(int smallIconDrawableId, RemoteViews contentView) { - if (!isLegacy() || mColorUtil.isGrayscale(mContext, smallIconDrawableId)) { + if (!isLegacy() || mColorUtil.isGrayscaleIcon(mContext, smallIconDrawableId)) { contentView.setDrawableParameters(R.id.right_icon, false, -1, 0xFFFFFFFF, PorterDuff.Mode.SRC_ATOP, -1); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 9ed8960..282444a 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -115,13 +115,14 @@ public class DevicePolicyManager { = "android.app.action.ACTION_PROVISION_MANAGED_PROFILE"; /** - * A {@link Parcelable} extra of type {@link PersistableBundle} that allows a mobile device - * management application that starts managed profile provisioning to pass data to itself on the - * managed profile when provisioning completes. The mobile device management application sends - * this extra in an intent with the action {@link #ACTION_PROVISION_MANAGED_PROFILE} and - * receives it in {@link DeviceAdminReceiver#onProfileProvisioningComplete} via an intent with - * the action {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE}. The bundle is - * not changed during the managed profile provisioning. + * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that allows + * a mobile device management application that starts managed profile provisioning to pass data + * to itself on the managed profile when provisioning completes. The mobile device management + * application sends this extra in an intent with the action + * {@link #ACTION_PROVISION_MANAGED_PROFILE} and receives it in + * {@link DeviceAdminReceiver#onProfileProvisioningComplete} via an intent with the action + * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE}. The bundle is not changed + * during the managed profile provisioning. */ public static final String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE = "android.app.extra.ADMIN_EXTRA_BUNDLE"; @@ -1785,16 +1786,24 @@ public class DevicePolicyManager { * If a user has installed any certificates by other means than device policy these will be * included too. * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @return a List of byte[] arrays, each encoding one user CA certificate. */ - public List<byte[]> getInstalledCaCerts() { - final TrustedCertificateStore certStore = new TrustedCertificateStore(); + public List<byte[]> getInstalledCaCerts(ComponentName admin) { List<byte[]> certs = new ArrayList<byte[]>(); - for (String alias : certStore.userAliases()) { + if (mService != null) { try { - certs.add(certStore.getCertificate(alias).getEncoded()); - } catch (CertificateException ce) { - Log.w(TAG, "Could not encode certificate: " + alias, ce); + mService.enforceCanManageCaCerts(admin); + final TrustedCertificateStore certStore = new TrustedCertificateStore(); + for (String alias : certStore.userAliases()) { + try { + certs.add(certStore.getCertificate(alias).getEncoded()); + } catch (CertificateException ce) { + Log.w(TAG, "Could not encode certificate: " + alias, ce); + } + } + } catch (RemoteException re) { + Log.w(TAG, "Failed talking with device policy service", re); } } return certs; @@ -1821,13 +1830,19 @@ public class DevicePolicyManager { /** * Returns whether this certificate is installed as a trusted CA. * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param certBuffer encoded form of the certificate to look up. */ - public boolean hasCaCertInstalled(byte[] certBuffer) { - try { - return getCaCertAlias(certBuffer) != null; - } catch (CertificateException ce) { - Log.w(TAG, "Could not parse certificate", ce); + public boolean hasCaCertInstalled(ComponentName admin, byte[] certBuffer) { + if (mService != null) { + try { + mService.enforceCanManageCaCerts(admin); + return getCaCertAlias(certBuffer) != null; + } catch (RemoteException re) { + Log.w(TAG, "Failed talking with device policy service", re); + } catch (CertificateException ce) { + Log.w(TAG, "Could not parse certificate", ce); + } } return false; } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index c984cf9..57d8b95 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -124,6 +124,7 @@ interface IDevicePolicyManager { boolean installCaCert(in ComponentName admin, in byte[] certBuffer); void uninstallCaCert(in ComponentName admin, in String alias); + void enforceCanManageCaCerts(in ComponentName admin); void addPersistentPreferredActivity(in ComponentName admin, in IntentFilter filter, in ComponentName activity); void clearPackagePersistentPreferredActivities(in ComponentName admin, String packageName); diff --git a/core/java/android/app/job/JobScheduler.java b/core/java/android/app/job/JobScheduler.java index ca7022d..89efeb2 100644 --- a/core/java/android/app/job/JobScheduler.java +++ b/core/java/android/app/job/JobScheduler.java @@ -21,14 +21,24 @@ import java.util.List; import android.content.Context; /** - * Class for scheduling various types of jobs with the scheduling framework on the device. + * This is an API for scheduling various types of jobs against the framework that will be executed + * in your application's own process. + * <p> * See {@link android.app.job.JobInfo} for more description of the types of jobs that can be run - * and how to construct them. + * and how to construct them. You will construct these JobInfo objects and pass them to the + * JobScheduler with {@link #schedule(JobInfo)}. When the criteria declared are met, the + * system will execute this job on your application's {@link android.app.job.JobService}. + * You identify which JobService is meant to execute the logic for your job when you create the + * JobInfo with + * {@link android.app.job.JobInfo.Builder#JobInfo.Builder(int,android.content.ComponentName)}. + * </p> + * <p> * The framework will be intelligent about when you receive your callbacks, and attempt to batch * and defer them as much as possible. Typically if you don't specify a deadline on your job, it * can be run at any moment depending on the current state of the JobScheduler's internal queue, * however it might be deferred as long as until the next time the device is connected to a power * source. + * </p> * <p>You do not * instantiate this class directly; instead, retrieve it through * {@link android.content.Context#getSystemService diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java index b98e5ae..36997e5 100644 --- a/core/java/android/bluetooth/BluetoothSocket.java +++ b/core/java/android/bluetooth/BluetoothSocket.java @@ -375,6 +375,14 @@ public final class BluetoothSocket implements Closeable { } // else ASSERT(mPort == channel) ret = 0; } catch (IOException e) { + if (mPfd != null) { + try { + mPfd.close(); + } catch (IOException e1) { + Log.e(TAG, "bindListen, close mPfd: " + e1); + } + mPfd = null; + } Log.e(TAG, "bindListen, fail to get port number, exception: " + e); return -1; } diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java index 5ce9d5c..0ff5f6a 100644 --- a/core/java/android/os/UserHandle.java +++ b/core/java/android/os/UserHandle.java @@ -234,6 +234,7 @@ public final class UserHandle implements Parcelable { * @return user id of the current process * @hide */ + @SystemApi public static final int myUserId() { return getUserId(Process.myUid()); } @@ -253,7 +254,11 @@ public final class UserHandle implements Parcelable { mHandle = h; } - /** @hide */ + /** + * Returns the userId stored in this UserHandle. + * @hide + */ + @SystemApi public int getIdentifier() { return mHandle; } diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index f793667..59220e1 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -15,6 +15,7 @@ */ package android.os; +import android.annotation.SystemApi; import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.content.Context; @@ -424,6 +425,19 @@ public class UserManager { } /** + * Checks if the calling app is running in a managed profile. + * Requires {@link android.Manifest.permission#MANAGE_USERS} permission. + * + * @return whether the caller is in a managed profile. + * @hide + */ + @SystemApi + public boolean isManagedProfile() { + UserInfo user = getUserInfo(UserHandle.myUserId()); + return user != null ? user.isManagedProfile() : false; + } + + /** * Return whether the given user is actively running. This means that * the user is in the "started" state, not "stopped" -- it is currently * allowed to run code through scheduled alarms, receiving broadcasts, diff --git a/core/java/android/transition/ChangeTransform.java b/core/java/android/transition/ChangeTransform.java index d579f54..cb0a875 100644 --- a/core/java/android/transition/ChangeTransform.java +++ b/core/java/android/transition/ChangeTransform.java @@ -45,6 +45,10 @@ public class ChangeTransform extends Transition { private static final String PROPNAME_TRANSFORMS = "android:changeTransform:transforms"; private static final String PROPNAME_PARENT = "android:changeTransform:parent"; private static final String PROPNAME_PARENT_MATRIX = "android:changeTransform:parentMatrix"; + private static final String PROPNAME_INTERMEDIATE_PARENT_MATRIX = + "android:changeTransform:intermediateParentMatrix"; + private static final String PROPNAME_INTERMEDIATE_MATRIX = + "android:changeTransform:intermediateMatrix"; private static final String[] sTransitionProperties = { PROPNAME_MATRIX, @@ -172,6 +176,10 @@ public class ChangeTransform extends Transition { parent.transformMatrixToGlobal(parentMatrix); parentMatrix.preTranslate(-parent.getScrollX(), -parent.getScrollY()); transitionValues.values.put(PROPNAME_PARENT_MATRIX, parentMatrix); + transitionValues.values.put(PROPNAME_INTERMEDIATE_MATRIX, + view.getTag(R.id.transitionTransform)); + transitionValues.values.put(PROPNAME_INTERMEDIATE_PARENT_MATRIX, + view.getTag(R.id.parentMatrix)); } return; } @@ -199,12 +207,13 @@ public class ChangeTransform extends Transition { ViewGroup endParent = (ViewGroup) endValues.values.get(PROPNAME_PARENT); boolean handleParentChange = mReparent && !parentsMatch(startParent, endParent); - Matrix startMatrix = (Matrix) startValues.view.getTag(R.id.transitionTransform); + Matrix startMatrix = (Matrix) startValues.values.get(PROPNAME_INTERMEDIATE_MATRIX); if (startMatrix != null) { startValues.values.put(PROPNAME_MATRIX, startMatrix); } - Matrix startParentMatrix = (Matrix) startValues.view.getTag(R.id.parentMatrix); + Matrix startParentMatrix = (Matrix) + startValues.values.get(PROPNAME_INTERMEDIATE_PARENT_MATRIX); if (startParentMatrix != null) { startValues.values.put(PROPNAME_PARENT_MATRIX, startParentMatrix); } @@ -250,9 +259,11 @@ public class ChangeTransform extends Transition { ObjectAnimator animator = ObjectAnimator.ofObject(view, ANIMATION_MATRIX_PROPERTY, new TransitionUtils.MatrixEvaluator(), startMatrix, endMatrix); + final Matrix finalEndMatrix = endMatrix; + AnimatorListenerAdapter listener = new AnimatorListenerAdapter() { private boolean mIsCanceled; - private Matrix mTempMatrix; + private Matrix mTempMatrix = new Matrix(); @Override public void onAnimationCancel(Animator animation) { @@ -262,8 +273,7 @@ public class ChangeTransform extends Transition { @Override public void onAnimationEnd(Animator animation) { if (!mIsCanceled) { - view.setTagInternal(R.id.transitionTransform, null); - view.setTagInternal(R.id.parentMatrix, null); + setCurrentMatrix(finalEndMatrix); } ANIMATION_MATRIX_PROPERTY.set(view, null); transforms.restore(view); @@ -273,19 +283,19 @@ public class ChangeTransform extends Transition { public void onAnimationPause(Animator animation) { ValueAnimator animator = (ValueAnimator) animation; Matrix currentMatrix = (Matrix) animator.getAnimatedValue(); - if (mTempMatrix == null) { - mTempMatrix = new Matrix(currentMatrix); - } else { - mTempMatrix.set(currentMatrix); - } - view.setTagInternal(R.id.transitionTransform, mTempMatrix); - transforms.restore(view); + setCurrentMatrix(currentMatrix); } @Override public void onAnimationResume(Animator animation) { setIdentityTransforms(view); } + + private void setCurrentMatrix(Matrix currentMatrix) { + mTempMatrix.set(currentMatrix); + view.setTagInternal(R.id.transitionTransform, mTempMatrix); + transforms.restore(view); + } }; animator.addListener(listener); @@ -423,6 +433,8 @@ public class ChangeTransform extends Transition { public void onTransitionEnd(Transition transition) { transition.removeListener(this); GhostView.removeGhost(mView); + mView.setTagInternal(R.id.transitionTransform, null); + mView.setTagInternal(R.id.parentMatrix, null); } @Override diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index 964b054..0701b53 100644 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -660,8 +660,96 @@ public class KeyEvent extends InputEvent implements Parcelable { /** Key code constant: Voice Assist key. * Launches the global voice assist activity. Not delivered to applications. */ public static final int KEYCODE_VOICE_ASSIST = 231; - - private static final int LAST_KEYCODE = KEYCODE_VOICE_ASSIST; + /** Key code constant: Radio key. + * Toggles TV service / Radio service. */ + public static final int KEYCODE_TV_RADIO_SERVICE = 232; + /** Key code constant: Teletext key. + * Displays Teletext service. */ + public static final int KEYCODE_TV_TELETEXT = 233; + /** Key code constant: Number entry key. + * Initiates to enter multi-digit channel nubmber when each digit key is assigned + * for selecting separate channel. Corresponds to Number Entry Mode (0x1D) of CEC + * User Control Code. */ + public static final int KEYCODE_TV_NUMBER_ENTRY = 234; + /** Key code constant: Analog Terrestrial key. + * Switches to analog terrestrial broadcast service. */ + public static final int KEYCODE_TV_TERRESTRIAL_ANALOG = 235; + /** Key code constant: Digital Terrestrial key. + * Switches to digital terrestrial broadcast service. */ + public static final int KEYCODE_TV_TERRESTRIAL_DIGITAL = 236; + /** Key code constant: Satellite key. + * Switches to digital satellite broadcast service. */ + public static final int KEYCODE_TV_SATELLITE = 237; + /** Key code constant: BS key. + * Switches to BS digital satellite broadcasting service available in Japan. */ + public static final int KEYCODE_TV_SATELLITE_BS = 238; + /** Key code constant: CS key. + * Switches to CS digital satellite broadcasting service available in Japan. */ + public static final int KEYCODE_TV_SATELLITE_CS = 239; + /** Key code constant: BS/CS key. + * Toggles between BS and CS digital satellite services. */ + public static final int KEYCODE_TV_SATELLITE_SERVICE = 240; + /** Key code constant: Toggle Network key. + * Toggles selecting broacast services. */ + public static final int KEYCODE_TV_NETWORK = 241; + /** Key code constant: Antenna/Cable key. + * Toggles broadcast input source between antenna and cable. */ + public static final int KEYCODE_TV_ANTENNA_CABLE = 242; + /** Key code constant: HDMI #1 key. + * Switches to HDMI input #1. */ + public static final int KEYCODE_TV_INPUT_HDMI_1 = 243; + /** Key code constant: HDMI #2 key. + * Switches to HDMI input #2. */ + public static final int KEYCODE_TV_INPUT_HDMI_2 = 244; + /** Key code constant: HDMI #3 key. + * Switches to HDMI input #3. */ + public static final int KEYCODE_TV_INPUT_HDMI_3 = 245; + /** Key code constant: HDMI #4 key. + * Switches to HDMI input #4. */ + public static final int KEYCODE_TV_INPUT_HDMI_4 = 246; + /** Key code constant: Composite #1 key. + * Switches to composite video input #1. */ + public static final int KEYCODE_TV_INPUT_COMPOSITE_1 = 247; + /** Key code constant: Composite #2 key. + * Switches to composite video input #2. */ + public static final int KEYCODE_TV_INPUT_COMPOSITE_2 = 248; + /** Key code constant: Component #1 key. + * Switches to component video input #1. */ + public static final int KEYCODE_TV_INPUT_COMPONENT_1 = 249; + /** Key code constant: Component #2 key. + * Switches to component video input #2. */ + public static final int KEYCODE_TV_INPUT_COMPONENT_2 = 250; + /** Key code constant: VGA #1 key. + * Switches to VGA (analog RGB) input #1. */ + public static final int KEYCODE_TV_INPUT_VGA_1 = 251; + /** Key code constant: Audio description key. + * Toggles audio description off / on. */ + public static final int KEYCODE_TV_AUDIO_DESCRIPTION = 252; + /** Key code constant: Audio description mixing volume up key. + * Louden audio description volume as compared with normal audio volume. */ + public static final int KEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP = 253; + /** Key code constant: Audio description mixing volume down key. + * Lessen audio description volume as compared with normal audio volume. */ + public static final int KEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN = 254; + /** Key code constant: Zoom mode key. + * Changes Zoom mode (Normal, Full, Zoom, Wide-zoom, etc.) */ + public static final int KEYCODE_TV_ZOOM_MODE = 255; + /** Key code constant: Contents menu key. + * Goes to the title list. Corresponds to Contents Menu (0x0B) of CEC User Control + * Code */ + public static final int KEYCODE_TV_CONTENTS_MENU = 256; + /** Key code constant: Media context menu key. + * Goes to the context menu of media contents. Corresponds to Media Context-sensitive + * Menu (0x11) of CEC User Control Code. */ + public static final int KEYCODE_TV_MEDIA_CONTEXT_MENU = 257; + /** Key code constant: Timer programming key. + * Goes to the timer recording menu. Corresponds to Timer Programming (0x54) of + * CEC User Control Code. */ + public static final int KEYCODE_TV_TIMER_PROGRAMMING = 258; + /** Key code constant: Help key. */ + public static final int KEYCODE_HELP = 259; + + private static final int LAST_KEYCODE = KEYCODE_HELP; // NOTE: If you add a new keycode here you must also add it to: // isSystem() diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index ca08ecc..5d2822d 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -126,7 +126,7 @@ public class ThreadedRenderer extends HardwareRenderer { void destroy() { mInitialized = false; updateEnabledState(null); - nDestroyCanvasAndSurface(mNativeProxy); + nDestroy(mNativeProxy); } private void updateEnabledState(Surface surface) { @@ -488,7 +488,7 @@ public class ThreadedRenderer extends HardwareRenderer { private static native void nSetOpaque(long nativeProxy, boolean opaque); private static native int nSyncAndDrawFrame(long nativeProxy, long frameTimeNanos, long recordDuration, float density); - private static native void nDestroyCanvasAndSurface(long nativeProxy); + private static native void nDestroy(long nativeProxy); private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode); private static native void nInvokeFunctor(long functor, boolean waitForCompletion); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index fce6f0b..21e7c6b 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -4908,36 +4908,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } onFocusChanged(true, direction, previouslyFocusedRect); - manageFocusHotspot(true, oldFocus); refreshDrawableState(); } } /** - * Forwards focus information to the background drawable, if necessary. When - * the view is gaining focus, <code>v</code> is the previous focus holder. - * When the view is losing focus, <code>v</code> is the next focus holder. - * - * @param focused whether this view is focused - * @param v previous or the next focus holder, or null if none - */ - private void manageFocusHotspot(boolean focused, View v) { - final Rect r = new Rect(); - if (v != null && mAttachInfo != null) { - v.getHotspotBounds(r); - final int[] location = mAttachInfo.mTmpLocation; - getLocationOnScreen(location); - r.offset(-location[0], -location[1]); - } else { - r.set(0, 0, mRight - mLeft, mBottom - mTop); - } - - final float x = r.exactCenterX(); - final float y = r.exactCenterY(); - drawableHotspotChanged(x, y); - } - - /** * Populates <code>outRect</code> with the hotspot bounds. By default, * the hotspot bounds are identical to the screen bounds. * @@ -5060,8 +5035,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } onFocusChanged(false, 0, null); - - manageFocusHotspot(false, focused); refreshDrawableState(); if (propagate && (!refocus || !rootViewRequestFocus())) { diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index e1f19ee..edfa7af 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -1810,21 +1810,6 @@ public class WebView extends AbsoluteLayout } /** - * Sets whether the application wants to opt out from using the Data Reduction Proxy - * service. - * Data reduction proxy can only be enabled by the user and will almost always be - * transparent to the application. In rare cases where using the proxy interferes - * with the app, the application developer can use this API to opt out from using the - * proxy. Note that this may increase network bandwidth usage. - * - * See <a href=http://developer.chrome.com/multidevice/data-compression> - * Data Compression Proxy</a> - */ - public static void optOutDataReductionProxy() { - getFactory().getStatics().optOutDataReductionProxy(); - } - - /** * Gets the list of currently loaded plugins. * * @return the list of currently loaded plugins diff --git a/core/java/android/webkit/WebViewFactoryProvider.java b/core/java/android/webkit/WebViewFactoryProvider.java index 48f3ca3..20bb932 100644 --- a/core/java/android/webkit/WebViewFactoryProvider.java +++ b/core/java/android/webkit/WebViewFactoryProvider.java @@ -61,12 +61,6 @@ public interface WebViewFactoryProvider { /** * Implements the API method: - * {@link android.webkit.WebView#optOutDataReductionProxy() } - */ - void optOutDataReductionProxy(); - - /** - * Implements the API method: * {@link android.webkit.WebView#setSlowWholeDocumentDrawEnabled(boolean) } */ void enableSlowWholeDocumentDraw(); diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java index ee17b78..345eafb 100644 --- a/core/java/android/widget/NumberPicker.java +++ b/core/java/android/widget/NumberPicker.java @@ -1878,6 +1878,9 @@ public class NumberPicker extends LinearLayout { if (mOnValueChangeListener != null) { mOnValueChangeListener.onValueChange(this, previous, mValue); } + + mAccessibilityNodeProvider.sendAccessibilityEventForVirtualText( + AccessibilityEvent.TYPE_VIEW_FOCUSED); } /** @@ -2556,6 +2559,7 @@ public class NumberPicker extends LinearLayout { getLocationOnScreen(locationOnScreen); boundsInScreen.offset(locationOnScreen[0], locationOnScreen[1]); info.setBoundsInScreen(boundsInScreen); + info.setLiveRegion(View.ACCESSIBILITY_LIVE_REGION_ASSERTIVE); return info; } diff --git a/core/java/com/android/internal/util/ImageUtils.java b/core/java/com/android/internal/util/ImageUtils.java index a5ce6e0..c153904 100644 --- a/core/java/com/android/internal/util/ImageUtils.java +++ b/core/java/com/android/internal/util/ImageUtils.java @@ -17,6 +17,10 @@ package com.android.internal.util; import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.PorterDuff; /** * Utility class for image analysis and processing. @@ -31,17 +35,49 @@ public class ImageUtils { // Alpha amount for which values below are considered transparent. private static final int ALPHA_TOLERANCE = 50; + // Size of the smaller bitmap we're actually going to scan. + private static final int COMPACT_BITMAP_SIZE = 64; // pixels + private int[] mTempBuffer; + private Bitmap mTempCompactBitmap; + private Canvas mTempCompactBitmapCanvas; + private Paint mTempCompactBitmapPaint; + private final Matrix mTempMatrix = new Matrix(); /** * Checks whether a bitmap is grayscale. Grayscale here means "very close to a perfect * gray". + * + * Instead of scanning every pixel in the bitmap, we first resize the bitmap to no more than + * COMPACT_BITMAP_SIZE^2 pixels using filtering. The hope is that any non-gray color elements + * will survive the squeezing process, contaminating the result with color. */ public boolean isGrayscale(Bitmap bitmap) { - final int height = bitmap.getHeight(); - final int width = bitmap.getWidth(); - int size = height*width; + int height = bitmap.getHeight(); + int width = bitmap.getWidth(); + + // shrink to a more manageable (yet hopefully no more or less colorful) size + if (height > COMPACT_BITMAP_SIZE || width > COMPACT_BITMAP_SIZE) { + if (mTempCompactBitmap == null) { + mTempCompactBitmap = Bitmap.createBitmap( + COMPACT_BITMAP_SIZE, COMPACT_BITMAP_SIZE, Bitmap.Config.ARGB_8888 + ); + mTempCompactBitmapCanvas = new Canvas(mTempCompactBitmap); + mTempCompactBitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mTempCompactBitmapPaint.setFilterBitmap(true); + } + mTempMatrix.reset(); + mTempMatrix.setScale( + (float) COMPACT_BITMAP_SIZE / width, + (float) COMPACT_BITMAP_SIZE / height, + 0, 0); + mTempCompactBitmapCanvas.drawColor(0, PorterDuff.Mode.SRC); // select all, erase + mTempCompactBitmapCanvas.drawBitmap(bitmap, mTempMatrix, mTempCompactBitmapPaint); + bitmap = mTempCompactBitmap; + width = height = COMPACT_BITMAP_SIZE; + } + final int size = height*width; ensureBufferSize(size); bitmap.getPixels(mTempBuffer, 0, width, 0, 0, width, height); for (int i = 0; i < size; i++) { diff --git a/core/java/com/android/internal/util/NotificationColorUtil.java b/core/java/com/android/internal/util/NotificationColorUtil.java index 665055c..3249ea3 100644 --- a/core/java/com/android/internal/util/NotificationColorUtil.java +++ b/core/java/com/android/internal/util/NotificationColorUtil.java @@ -50,23 +50,36 @@ public class NotificationColorUtil { private final WeakHashMap<Bitmap, Pair<Boolean, Integer>> mGrayscaleBitmapCache = new WeakHashMap<Bitmap, Pair<Boolean, Integer>>(); - public static NotificationColorUtil getInstance() { + private final int mGrayscaleIconMaxSize; // @dimen/notification_large_icon_width (64dp) + + public static NotificationColorUtil getInstance(Context context) { synchronized (sLock) { if (sInstance == null) { - sInstance = new NotificationColorUtil(); + sInstance = new NotificationColorUtil(context); } return sInstance; } } + private NotificationColorUtil(Context context) { + mGrayscaleIconMaxSize = context.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.notification_large_icon_width); + } + /** - * Checks whether a bitmap is grayscale. Grayscale here means "very close to a perfect - * gray". + * Checks whether a Bitmap is a small grayscale icon. + * Grayscale here means "very close to a perfect gray"; icon means "no larger than 64dp". * * @param bitmap The bitmap to test. - * @return Whether the bitmap is grayscale. + * @return True if the bitmap is grayscale; false if it is color or too large to examine. */ - public boolean isGrayscale(Bitmap bitmap) { + public boolean isGrayscaleIcon(Bitmap bitmap) { + // quick test: reject large bitmaps + if (bitmap.getWidth() > mGrayscaleIconMaxSize + || bitmap.getHeight() > mGrayscaleIconMaxSize) { + return false; + } + synchronized (sLock) { Pair<Boolean, Integer> cached = mGrayscaleBitmapCache.get(bitmap); if (cached != null) { @@ -92,22 +105,22 @@ public class NotificationColorUtil { } /** - * Checks whether a drawable is grayscale. Grayscale here means "very close to a perfect - * gray". + * Checks whether a Drawable is a small grayscale icon. + * Grayscale here means "very close to a perfect gray"; icon means "no larger than 64dp". * * @param d The drawable to test. - * @return Whether the drawable is grayscale. + * @return True if the bitmap is grayscale; false if it is color or too large to examine. */ - public boolean isGrayscale(Drawable d) { + public boolean isGrayscaleIcon(Drawable d) { if (d == null) { return false; } else if (d instanceof BitmapDrawable) { BitmapDrawable bd = (BitmapDrawable) d; - return bd.getBitmap() != null && isGrayscale(bd.getBitmap()); + return bd.getBitmap() != null && isGrayscaleIcon(bd.getBitmap()); } else if (d instanceof AnimationDrawable) { AnimationDrawable ad = (AnimationDrawable) d; int count = ad.getNumberOfFrames(); - return count > 0 && isGrayscale(ad.getFrame(0)); + return count > 0 && isGrayscaleIcon(ad.getFrame(0)); } else if (d instanceof VectorDrawable) { // We just assume you're doing the right thing if using vectors return true; @@ -117,16 +130,16 @@ public class NotificationColorUtil { } /** - * Checks whether a drawable with a resoure id is grayscale. Grayscale here means "very close - * to a perfect gray". + * Checks whether a drawable with a resoure id is a small grayscale icon. + * Grayscale here means "very close to a perfect gray"; icon means "no larger than 64dp". * * @param context The context to load the drawable from. - * @return Whether the drawable is grayscale. + * @return True if the bitmap is grayscale; false if it is color or too large to examine. */ - public boolean isGrayscale(Context context, int drawableResId) { + public boolean isGrayscaleIcon(Context context, int drawableResId) { if (drawableResId != 0) { try { - return isGrayscale(context.getDrawable(drawableResId)); + return isGrayscaleIcon(context.getDrawable(drawableResId)); } catch (Resources.NotFoundException ex) { Log.e(TAG, "Drawable not found: " + drawableResId); return false; |