diff options
Diffstat (limited to 'core/java')
30 files changed, 730 insertions, 150 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index fa15ad7..cf6c049 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -1742,6 +1742,12 @@ public final class ActivityThread { new LoadedApk(this, aInfo, compatInfo, baseLoader, securityViolation, includeCode && (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage); + + if (mSystemThread && "android".equals(aInfo.packageName)) { + packageInfo.installSystemApplicationInfo(aInfo, + getSystemContext().mPackageInfo.getClassLoader()); + } + if (includeCode) { mPackages.put(aInfo.packageName, new WeakReference<LoadedApk>(packageInfo)); @@ -1802,10 +1808,6 @@ public final class ActivityThread { synchronized (this) { getSystemContext().installSystemApplicationInfo(info, classLoader); - // The code package for "android" in the system server needs - // to be the system context's package. - mPackages.put("android", new WeakReference<LoadedApk>(getSystemContext().mPackageInfo)); - // give ourselves a default profiler mProfiler = new Profiler(); } diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java index 7894887..ecf19c7 100644 --- a/core/java/android/app/EnterTransitionCoordinator.java +++ b/core/java/android/app/EnterTransitionCoordinator.java @@ -133,16 +133,17 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { return; } mAreViewsReady = true; + final ViewGroup decor = getDecor(); // Ensure the views have been laid out before capturing the views -- we need the epicenter. - if (sharedElements.isEmpty() || !sharedElements.valueAt(0).isLayoutRequested()) { + if (decor == null || (decor.isAttachedToWindow() && + (sharedElements.isEmpty() || !sharedElements.valueAt(0).isLayoutRequested()))) { viewsReady(sharedElements); } else { - final View sharedElement = sharedElements.valueAt(0); - sharedElement.getViewTreeObserver() + decor.getViewTreeObserver() .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { - sharedElement.getViewTreeObserver().removeOnPreDrawListener(this); + decor.getViewTreeObserver().removeOnPreDrawListener(this); viewsReady(sharedElements); return true; } diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 9849c51..c65f017 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -4340,6 +4340,19 @@ public class Notification implements Parcelable */ public static final int SIZE_FULL_SCREEN = 5; + /** + * Sentinel value for use with {@link #setHintScreenTimeout} to keep the screen on for a + * short amount of time when this notification is displayed on the screen. This + * is the default value. + */ + public static final int SCREEN_TIMEOUT_SHORT = 0; + + /** + * Sentinel value for use with {@link #setHintScreenTimeout} to keep the screen on + * for a longer amount of time when this notification is displayed on the screen. + */ + public static final int SCREEN_TIMEOUT_LONG = -1; + /** Notification extra which contains wearable extensions */ private static final String EXTRA_WEARABLE_EXTENSIONS = "android.wearable.EXTENSIONS"; @@ -4355,12 +4368,14 @@ public class Notification implements Parcelable private static final String KEY_CUSTOM_SIZE_PRESET = "customSizePreset"; private static final String KEY_CUSTOM_CONTENT_HEIGHT = "customContentHeight"; private static final String KEY_GRAVITY = "gravity"; + private static final String KEY_HINT_SCREEN_TIMEOUT = "hintScreenTimeout"; // Flags bitwise-ored to mFlags private static final int FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE = 0x1; private static final int FLAG_HINT_HIDE_ICON = 1 << 1; private static final int FLAG_HINT_SHOW_BACKGROUND_ONLY = 1 << 2; private static final int FLAG_START_SCROLL_BOTTOM = 1 << 3; + private static final int FLAG_HINT_AVOID_BACKGROUND_CLIPPING = 1 << 4; // Default value for flags integer private static final int DEFAULT_FLAGS = FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE; @@ -4379,6 +4394,7 @@ public class Notification implements Parcelable private int mCustomSizePreset = SIZE_DEFAULT; private int mCustomContentHeight; private int mGravity = DEFAULT_GRAVITY; + private int mHintScreenTimeout; /** * Create a {@link android.app.Notification.WearableExtender} with default @@ -4414,6 +4430,7 @@ public class Notification implements Parcelable SIZE_DEFAULT); mCustomContentHeight = wearableBundle.getInt(KEY_CUSTOM_CONTENT_HEIGHT); mGravity = wearableBundle.getInt(KEY_GRAVITY, DEFAULT_GRAVITY); + mHintScreenTimeout = wearableBundle.getInt(KEY_HINT_SCREEN_TIMEOUT); } } @@ -4461,6 +4478,9 @@ public class Notification implements Parcelable if (mGravity != DEFAULT_GRAVITY) { wearableBundle.putInt(KEY_GRAVITY, mGravity); } + if (mHintScreenTimeout != 0) { + wearableBundle.putInt(KEY_HINT_SCREEN_TIMEOUT, mHintScreenTimeout); + } builder.getExtras().putBundle(EXTRA_WEARABLE_EXTENSIONS, wearableBundle); return builder; @@ -4480,6 +4500,7 @@ public class Notification implements Parcelable that.mCustomSizePreset = this.mCustomSizePreset; that.mCustomContentHeight = this.mCustomContentHeight; that.mGravity = this.mGravity; + that.mHintScreenTimeout = this.mHintScreenTimeout; return that; } @@ -4875,6 +4896,48 @@ public class Notification implements Parcelable return (mFlags & FLAG_HINT_SHOW_BACKGROUND_ONLY) != 0; } + /** + * Set a hint that this notification's background should not be clipped if possible. + * @param hintAvoidBackgroundClipping {@code true} to avoid clipping if possible. + * @return this object for method chaining + */ + public WearableExtender setHintAvoidBackgroundClipping( + boolean hintAvoidBackgroundClipping) { + setFlag(FLAG_HINT_AVOID_BACKGROUND_CLIPPING, hintAvoidBackgroundClipping); + return this; + } + + /** + * Get a hint that this notification's background should not be clipped if possible. + * @return {@code true} if it's ok if the background is clipped on the screen, false + * otherwise. The default value is {@code false} if this was never set. + */ + public boolean getHintAvoidBackgroundClipping() { + return (mFlags & FLAG_HINT_AVOID_BACKGROUND_CLIPPING) != 0; + } + + /** + * Set a hint that the screen should remain on for at least this duration when + * this notification is displayed on the screen. + * @param timeout The requested screen timeout in milliseconds. Can also be either + * {@link #SCREEN_TIMEOUT_SHORT} or {@link #SCREEN_TIMEOUT_LONG}. + * @return this object for method chaining + */ + public WearableExtender setHintScreenTimeout(int timeout) { + mHintScreenTimeout = timeout; + return this; + } + + /** + * Get the duration, in milliseconds, that the screen should remain on for + * when this notification is displayed. + * @return the duration in milliseconds if > 0, or either one of the sentinel values + * {@link #SCREEN_TIMEOUT_SHORT} or {@link #SCREEN_TIMEOUT_LONG}. + */ + public int getHintScreenTimeout() { + return mHintScreenTimeout; + } + private void setFlag(int mask, boolean value) { if (value) { mFlags |= mask; diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index a30ae57..74502fc 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -3133,9 +3133,10 @@ public class DevicePolicyManager { } /** - * Called by a profile owner to disable account management for a specific type of account. + * Called by a device owner or profile owner to disable account management for a specific type + * of account. * - * <p>The calling device admin must be a profile owner. If it is not, a + * <p>The calling device admin must be a device owner or profile owner. If it is not, a * security exception will be thrown. * * <p>When account management is disabled for an account type, adding or removing an account diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 7676e4b..e06f034 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -41,6 +41,7 @@ import android.os.Bundle; import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; +import android.os.Process; import android.os.StrictMode; import android.os.UserHandle; import android.provider.DocumentsContract; @@ -7498,8 +7499,10 @@ public class Intent implements Parcelable, Cloneable { */ public void prepareToEnterProcess() { if (mContentUserHint != UserHandle.USER_CURRENT) { - fixUris(mContentUserHint); - mContentUserHint = UserHandle.USER_CURRENT; + if (UserHandle.getAppId(Process.myUid()) != Process.SYSTEM_UID) { + fixUris(mContentUserHint); + mContentUserHint = UserHandle.USER_CURRENT; + } } } diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java index 5ee0b67..c164340 100644 --- a/core/java/android/content/pm/LauncherApps.java +++ b/core/java/android/content/pm/LauncherApps.java @@ -499,20 +499,4 @@ public class LauncherApps { obtainMessage(MSG_UNAVAILABLE, info).sendToTarget(); } } - - /** - * TODO Remove after 2014-09-22 - * @hide - */ - public void addCallback(Callback callback) { - registerCallback(callback); - } - - /** - * TODO Remove after 2014-09-22 - * @hide - */ - public void removeCallback(Callback callback) { - unregisterCallback(callback); - } } diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java index 8447dde..bb162153 100644 --- a/core/java/android/hardware/display/DisplayManagerInternal.java +++ b/core/java/android/hardware/display/DisplayManagerInternal.java @@ -172,9 +172,12 @@ public abstract class DisplayManagerInternal { // If true, enables automatic brightness control. public boolean useAutoBrightness; - //If true, scales the brightness to half of desired. + // If true, scales the brightness to half of desired. public boolean lowPowerMode; + // If true, applies a brightness boost. + public boolean boostScreenBrightness; + // If true, prevents the screen from completely turning on if it is currently off. // The display does not enter a "ready" state if this flag is true and screen on is // blocked. The window manager policy blocks screen on while it prepares the keyguard to @@ -216,6 +219,7 @@ public abstract class DisplayManagerInternal { useAutoBrightness = other.useAutoBrightness; blockScreenOn = other.blockScreenOn; lowPowerMode = other.lowPowerMode; + boostScreenBrightness = other.boostScreenBrightness; dozeScreenBrightness = other.dozeScreenBrightness; dozeScreenState = other.dozeScreenState; } @@ -235,6 +239,7 @@ public abstract class DisplayManagerInternal { && useAutoBrightness == other.useAutoBrightness && blockScreenOn == other.blockScreenOn && lowPowerMode == other.lowPowerMode + && boostScreenBrightness == other.boostScreenBrightness && dozeScreenBrightness == other.dozeScreenBrightness && dozeScreenState == other.dozeScreenState; } @@ -253,6 +258,7 @@ public abstract class DisplayManagerInternal { + ", useAutoBrightness=" + useAutoBrightness + ", blockScreenOn=" + blockScreenOn + ", lowPowerMode=" + lowPowerMode + + ", boostScreenBrightness=" + boostScreenBrightness + ", dozeScreenBrightness=" + dozeScreenBrightness + ", dozeScreenState=" + Display.stateToString(dozeScreenState); } diff --git a/core/java/android/net/PskKeyManager.java b/core/java/android/net/PskKeyManager.java index d162282..f82e635 100644 --- a/core/java/android/net/PskKeyManager.java +++ b/core/java/android/net/PskKeyManager.java @@ -81,6 +81,13 @@ import javax.net.ssl.SSLEngine; * Subclasses should normally provide their own implementation of {@code getKey} because the default * implementation returns no key, which aborts the handshake. * + * <h3>Known issues</h3> + * The implementation of {@code ECDHE_PSK} cipher suites in API Level 21 contains a bug which breaks + * compatibility with other implementations. {@code ECDHE_PSK} cipher suites are enabled by default + * on platforms with API Level 21 when an {@code SSLContext} is initialized with a + * {@code PskKeyManager}. A workaround is to disable {@code ECDHE_PSK} cipher suites on platforms + * with API Level 21. + * * <h3>Example</h3> * The following example illustrates how to create an {@code SSLContext} which enables the use of * TLS-PSK in {@code SSLSocket}, {@code SSLServerSocket} and {@code SSLEngine} instances obtained diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java index 084ca30..3f42d25 100644 --- a/core/java/android/os/Debug.java +++ b/core/java/android/os/Debug.java @@ -165,7 +165,7 @@ public final class Debug public int otherSwappedOut; /** @hide */ - public static final int NUM_OTHER_STATS = 16; + public static final int NUM_OTHER_STATS = 17; /** @hide */ public static final int NUM_DVK_STATS = 5; @@ -296,23 +296,24 @@ public final class Debug case 1: return "Stack"; case 2: return "Cursor"; case 3: return "Ashmem"; - case 4: return "Other dev"; - case 5: return ".so mmap"; - case 6: return ".jar mmap"; - case 7: return ".apk mmap"; - case 8: return ".ttf mmap"; - case 9: return ".dex mmap"; - case 10: return "code mmap"; - case 11: return "image mmap"; - case 12: return "Other mmap"; - case 13: return "Graphics"; - case 14: return "GL"; - case 15: return "Memtrack"; - case 16: return ".Heap"; - case 17: return ".LOS"; - case 18: return ".LinearAlloc"; - case 19: return ".GC"; - case 20: return ".JITCache"; + case 4: return "Gfx driver"; + case 5: return "Other dev"; + case 6: return ".so mmap"; + case 7: return ".jar mmap"; + case 8: return ".apk mmap"; + case 9: return ".ttf mmap"; + case 10: return ".dex mmap"; + case 11: return ".oat mmap"; + case 12: return ".art mmap"; + case 13: return "Other mmap"; + case 14: return "Graphics"; + case 15: return "GL"; + case 16: return "Memtrack"; + case 17: return ".Heap"; + case 18: return ".LOS"; + case 19: return ".LinearAlloc"; + case 20: return ".GC"; + case 21: return ".JITCache"; default: return "????"; } } diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl index 182dbee..ec30684 100644 --- a/core/java/android/os/IPowerManager.aidl +++ b/core/java/android/os/IPowerManager.aidl @@ -50,6 +50,7 @@ interface IPowerManager void setStayOnSetting(int val); void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs); + void boostScreenBrightness(long time); // temporarily overrides the screen brightness settings to allow the user to // see the effect of a settings change without applying it immediately diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 3b6ce53..8307d9b 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -669,6 +669,28 @@ public final class PowerManager { } /** + * Boosts the brightness of the screen to maximum for a predetermined + * period of time. This is used to make the screen more readable in bright + * daylight for a short duration. + * <p> + * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission. + * </p> + * + * @param time The time when the request to boost was issued, in the + * {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly + * order the boost request with other power management functions. It should be set + * to the timestamp of the input event that caused the request to boost. + * + * @hide Requires signature permission. + */ + public void boostScreenBrightness(long time) { + try { + mService.boostScreenBrightness(time); + } catch (RemoteException e) { + } + } + + /** * Sets the brightness of the backlights (screen, keyboard, button). * <p> * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission. diff --git a/core/java/android/print/IPrintDocumentAdapter.aidl b/core/java/android/print/IPrintDocumentAdapter.aidl index 9d384fb..8f33e0b 100644 --- a/core/java/android/print/IPrintDocumentAdapter.aidl +++ b/core/java/android/print/IPrintDocumentAdapter.aidl @@ -37,4 +37,5 @@ oneway interface IPrintDocumentAdapter { void write(in PageRange[] pages, in ParcelFileDescriptor fd, IWriteResultCallback callback, int sequence); void finish(); + void kill(String reason); } diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java index bf8ac65..3fb812e 100644 --- a/core/java/android/print/PrintManager.java +++ b/core/java/android/print/PrintManager.java @@ -634,6 +634,17 @@ public final class PrintManager { } @Override + public void kill(String reason) { + synchronized (mLock) { + // If destroyed the handler is null. + if (!isDestroyedLocked()) { + mHandler.obtainMessage(MyHandler.MSG_ON_KILL, + reason).sendToTarget(); + } + } + } + + @Override public void onActivityPaused(Activity activity) { /* do nothing */ } @@ -719,6 +730,7 @@ public final class PrintManager { public static final int MSG_ON_LAYOUT = 2; public static final int MSG_ON_WRITE = 3; public static final int MSG_ON_FINISH = 4; + public static final int MSG_ON_KILL = 5; public MyHandler(Looper looper) { super(looper, null, true); @@ -794,6 +806,15 @@ public final class PrintManager { } } break; + case MSG_ON_KILL: { + if (DEBUG) { + Log.i(LOG_TAG, "onKill()"); + } + + String reason = (String) message.obj; + throw new RuntimeException(reason); + } + default: { throw new IllegalArgumentException("Unknown message: " + message.what); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 369efac..1ea520d 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2625,12 +2625,6 @@ public final class Settings { public static final String LOCK_TO_APP_ENABLED = "lock_to_app_enabled"; /** - * Whether lock-to-app will lock the keyguard when exiting. - * @hide - */ - public static final String LOCK_TO_APP_EXIT_LOCKED = "lock_to_app_exit_locked"; - - /** * I am the lolrus. * <p> * Nonzero values indicate that the user has a bukkit. @@ -2704,6 +2698,7 @@ public final class Settings { POINTER_SPEED, VIBRATE_WHEN_RINGING, RINGTONE, + LOCK_TO_APP_ENABLED, NOTIFICATION_SOUND }; @@ -3666,6 +3661,12 @@ public final class Settings { "lock_biometric_weak_flags"; /** + * Whether lock-to-app will lock the keyguard when exiting. + * @hide + */ + public static final String LOCK_TO_APP_EXIT_LOCKED = "lock_to_app_exit_locked"; + + /** * Whether autolock is enabled (0 = false, 1 = true) */ public static final String LOCK_PATTERN_ENABLED = "lock_pattern_autolock"; @@ -6629,7 +6630,8 @@ public final class Settings { WIFI_NUM_OPEN_NETWORKS_KEPT, EMERGENCY_TONE, CALL_AUTO_RETRY, - DOCK_AUDIO_MEDIA_ENABLED + DOCK_AUDIO_MEDIA_ENABLED, + LOW_POWER_MODE_TRIGGER_LEVEL }; // Populated lazily, guarded by class object: diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java index 9fec9a1..933bcee 100755 --- a/core/java/android/text/format/DateFormat.java +++ b/core/java/android/text/format/DateFormat.java @@ -60,27 +60,45 @@ import libcore.icu.LocaleData; * {@code SimpleDateFormat}. */ public class DateFormat { - /** @deprecated Use a literal {@code '} instead. */ + /** + * @deprecated Use a literal {@code '} instead. + * @removed + */ @Deprecated public static final char QUOTE = '\''; - /** @deprecated Use a literal {@code 'a'} instead. */ + /** + * @deprecated Use a literal {@code 'a'} instead. + * @removed + */ @Deprecated public static final char AM_PM = 'a'; - /** @deprecated Use a literal {@code 'a'} instead; 'A' was always equivalent to 'a'. */ + /** + * @deprecated Use a literal {@code 'a'} instead; 'A' was always equivalent to 'a'. + * @removed + */ @Deprecated public static final char CAPITAL_AM_PM = 'A'; - /** @deprecated Use a literal {@code 'd'} instead. */ + /** + * @deprecated Use a literal {@code 'd'} instead. + * @removed + */ @Deprecated public static final char DATE = 'd'; - /** @deprecated Use a literal {@code 'E'} instead. */ + /** + * @deprecated Use a literal {@code 'E'} instead. + * @removed + */ @Deprecated public static final char DAY = 'E'; - /** @deprecated Use a literal {@code 'h'} instead. */ + /** + * @deprecated Use a literal {@code 'h'} instead. + * @removed + */ @Deprecated public static final char HOUR = 'h'; @@ -88,31 +106,51 @@ public class DateFormat { * @deprecated Use a literal {@code 'H'} (for compatibility with {@link SimpleDateFormat} * and Unicode) or {@code 'k'} (for compatibility with Android releases up to and including * Jelly Bean MR-1) instead. Note that the two are incompatible. + * + * @removed */ @Deprecated public static final char HOUR_OF_DAY = 'k'; - /** @deprecated Use a literal {@code 'm'} instead. */ + /** + * @deprecated Use a literal {@code 'm'} instead. + * @removed + */ @Deprecated public static final char MINUTE = 'm'; - /** @deprecated Use a literal {@code 'M'} instead. */ + /** + * @deprecated Use a literal {@code 'M'} instead. + * @removed + */ @Deprecated public static final char MONTH = 'M'; - /** @deprecated Use a literal {@code 'L'} instead. */ + /** + * @deprecated Use a literal {@code 'L'} instead. + * @removed + */ @Deprecated public static final char STANDALONE_MONTH = 'L'; - /** @deprecated Use a literal {@code 's'} instead. */ + /** + * @deprecated Use a literal {@code 's'} instead. + * @removed + */ @Deprecated public static final char SECONDS = 's'; - /** @deprecated Use a literal {@code 'z'} instead. */ + /** + * @deprecated Use a literal {@code 'z'} instead. + * @removed + */ @Deprecated public static final char TIME_ZONE = 'z'; - /** @deprecated Use a literal {@code 'y'} instead. */ + /** + * @deprecated Use a literal {@code 'y'} instead. + * @removed + */ @Deprecated public static final char YEAR = 'y'; @@ -306,9 +344,9 @@ public class DateFormat { } /** - * Gets the current date format stored as a char array. The array will contain - * 3 elements ({@link #DATE}, {@link #MONTH}, and {@link #YEAR}) in the order - * specified by the user's format preference. Note that this order is + * Gets the current date format stored as a char array. Returns a 3 element + * array containing the day ({@code 'd'}), month ({@code 'M'}), and year ({@code 'y'})) + * in the order specified by the user's format preference. Note that this order is * <i>only</i> appropriate for all-numeric dates; spelled-out (MEDIUM and LONG) * dates will generally contain other punctuation, spaces, or words, * not just the day, month, and year, and not necessarily in the same diff --git a/core/java/android/util/TypedValue.java b/core/java/android/util/TypedValue.java index d42ed03..74d4245 100644 --- a/core/java/android/util/TypedValue.java +++ b/core/java/android/util/TypedValue.java @@ -312,6 +312,18 @@ public class TypedValue { } /** + * Return the complex unit type for this value. For example, a dimen type + * with value 12sp will return {@link #COMPLEX_UNIT_SP}. Only use for values + * whose type is {@link #TYPE_DIMENSION}. + * + * @return The complex unit type. + */ + public int getComplexUnit() + { + return COMPLEX_UNIT_MASK & (data>>TypedValue.COMPLEX_UNIT_SHIFT); + } + + /** * Converts an unpacked complex data value holding a dimension to its final floating * point value. The two parameters <var>unit</var> and <var>value</var> * are as in {@link #TYPE_DIMENSION}. diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java index debf45d..b95f9a4 100644 --- a/core/java/android/view/RenderNodeAnimator.java +++ b/core/java/android/view/RenderNodeAnimator.java @@ -219,7 +219,7 @@ public class RenderNodeAnimator extends Animator { @Override public void cancel() { - if (mState != STATE_FINISHED) { + if (mState != STATE_PREPARE && mState != STATE_FINISHED) { if (mState == STATE_DELAYED) { getHelper().removeDelayedAnimation(this); notifyStartListeners(); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index e4f95a4..1d09696 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -3109,6 +3109,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private MatchLabelForPredicate mMatchLabelForPredicate; /** + * Specifies a view before which this one is visited in accessibility traversal. + */ + private int mAccessibilityTraversalBeforeId = NO_ID; + + /** + * Specifies a view after which this one is visited in accessibility traversal. + */ + private int mAccessibilityTraversalAfterId = NO_ID; + + /** * Predicate for matching a view by its id. */ private MatchIdPredicate mMatchIdPredicate; @@ -3888,6 +3898,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, case com.android.internal.R.styleable.View_contentDescription: setContentDescription(a.getString(attr)); break; + case com.android.internal.R.styleable.View_accessibilityTraversalBefore: + setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID)); + break; + case com.android.internal.R.styleable.View_accessibilityTraversalAfter: + setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID)); + break; case com.android.internal.R.styleable.View_labelFor: setLabelFor(a.getResourceId(attr, NO_ID)); break; @@ -5611,6 +5627,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (rootView == null) { rootView = this; } + View label = rootView.findLabelForView(this, mID); if (label != null) { info.setLabeledBy(label); @@ -5639,6 +5656,30 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } + if (mAccessibilityTraversalBeforeId != View.NO_ID) { + View rootView = getRootView(); + if (rootView == null) { + rootView = this; + } + View next = rootView.findViewInsideOutShouldExist(this, + mAccessibilityTraversalBeforeId); + if (next != null) { + info.setTraversalBefore(next); + } + } + + if (mAccessibilityTraversalAfterId != View.NO_ID) { + View rootView = getRootView(); + if (rootView == null) { + rootView = this; + } + View next = rootView.findViewInsideOutShouldExist(this, + mAccessibilityTraversalAfterId); + if (next != null) { + info.setTraversalAfter(next); + } + } + info.setVisibleToUser(isVisibleToUser()); info.setPackageName(mContext.getPackageName()); @@ -6043,6 +6084,94 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Sets the id of a view before which this one is visited in accessibility traversal. + * A screen-reader must visit the content of this view before the content of the one + * it precedes. For example, if view B is set to be before view A, then a screen-reader + * will traverse the entire content of B before traversing the entire content of A, + * regardles of what traversal strategy it is using. + * <p> + * Views that do not have specified before/after relationships are traversed in order + * determined by the screen-reader. + * </p> + * <p> + * Setting that this view is before a view that is not important for accessibility + * or if this view is not important for accessibility will have no effect as the + * screen-reader is not aware of unimportant views. + * </p> + * + * @param beforeId The id of a view this one precedes in accessibility traversal. + * + * @attr ref android.R.styleable#View_accessibilityTraversalBefore + * + * @see #setImportantForAccessibility(int) + */ + @RemotableViewMethod + public void setAccessibilityTraversalBefore(int beforeId) { + if (mAccessibilityTraversalBeforeId == beforeId) { + return; + } + mAccessibilityTraversalBeforeId = beforeId; + notifyViewAccessibilityStateChangedIfNeeded( + AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + } + + /** + * Gets the id of a view before which this one is visited in accessibility traversal. + * + * @return The id of a view this one precedes in accessibility traversal if + * specified, otherwise {@link #NO_ID}. + * + * @see #setAccessibilityTraversalBefore(int) + */ + public int getAccessibilityTraversalBefore() { + return mAccessibilityTraversalBeforeId; + } + + /** + * Sets the id of a view after which this one is visited in accessibility traversal. + * A screen-reader must visit the content of the other view before the content of this + * one. For example, if view B is set to be after view A, then a screen-reader + * will traverse the entire content of A before traversing the entire content of B, + * regardles of what traversal strategy it is using. + * <p> + * Views that do not have specified before/after relationships are traversed in order + * determined by the screen-reader. + * </p> + * <p> + * Setting that this view is after a view that is not important for accessibility + * or if this view is not important for accessibility will have no effect as the + * screen-reader is not aware of unimportant views. + * </p> + * + * @param afterId The id of a view this one succedees in accessibility traversal. + * + * @attr ref android.R.styleable#View_accessibilityTraversalAfter + * + * @see #setImportantForAccessibility(int) + */ + @RemotableViewMethod + public void setAccessibilityTraversalAfter(int afterId) { + if (mAccessibilityTraversalAfterId == afterId) { + return; + } + mAccessibilityTraversalAfterId = afterId; + notifyViewAccessibilityStateChangedIfNeeded( + AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + } + + /** + * Gets the id of a view after which this one is visited in accessibility traversal. + * + * @return The id of a view this one succeedes in accessibility traversal if + * specified, otherwise {@link #NO_ID}. + * + * @see #setAccessibilityTraversalAfter(int) + */ + public int getAccessibilityTraversalAfter() { + return mAccessibilityTraversalAfterId; + } + + /** * Gets the id of a view for which this view serves as a label for * accessibility purposes. * @@ -6061,11 +6190,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @RemotableViewMethod public void setLabelFor(int id) { + if (mLabelForId == id) { + return; + } mLabelForId = id; if (mLabelForId != View.NO_ID && mID == View.NO_ID) { mID = generateViewId(); } + notifyViewAccessibilityStateChangedIfNeeded( + AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); } /** diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index f0d5252..6450146 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1649,6 +1649,9 @@ public final class ViewRootImpl implements ViewParent, mLastScrolledFocus.clear(); } mScrollY = mCurScrollY = 0; + if (mView instanceof RootViewSurfaceTaker) { + ((RootViewSurfaceTaker) mView).onRootViewScrollYChanged(mCurScrollY); + } if (mScroller != null) { mScroller.abortAnimation(); } @@ -2419,6 +2422,9 @@ public final class ViewRootImpl implements ViewParent, if (mCurScrollY != curScrollY) { mCurScrollY = curScrollY; fullRedrawNeeded = true; + if (mView instanceof RootViewSurfaceTaker) { + ((RootViewSurfaceTaker) mView).onRootViewScrollYChanged(mCurScrollY); + } } final float appScale = mAttachInfo.mApplicationScale; diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index 3987fbc..b5afdf7 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -547,6 +547,8 @@ public class AccessibilityNodeInfo implements Parcelable { private long mParentNodeId = ROOT_NODE_ID; private long mLabelForId = ROOT_NODE_ID; private long mLabeledById = ROOT_NODE_ID; + private long mTraversalBefore = ROOT_NODE_ID; + private long mTraversalAfter = ROOT_NODE_ID; private int mBooleanProperties; private final Rect mBoundsInParent = new Rect(); @@ -1046,6 +1048,126 @@ public class AccessibilityNodeInfo implements Parcelable { } /** + * Gets the node before which this one is visited during traversal. A screen-reader + * must visit the content of this node before the content of the one it precedes. + * + * @return The succeeding node if such or <code>null</code>. + * + * @see #setTraversalBefore(android.view.View) + * @see #setTraversalBefore(android.view.View, int) + */ + public AccessibilityNodeInfo getTraversalBefore() { + enforceSealed(); + return getNodeForAccessibilityId(mTraversalBefore); + } + + /** + * Sets the view before whose node this one should be visited during traversal. A + * screen-reader must visit the content of this node before the content of the one + * it precedes. + * <p> + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. + * This class is made immutable before being delivered to an AccessibilityService. + * </p> + * + * @param view The view providing the preceding node. + * + * @see #getTraversalBefore() + */ + public void setTraversalBefore(View view) { + setTraversalBefore(view, UNDEFINED_ITEM_ID); + } + + /** + * Sets the node before which this one is visited during traversal. A screen-reader + * must visit the content of this node before the content of the one it precedes. + * The successor is a virtual descendant of the given <code>root</code>. If + * <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root is set + * as the successor. + * <p> + * A virtual descendant is an imaginary View that is reported as a part of the view + * hierarchy for accessibility purposes. This enables custom views that draw complex + * content to report them selves as a tree of virtual views, thus conveying their + * logical structure. + * </p> + * <p> + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. + * This class is made immutable before being delivered to an AccessibilityService. + * </p> + * + * @param root The root of the virtual subtree. + * @param virtualDescendantId The id of the virtual descendant. + */ + public void setTraversalBefore(View root, int virtualDescendantId) { + enforceNotSealed(); + final int rootAccessibilityViewId = (root != null) + ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID; + mTraversalBefore = makeNodeId(rootAccessibilityViewId, virtualDescendantId); + } + + /** + * Gets the node after which this one is visited in accessibility traversal. + * A screen-reader must visit the content of the other node before the content + * of this one. + * + * @return The succeeding node if such or <code>null</code>. + * + * @see #setTraversalAfter(android.view.View) + * @see #setTraversalAfter(android.view.View, int) + */ + public AccessibilityNodeInfo getTraversalAfter() { + enforceSealed(); + return getNodeForAccessibilityId(mTraversalAfter); + } + + /** + * Sets the view whose node is visited after this one in accessibility traversal. + * A screen-reader must visit the content of the other node before the content + * of this one. + * <p> + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. + * This class is made immutable before being delivered to an AccessibilityService. + * </p> + * + * @param view The previous view. + * + * @see #getTraversalAfter() + */ + public void setTraversalAfter(View view) { + setTraversalAfter(view, UNDEFINED_ITEM_ID); + } + + /** + * Sets the node after which this one is visited in accessibility traversal. + * A screen-reader must visit the content of the other node before the content + * of this one. If <code>virtualDescendantId</code> equals to {@link View#NO_ID} + * the root is set as the predecessor. + * <p> + * A virtual descendant is an imaginary View that is reported as a part of the view + * hierarchy for accessibility purposes. This enables custom views that draw complex + * content to report them selves as a tree of virtual views, thus conveying their + * logical structure. + * </p> + * <p> + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. + * This class is made immutable before being delivered to an AccessibilityService. + * </p> + * + * @param root The root of the virtual subtree. + * @param virtualDescendantId The id of the virtual descendant. + */ + public void setTraversalAfter(View root, int virtualDescendantId) { + enforceNotSealed(); + final int rootAccessibilityViewId = (root != null) + ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID; + mTraversalAfter = makeNodeId(rootAccessibilityViewId, virtualDescendantId); + } + + /** * Sets the maximum text length, or -1 for no limit. * <p> * Typically used to indicate that an editable text field has a limit on @@ -1229,13 +1351,7 @@ public class AccessibilityNodeInfo implements Parcelable { */ public AccessibilityNodeInfo getParent() { enforceSealed(); - if (!canPerformRequestOverConnection(mParentNodeId)) { - return null; - } - AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); - return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, - mWindowId, mParentNodeId, false, FLAG_PREFETCH_PREDECESSORS - | FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS); + return getNodeForAccessibilityId(mParentNodeId); } /** @@ -2055,13 +2171,7 @@ public class AccessibilityNodeInfo implements Parcelable { */ public AccessibilityNodeInfo getLabelFor() { enforceSealed(); - if (!canPerformRequestOverConnection(mLabelForId)) { - return null; - } - AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); - return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, - mWindowId, mLabelForId, false, FLAG_PREFETCH_PREDECESSORS - | FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS); + return getNodeForAccessibilityId(mLabelForId); } /** @@ -2113,13 +2223,7 @@ public class AccessibilityNodeInfo implements Parcelable { */ public AccessibilityNodeInfo getLabeledBy() { enforceSealed(); - if (!canPerformRequestOverConnection(mLabeledById)) { - return null; - } - AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); - return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, - mWindowId, mLabeledById, false, FLAG_PREFETCH_PREDECESSORS - | FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS); + return getNodeForAccessibilityId(mLabeledById); } /** @@ -2453,6 +2557,9 @@ public class AccessibilityNodeInfo implements Parcelable { parcel.writeLong(mParentNodeId); parcel.writeLong(mLabelForId); parcel.writeLong(mLabeledById); + parcel.writeLong(mTraversalBefore); + parcel.writeLong(mTraversalAfter); + parcel.writeInt(mConnectionId); final LongArray childIds = mChildNodeIds; @@ -2571,6 +2678,8 @@ public class AccessibilityNodeInfo implements Parcelable { mParentNodeId = other.mParentNodeId; mLabelForId = other.mLabelForId; mLabeledById = other.mLabeledById; + mTraversalBefore = other.mTraversalBefore; + mTraversalAfter = other.mTraversalAfter; mWindowId = other.mWindowId; mConnectionId = other.mConnectionId; mBoundsInParent.set(other.mBoundsInParent); @@ -2633,6 +2742,9 @@ public class AccessibilityNodeInfo implements Parcelable { mParentNodeId = parcel.readLong(); mLabelForId = parcel.readLong(); mLabeledById = parcel.readLong(); + mTraversalBefore = parcel.readLong(); + mTraversalAfter = parcel.readLong(); + mConnectionId = parcel.readInt(); final int childrenSize = parcel.readInt(); @@ -2725,6 +2837,8 @@ public class AccessibilityNodeInfo implements Parcelable { mParentNodeId = ROOT_NODE_ID; mLabelForId = ROOT_NODE_ID; mLabeledById = ROOT_NODE_ID; + mTraversalBefore = ROOT_NODE_ID; + mTraversalAfter = ROOT_NODE_ID; mWindowId = UNDEFINED_ITEM_ID; mConnectionId = UNDEFINED_CONNECTION_ID; mMaxTextLength = -1; @@ -2911,6 +3025,8 @@ public class AccessibilityNodeInfo implements Parcelable { builder.append("; accessibilityViewId: " + getAccessibilityViewId(mSourceNodeId)); builder.append("; virtualDescendantId: " + getVirtualDescendantId(mSourceNodeId)); builder.append("; mParentNodeId: " + mParentNodeId); + builder.append("; traversalBefore: ").append(mTraversalBefore); + builder.append("; traversalAfter: ").append(mTraversalAfter); int granularities = mMovementGranularities; builder.append("; MovementGranularities: ["); @@ -2963,6 +3079,16 @@ public class AccessibilityNodeInfo implements Parcelable { return builder.toString(); } + private AccessibilityNodeInfo getNodeForAccessibilityId(long accessibilityId) { + if (!canPerformRequestOverConnection(accessibilityId)) { + return null; + } + AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); + return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, + mWindowId, accessibilityId, false, FLAG_PREFETCH_PREDECESSORS + | FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS); + } + /** * A class defining an action that can be performed on an {@link AccessibilityNodeInfo}. * Each action has a unique id that is mandatory and optional data. diff --git a/core/java/android/widget/OverScroller.java b/core/java/android/widget/OverScroller.java index 7b3dd31..a40d4f8 100644 --- a/core/java/android/widget/OverScroller.java +++ b/core/java/android/widget/OverScroller.java @@ -904,6 +904,10 @@ public class OverScroller { final long time = AnimationUtils.currentAnimationTimeMillis(); final long currentTime = time - mStartTime; + if (currentTime == 0) { + // Skip work but report that we're still going if we have a nonzero duration. + return mDuration > 0; + } if (currentTime > mDuration) { return false; } diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 80f364b..dd7fa18 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -2528,6 +2528,26 @@ public class RemoteViews implements Parcelable, Filter { } /** + * Equivalent to calling {@link android.view.View#setAccessibilityTraversalBefore(int)}. + * + * @param viewId The id of the view whose before view in accessibility traversal to set. + * @param nextId The id of the next in the accessibility traversal. + **/ + public void setAccessibilityTraversalBefore(int viewId, int nextId) { + setInt(viewId, "setAccessibilityTraversalBefore", nextId); + } + + /** + * Equivalent to calling {@link android.view.View#setAccessibilityTraversalAfter(int)}. + * + * @param viewId The id of the view whose after view in accessibility traversal to set. + * @param nextId The id of the next in the accessibility traversal. + **/ + public void setAccessibilityTraversalAfter(int viewId, int nextId) { + setInt(viewId, "setAccessibilityTraversalAfter", nextId); + } + + /** * Equivalent to calling View.setLabelFor(int). * * @param viewId The id of the view whose property to set. diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java index d4d186c..f90d64a 100644 --- a/core/java/android/widget/Toolbar.java +++ b/core/java/android/widget/Toolbar.java @@ -1752,6 +1752,17 @@ public class Toolbar extends ViewGroup { } /** + * Accessor to enable LayoutLib to get ActionMenuPresenter directly. + */ + ActionMenuPresenter getOuterActionMenuPresenter() { + return mOuterActionMenuPresenter; + } + + Context getPopupContext() { + return mPopupContext; + } + + /** * Interface responsible for receiving menu item click events if the items themselves * do not have individual item click listeners. */ diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 0bc1a8d..64bd6b6 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -20,6 +20,7 @@ import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.IntentSender; +import android.content.pm.ActivityInfo; import android.os.Bundle; import android.os.Parcelable; import android.util.Log; @@ -75,16 +76,21 @@ public class ChooserActivity extends ResolverActivity { } @Override - public Intent getReplacementIntent(String packageName, Intent defIntent) { + public Intent getReplacementIntent(ActivityInfo aInfo, Intent defIntent) { + Intent result = defIntent; if (mReplacementExtras != null) { - final Bundle replExtras = mReplacementExtras.getBundle(packageName); + final Bundle replExtras = mReplacementExtras.getBundle(aInfo.packageName); if (replExtras != null) { - final Intent result = new Intent(defIntent); + result = new Intent(defIntent); result.putExtras(replExtras); - return result; } } - return defIntent; + if (aInfo.name.equals(IntentForwarderActivity.FORWARD_INTENT_TO_USER_OWNER) + || aInfo.name.equals(IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE)) { + result = Intent.createChooser(result, + getIntent().getCharSequenceExtra(Intent.EXTRA_TITLE)); + } + return result; } @Override diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java index 6e2f84a..9656a21 100644 --- a/core/java/com/android/internal/app/IntentForwarderActivity.java +++ b/core/java/com/android/internal/app/IntentForwarderActivity.java @@ -58,21 +58,22 @@ public class IntentForwarderActivity extends Activity { Intent intentReceived = getIntent(); String className = intentReceived.getComponent().getClassName(); - final UserHandle userDest; + final int targetUserId; final int userMessageId; if (className.equals(FORWARD_INTENT_TO_USER_OWNER)) { userMessageId = com.android.internal.R.string.forward_intent_to_owner; - userDest = UserHandle.OWNER; + targetUserId = UserHandle.USER_OWNER; } else if (className.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) { userMessageId = com.android.internal.R.string.forward_intent_to_work; - userDest = getManagedProfile(); + targetUserId = getManagedProfile(); } else { Slog.wtf(TAG, IntentForwarderActivity.class.getName() + " cannot be called directly"); userMessageId = -1; - userDest = null; + targetUserId = UserHandle.USER_NULL; } - if (userDest == null) { // This covers the case where there is no managed profile. + if (targetUserId == UserHandle.USER_NULL) { + // This covers the case where there is no managed profile. finish(); return; } @@ -83,31 +84,24 @@ public class IntentForwarderActivity extends Activity { newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT |Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP); int callingUserId = getUserId(); - IPackageManager ipm = AppGlobals.getPackageManager(); - String resolvedType = newIntent.resolveTypeIfNeeded(getContentResolver()); - boolean canForward = false; - Intent selector = newIntent.getSelector(); - if (selector == null) { - selector = newIntent; - } - try { - canForward = ipm.canForwardTo(selector, resolvedType, callingUserId, - userDest.getIdentifier()); - } catch (RemoteException e) { - Slog.e(TAG, "PackageManagerService is dead?"); - } - if (canForward) { - newIntent.setContentUserHint(callingUserId); + + if (canForward(newIntent, targetUserId)) { + if (newIntent.getAction().equals(Intent.ACTION_CHOOSER)) { + Intent innerIntent = (Intent) newIntent.getParcelableExtra(Intent.EXTRA_INTENT); + innerIntent.setContentUserHint(callingUserId); + } else { + newIntent.setContentUserHint(callingUserId); + } final android.content.pm.ResolveInfo ri = getPackageManager().resolveActivityAsUser( - newIntent, MATCH_DEFAULT_ONLY, userDest.getIdentifier()); + newIntent, MATCH_DEFAULT_ONLY, targetUserId); // Only show a disclosure if this is a normal (non-OS) app final boolean shouldShowDisclosure = !UserHandle.isSameApp(ri.activityInfo.applicationInfo.uid, Process.SYSTEM_UID); try { - startActivityAsCaller(newIntent, null, userDest.getIdentifier()); + startActivityAsCaller(newIntent, null, targetUserId); } catch (RuntimeException e) { int launchedFromUid = -1; String launchedFromPackage = "?"; @@ -129,26 +123,55 @@ public class IntentForwarderActivity extends Activity { } } else { Slog.wtf(TAG, "the intent: " + newIntent + "cannot be forwarded from user " - + callingUserId + " to user " + userDest.getIdentifier()); + + callingUserId + " to user " + targetUserId); } finish(); } + boolean canForward(Intent intent, int targetUserId) { + IPackageManager ipm = AppGlobals.getPackageManager(); + if (intent.getAction().equals(Intent.ACTION_CHOOSER)) { + // The EXTRA_INITIAL_INTENTS may not be allowed to be forwarded. + if (intent.hasExtra(Intent.EXTRA_INITIAL_INTENTS)) { + Slog.wtf(TAG, "An chooser intent with extra initial intents cannot be forwarded to" + + " a different user"); + return false; + } + if (intent.hasExtra(Intent.EXTRA_REPLACEMENT_EXTRAS)) { + Slog.wtf(TAG, "A chooser intent with replacement extras cannot be forwarded to a" + + " different user"); + return false; + } + intent = (Intent) intent.getParcelableExtra(Intent.EXTRA_INTENT); + } + String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); + if (intent.getSelector() != null) { + intent = intent.getSelector(); + } + try { + return ipm.canForwardTo(intent, resolvedType, getUserId(), + targetUserId); + } catch (RemoteException e) { + Slog.e(TAG, "PackageManagerService is dead?"); + return false; + } + } + /** - * Returns the managed profile for this device or null if there is no managed - * profile. + * Returns the userId of the managed profile for this device or UserHandle.USER_NULL if there is + * no managed profile. * * TODO: Remove the assumption that there is only one managed profile * on the device. */ - private UserHandle getManagedProfile() { + private int getManagedProfile() { UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE); List<UserInfo> relatedUsers = userManager.getProfiles(UserHandle.USER_OWNER); for (UserInfo userInfo : relatedUsers) { - if (userInfo.isManagedProfile()) return new UserHandle(userInfo.id); + if (userInfo.isManagedProfile()) return userInfo.id; } Slog.wtf(TAG, FORWARD_INTENT_TO_MANAGED_PROFILE + " has been called, but there is no managed profile"); - return null; + return UserHandle.USER_NULL; } } diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index ccffa19..376db6e 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -100,6 +100,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic private int mMaxColumns; private int mLastSelected = ListView.INVALID_POSITION; private boolean mResolvingHome = false; + private int mProfileSwitchMessageId = -1; private UsageStatsManager mUsm; private Map<String, UsageStats> mStats; @@ -200,6 +201,11 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic List<ResolveInfo> rList, boolean alwaysUseOption) { setTheme(R.style.Theme_DeviceDefault_Resolver); super.onCreate(savedInstanceState); + + // Determine whether we should show that intent is forwarded + // from managed profile to owner or other way around. + setProfileSwitchMessageId(intent.getContentUserHint()); + try { mLaunchedFromUid = ActivityManagerNative.getDefault().getLaunchedFromUid( getActivityToken()); @@ -278,9 +284,9 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic final ResolverDrawerLayout rdl = (ResolverDrawerLayout) findViewById(R.id.contentPanel); if (rdl != null) { - rdl.setOnClickOutsideListener(new View.OnClickListener() { + rdl.setOnDismissedListener(new ResolverDrawerLayout.OnDismissedListener() { @Override - public void onClick(View v) { + public void onDismissed() { finish(); } }); @@ -320,6 +326,22 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic } } + private void setProfileSwitchMessageId(int contentUserHint) { + if (contentUserHint != UserHandle.USER_CURRENT && + contentUserHint != UserHandle.myUserId()) { + UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE); + UserInfo originUserInfo = userManager.getUserInfo(contentUserHint); + boolean originIsManaged = originUserInfo != null ? originUserInfo.isManagedProfile() + : false; + boolean targetIsManaged = userManager.isManagedProfile(); + if (originIsManaged && !targetIsManaged) { + mProfileSwitchMessageId = com.android.internal.R.string.forward_intent_to_owner; + } else if (!originIsManaged && targetIsManaged) { + mProfileSwitchMessageId = com.android.internal.R.string.forward_intent_to_work; + } + } + } + /** * Turn on launch mode that is safe to use when forwarding intents received from * applications and running in system processes. This mode uses Activity.startActivityAsCaller @@ -529,7 +551,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic /** * Replace me in subclasses! */ - public Intent getReplacementIntent(String packageName, Intent defIntent) { + public Intent getReplacementIntent(ActivityInfo aInfo, Intent defIntent) { return defIntent; } @@ -642,6 +664,11 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic } public void safelyStartActivity(Intent intent) { + // If needed, show that intent is forwarded + // from managed profile to owner or other way around. + if (mProfileSwitchMessageId != -1) { + Toast.makeText(this, getString(mProfileSwitchMessageId), Toast.LENGTH_LONG).show(); + } if (!mSafeForwardingMode) { startActivity(intent); onActivityStarted(intent); @@ -943,7 +970,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic DisplayResolveInfo dri = filtered ? getItem(position) : mList.get(position); Intent intent = new Intent(dri.origIntent != null ? dri.origIntent : - getReplacementIntent(dri.ri.activityInfo.packageName, mIntent)); + getReplacementIntent(dri.ri.activityInfo, mIntent)); intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT |Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP); ActivityInfo ai = dri.ri.activityInfo; diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index e6bcea1..5e610ed 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -51,7 +51,7 @@ interface IStatusBarService void onNotificationVisibilityChanged( in String[] newlyVisibleKeys, in String[] noLongerVisibleKeys); void onNotificationExpansionChanged(in String key, in boolean userAction, in boolean expanded); - void setSystemUiVisibility(int vis, int mask); + void setSystemUiVisibility(int vis, int mask, String cause); void setWindowState(int window, int state); void showRecentApps(boolean triggeredFromAltTab); diff --git a/core/java/com/android/internal/util/MemInfoReader.java b/core/java/com/android/internal/util/MemInfoReader.java index 1dd9464..b71fa06 100644 --- a/core/java/com/android/internal/util/MemInfoReader.java +++ b/core/java/com/android/internal/util/MemInfoReader.java @@ -106,4 +106,8 @@ public final class MemInfoReader { public long getZramTotalSizeKb() { return mInfos[Debug.MEMINFO_ZRAM_TOTAL]; } + + public long[] getRawInfo() { + return mInfos; + } } diff --git a/core/java/com/android/internal/view/RootViewSurfaceTaker.java b/core/java/com/android/internal/view/RootViewSurfaceTaker.java index 9c1b558..433ec73 100644 --- a/core/java/com/android/internal/view/RootViewSurfaceTaker.java +++ b/core/java/com/android/internal/view/RootViewSurfaceTaker.java @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2010 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 com.android.internal.view; import android.view.InputQueue; @@ -10,4 +25,5 @@ public interface RootViewSurfaceTaker { void setSurfaceFormat(int format); void setSurfaceKeepScreenOn(boolean keepOn); InputQueue.Callback willYouTakeTheInputQueue(); + void onRootViewScrollYChanged(int scrollY); } diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java index 375822f..25b4945 100644 --- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java +++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java @@ -63,18 +63,22 @@ public class ResolverDrawerLayout extends ViewGroup { private float mCollapseOffset; private int mCollapsibleHeight; + private int mUncollapsibleHeight; private int mTopOffset; private boolean mIsDragging; private boolean mOpenOnClick; private boolean mOpenOnLayout; + private boolean mDismissOnScrollerFinished; private final int mTouchSlop; private final float mMinFlingVelocity; private final OverScroller mScroller; private final VelocityTracker mVelocityTracker; - private OnClickListener mClickOutsideListener; + private OnDismissedListener mOnDismissedListener; + private RunOnDismissedListener mRunOnDismissedListener; + private float mInitialTouchX; private float mInitialTouchY; private float mLastTouchY; @@ -143,8 +147,8 @@ public class ResolverDrawerLayout extends ViewGroup { return isSmallCollapsed() ? mMaxCollapsedHeightSmall : mMaxCollapsedHeight; } - public void setOnClickOutsideListener(OnClickListener listener) { - mClickOutsideListener = listener; + public void setOnDismissedListener(OnDismissedListener listener) { + mOnDismissedListener = listener; } @Override @@ -194,7 +198,7 @@ public class ResolverDrawerLayout extends ViewGroup { } if (mIsDragging) { - mScroller.abortAnimation(); + abortAnimation(); } return mIsDragging || mOpenOnClick; } @@ -213,12 +217,9 @@ public class ResolverDrawerLayout extends ViewGroup { mInitialTouchX = x; mInitialTouchY = mLastTouchY = y; mActivePointerId = ev.getPointerId(0); - if (findChildUnder(mInitialTouchX, mInitialTouchY) == null && - mClickOutsideListener != null) { - mIsDragging = handled = true; - } - handled |= mCollapsibleHeight > 0; - mScroller.abortAnimation(); + mIsDragging = findChildUnder(mInitialTouchX, mInitialTouchY) != null; + handled = (!mIsDragging && mOnDismissedListener != null) || mCollapsibleHeight > 0; + abortAnimation(); } break; @@ -264,11 +265,12 @@ public class ResolverDrawerLayout extends ViewGroup { break; case MotionEvent.ACTION_UP: { + final boolean wasDragging = mIsDragging; mIsDragging = false; - if (!mIsDragging && findChildUnder(mInitialTouchX, mInitialTouchY) == null && + if (!wasDragging && findChildUnder(mInitialTouchX, mInitialTouchY) == null && findChildUnder(ev.getX(), ev.getY()) == null) { - if (mClickOutsideListener != null) { - mClickOutsideListener.onClick(this); + if (mOnDismissedListener != null) { + dispatchOnDismissed(); resetTouch(); return true; } @@ -281,7 +283,13 @@ public class ResolverDrawerLayout extends ViewGroup { mVelocityTracker.computeCurrentVelocity(1000); final float yvel = mVelocityTracker.getYVelocity(mActivePointerId); if (Math.abs(yvel) > mMinFlingVelocity) { - smoothScrollTo(yvel < 0 ? 0 : mCollapsibleHeight, yvel); + if (mOnDismissedListener != null + && yvel > 0 && mCollapseOffset > mCollapsibleHeight) { + smoothScrollTo(mCollapsibleHeight + mUncollapsibleHeight, yvel); + mDismissOnScrollerFinished = true; + } else { + smoothScrollTo(yvel < 0 ? 0 : mCollapsibleHeight, yvel); + } } else { smoothScrollTo( mCollapseOffset < mCollapsibleHeight / 2 ? 0 : mCollapsibleHeight, 0); @@ -327,17 +335,27 @@ public class ResolverDrawerLayout extends ViewGroup { @Override public void computeScroll() { super.computeScroll(); - if (!mScroller.isFinished()) { - final boolean keepGoing = mScroller.computeScrollOffset(); + if (mScroller.computeScrollOffset()) { + final boolean keepGoing = !mScroller.isFinished(); performDrag(mScroller.getCurrY() - mCollapseOffset); if (keepGoing) { postInvalidateOnAnimation(); + } else if (mDismissOnScrollerFinished && mOnDismissedListener != null) { + mRunOnDismissedListener = new RunOnDismissedListener(); + post(mRunOnDismissedListener); } } } + private void abortAnimation() { + mScroller.abortAnimation(); + mRunOnDismissedListener = null; + mDismissOnScrollerFinished = false; + } + private float performDrag(float dy) { - final float newPos = Math.max(0, Math.min(mCollapseOffset + dy, mCollapsibleHeight)); + final float newPos = Math.max(0, Math.min(mCollapseOffset + dy, + mCollapsibleHeight + mUncollapsibleHeight)); if (newPos != mCollapseOffset) { dy = newPos - mCollapseOffset; final int childCount = getChildCount(); @@ -356,11 +374,18 @@ public class ResolverDrawerLayout extends ViewGroup { return 0; } - private void smoothScrollTo(int yOffset, float velocity) { - if (getMaxCollapsedHeight() == 0) { - return; + void dispatchOnDismissed() { + if (mOnDismissedListener != null) { + mOnDismissedListener.onDismissed(); } - mScroller.abortAnimation(); + if (mRunOnDismissedListener != null) { + removeCallbacks(mRunOnDismissedListener); + mRunOnDismissedListener = null; + } + } + + private void smoothScrollTo(int yOffset, float velocity) { + abortAnimation(); final int sy = (int) mCollapseOffset; int dy = yOffset - sy; if (dy == 0) { @@ -490,6 +515,7 @@ public class ResolverDrawerLayout extends ViewGroup { protected void onDetachedFromWindow() { super.onDetachedFromWindow(); getViewTreeObserver().removeOnTouchModeChangeListener(mTouchModeChangeListener); + abortAnimation(); } @Override @@ -585,6 +611,7 @@ public class ResolverDrawerLayout extends ViewGroup { mCollapsibleHeight = Math.max(0, heightUsed - alwaysShowHeight - getMaxCollapsedHeight()); + mUncollapsibleHeight = heightUsed - mCollapsibleHeight; if (isLaidOut()) { mCollapseOffset = Math.min(mCollapseOffset, mCollapsibleHeight); @@ -734,4 +761,15 @@ public class ResolverDrawerLayout extends ViewGroup { } }; } + + public interface OnDismissedListener { + public void onDismissed(); + } + + private class RunOnDismissedListener implements Runnable { + @Override + public void run() { + dispatchOnDismissed(); + } + } } |
