summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt21
-rw-r--r--api/system-current.txt21
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java22
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl4
-rw-r--r--core/java/android/content/Intent.java71
-rw-r--r--core/java/android/hardware/camera2/legacy/RequestThreadManager.java3
-rw-r--r--core/java/android/text/StaticLayout.java3
-rw-r--r--core/java/android/view/View.java339
-rw-r--r--core/java/android/view/ViewGroup.java16
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java28
-rw-r--r--core/java/android/widget/Editor.java3
-rw-r--r--core/java/android/widget/ListPopupWindow.java18
-rw-r--r--core/java/android/widget/PopupWindow.java6
-rw-r--r--core/java/com/android/internal/app/AlertController.java74
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java233
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java289
-rw-r--r--core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java14
-rw-r--r--core/java/com/android/internal/view/IInputMethodManager.aidl3
-rw-r--r--core/java/com/android/internal/widget/ButtonBarLayout.java38
-rw-r--r--core/jni/Android.mk1
-rw-r--r--core/jni/android_media_AudioRecord.cpp92
-rw-r--r--core/jni/android_media_AudioSystem.cpp5
-rw-r--r--core/jni/android_media_AudioTrack.cpp50
-rw-r--r--core/jni/android_media_DeviceCallback.cpp82
-rw-r--r--core/jni/android_media_DeviceCallback.h47
-rw-r--r--core/res/AndroidManifest.xml21
-rw-r--r--core/res/res/drawable/scroll_indicator_material.xml23
-rw-r--r--core/res/res/layout/alert_dialog_button_bar_material.xml3
-rw-r--r--core/res/res/layout/alert_dialog_material.xml53
-rw-r--r--core/res/res/values/attrs.xml29
-rw-r--r--core/res/res/values/public.xml2
-rwxr-xr-xcore/res/res/values/symbols.xml4
-rw-r--r--core/res/res/values/themes_material.xml8
-rw-r--r--graphics/java/android/graphics/drawable/DrawableContainer.java4
-rw-r--r--keystore/java/android/security/AndroidKeyStoreProvider.java6
-rw-r--r--keystore/java/android/security/KeyStoreCipherSpi.java11
-rw-r--r--keystore/java/android/security/KeyStoreCryptoOperation.java4
-rw-r--r--keystore/java/android/security/KeyStoreHmacSpi.java11
-rw-r--r--libs/hwui/tests/main.cpp93
-rw-r--r--media/java/android/media/AudioDevicePort.java10
-rw-r--r--media/java/android/media/AudioDevicesManager.java17
-rw-r--r--media/java/android/media/AudioManager.java12
-rw-r--r--media/java/android/media/AudioMixPort.java19
-rw-r--r--media/java/android/media/AudioPort.java8
-rw-r--r--media/java/android/media/AudioRecord.java58
-rw-r--r--media/java/android/media/AudioSystem.java6
-rw-r--r--media/java/android/media/AudioTrack.java53
-rw-r--r--media/java/android/media/MediaCodec.java6
-rw-r--r--packages/Keyguard/res/values/strings.xml2
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java3
-rw-r--r--packages/PrintSpooler/res/values/themes.xml5
-rw-r--r--packages/SettingsLib/res/values/strings.xml6
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java32
-rw-r--r--packages/Shell/AndroidManifest.xml2
-rw-r--r--packages/SystemUI/res/layout/zen_mode_panel.xml2
-rw-r--r--packages/SystemUI/res/values/strings.xml4
-rw-r--r--packages/SystemUI/src/com/android/systemui/EventLogConstants.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java13
-rw-r--r--packages/VpnDialogs/AndroidManifest.xml4
-rw-r--r--packages/WallpaperCropper/res/values/styles.xml4
-rw-r--r--rs/java/android/renderscript/Script.java4
-rw-r--r--rs/jni/android_renderscript_RenderScript.cpp4
-rw-r--r--services/backup/java/com/android/server/backup/BackupManagerService.java71
-rw-r--r--services/core/java/com/android/server/InputMethodManagerService.java32
-rw-r--r--services/core/java/com/android/server/content/SyncManager.java138
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java3
-rw-r--r--services/core/java/com/android/server/notification/CalendarTracker.java19
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java43
-rw-r--r--telecomm/java/android/telecom/Call.java4
-rw-r--r--telecomm/java/android/telecom/Connection.java26
-rw-r--r--telecomm/java/android/telecom/ParcelableCall.java4
-rw-r--r--telecomm/java/android/telecom/RemoteConnection.java4
-rw-r--r--telecomm/java/android/telecom/VideoCallImpl.java24
-rw-r--r--telecomm/java/com/android/internal/telecom/IVideoProvider.aidl2
-rw-r--r--telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl2
79 files changed, 2010 insertions, 441 deletions
diff --git a/api/current.txt b/api/current.txt
index 8716381..0ef4766 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1049,6 +1049,7 @@ package android {
field public static final int screenOrientation = 16842782; // 0x101001e
field public static final int screenSize = 16843466; // 0x10102ca
field public static final int scrollHorizontally = 16843099; // 0x101015b
+ field public static final int scrollIndicators = 16844023; // 0x10104f7
field public static final int scrollViewStyle = 16842880; // 0x1010080
field public static final int scrollX = 16842962; // 0x10100d2
field public static final int scrollY = 16842963; // 0x10100d3
@@ -5791,8 +5792,8 @@ package android.app.admin {
method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
method public boolean setDeviceInitializer(android.content.ComponentName, android.content.ComponentName, java.lang.String) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
+ method public boolean setKeyguardDisabled(android.content.ComponentName, boolean);
method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
- method public boolean setKeyguardEnabledState(android.content.ComponentName, boolean);
method public void setLockTaskPackages(android.content.ComponentName, java.lang.String[]) throws java.lang.SecurityException;
method public void setMasterVolumeMuted(android.content.ComponentName, boolean);
method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
@@ -5818,7 +5819,7 @@ package android.app.admin {
method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName);
method public void setScreenCaptureDisabled(android.content.ComponentName, boolean);
method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
- method public void setStatusBarEnabledState(android.content.ComponentName, boolean);
+ method public boolean setStatusBarDisabled(android.content.ComponentName, boolean);
method public int setStorageEncryption(android.content.ComponentName, boolean);
method public void setSystemUpdatePolicy(android.content.ComponentName, android.app.admin.SystemUpdatePolicy);
method public void setTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName, android.os.PersistableBundle);
@@ -8281,6 +8282,7 @@ package android.content {
field public static final java.lang.String EXTRA_ALARM_COUNT = "android.intent.extra.ALARM_COUNT";
field public static final java.lang.String EXTRA_ALLOW_MULTIPLE = "android.intent.extra.ALLOW_MULTIPLE";
field public static final deprecated java.lang.String EXTRA_ALLOW_REPLACE = "android.intent.extra.ALLOW_REPLACE";
+ field public static final java.lang.String EXTRA_ALTERNATE_INTENTS = "android.intent.extra.ALTERNATE_INTENTS";
field public static final java.lang.String EXTRA_ASSIST_CONTEXT = "android.intent.extra.ASSIST_CONTEXT";
field public static final java.lang.String EXTRA_ASSIST_INPUT_HINT_KEYBOARD = "android.intent.extra.ASSIST_INPUT_HINT_KEYBOARD";
field public static final java.lang.String EXTRA_ASSIST_PACKAGE = "android.intent.extra.ASSIST_PACKAGE";
@@ -8292,6 +8294,7 @@ package android.content {
field public static final java.lang.String EXTRA_CHANGED_COMPONENT_NAME_LIST = "android.intent.extra.changed_component_name_list";
field public static final java.lang.String EXTRA_CHANGED_PACKAGE_LIST = "android.intent.extra.changed_package_list";
field public static final java.lang.String EXTRA_CHANGED_UID_LIST = "android.intent.extra.changed_uid_list";
+ field public static final java.lang.String EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER = "android.intent.extra.CHOOSER_REFINEMENT_INTENT_SENDER";
field public static final java.lang.String EXTRA_CHOOSER_TARGETS = "android.intent.extra.CHOOSER_TARGETS";
field public static final java.lang.String EXTRA_CHOSEN_COMPONENT = "android.intent.extra.CHOSEN_COMPONENT";
field public static final java.lang.String EXTRA_CHOSEN_COMPONENT_INTENT_SENDER = "android.intent.extra.CHOSEN_COMPONENT_INTENT_SENDER";
@@ -8324,6 +8327,7 @@ package android.content {
field public static final java.lang.String EXTRA_RESTRICTIONS_BUNDLE = "android.intent.extra.restrictions_bundle";
field public static final java.lang.String EXTRA_RESTRICTIONS_INTENT = "android.intent.extra.restrictions_intent";
field public static final java.lang.String EXTRA_RESTRICTIONS_LIST = "android.intent.extra.restrictions_list";
+ field public static final java.lang.String EXTRA_RESULT_RECEIVER = "android.intent.extra.RESULT_RECEIVER";
field public static final java.lang.String EXTRA_RETURN_RESULT = "android.intent.extra.RETURN_RESULT";
field public static final java.lang.String EXTRA_SHORTCUT_ICON = "android.intent.extra.shortcut.ICON";
field public static final java.lang.String EXTRA_SHORTCUT_ICON_RESOURCE = "android.intent.extra.shortcut.ICON_RESOURCE";
@@ -30446,7 +30450,7 @@ package android.telecom {
method public void handleCallSessionEvent(int);
method public abstract void onRequestCameraCapabilities();
method public abstract void onRequestConnectionDataUsage();
- method public abstract void onSendSessionModifyRequest(android.telecom.VideoProfile);
+ method public abstract void onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile);
method public abstract void onSendSessionModifyResponse(android.telecom.VideoProfile);
method public abstract void onSetCamera(java.lang.String);
method public abstract void onSetDeviceOrientation(int);
@@ -36200,6 +36204,7 @@ package android.view {
method public int getScrollBarFadeDuration();
method public int getScrollBarSize();
method public int getScrollBarStyle();
+ method public int getScrollIndicators();
method public final int getScrollX();
method public final int getScrollY();
method public int getSolidColor();
@@ -36281,6 +36286,7 @@ package android.view {
method public boolean isSaveEnabled();
method public boolean isSaveFromParentEnabled();
method public boolean isScrollContainer();
+ method public boolean isScrollIndicatorEnabled(int);
method public boolean isScrollbarFadingEnabled();
method public boolean isSelected();
method public boolean isShown();
@@ -36480,6 +36486,8 @@ package android.view {
method public void setScrollBarSize(int);
method public void setScrollBarStyle(int);
method public void setScrollContainer(boolean);
+ method public void setScrollIndicators(int);
+ method public void setScrollIndicators(int, int);
method public void setScrollX(int);
method public void setScrollY(int);
method public void setScrollbarFadingEnabled(boolean);
@@ -36605,6 +36613,12 @@ package android.view {
field public static final int SCROLL_AXIS_HORIZONTAL = 1; // 0x1
field public static final int SCROLL_AXIS_NONE = 0; // 0x0
field public static final int SCROLL_AXIS_VERTICAL = 2; // 0x2
+ field public static final int SCROLL_INDICATOR_BOTTOM = 2; // 0x2
+ field public static final int SCROLL_INDICATOR_END = 32; // 0x20
+ field public static final int SCROLL_INDICATOR_LEFT = 4; // 0x4
+ field public static final int SCROLL_INDICATOR_RIGHT = 8; // 0x8
+ field public static final int SCROLL_INDICATOR_START = 16; // 0x10
+ field public static final int SCROLL_INDICATOR_TOP = 1; // 0x1
field protected static final int[] SELECTED_STATE_SET;
field protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
field public static final int SOUND_EFFECTS_ENABLED = 134217728; // 0x8000000
@@ -40647,6 +40661,7 @@ package android.widget {
method public void setSoftInputMode(int);
method public void setVerticalOffset(int);
method public void setWidth(int);
+ method public void setWindowLayoutType(int);
method public void show();
field public static final int INPUT_METHOD_FROM_FOCUSABLE = 0; // 0x0
field public static final int INPUT_METHOD_NEEDED = 1; // 0x1
diff --git a/api/system-current.txt b/api/system-current.txt
index f11e113..3aa6ca0 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1121,6 +1121,7 @@ package android {
field public static final int screenOrientation = 16842782; // 0x101001e
field public static final int screenSize = 16843466; // 0x10102ca
field public static final int scrollHorizontally = 16843099; // 0x101015b
+ field public static final int scrollIndicators = 16844023; // 0x10104f7
field public static final int scrollViewStyle = 16842880; // 0x1010080
field public static final int scrollX = 16842962; // 0x10100d2
field public static final int scrollY = 16842963; // 0x10100d3
@@ -5897,8 +5898,8 @@ package android.app.admin {
method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
method public boolean setDeviceInitializer(android.content.ComponentName, android.content.ComponentName, java.lang.String) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
+ method public boolean setKeyguardDisabled(android.content.ComponentName, boolean);
method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
- method public boolean setKeyguardEnabledState(android.content.ComponentName, boolean);
method public void setLockTaskPackages(android.content.ComponentName, java.lang.String[]) throws java.lang.SecurityException;
method public void setMasterVolumeMuted(android.content.ComponentName, boolean);
method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
@@ -5924,7 +5925,7 @@ package android.app.admin {
method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName);
method public void setScreenCaptureDisabled(android.content.ComponentName, boolean);
method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
- method public void setStatusBarEnabledState(android.content.ComponentName, boolean);
+ method public boolean setStatusBarDisabled(android.content.ComponentName, boolean);
method public int setStorageEncryption(android.content.ComponentName, boolean);
method public void setSystemUpdatePolicy(android.content.ComponentName, android.app.admin.SystemUpdatePolicy);
method public void setTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName, android.os.PersistableBundle);
@@ -8507,6 +8508,7 @@ package android.content {
field public static final java.lang.String EXTRA_ALARM_COUNT = "android.intent.extra.ALARM_COUNT";
field public static final java.lang.String EXTRA_ALLOW_MULTIPLE = "android.intent.extra.ALLOW_MULTIPLE";
field public static final deprecated java.lang.String EXTRA_ALLOW_REPLACE = "android.intent.extra.ALLOW_REPLACE";
+ field public static final java.lang.String EXTRA_ALTERNATE_INTENTS = "android.intent.extra.ALTERNATE_INTENTS";
field public static final java.lang.String EXTRA_ASSIST_CONTEXT = "android.intent.extra.ASSIST_CONTEXT";
field public static final java.lang.String EXTRA_ASSIST_INPUT_HINT_KEYBOARD = "android.intent.extra.ASSIST_INPUT_HINT_KEYBOARD";
field public static final java.lang.String EXTRA_ASSIST_PACKAGE = "android.intent.extra.ASSIST_PACKAGE";
@@ -8518,6 +8520,7 @@ package android.content {
field public static final java.lang.String EXTRA_CHANGED_COMPONENT_NAME_LIST = "android.intent.extra.changed_component_name_list";
field public static final java.lang.String EXTRA_CHANGED_PACKAGE_LIST = "android.intent.extra.changed_package_list";
field public static final java.lang.String EXTRA_CHANGED_UID_LIST = "android.intent.extra.changed_uid_list";
+ field public static final java.lang.String EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER = "android.intent.extra.CHOOSER_REFINEMENT_INTENT_SENDER";
field public static final java.lang.String EXTRA_CHOOSER_TARGETS = "android.intent.extra.CHOOSER_TARGETS";
field public static final java.lang.String EXTRA_CHOSEN_COMPONENT = "android.intent.extra.CHOSEN_COMPONENT";
field public static final java.lang.String EXTRA_CHOSEN_COMPONENT_INTENT_SENDER = "android.intent.extra.CHOSEN_COMPONENT_INTENT_SENDER";
@@ -8553,6 +8556,7 @@ package android.content {
field public static final java.lang.String EXTRA_RESTRICTIONS_BUNDLE = "android.intent.extra.restrictions_bundle";
field public static final java.lang.String EXTRA_RESTRICTIONS_INTENT = "android.intent.extra.restrictions_intent";
field public static final java.lang.String EXTRA_RESTRICTIONS_LIST = "android.intent.extra.restrictions_list";
+ field public static final java.lang.String EXTRA_RESULT_RECEIVER = "android.intent.extra.RESULT_RECEIVER";
field public static final java.lang.String EXTRA_RETURN_RESULT = "android.intent.extra.RETURN_RESULT";
field public static final java.lang.String EXTRA_SHORTCUT_ICON = "android.intent.extra.shortcut.ICON";
field public static final java.lang.String EXTRA_SHORTCUT_ICON_RESOURCE = "android.intent.extra.shortcut.ICON_RESOURCE";
@@ -32567,7 +32571,7 @@ package android.telecom {
method public void handleCallSessionEvent(int);
method public abstract void onRequestCameraCapabilities();
method public abstract void onRequestConnectionDataUsage();
- method public abstract void onSendSessionModifyRequest(android.telecom.VideoProfile);
+ method public abstract void onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile);
method public abstract void onSendSessionModifyResponse(android.telecom.VideoProfile);
method public abstract void onSetCamera(java.lang.String);
method public abstract void onSetDeviceOrientation(int);
@@ -38411,6 +38415,7 @@ package android.view {
method public int getScrollBarFadeDuration();
method public int getScrollBarSize();
method public int getScrollBarStyle();
+ method public int getScrollIndicators();
method public final int getScrollX();
method public final int getScrollY();
method public int getSolidColor();
@@ -38492,6 +38497,7 @@ package android.view {
method public boolean isSaveEnabled();
method public boolean isSaveFromParentEnabled();
method public boolean isScrollContainer();
+ method public boolean isScrollIndicatorEnabled(int);
method public boolean isScrollbarFadingEnabled();
method public boolean isSelected();
method public boolean isShown();
@@ -38691,6 +38697,8 @@ package android.view {
method public void setScrollBarSize(int);
method public void setScrollBarStyle(int);
method public void setScrollContainer(boolean);
+ method public void setScrollIndicators(int);
+ method public void setScrollIndicators(int, int);
method public void setScrollX(int);
method public void setScrollY(int);
method public void setScrollbarFadingEnabled(boolean);
@@ -38816,6 +38824,12 @@ package android.view {
field public static final int SCROLL_AXIS_HORIZONTAL = 1; // 0x1
field public static final int SCROLL_AXIS_NONE = 0; // 0x0
field public static final int SCROLL_AXIS_VERTICAL = 2; // 0x2
+ field public static final int SCROLL_INDICATOR_BOTTOM = 2; // 0x2
+ field public static final int SCROLL_INDICATOR_END = 32; // 0x20
+ field public static final int SCROLL_INDICATOR_LEFT = 4; // 0x4
+ field public static final int SCROLL_INDICATOR_RIGHT = 8; // 0x8
+ field public static final int SCROLL_INDICATOR_START = 16; // 0x10
+ field public static final int SCROLL_INDICATOR_TOP = 1; // 0x1
field protected static final int[] SELECTED_STATE_SET;
field protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
field public static final int SOUND_EFFECTS_ENABLED = 134217728; // 0x8000000
@@ -43169,6 +43183,7 @@ package android.widget {
method public void setSoftInputMode(int);
method public void setVerticalOffset(int);
method public void setWidth(int);
+ method public void setWindowLayoutType(int);
method public void show();
field public static final int INPUT_METHOD_FROM_FOCUSABLE = 0; // 0x0
field public static final int INPUT_METHOD_NEEDED = 1; // 0x1
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 4b72dc3..8009b6c 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -4294,14 +4294,14 @@ public class DevicePolicyManager {
* being disabled.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @param enabled New state of the keyguard.
+ * @param disabled {@code true} disables the keyguard, {@code false} reenables it.
*
* @return {@code false} if attempting to disable the keyguard while a lock password was in
- * place. {@code true} otherwise."
+ * place. {@code true} otherwise.
*/
- public boolean setKeyguardEnabledState(ComponentName admin, boolean enabled) {
+ public boolean setKeyguardDisabled(ComponentName admin, boolean disabled) {
try {
- return mService.setKeyguardEnabledState(admin, enabled);
+ return mService.setKeyguardDisabled(admin, disabled);
} catch (RemoteException re) {
Log.w(TAG, "Failed talking with device policy service", re);
return false;
@@ -4309,18 +4309,22 @@ public class DevicePolicyManager {
}
/**
- * Called by device owner to set the enabled state of the status bar. Disabling the status
- * bar blocks notifications, quick settings and other screen overlays that allow escaping from
+ * Called by device owner to disable the status bar. Disabling the status bar blocks
+ * notifications, quick settings and other screen overlays that allow escaping from
* a single use device.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @param enabled New state of the status bar.
+ * @param disabled {@code true} disables the status bar, {@code false} reenables it.
+ *
+ * @return {@code false} if attempting to disable the status bar failed.
+ * {@code true} otherwise.
*/
- public void setStatusBarEnabledState(ComponentName admin, boolean enabled) {
+ public boolean setStatusBarDisabled(ComponentName admin, boolean disabled) {
try {
- mService.setStatusBarEnabledState(admin, enabled);
+ return mService.setStatusBarDisabled(admin, disabled);
} catch (RemoteException re) {
Log.w(TAG, "Failed talking with device policy service", re);
+ return false;
}
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 833bc00..e81e7c1 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -224,8 +224,8 @@ interface IDevicePolicyManager {
void setSystemUpdatePolicy(in ComponentName who, in PersistableBundle policy);
PersistableBundle getSystemUpdatePolicy();
- boolean setKeyguardEnabledState(in ComponentName admin, boolean enabled);
- void setStatusBarEnabledState(in ComponentName who, boolean enabled);
+ boolean setKeyguardDisabled(in ComponentName admin, boolean disabled);
+ boolean setStatusBarDisabled(in ComponentName who, boolean disabled);
boolean getDoNotAskCredentialsOnBoot();
void notifyPendingSystemUpdate(in long updateReceivedTime);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 54fe786..d0298cd 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -17,6 +17,7 @@
package android.content;
import android.content.pm.ApplicationInfo;
+import android.os.ResultReceiver;
import android.provider.MediaStore;
import android.util.ArraySet;
@@ -3291,11 +3292,79 @@ public class Intent implements Parcelable, Cloneable {
/**
* An Intent describing the choices you would like shown with
- * {@link #ACTION_PICK_ACTIVITY}.
+ * {@link #ACTION_PICK_ACTIVITY} or {@link #ACTION_CHOOSER}.
*/
public static final String EXTRA_INTENT = "android.intent.extra.INTENT";
/**
+ * An Intent[] describing additional, alternate choices you would like shown with
+ * {@link #ACTION_CHOOSER}.
+ *
+ * <p>An app may be capable of providing several different payload types to complete a
+ * user's intended action. For example, an app invoking {@link #ACTION_SEND} to share photos
+ * with another app may use EXTRA_ALTERNATE_INTENTS to have the chooser transparently offer
+ * several different supported sending mechanisms for sharing, such as the actual "image/*"
+ * photo data or a hosted link where the photos can be viewed.</p>
+ *
+ * <p>The intent present in {@link #EXTRA_INTENT} will be treated as the
+ * first/primary/preferred intent in the set. Additional intents specified in
+ * this extra are ordered; by default intents that appear earlier in the array will be
+ * preferred over intents that appear later in the array as matches for the same
+ * target component. To alter this preference, a calling app may also supply
+ * {@link #EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER}.</p>
+ */
+ public static final String EXTRA_ALTERNATE_INTENTS = "android.intent.extra.ALTERNATE_INTENTS";
+
+ /**
+ * An {@link IntentSender} for an Activity that will be invoked when the user makes a selection
+ * from the chooser activity presented by {@link #ACTION_CHOOSER}.
+ *
+ * <p>An app preparing an action for another app to complete may wish to allow the user to
+ * disambiguate between several options for completing the action based on the chosen target
+ * or otherwise refine the action before it is invoked.
+ * </p>
+ *
+ * <p>When sent, this IntentSender may be filled in with the following extras:</p>
+ * <ul>
+ * <li>{@link #EXTRA_INTENT} The first intent that matched the user's chosen target</li>
+ * <li>{@link #EXTRA_ALTERNATE_INTENTS} Any additional intents that also matched the user's
+ * chosen target beyond the first</li>
+ * <li>{@link #EXTRA_RESULT_RECEIVER} A {@link ResultReceiver} that the refinement activity
+ * should fill in and send once the disambiguation is complete</li>
+ * </ul>
+ */
+ public static final String EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER
+ = "android.intent.extra.CHOOSER_REFINEMENT_INTENT_SENDER";
+
+ /**
+ * A {@link ResultReceiver} used to return data back to the sender.
+ *
+ * <p>Used to complete an app-specific
+ * {@link #EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER refinement} for {@link #ACTION_CHOOSER}.</p>
+ *
+ * <p>If {@link #EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER} is present in the intent
+ * used to start a {@link #ACTION_CHOOSER} activity this extra will be
+ * {@link #fillIn(Intent, int) filled in} to that {@link IntentSender} and sent
+ * when the user selects a target component from the chooser. It is up to the recipient
+ * to send a result to this ResultReceiver to signal that disambiguation is complete
+ * and that the chooser should invoke the user's choice.</p>
+ *
+ * <p>The disambiguator should provide a Bundle to the ResultReceiver with an intent
+ * assigned to the key {@link #EXTRA_INTENT}. This supplied intent will be used by the chooser
+ * to match and fill in the final Intent or ChooserTarget before starting it.
+ * The supplied intent must {@link #filterEquals(Intent) match} one of the intents from
+ * {@link #EXTRA_INTENT} or {@link #EXTRA_ALTERNATE_INTENTS} passed to
+ * {@link #EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER} to be accepted.</p>
+ *
+ * <p>The result code passed to the ResultReceiver should be
+ * {@link android.app.Activity#RESULT_OK} if the refinement succeeded and the supplied intent's
+ * target in the chooser should be started, or {@link android.app.Activity#RESULT_CANCELED} if
+ * the chooser should finish without starting a target.</p>
+ */
+ public static final String EXTRA_RESULT_RECEIVER
+ = "android.intent.extra.RESULT_RECEIVER";
+
+ /**
* A CharSequence dialog title to provide to the user when used with a
* {@link #ACTION_CHOOSER}.
*/
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index a4d6be0..691798f 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -326,9 +326,6 @@ public class RequestThreadManager {
}
try {
- startPreview(); // If preview is not running (i.e. after a JPEG capture), we need to
- // explicitely start and stop preview before setting preview surface.
- // null.
stopPreview();
} catch (RuntimeException e) {
Log.e(TAG, "Received device exception in configure call: ", e);
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 451abea..59c7c6d 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -91,6 +91,7 @@ public class StaticLayout extends Layout {
b.mEllipsizedWidth = width;
b.mEllipsize = null;
b.mMaxLines = Integer.MAX_VALUE;
+ b.mBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE;
b.mMeasuredText = MeasuredText.obtain();
return b;
@@ -100,6 +101,8 @@ public class StaticLayout extends Layout {
b.mPaint = null;
b.mText = null;
MeasuredText.recycle(b.mMeasuredText);
+ b.mMeasuredText = null;
+ nFinishBuilder(b.mNativePtr);
sPool.release(b);
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 75dc0a2..f62e6a2 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2395,10 +2395,143 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
+ /**
+ * Flag indicating that the bottom scroll indicator should be displayed
+ * when this view can scroll up.
+ */
+ static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
+
+ /**
+ * Flag indicating that the bottom scroll indicator should be displayed
+ * when this view can scroll down.
+ */
+ static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
+
+ /**
+ * Flag indicating that the left scroll indicator should be displayed
+ * when this view can scroll left.
+ */
+ static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
+
+ /**
+ * Flag indicating that the right scroll indicator should be displayed
+ * when this view can scroll right.
+ */
+ static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
+
+ /**
+ * Flag indicating that the start scroll indicator should be displayed
+ * when this view can scroll in the start direction.
+ */
+ static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
+
+ /**
+ * Flag indicating that the end scroll indicator should be displayed
+ * when this view can scroll in the end direction.
+ */
+ static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
+
/* End of masks for mPrivateFlags3 */
static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
+ static final int SCROLL_INDICATORS_NONE = 0x0000;
+
+ /**
+ * Mask for use with setFlags indicating bits used for indicating which
+ * scroll indicators are enabled.
+ */
+ static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
+ | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
+ | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
+ | PFLAG3_SCROLL_INDICATOR_END;
+
+ /**
+ * Left-shift required to translate between public scroll indicator flags
+ * and internal PFLAGS3 flags. When used as a right-shift, translates
+ * PFLAGS3 flags to public flags.
+ */
+ static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true,
+ value = {
+ SCROLL_INDICATOR_TOP,
+ SCROLL_INDICATOR_BOTTOM,
+ SCROLL_INDICATOR_LEFT,
+ SCROLL_INDICATOR_RIGHT,
+ SCROLL_INDICATOR_START,
+ SCROLL_INDICATOR_END,
+ })
+ public @interface ScrollIndicators {}
+
+ /**
+ * Scroll indicator direction for the top edge of the view.
+ *
+ * @see #setScrollIndicators(int)
+ * @see #setScrollIndicators(int, int)
+ * @see #getScrollIndicators()
+ */
+ public static final int SCROLL_INDICATOR_TOP =
+ PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
+
+ /**
+ * Scroll indicator direction for the bottom edge of the view.
+ *
+ * @see #setScrollIndicators(int)
+ * @see #setScrollIndicators(int, int)
+ * @see #getScrollIndicators()
+ */
+ public static final int SCROLL_INDICATOR_BOTTOM =
+ PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
+
+ /**
+ * Scroll indicator direction for the left edge of the view.
+ *
+ * @see #setScrollIndicators(int)
+ * @see #setScrollIndicators(int, int)
+ * @see #getScrollIndicators()
+ */
+ public static final int SCROLL_INDICATOR_LEFT =
+ PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
+
+ /**
+ * Scroll indicator direction for the right edge of the view.
+ *
+ * @see #setScrollIndicators(int)
+ * @see #setScrollIndicators(int, int)
+ * @see #getScrollIndicators()
+ */
+ public static final int SCROLL_INDICATOR_RIGHT =
+ PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
+
+ /**
+ * Scroll indicator direction for the starting edge of the view.
+ * <p>
+ * Resolved according to the view's layout direction, see
+ * {@link #getLayoutDirection()} for more information.
+ *
+ * @see #setScrollIndicators(int)
+ * @see #setScrollIndicators(int, int)
+ * @see #getScrollIndicators()
+ */
+ public static final int SCROLL_INDICATOR_START =
+ PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
+
+ /**
+ * Scroll indicator direction for the ending edge of the view.
+ * <p>
+ * Resolved according to the view's layout direction, see
+ * {@link #getLayoutDirection()} for more information.
+ *
+ * @see #setScrollIndicators(int)
+ * @see #setScrollIndicators(int, int)
+ * @see #getScrollIndicators()
+ */
+ public static final int SCROLL_INDICATOR_END =
+ PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
+
/**
* <p>Indicates that we are allowing {@link android.view.ViewAssistStructure} to traverse
* into this view.<p>
@@ -3217,6 +3350,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
@ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
private ForegroundInfo mForegroundInfo;
+ private Drawable mScrollIndicatorDrawable;
+
/**
* RenderNode used for backgrounds.
* <p>
@@ -3769,6 +3904,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
int overScrollMode = mOverScrollMode;
boolean initializeScrollbars = false;
+ boolean initializeScrollIndicators = false;
boolean startPaddingDefined = false;
boolean endPaddingDefined = false;
@@ -4135,6 +4271,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
mForegroundInfo.mInsidePadding = a.getBoolean(attr,
mForegroundInfo.mInsidePadding);
+ case R.styleable.View_scrollIndicators:
+ final int scrollIndicators =
+ a.getInt(attr, SCROLL_INDICATORS_NONE) & SCROLL_INDICATORS_PFLAG3_MASK;
+ if (scrollIndicators != 0) {
+ viewFlagValues |= scrollIndicators;
+ viewFlagMasks |= SCROLL_INDICATORS_PFLAG3_MASK;
+ initializeScrollIndicators = true;
+ }
break;
}
}
@@ -4211,6 +4355,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
initializeScrollbarsInternal(a);
}
+ if (initializeScrollIndicators) {
+ initializeScrollIndicatorsInternal();
+ }
+
a.recycle();
// Needs to be called after mViewFlags is set
@@ -4682,6 +4830,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
resolvePadding();
}
+ private void initializeScrollIndicatorsInternal() {
+ // Some day maybe we'll break this into top/left/start/etc. and let the
+ // client control it. Until then, you can have any scroll indicator you
+ // want as long as it's a 1dp foreground-colored rectangle.
+ if (mScrollIndicatorDrawable == null) {
+ mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
+ }
+ }
+
/**
* <p>
* Initalizes the scrollability cache if necessary.
@@ -4721,6 +4878,118 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
return mVerticalScrollbarPosition;
}
+ /**
+ * Sets the state of all scroll indicators.
+ * <p>
+ * See {@link #setScrollIndicators(int, int)} for usage information.
+ *
+ * @param indicators a bitmask of indicators that should be enabled, or
+ * {@code 0} to disable all indicators
+ * @see #setScrollIndicators(int, int)
+ * @see #getScrollIndicators()
+ * @attr ref android.R.styleable#View_scrollIndicators
+ */
+ public void setScrollIndicators(@ScrollIndicators int indicators) {
+ setScrollIndicators(indicators, SCROLL_INDICATORS_PFLAG3_MASK);
+ }
+
+ /**
+ * Sets the state of the scroll indicators specified by the mask. To change
+ * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
+ * <p>
+ * When a scroll indicator is enabled, it will be displayed if the view
+ * can scroll in the direction of the indicator.
+ * <p>
+ * Multiple indicator types may be enabled or disabled by passing the
+ * logical OR of the desired types. If multiple types are specified, they
+ * will all be set to the same enabled state.
+ * <p>
+ * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
+ *
+ * @param indicators the indicator direction, or the logical OR of multiple
+ * indicator directions. One or more of:
+ * <ul>
+ * <li>{@link #SCROLL_INDICATOR_TOP}</li>
+ * <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
+ * <li>{@link #SCROLL_INDICATOR_LEFT}</li>
+ * <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
+ * <li>{@link #SCROLL_INDICATOR_START}</li>
+ * <li>{@link #SCROLL_INDICATOR_END}</li>
+ * </ul>
+ * @see #setScrollIndicators(int)
+ * @see #getScrollIndicators()
+ * @attr ref android.R.styleable#View_scrollIndicators
+ */
+ public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
+ // Shift and sanitize mask.
+ mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
+ mask &= SCROLL_INDICATORS_PFLAG3_MASK;
+
+ // Shift and mask indicators.
+ indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
+ indicators &= mask;
+
+ // Merge with non-masked flags.
+ final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
+
+ if (mPrivateFlags3 != updatedFlags) {
+ mPrivateFlags3 = updatedFlags;
+
+ if (indicators != 0) {
+ initializeScrollIndicatorsInternal();
+ }
+ invalidate();
+ }
+ }
+
+ /**
+ * Returns a bitmask representing the enabled scroll indicators.
+ * <p>
+ * For example, if the top and left scroll indicators are enabled and all
+ * other indicators are disabled, the return value will be
+ * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
+ * <p>
+ * To check whether the bottom scroll indicator is enabled, use the value
+ * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
+ *
+ * @return a bitmask representing the enabled scroll indicators
+ */
+ @ScrollIndicators
+ public int getScrollIndicators() {
+ return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
+ >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
+ }
+
+ /**
+ * Returns whether the specified scroll indicator is enabled.
+ * <p>
+ * Multiple indicator types may be queried by passing the logical OR of the
+ * desired types. If multiple types are specified, the return value
+ * represents whether they are all enabled.
+ *
+ * @param direction the indicator direction, or the logical OR of multiple
+ * indicator directions. One or more of:
+ * <ul>
+ * <li>{@link #SCROLL_INDICATOR_TOP}</li>
+ * <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
+ * <li>{@link #SCROLL_INDICATOR_LEFT}</li>
+ * <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
+ * <li>{@link #SCROLL_INDICATOR_START}</li>
+ * <li>{@link #SCROLL_INDICATOR_END}</li>
+ * </ul>
+ * @return {@code true} if the specified indicator(s) are enabled,
+ * {@code false} otherwise
+ * @attr ref android.R.styleable#View_scrollIndicators
+ */
+ public boolean isScrollIndicatorEnabled(int direction) {
+ // Shift and sanitize input.
+ direction <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
+ direction &= SCROLL_INDICATORS_PFLAG3_MASK;
+
+ // All of the flags must be set.
+ return (mPrivateFlags3 & direction) == direction;
+ }
+
ListenerInfo getListenerInfo() {
if (mListenerInfo != null) {
return mListenerInfo;
@@ -13444,6 +13713,75 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
}
+ void getScrollIndicatorBounds(@NonNull Rect out) {
+ out.left = mScrollX;
+ out.right = mScrollX + mRight - mLeft;
+ out.top = mScrollY;
+ out.bottom = mScrollY + mBottom - mTop;
+ }
+
+ private void onDrawScrollIndicators(Canvas c) {
+ if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
+ // No scroll indicators enabled.
+ return;
+ }
+
+ final Drawable dr = mScrollIndicatorDrawable;
+ if (dr == null) {
+ // Scroll indicators aren't supported here.
+ return;
+ }
+
+ final int h = dr.getIntrinsicHeight();
+ final int w = dr.getIntrinsicWidth();
+ final Rect rect = mAttachInfo.mTmpInvalRect;
+ getScrollIndicatorBounds(rect);
+
+ if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
+ final boolean canScrollUp = canScrollVertically(-1);
+ if (canScrollUp) {
+ dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
+ dr.draw(c);
+ }
+ }
+
+ if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
+ final boolean canScrollDown = canScrollVertically(1);
+ if (canScrollDown) {
+ dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
+ dr.draw(c);
+ }
+ }
+
+ final int leftRtl;
+ final int rightRtl;
+ if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
+ leftRtl = PFLAG3_SCROLL_INDICATOR_END;
+ rightRtl = PFLAG3_SCROLL_INDICATOR_START;
+ } else {
+ leftRtl = PFLAG3_SCROLL_INDICATOR_START;
+ rightRtl = PFLAG3_SCROLL_INDICATOR_END;
+ }
+
+ final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
+ if ((mPrivateFlags3 & leftMask) != 0) {
+ final boolean canScrollLeft = canScrollHorizontally(-1);
+ if (canScrollLeft) {
+ dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
+ dr.draw(c);
+ }
+ }
+
+ final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
+ if ((mPrivateFlags3 & rightMask) != 0) {
+ final boolean canScrollRight = canScrollHorizontally(1);
+ if (canScrollRight) {
+ dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
+ dr.draw(c);
+ }
+ }
+ }
+
/**
* <p>Request the drawing of the horizontal and the vertical scrollbar. The
* scrollbars are painted only if they have been awakened first.</p>
@@ -17272,6 +17610,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @param canvas canvas to draw into
*/
public void onDrawForeground(Canvas canvas) {
+ onDrawScrollIndicators(canvas);
onDrawScrollBars(canvas);
final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index f240fd6..babb4e9 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -18,6 +18,7 @@ package android.view;
import android.animation.LayoutTransition;
import android.annotation.IdRes;
+import android.annotation.NonNull;
import android.annotation.UiThread;
import android.content.Context;
import android.content.Intent;
@@ -3547,6 +3548,21 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
return child.draw(canvas, this, drawingTime);
}
+ @Override
+ void getScrollIndicatorBounds(@NonNull Rect out) {
+ super.getScrollIndicatorBounds(out);
+
+ // If we have padding and we're supposed to clip children to that
+ // padding, offset the scroll indicators to match our clip bounds.
+ final boolean clipToPadding = (mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK;
+ if (clipToPadding) {
+ out.left += mPaddingLeft;
+ out.right -= mPaddingRight;
+ out.top += mPaddingTop;
+ out.bottom -= mPaddingBottom;
+ }
+ }
+
/**
* Returns whether this group's children are clipped to their bounds before drawing.
* The default value is true.
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 78604bf..040fd37 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -247,6 +247,13 @@ public final class InputMethodManager {
/** @hide */
public static final int DISPATCH_HANDLED = 1;
+ /** @hide */
+ public static final int SHOW_IM_PICKER_MODE_AUTO = 0;
+ /** @hide */
+ public static final int SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES = 1;
+ /** @hide */
+ public static final int SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES = 2;
+
final IInputMethodManager mService;
final Looper mMainLooper;
@@ -1890,9 +1897,28 @@ public final class InputMethodManager {
}
}
+ /**
+ * Shows the input method chooser dialog.
+ *
+ * @param showAuxiliarySubtypes Set true to show auxiliary input methods.
+ * @hide
+ */
+ public void showInputMethodPicker(boolean showAuxiliarySubtypes) {
+ synchronized (mH) {
+ try {
+ final int mode = showAuxiliarySubtypes ?
+ SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES:
+ SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES;
+ mService.showInputMethodPickerFromClient(mClient, mode);
+ } catch (RemoteException e) {
+ Log.w(TAG, "IME died: " + mCurId, e);
+ }
+ }
+ }
+
private void showInputMethodPickerLocked() {
try {
- mService.showInputMethodPickerFromClient(mClient);
+ mService.showInputMethodPickerFromClient(mClient, SHOW_IM_PICKER_MODE_AUTO);
} catch (RemoteException e) {
Log.w(TAG, "IME died: " + mCurId, e);
}
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 8d35b83..712fdba 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -2421,7 +2421,8 @@ public class Editor {
public PinnedPopupWindow() {
createPopupWindow();
- mPopupWindow.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL);
+ mPopupWindow.setWindowLayoutType(
+ WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL);
mPopupWindow.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
mPopupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 310412f..05866f0 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -39,6 +39,7 @@ import android.view.View.OnTouchListener;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewParent;
+import android.view.WindowManager;
import android.view.animation.AccelerateDecelerateInterpolator;
import com.android.internal.R;
@@ -77,6 +78,7 @@ public class ListPopupWindow {
private int mDropDownWidth = ViewGroup.LayoutParams.WRAP_CONTENT;
private int mDropDownHorizontalOffset;
private int mDropDownVerticalOffset;
+ private int mDropDownWindowLayoutType = WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
private boolean mDropDownVerticalOffsetSet;
private int mDropDownGravity = Gravity.NO_GRAVITY;
@@ -515,6 +517,19 @@ public class ListPopupWindow {
}
/**
+ * Set the layout type for this popup window.
+ * <p>
+ * See {@link WindowManager.LayoutParams#type} for possible values.
+ *
+ * @param layoutType Layout type for this window.
+ *
+ * @see WindowManager.LayoutParams#type
+ */
+ public void setWindowLayoutType(int layoutType) {
+ mDropDownWindowLayoutType = layoutType;
+ }
+
+ /**
* Sets a listener to receive events when a list item is clicked.
*
* @param clickListener Listener to register
@@ -567,8 +582,9 @@ public class ListPopupWindow {
public void show() {
int height = buildDropDown();
- boolean noInputMethod = isInputMethodNotNeeded();
+ final boolean noInputMethod = isInputMethodNotNeeded();
mPopup.setAllowScrollingAnchorParent(!noInputMethod);
+ mPopup.setWindowLayoutType(mDropDownWindowLayoutType);
if (mPopup.isShowing()) {
final int widthSpec;
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index c3ac278..b4cbf35 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -829,9 +829,9 @@ public class PopupWindow {
}
/**
- * Set the layout type for this window. This value will be passed through to
- * {@link WindowManager.LayoutParams#type} therefore the value should match any value
- * {@link WindowManager.LayoutParams#type} accepts.
+ * Set the layout type for this window.
+ * <p>
+ * See {@link WindowManager.LayoutParams#type} for possible values.
*
* @param layoutType Layout type for this window.
*
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index b8110e3..61ee00c 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -526,11 +526,15 @@ public class AlertController {
mWindow.setCloseOnTouchOutsideIfNotSet(true);
}
- // Only display the divider if we have a title and a custom view or a
- // message.
if (hasTopPanel) {
+ // Only clip scrolling content to padding if we have a title.
+ if (mScrollView != null) {
+ mScrollView.setClipToPadding(true);
+ }
+
+ // Only show the divider if we have a title.
final View divider;
- if (mMessage != null || hasCustomPanel || mListView != null) {
+ if (mMessage != null || mListView != null || hasCustomPanel) {
divider = topPanel.findViewById(R.id.titleDivider);
} else {
divider = topPanel.findViewById(R.id.titleDividerTop);
@@ -541,6 +545,17 @@ public class AlertController {
}
}
+ // Update scroll indicators as needed.
+ if (!hasCustomPanel) {
+ final View content = mListView != null ? mListView : mScrollView;
+ if (content != null) {
+ final int indicators = (hasTopPanel ? View.SCROLL_INDICATOR_TOP : 0)
+ | (hasButtonPanel ? View.SCROLL_INDICATOR_BOTTOM : 0);
+ content.setScrollIndicators(indicators,
+ View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_BOTTOM);
+ }
+ }
+
final TypedArray a = mContext.obtainStyledAttributes(
null, R.styleable.AlertDialog, R.attr.alertDialogStyle, 0);
setBackground(a, topPanel, contentPanel, customPanel, buttonPanel,
@@ -654,59 +669,6 @@ public class AlertController {
contentPanel.setVisibility(View.GONE);
}
}
-
- // Set up scroll indicators (if present).
- final View indicatorUp = contentPanel.findViewById(R.id.scrollIndicatorUp);
- final View indicatorDown = contentPanel.findViewById(R.id.scrollIndicatorDown);
- if (indicatorUp != null || indicatorDown != null) {
- if (mMessage != null) {
- // We're just showing the ScrollView, set up listener.
- mScrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
- @Override
- public void onScrollChange(View v, int scrollX, int scrollY,
- int oldScrollX, int oldScrollY) {
- manageScrollIndicators(v, indicatorUp, indicatorDown);
- }
- });
- // Set up the indicators following layout.
- mScrollView.post(new Runnable() {
- @Override
- public void run() {
- manageScrollIndicators(mScrollView, indicatorUp, indicatorDown);
- }
- });
-
- } else if (mListView != null) {
- // We're just showing the AbsListView, set up listener.
- mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
- @Override
- public void onScrollStateChanged(AbsListView view, int scrollState) {
- // That's cool, I guess?
- }
-
- @Override
- public void onScroll(AbsListView v, int firstVisibleItem,
- int visibleItemCount, int totalItemCount) {
- manageScrollIndicators(v, indicatorUp, indicatorDown);
- }
- });
- // Set up the indicators following layout.
- mListView.post(new Runnable() {
- @Override
- public void run() {
- manageScrollIndicators(mListView, indicatorUp, indicatorDown);
- }
- });
- } else {
- // We don't have any content to scroll, remove the indicators.
- if (indicatorUp != null) {
- contentPanel.removeView(indicatorUp);
- }
- if (indicatorDown != null) {
- contentPanel.removeView(indicatorDown);
- }
- }
- }
}
private static void manageScrollIndicators(View v, View upIndicator, View downIndicator) {
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index e347faa..62ca1f0 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -21,6 +21,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
+import android.content.IntentSender.SendIntentException;
import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
@@ -34,6 +35,7 @@ import android.os.IBinder;
import android.os.Message;
import android.os.Parcelable;
import android.os.RemoteException;
+import android.os.ResultReceiver;
import android.os.UserHandle;
import android.service.chooser.ChooserTarget;
import android.service.chooser.ChooserTargetService;
@@ -53,11 +55,13 @@ public class ChooserActivity extends ResolverActivity {
private static final boolean DEBUG = false;
- private static final int QUERY_TARGET_LIMIT = 5;
+ private static final int QUERY_TARGET_SERVICE_LIMIT = 5;
private static final int WATCHDOG_TIMEOUT_MILLIS = 5000;
private Bundle mReplacementExtras;
private IntentSender mChosenComponentSender;
+ private IntentSender mRefinementIntentSender;
+ private RefinementResultReceiver mRefinementResultReceiver;
private ChooserTarget[] mCallerChooserTargets;
@@ -113,6 +117,32 @@ public class ChooserActivity extends ResolverActivity {
if (target != null) {
modifyTargetIntent(target);
}
+ Parcelable[] targetsParcelable
+ = intent.getParcelableArrayExtra(Intent.EXTRA_ALTERNATE_INTENTS);
+ if (targetsParcelable != null) {
+ final boolean offset = target == null;
+ Intent[] additionalTargets =
+ new Intent[offset ? targetsParcelable.length - 1 : targetsParcelable.length];
+ for (int i = 0; i < targetsParcelable.length; i++) {
+ if (!(targetsParcelable[i] instanceof Intent)) {
+ Log.w(TAG, "EXTRA_ALTERNATE_INTENTS array entry #" + i + " is not an Intent: "
+ + targetsParcelable[i]);
+ finish();
+ super.onCreate(null);
+ return;
+ }
+ final Intent additionalTarget = (Intent) targetsParcelable[i];
+ if (i == 0 && target == null) {
+ target = additionalTarget;
+ modifyTargetIntent(target);
+ } else {
+ additionalTargets[offset ? i - 1 : i] = additionalTarget;
+ modifyTargetIntent(additionalTarget);
+ }
+ }
+ setAdditionalTargets(additionalTargets);
+ }
+
mReplacementExtras = intent.getBundleExtra(Intent.EXTRA_REPLACEMENT_EXTRAS);
CharSequence title = intent.getCharSequenceExtra(Intent.EXTRA_TITLE);
int defaultTitleRes = 0;
@@ -125,7 +155,7 @@ public class ChooserActivity extends ResolverActivity {
initialIntents = new Intent[pa.length];
for (int i=0; i<pa.length; i++) {
if (!(pa[i] instanceof Intent)) {
- Log.w("ChooserActivity", "Initial intent #" + i + " not an Intent: " + pa[i]);
+ Log.w(TAG, "Initial intent #" + i + " not an Intent: " + pa[i]);
finish();
super.onCreate(null);
return;
@@ -141,8 +171,7 @@ public class ChooserActivity extends ResolverActivity {
final ChooserTarget[] targets = new ChooserTarget[pa.length];
for (int i = 0; i < pa.length; i++) {
if (!(pa[i] instanceof ChooserTarget)) {
- Log.w("ChooserActivity", "Chooser target #" + i + " is not a ChooserTarget: " +
- pa[i]);
+ Log.w(TAG, "Chooser target #" + i + " is not a ChooserTarget: " + pa[i]);
finish();
super.onCreate(null);
return;
@@ -153,12 +182,23 @@ public class ChooserActivity extends ResolverActivity {
}
mChosenComponentSender = intent.getParcelableExtra(
Intent.EXTRA_CHOSEN_COMPONENT_INTENT_SENDER);
+ mRefinementIntentSender = intent.getParcelableExtra(
+ Intent.EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER);
setSafeForwardingMode(true);
super.onCreate(savedInstanceState, target, title, defaultTitleRes, initialIntents,
null, false);
}
@Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (mRefinementResultReceiver != null) {
+ mRefinementResultReceiver.destroy();
+ mRefinementResultReceiver = null;
+ }
+ }
+
+ @Override
public Intent getReplacementIntent(ActivityInfo aInfo, Intent defIntent) {
Intent result = defIntent;
if (mReplacementExtras != null) {
@@ -211,6 +251,37 @@ public class ChooserActivity extends ResolverActivity {
}
}
+ @Override
+ protected boolean onTargetSelected(TargetInfo target, boolean alwaysCheck) {
+ if (mRefinementIntentSender != null) {
+ final Intent fillIn = new Intent();
+ final List<Intent> sourceIntents = target.getAllSourceIntents();
+ if (!sourceIntents.isEmpty()) {
+ fillIn.putExtra(Intent.EXTRA_INTENT, sourceIntents.get(0));
+ if (sourceIntents.size() > 1) {
+ final Intent[] alts = new Intent[sourceIntents.size() - 1];
+ for (int i = 1, N = sourceIntents.size(); i < N; i++) {
+ alts[i - 1] = sourceIntents.get(i);
+ }
+ fillIn.putExtra(Intent.EXTRA_ALTERNATE_INTENTS, alts);
+ }
+ if (mRefinementResultReceiver != null) {
+ mRefinementResultReceiver.destroy();
+ }
+ mRefinementResultReceiver = new RefinementResultReceiver(this, target, null);
+ fillIn.putExtra(Intent.EXTRA_RESULT_RECEIVER,
+ mRefinementResultReceiver);
+ try {
+ mRefinementIntentSender.sendIntent(this, 0, fillIn, null, null);
+ return false;
+ } catch (SendIntentException e) {
+ Log.e(TAG, "Refinement IntentSender failed to send", e);
+ }
+ }
+ }
+ return super.onTargetSelected(target, alwaysCheck);
+ }
+
void queryTargetServices(ChooserListAdapter adapter) {
final PackageManager pm = getPackageManager();
int targetsToQuery = 0;
@@ -258,8 +329,9 @@ public class ChooserActivity extends ResolverActivity {
targetsToQuery++;
}
}
- if (targetsToQuery >= QUERY_TARGET_LIMIT) {
- if (DEBUG) Log.d(TAG, "queryTargets hit query target limit " + QUERY_TARGET_LIMIT);
+ if (targetsToQuery >= QUERY_TARGET_SERVICE_LIMIT) {
+ if (DEBUG) Log.d(TAG, "queryTargets hit query target limit "
+ + QUERY_TARGET_SERVICE_LIMIT);
break;
}
}
@@ -303,6 +375,43 @@ public class ChooserActivity extends ResolverActivity {
mTargetResultHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT);
}
+ void onRefinementResult(TargetInfo selectedTarget, Intent matchingIntent) {
+ if (mRefinementResultReceiver != null) {
+ mRefinementResultReceiver.destroy();
+ mRefinementResultReceiver = null;
+ }
+
+ if (selectedTarget == null) {
+ Log.e(TAG, "Refinement result intent did not match any known targets; canceling");
+ } else if (!checkTargetSourceIntent(selectedTarget, matchingIntent)) {
+ Log.e(TAG, "onRefinementResult: Selected target " + selectedTarget
+ + " cannot match refined source intent " + matchingIntent);
+ } else if (super.onTargetSelected(selectedTarget.cloneFilledIn(matchingIntent, 0), false)) {
+ finish();
+ return;
+ }
+ onRefinementCanceled();
+ }
+
+ void onRefinementCanceled() {
+ if (mRefinementResultReceiver != null) {
+ mRefinementResultReceiver.destroy();
+ mRefinementResultReceiver = null;
+ }
+ finish();
+ }
+
+ boolean checkTargetSourceIntent(TargetInfo target, Intent matchingIntent) {
+ final List<Intent> targetIntents = target.getAllSourceIntents();
+ for (int i = 0, N = targetIntents.size(); i < N; i++) {
+ final Intent targetIntent = targetIntents.get(i);
+ if (targetIntent.filterEquals(matchingIntent)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
ResolveListAdapter createAdapter(Context context, Intent[] initialIntents,
List<ResolveInfo> rList, int launchedFromUid, boolean filterLastUsed) {
@@ -313,17 +422,19 @@ public class ChooserActivity extends ResolverActivity {
return adapter;
}
- class ChooserTargetInfo implements TargetInfo {
- private final TargetInfo mSourceInfo;
+ final class ChooserTargetInfo implements TargetInfo {
+ private final DisplayResolveInfo mSourceInfo;
private final ResolveInfo mBackupResolveInfo;
private final ChooserTarget mChooserTarget;
private final Drawable mDisplayIcon;
+ private final Intent mFillInIntent;
+ private final int mFillInFlags;
public ChooserTargetInfo(ChooserTarget target) {
this(null, target);
}
- public ChooserTargetInfo(TargetInfo sourceInfo, ChooserTarget chooserTarget) {
+ public ChooserTargetInfo(DisplayResolveInfo sourceInfo, ChooserTarget chooserTarget) {
mSourceInfo = sourceInfo;
mChooserTarget = chooserTarget;
mDisplayIcon = new BitmapDrawable(getResources(), chooserTarget.getIcon());
@@ -333,6 +444,18 @@ public class ChooserActivity extends ResolverActivity {
} else {
mBackupResolveInfo = getPackageManager().resolveActivity(getResolvedIntent(), 0);
}
+
+ mFillInIntent = null;
+ mFillInFlags = 0;
+ }
+
+ private ChooserTargetInfo(ChooserTargetInfo other, Intent fillInIntent, int flags) {
+ mSourceInfo = other.mSourceInfo;
+ mBackupResolveInfo = other.mBackupResolveInfo;
+ mChooserTarget = other.mChooserTarget;
+ mDisplayIcon = other.mDisplayIcon;
+ mFillInIntent = fillInIntent;
+ mFillInFlags = flags;
}
@Override
@@ -358,22 +481,42 @@ public class ChooserActivity extends ResolverActivity {
}
private Intent getFillInIntent() {
- return mSourceInfo != null ? mSourceInfo.getResolvedIntent() : getTargetIntent();
+ Intent result = mSourceInfo != null
+ ? mSourceInfo.getResolvedIntent() : getTargetIntent();
+ if (result == null) {
+ Log.e(TAG, "ChooserTargetInfo#getFillInIntent: no fillIn intent available");
+ } else if (mFillInIntent != null) {
+ result = new Intent(result);
+ result.fillIn(mFillInIntent, mFillInFlags);
+ }
+ return result;
}
@Override
public boolean start(Activity activity, Bundle options) {
- return mChooserTarget.sendIntent(activity, getFillInIntent());
+ final Intent intent = getFillInIntent();
+ if (intent == null) {
+ return false;
+ }
+ return mChooserTarget.sendIntent(activity, intent);
}
@Override
public boolean startAsCaller(Activity activity, Bundle options, int userId) {
- return mChooserTarget.sendIntentAsCaller(activity, getFillInIntent(), userId);
+ final Intent intent = getFillInIntent();
+ if (intent == null) {
+ return false;
+ }
+ return mChooserTarget.sendIntentAsCaller(activity, intent, userId);
}
@Override
public boolean startAsUser(Activity activity, Bundle options, UserHandle user) {
- return mChooserTarget.sendIntentAsUser(activity, getFillInIntent(), user);
+ final Intent intent = getFillInIntent();
+ if (intent == null) {
+ return false;
+ }
+ return mChooserTarget.sendIntentAsUser(activity, intent, user);
}
@Override
@@ -395,6 +538,21 @@ public class ChooserActivity extends ResolverActivity {
public Drawable getDisplayIcon() {
return mDisplayIcon;
}
+
+ @Override
+ public TargetInfo cloneFilledIn(Intent fillInIntent, int flags) {
+ return new ChooserTargetInfo(this, fillInIntent, flags);
+ }
+
+ @Override
+ public List<Intent> getAllSourceIntents() {
+ final List<Intent> results = new ArrayList<>();
+ if (mSourceInfo != null) {
+ // We only queried the service for the first one in our sourceinfo.
+ results.add(mSourceInfo.getAllSourceIntents().get(0));
+ }
+ return results;
+ }
}
public class ChooserListAdapter extends ResolveListAdapter {
@@ -542,4 +700,53 @@ public class ChooserActivity extends ResolverActivity {
connection = c;
}
}
+
+ static class RefinementResultReceiver extends ResultReceiver {
+ private ChooserActivity mChooserActivity;
+ private TargetInfo mSelectedTarget;
+
+ public RefinementResultReceiver(ChooserActivity host, TargetInfo target,
+ Handler handler) {
+ super(handler);
+ mChooserActivity = host;
+ mSelectedTarget = target;
+ }
+
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ if (mChooserActivity == null) {
+ Log.e(TAG, "Destroyed RefinementResultReceiver received a result");
+ return;
+ }
+ if (resultData == null) {
+ Log.e(TAG, "RefinementResultReceiver received null resultData");
+ return;
+ }
+
+ switch (resultCode) {
+ case RESULT_CANCELED:
+ mChooserActivity.onRefinementCanceled();
+ break;
+ case RESULT_OK:
+ Parcelable intentParcelable = resultData.getParcelable(Intent.EXTRA_INTENT);
+ if (intentParcelable instanceof Intent) {
+ mChooserActivity.onRefinementResult(mSelectedTarget,
+ (Intent) intentParcelable);
+ } else {
+ Log.e(TAG, "RefinementResultReceiver received RESULT_OK but no Intent"
+ + " in resultData with key Intent.EXTRA_INTENT");
+ }
+ break;
+ default:
+ Log.w(TAG, "Unknown result code " + resultCode
+ + " sent to RefinementResultReceiver");
+ break;
+ }
+ }
+
+ public void destroy() {
+ mChooserActivity = null;
+ mSelectedTarget = null;
+ }
+ }
}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 8dd7836..2048664 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -102,7 +102,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
private int mLastSelected = AbsListView.INVALID_POSITION;
private boolean mResolvingHome = false;
private int mProfileSwitchMessageId = -1;
- private Intent mIntent;
+ private final ArrayList<Intent> mIntents = new ArrayList<>();
private UsageStatsManager mUsm;
private Map<String, UsageStats> mStats;
@@ -229,7 +229,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
final ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
mIconDpi = am.getLauncherLargeIconDensity();
- mIntent = new Intent(intent);
+ mIntents.add(0, new Intent(intent));
mAdapter = createAdapter(this, initialIntents, rList, mLaunchedFromUid, alwaysUseOption);
final int layoutId;
@@ -250,7 +250,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
return;
}
- int count = mAdapter.mList.size();
+ int count = mAdapter.mDisplayList.size();
if (count > 1 || (count == 1 && mAdapter.getOtherProfile() != null)) {
setContentView(layoutId);
mAdapterView = (AbsListView) findViewById(R.id.resolver_list);
@@ -376,8 +376,16 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
}
}
+ protected final void setAdditionalTargets(Intent[] intents) {
+ if (intents != null) {
+ for (Intent intent : intents) {
+ mIntents.add(intent);
+ }
+ }
+ }
+
public Intent getTargetIntent() {
- return mIntent;
+ return mIntents.isEmpty() ? null : mIntents.get(0);
}
private String getReferrerPackageName() {
@@ -630,8 +638,9 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
}
TargetInfo target = mAdapter.targetInfoForPosition(which, filtered);
- onTargetSelected(target, always);
- finish();
+ if (onTargetSelected(target, always)) {
+ finish();
+ }
}
/**
@@ -641,7 +650,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
return defIntent;
}
- protected void onTargetSelected(TargetInfo target, boolean alwaysCheck) {
+ protected boolean onTargetSelected(TargetInfo target, boolean alwaysCheck) {
final ResolveInfo ri = target.getResolveInfo();
final Intent intent = target != null ? target.getResolvedIntent() : null;
@@ -728,7 +737,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
ComponentName[] set = new ComponentName[N];
int bestMatch = 0;
for (int i=0; i<N; i++) {
- ResolveInfo r = mAdapter.mOrigResolveList.get(i);
+ ResolveInfo r = mAdapter.mOrigResolveList.get(i).getResolveInfoAt(0);
set[i] = new ComponentName(r.activityInfo.packageName,
r.activityInfo.name);
if (r.match > bestMatch) bestMatch = r.match;
@@ -774,6 +783,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
if (target != null) {
safelyStartActivity(target);
}
+ return true;
}
void safelyStartActivity(TargetInfo cti) {
@@ -837,15 +847,17 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
private Drawable mDisplayIcon;
private final CharSequence mExtendedInfo;
private final Intent mResolvedIntent;
+ private final List<Intent> mSourceIntents = new ArrayList<>();
- DisplayResolveInfo(ResolveInfo pri, CharSequence pLabel,
+ DisplayResolveInfo(Intent originalIntent, ResolveInfo pri, CharSequence pLabel,
CharSequence pInfo, Intent pOrigIntent) {
+ mSourceIntents.add(originalIntent);
mResolveInfo = pri;
mDisplayLabel = pLabel;
mExtendedInfo = pInfo;
final Intent intent = new Intent(pOrigIntent != null ? pOrigIntent :
- getReplacementIntent(pri.activityInfo, mIntent));
+ getReplacementIntent(pri.activityInfo, getTargetIntent()));
intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT
| Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
final ActivityInfo ai = mResolveInfo.activityInfo;
@@ -854,6 +866,16 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
mResolvedIntent = intent;
}
+ private DisplayResolveInfo(DisplayResolveInfo other, Intent fillInIntent, int flags) {
+ mSourceIntents.addAll(other.getAllSourceIntents());
+ mResolveInfo = other.mResolveInfo;
+ mDisplayLabel = other.mDisplayLabel;
+ mDisplayIcon = other.mDisplayIcon;
+ mExtendedInfo = other.mExtendedInfo;
+ mResolvedIntent = new Intent(other.mResolvedIntent);
+ mResolvedIntent.fillIn(fillInIntent, flags);
+ }
+
public ResolveInfo getResolveInfo() {
return mResolveInfo;
}
@@ -866,6 +888,20 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
return mDisplayIcon;
}
+ @Override
+ public TargetInfo cloneFilledIn(Intent fillInIntent, int flags) {
+ return new DisplayResolveInfo(this, fillInIntent, flags);
+ }
+
+ @Override
+ public List<Intent> getAllSourceIntents() {
+ return mSourceIntents;
+ }
+
+ public void addAlternateSourceIntent(Intent alt) {
+ mSourceIntents.add(alt);
+ }
+
public void setDisplayIcon(Drawable icon) {
mDisplayIcon = icon;
}
@@ -986,6 +1022,16 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
* @return The drawable that should be used to represent this target
*/
public Drawable getDisplayIcon();
+
+ /**
+ * Clone this target with the given fill-in information.
+ */
+ public TargetInfo cloneFilledIn(Intent fillInIntent, int flags);
+
+ /**
+ * @return the list of supported source intents deduped against this single target
+ */
+ public List<Intent> getAllSourceIntents();
}
class ResolveListAdapter extends BaseAdapter {
@@ -998,8 +1044,8 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
protected final LayoutInflater mInflater;
- List<DisplayResolveInfo> mList;
- List<ResolveInfo> mOrigResolveList;
+ List<DisplayResolveInfo> mDisplayList;
+ List<ResolvedComponentInfo> mOrigResolveList;
private int mLastChosenPosition = -1;
private boolean mFilterLastUsed;
@@ -1010,7 +1056,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
mBaseResolveList = rList;
mLaunchedFromUid = launchedFromUid;
mInflater = LayoutInflater.from(context);
- mList = new ArrayList<>();
+ mDisplayList = new ArrayList<>();
mFilterLastUsed = filterLastUsed;
rebuildList();
}
@@ -1027,7 +1073,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
public DisplayResolveInfo getFilteredItem() {
if (mFilterLastUsed && mLastChosenPosition >= 0) {
// Not using getItem since it offsets to dodge this position for the list
- return mList.get(mLastChosenPosition);
+ return mDisplayList.get(mLastChosenPosition);
}
return null;
}
@@ -1048,11 +1094,12 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
}
private void rebuildList() {
- List<ResolveInfo> currentResolveList;
+ List<ResolvedComponentInfo> currentResolveList = null;
try {
+ final Intent primaryIntent = getTargetIntent();
mLastChosen = AppGlobals.getPackageManager().getLastChosenActivity(
- mIntent, mIntent.resolveTypeIfNeeded(getContentResolver()),
+ primaryIntent, primaryIntent.resolveTypeIfNeeded(getContentResolver()),
PackageManager.MATCH_DEFAULT_ONLY);
} catch (RemoteException re) {
Log.d(TAG, "Error calling setLastChosenActivity\n" + re);
@@ -1060,15 +1107,27 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
// Clear the value of mOtherProfile from previous call.
mOtherProfile = null;
- mList.clear();
+ mDisplayList.clear();
if (mBaseResolveList != null) {
- currentResolveList = mOrigResolveList = mBaseResolveList;
+ currentResolveList = mOrigResolveList = new ArrayList<>();
+ addResolveListDedupe(currentResolveList, getTargetIntent(), mBaseResolveList);
} else {
- currentResolveList = mOrigResolveList = mPm.queryIntentActivities(mIntent,
- PackageManager.MATCH_DEFAULT_ONLY
- | (shouldGetResolvedFilter() ? PackageManager.GET_RESOLVED_FILTER : 0)
- | (shouldGetActivityMetadata() ? PackageManager.GET_META_DATA : 0)
- );
+ final boolean shouldGetResolvedFilter = shouldGetResolvedFilter();
+ final boolean shouldGetActivityMetadata = shouldGetActivityMetadata();
+ for (int i = 0, N = mIntents.size(); i < N; i++) {
+ final Intent intent = mIntents.get(i);
+ final List<ResolveInfo> infos = mPm.queryIntentActivities(intent,
+ PackageManager.MATCH_DEFAULT_ONLY
+ | (shouldGetResolvedFilter ? PackageManager.GET_RESOLVED_FILTER : 0)
+ | (shouldGetActivityMetadata ? PackageManager.GET_META_DATA : 0));
+ if (infos != null) {
+ if (currentResolveList == null) {
+ currentResolveList = mOrigResolveList = new ArrayList<>();
+ }
+ addResolveListDedupe(currentResolveList, intent, infos);
+ }
+ }
+
// Filter out any activities that the launched uid does not
// have permission for. We don't do this when we have an explicit
// list of resolved activities, because that only happens when
@@ -1076,14 +1135,15 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
// they gave us.
if (currentResolveList != null) {
for (int i=currentResolveList.size()-1; i >= 0; i--) {
- ActivityInfo ai = currentResolveList.get(i).activityInfo;
+ ActivityInfo ai = currentResolveList.get(i)
+ .getResolveInfoAt(0).activityInfo;
int granted = ActivityManager.checkComponentPermission(
ai.permission, mLaunchedFromUid,
ai.applicationInfo.uid, ai.exported);
if (granted != PackageManager.PERMISSION_GRANTED) {
// Access not allowed!
if (mOrigResolveList == currentResolveList) {
- mOrigResolveList = new ArrayList<ResolveInfo>(mOrigResolveList);
+ mOrigResolveList = new ArrayList<>(mOrigResolveList);
}
currentResolveList.remove(i);
}
@@ -1094,9 +1154,10 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
if ((currentResolveList != null) && ((N = currentResolveList.size()) > 0)) {
// Only display the first matches that are either of equal
// priority or have asked to be default options.
- ResolveInfo r0 = currentResolveList.get(0);
+ ResolvedComponentInfo rci0 = currentResolveList.get(0);
+ ResolveInfo r0 = rci0.getResolveInfoAt(0);
for (int i=1; i<N; i++) {
- ResolveInfo ri = currentResolveList.get(i);
+ ResolveInfo ri = currentResolveList.get(i).getResolveInfoAt(0);
if (DEBUG) Log.v(
TAG,
r0.activityInfo.name + "=" +
@@ -1107,7 +1168,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
r0.isDefault != ri.isDefault) {
while (i < N) {
if (mOrigResolveList == currentResolveList) {
- mOrigResolveList = new ArrayList<ResolveInfo>(mOrigResolveList);
+ mOrigResolveList = new ArrayList<>(mOrigResolveList);
}
currentResolveList.remove(i);
N--;
@@ -1115,9 +1176,8 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
}
}
if (N > 1) {
- Comparator<ResolveInfo> rComparator =
- new ResolverComparator(ResolverActivity.this, mIntent);
- Collections.sort(currentResolveList, rComparator);
+ Collections.sort(currentResolveList,
+ new ResolverComparator(ResolverActivity.this, getTargetIntent()));
}
// First put the initial items at the top.
if (mInitialIntents != null) {
@@ -1146,14 +1206,15 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
ri.nonLocalizedLabel = li.getNonLocalizedLabel();
ri.icon = li.getIconResource();
}
- addResolveInfo(new DisplayResolveInfo(ri,
+ addResolveInfo(new DisplayResolveInfo(ii, ri,
ri.loadLabel(getPackageManager()), null, ii));
}
}
// Check for applications with same name and use application name or
// package name if necessary
- r0 = currentResolveList.get(0);
+ rci0 = currentResolveList.get(0);
+ r0 = rci0.getResolveInfoAt(0);
int start = 0;
CharSequence r0Label = r0.loadLabel(mPm);
mHasExtendedInfo = false;
@@ -1161,7 +1222,8 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
if (r0Label == null) {
r0Label = r0.activityInfo.packageName;
}
- ResolveInfo ri = currentResolveList.get(i);
+ ResolvedComponentInfo rci = currentResolveList.get(i);
+ ResolveInfo ri = rci.getResolveInfoAt(0);
CharSequence riLabel = ri.loadLabel(mPm);
if (riLabel == null) {
riLabel = ri.activityInfo.packageName;
@@ -1169,13 +1231,14 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
if (riLabel.equals(r0Label)) {
continue;
}
- processGroup(currentResolveList, start, (i-1), r0, r0Label);
+ processGroup(currentResolveList, start, (i-1), rci0, r0Label);
+ rci0 = rci;
r0 = ri;
r0Label = riLabel;
start = i;
}
// Process last group
- processGroup(currentResolveList, start, (N-1), r0, r0Label);
+ processGroup(currentResolveList, start, (N-1), rci0, r0Label);
}
// Layout doesn't handle both profile button and last chosen
@@ -1188,6 +1251,36 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
onListRebuilt();
}
+ private void addResolveListDedupe(List<ResolvedComponentInfo> into, Intent intent,
+ List<ResolveInfo> from) {
+ final int fromCount = from.size();
+ final int intoCount = into.size();
+ for (int i = 0; i < fromCount; i++) {
+ final ResolveInfo newInfo = from.get(i);
+ boolean found = false;
+ // Only loop to the end of into as it was before we started; no dupes in from.
+ for (int j = 0; j < intoCount; j++) {
+ final ResolvedComponentInfo rci = into.get(i);
+ if (isSameResolvedComponent(newInfo, rci)) {
+ found = true;
+ rci.add(intent, newInfo);
+ break;
+ }
+ }
+ if (!found) {
+ into.add(new ResolvedComponentInfo(new ComponentName(
+ newInfo.activityInfo.packageName, newInfo.activityInfo.name),
+ intent, newInfo));
+ }
+ }
+ }
+
+ private boolean isSameResolvedComponent(ResolveInfo a, ResolvedComponentInfo b) {
+ final ActivityInfo ai = a.activityInfo;
+ return ai.packageName.equals(b.name.getPackageName())
+ && ai.name.equals(b.name.getClassName());
+ }
+
public void onListRebuilt() {
// This space for rent
}
@@ -1196,18 +1289,18 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
return mFilterLastUsed;
}
- private void processGroup(List<ResolveInfo> rList, int start, int end, ResolveInfo ro,
- CharSequence roLabel) {
+ private void processGroup(List<ResolvedComponentInfo> rList, int start, int end,
+ ResolvedComponentInfo ro, CharSequence roLabel) {
// Process labels from start to i
int num = end - start+1;
if (num == 1) {
// No duplicate labels. Use label for entry at start
- addResolveInfo(new DisplayResolveInfo(ro, roLabel, null, null));
- updateLastChosenPosition(ro);
+ addResolveInfoWithAlternates(ro, null, roLabel);
} else {
mHasExtendedInfo = true;
boolean usePkg = false;
- CharSequence startApp = ro.activityInfo.applicationInfo.loadLabel(mPm);
+ CharSequence startApp = ro.getResolveInfoAt(0).activityInfo.applicationInfo
+ .loadLabel(mPm);
if (startApp == null) {
usePkg = true;
}
@@ -1217,7 +1310,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
new HashSet<CharSequence>();
duplicates.add(startApp);
for (int j = start+1; j <= end ; j++) {
- ResolveInfo jRi = rList.get(j);
+ ResolveInfo jRi = rList.get(j).getResolveInfoAt(0);
CharSequence jApp = jRi.activityInfo.applicationInfo.loadLabel(mPm);
if ( (jApp == null) || (duplicates.contains(jApp))) {
usePkg = true;
@@ -1230,26 +1323,46 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
duplicates.clear();
}
for (int k = start; k <= end; k++) {
- ResolveInfo add = rList.get(k);
+ final ResolvedComponentInfo rci = rList.get(k);
+ final ResolveInfo add = rci.getResolveInfoAt(0);
+ final CharSequence extraInfo;
if (usePkg) {
- // Use application name for all entries from start to end-1
- addResolveInfo(new DisplayResolveInfo(add, roLabel,
- add.activityInfo.packageName, null));
- } else {
// Use package name for all entries from start to end-1
- addResolveInfo(new DisplayResolveInfo(add, roLabel,
- add.activityInfo.applicationInfo.loadLabel(mPm), null));
+ extraInfo = add.activityInfo.packageName;
+ } else {
+ // Use application name for all entries from start to end-1
+ extraInfo = add.activityInfo.applicationInfo.loadLabel(mPm);
}
- updateLastChosenPosition(add);
+ addResolveInfoWithAlternates(rci, extraInfo, roLabel);
+ }
+ }
+ }
+
+ private void addResolveInfoWithAlternates(ResolvedComponentInfo rci,
+ CharSequence extraInfo, CharSequence roLabel) {
+ final int count = rci.getCount();
+ final Intent intent = rci.getIntentAt(0);
+ final ResolveInfo add = rci.getResolveInfoAt(0);
+ final Intent replaceIntent = getReplacementIntent(add.activityInfo, intent);
+ final DisplayResolveInfo dri = new DisplayResolveInfo(intent, add, roLabel,
+ extraInfo, replaceIntent);
+ addResolveInfo(dri);
+ if (replaceIntent == intent) {
+ // Only add alternates if we didn't get a specific replacement from
+ // the caller. If we have one it trumps potential alternates.
+ for (int i = 1, N = count; i < N; i++) {
+ final Intent altIntent = rci.getIntentAt(i);
+ dri.addAlternateSourceIntent(altIntent);
}
}
+ updateLastChosenPosition(add);
}
private void updateLastChosenPosition(ResolveInfo info) {
if (mLastChosen != null
&& mLastChosen.activityInfo.packageName.equals(info.activityInfo.packageName)
&& mLastChosen.activityInfo.name.equals(info.activityInfo.name)) {
- mLastChosenPosition = mList.size() - 1;
+ mLastChosenPosition = mDisplayList.size() - 1;
}
}
@@ -1259,20 +1372,21 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
// The first one we see gets special treatment.
mOtherProfile = dri;
} else {
- mList.add(dri);
+ mDisplayList.add(dri);
}
}
public ResolveInfo resolveInfoForPosition(int position, boolean filtered) {
- return (filtered ? getItem(position) : mList.get(position)).getResolveInfo();
+ return (filtered ? getItem(position) : mDisplayList.get(position))
+ .getResolveInfo();
}
public TargetInfo targetInfoForPosition(int position, boolean filtered) {
- return filtered ? getItem(position) : mList.get(position);
+ return filtered ? getItem(position) : mDisplayList.get(position);
}
public int getCount() {
- int result = mList.size();
+ int result = mDisplayList.size();
if (mFilterLastUsed && mLastChosenPosition >= 0) {
result--;
}
@@ -1283,7 +1397,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
if (mFilterLastUsed && mLastChosenPosition >= 0 && position >= mLastChosenPosition) {
position++;
}
- return mList.get(position);
+ return mDisplayList.get(position);
}
public long getItemId(int position) {
@@ -1295,8 +1409,8 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
}
public boolean hasResolvedTarget(ResolveInfo info) {
- for (int i = 0, N = mList.size(); i < N; i++) {
- if (info.equals(mList.get(i).getResolveInfo())) {
+ for (int i = 0, N = mDisplayList.size(); i < N; i++) {
+ if (info.equals(mDisplayList.get(i).getResolveInfo())) {
return true;
}
}
@@ -1304,11 +1418,12 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
}
protected int getDisplayResolveInfoCount() {
- return mList.size();
+ return mDisplayList.size();
}
protected DisplayResolveInfo getDisplayResolveInfo(int index) {
- return mList.get(index);
+ // Used to query services. We only query services for primary targets, not alternates.
+ return mDisplayList.get(index);
}
public final View getView(int position, View convertView, ViewGroup parent) {
@@ -1349,6 +1464,52 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
}
}
+ static final class ResolvedComponentInfo {
+ public final ComponentName name;
+ private final List<Intent> mIntents = new ArrayList<>();
+ private final List<ResolveInfo> mResolveInfos = new ArrayList<>();
+
+ public ResolvedComponentInfo(ComponentName name, Intent intent, ResolveInfo info) {
+ this.name = name;
+ add(intent, info);
+ }
+
+ public void add(Intent intent, ResolveInfo info) {
+ mIntents.add(intent);
+ mResolveInfos.add(info);
+ }
+
+ public int getCount() {
+ return mIntents.size();
+ }
+
+ public Intent getIntentAt(int index) {
+ return index >= 0 ? mIntents.get(index) : null;
+ }
+
+ public ResolveInfo getResolveInfoAt(int index) {
+ return index >= 0 ? mResolveInfos.get(index) : null;
+ }
+
+ public int findIntent(Intent intent) {
+ for (int i = 0, N = mIntents.size(); i < N; i++) {
+ if (intent.equals(mIntents.get(i))) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public int findResolveInfo(ResolveInfo info) {
+ for (int i = 0, N = mResolveInfos.size(); i < N; i++) {
+ if (info.equals(mResolveInfos.get(i))) {
+ return i;
+ }
+ }
+ return -1;
+ }
+ }
+
static class ViewHolder {
public TextView text;
public TextView text2;
@@ -1435,7 +1596,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
&& match <= IntentFilter.MATCH_CATEGORY_PATH;
}
- class ResolverComparator implements Comparator<ResolveInfo> {
+ class ResolverComparator implements Comparator<ResolvedComponentInfo> {
private final Collator mCollator;
private final boolean mHttp;
@@ -1446,7 +1607,10 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
}
@Override
- public int compare(ResolveInfo lhs, ResolveInfo rhs) {
+ public int compare(ResolvedComponentInfo lhsp, ResolvedComponentInfo rhsp) {
+ final ResolveInfo lhs = lhsp.getResolveInfoAt(0);
+ final ResolveInfo rhs = rhsp.getResolveInfoAt(0);
+
// We want to put the one targeted to another user at the end of the dialog.
if (lhs.targetUserId != UserHandle.USER_CURRENT) {
return 1;
@@ -1487,7 +1651,6 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
if (stats != null) {
return stats.getTotalTimeInForeground();
}
-
}
return 0;
}
diff --git a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
index 52485dd..ce94727 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
@@ -196,7 +196,7 @@ public class InputMethodSubtypeSwitchingController {
}
public List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeList(
- boolean showSubtypes, boolean inputShown, boolean isScreenLocked) {
+ boolean showSubtypes, boolean includeAuxiliarySubtypes, boolean isScreenLocked) {
final ArrayList<ImeSubtypeListItem> imList =
new ArrayList<ImeSubtypeListItem>();
final HashMap<InputMethodInfo, List<InputMethodSubtype>> immis =
@@ -205,6 +205,12 @@ public class InputMethodSubtypeSwitchingController {
if (immis == null || immis.size() == 0) {
return Collections.emptyList();
}
+ if (isScreenLocked && includeAuxiliarySubtypes) {
+ if (DEBUG) {
+ Slog.w(TAG, "Auxiliary subtypes are not allowed to be shown in lock screen.");
+ }
+ includeAuxiliarySubtypes = false;
+ }
mSortedImmis.clear();
mSortedImmis.putAll(immis);
for (InputMethodInfo imi : mSortedImmis.keySet()) {
@@ -227,7 +233,7 @@ public class InputMethodSubtypeSwitchingController {
final String subtypeHashCode = String.valueOf(subtype.hashCode());
// We show all enabled IMEs and subtypes when an IME is shown.
if (enabledSubtypeSet.contains(subtypeHashCode)
- && ((inputShown && !isScreenLocked) || !subtype.isAuxiliary())) {
+ && (includeAuxiliarySubtypes || !subtype.isAuxiliary())) {
final CharSequence subtypeLabel =
subtype.overridesImplicitlyEnabledSubtype() ? null : subtype
.getDisplayName(mContext, imi.getPackageName(),
@@ -516,8 +522,8 @@ public class InputMethodSubtypeSwitchingController {
}
public List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeListLocked(boolean showSubtypes,
- boolean inputShown, boolean isScreenLocked) {
+ boolean includingAuxiliarySubtypes, boolean isScreenLocked) {
return mSubtypeList.getSortedInputMethodAndSubtypeList(
- showSubtypes, inputShown, isScreenLocked);
+ showSubtypes, includingAuxiliarySubtypes, isScreenLocked);
}
}
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 6f104dd..60c5e42 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -59,7 +59,8 @@ interface IInputMethodManager {
int controlFlags, int softInputMode, int windowFlags,
in EditorInfo attribute, IInputContext inputContext);
- void showInputMethodPickerFromClient(in IInputMethodClient client);
+ void showInputMethodPickerFromClient(in IInputMethodClient client,
+ int auxiliarySubtypeMode);
void showInputMethodAndSubtypeEnablerFromClient(in IInputMethodClient client, String topId);
void setInputMethod(in IBinder token, String id);
void setInputMethodAndSubtype(in IBinder token, String id, in InputMethodSubtype subtype);
diff --git a/core/java/com/android/internal/widget/ButtonBarLayout.java b/core/java/com/android/internal/widget/ButtonBarLayout.java
index 64e6c69..f58ab03 100644
--- a/core/java/com/android/internal/widget/ButtonBarLayout.java
+++ b/core/java/com/android/internal/widget/ButtonBarLayout.java
@@ -17,6 +17,7 @@
package com.android.internal.widget;
import android.content.Context;
+import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
@@ -29,37 +30,39 @@ import com.android.internal.R;
* orientation when it can't fit its child views horizontally.
*/
public class ButtonBarLayout extends LinearLayout {
- /** Spacer used in horizontal orientation. */
- private final View mSpacer;
-
/** Whether the current configuration allows stacking. */
- private final boolean mAllowStacked;
+ private final boolean mAllowStacking;
/** Whether the layout is currently stacked. */
private boolean mStacked;
+ private int mLastWidthSize = -1;
+
public ButtonBarLayout(Context context, AttributeSet attrs) {
super(context, attrs);
- mAllowStacked = context.getResources().getBoolean(R.bool.allow_stacked_button_bar);
- mSpacer = findViewById(R.id.spacer);
+ final TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ButtonBarLayout);
+ mAllowStacking = ta.getBoolean(R.styleable.ButtonBarLayout_allowStacking, false);
+ ta.recycle();
+
+ mStacked = getOrientation() == VERTICAL;
}
@Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ if (mAllowStacking) {
+ final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+ if (widthSize > mLastWidthSize && mStacked) {
+ // We're being measured wider this time, try un-stacking.
+ setStacked(false);
+ }
- // Maybe we can fit the content now?
- if (w > oldw && mStacked) {
- setStacked(false);
+ mLastWidthSize = widthSize;
}
- }
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- if (mAllowStacked && getOrientation() == LinearLayout.HORIZONTAL) {
+ if (mAllowStacking && !mStacked) {
final int measuredWidth = getMeasuredWidthAndState();
final int measuredWidthState = measuredWidth & MEASURED_STATE_MASK;
if (measuredWidthState == MEASURED_STATE_TOO_SMALL) {
@@ -75,8 +78,9 @@ public class ButtonBarLayout extends LinearLayout {
setOrientation(stacked ? LinearLayout.VERTICAL : LinearLayout.HORIZONTAL);
setGravity(stacked ? Gravity.RIGHT : Gravity.BOTTOM);
- if (mSpacer != null) {
- mSpacer.setVisibility(stacked ? View.GONE : View.INVISIBLE);
+ final View spacer = findViewById(R.id.spacer);
+ if (spacer != null) {
+ spacer.setVisibility(stacked ? View.GONE : View.INVISIBLE);
}
// Reverse the child order. This is specific to the Material button
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index bbdd860..5448214 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -132,6 +132,7 @@ LOCAL_SRC_FILES:= \
android_media_AudioRecord.cpp \
android_media_AudioSystem.cpp \
android_media_AudioTrack.cpp \
+ android_media_DeviceCallback.cpp \
android_media_JetPlayer.cpp \
android_media_RemoteDisplay.cpp \
android_media_ToneGenerator.cpp \
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 8b65fd1..87b81d5 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -30,6 +30,7 @@
#include "android_media_AudioFormat.h"
#include "android_media_AudioErrors.h"
+#include "android_media_DeviceCallback.h"
// ----------------------------------------------------------------------------
@@ -44,6 +45,7 @@ struct audio_record_fields_t {
jmethodID postNativeEventInJava; //... event post callback method
jfieldID nativeRecorderInJavaObj; // provides access to the C++ AudioRecord object
jfieldID nativeCallbackCookie; // provides access to the AudioRecord callback data
+ jfieldID nativeDeviceCallback; // provides access to the JNIDeviceCallback instance
};
struct audio_attributes_fields_t {
jfieldID fieldRecSource; // AudioAttributes.mSource
@@ -120,6 +122,33 @@ static void recorderCallback(int event, void* user, void *info) {
}
}
+static sp<JNIDeviceCallback> getJniDeviceCallback(JNIEnv* env, jobject thiz)
+{
+ Mutex::Autolock l(sLock);
+ JNIDeviceCallback* const cb =
+ (JNIDeviceCallback*)env->GetLongField(thiz,
+ javaAudioRecordFields.nativeDeviceCallback);
+ return sp<JNIDeviceCallback>(cb);
+}
+
+static sp<JNIDeviceCallback> setJniDeviceCallback(JNIEnv* env,
+ jobject thiz,
+ const sp<JNIDeviceCallback>& cb)
+{
+ Mutex::Autolock l(sLock);
+ sp<JNIDeviceCallback> old =
+ (JNIDeviceCallback*)env->GetLongField(thiz,
+ javaAudioRecordFields.nativeDeviceCallback);
+ if (cb.get()) {
+ cb->incStrong((void*)setJniDeviceCallback);
+ }
+ if (old != 0) {
+ old->decStrong((void*)setJniDeviceCallback);
+ }
+ env->SetLongField(thiz, javaAudioRecordFields.nativeDeviceCallback, (jlong)cb.get());
+ return old;
+}
+
// ----------------------------------------------------------------------------
static sp<AudioRecord> getAudioRecord(JNIEnv* env, jobject thiz)
{
@@ -593,9 +622,63 @@ static jboolean android_media_AudioRecord_setInputDevice(
JNIEnv *env, jobject thiz, jint device_id) {
sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
+ if (lpRecorder == 0) {
+ return 0;
+ }
return lpRecorder->setInputDevice(device_id) == NO_ERROR;
}
+static jint android_media_AudioRecord_getRoutedDeviceId(
+ JNIEnv *env, jobject thiz) {
+
+ sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
+ if (lpRecorder == 0) {
+ return 0;
+ }
+ return (jint)lpRecorder->getRoutedDeviceId();
+}
+
+static void android_media_AudioRecord_enableDeviceCallback(
+ JNIEnv *env, jobject thiz) {
+
+ sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
+ if (lpRecorder == 0) {
+ return;
+ }
+ sp<JNIDeviceCallback> cb = getJniDeviceCallback(env, thiz);
+ if (cb != 0) {
+ return;
+ }
+ audiorecord_callback_cookie *cookie =
+ (audiorecord_callback_cookie *)env->GetLongField(thiz,
+ javaAudioRecordFields.nativeCallbackCookie);
+ if (cookie == NULL) {
+ return;
+ }
+
+ cb = new JNIDeviceCallback(env, thiz, cookie->audioRecord_ref,
+ javaAudioRecordFields.postNativeEventInJava);
+ status_t status = lpRecorder->addAudioDeviceCallback(cb);
+ if (status == NO_ERROR) {
+ setJniDeviceCallback(env, thiz, cb);
+ }
+}
+
+static void android_media_AudioRecord_disableDeviceCallback(
+ JNIEnv *env, jobject thiz) {
+
+ sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
+ if (lpRecorder == 0) {
+ return;
+ }
+ sp<JNIDeviceCallback> cb = setJniDeviceCallback(env, thiz, 0);
+ if (cb != 0) {
+ lpRecorder->removeAudioDeviceCallback(cb);
+ }
+}
+
+
+
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
static JNINativeMethod gMethods[] = {
@@ -628,12 +711,17 @@ static JNINativeMethod gMethods[] = {
{"native_get_min_buff_size",
"(III)I", (void *)android_media_AudioRecord_get_min_buff_size},
{"native_setInputDevice", "(I)Z", (void *)android_media_AudioRecord_setInputDevice},
+ {"native_getRoutedDeviceId", "()I", (void *)android_media_AudioRecord_getRoutedDeviceId},
+ {"native_enableDeviceCallback", "()V", (void *)android_media_AudioRecord_enableDeviceCallback},
+ {"native_disableDeviceCallback", "()V",
+ (void *)android_media_AudioRecord_disableDeviceCallback},
};
// field names found in android/media/AudioRecord.java
#define JAVA_POSTEVENT_CALLBACK_NAME "postEventFromNative"
#define JAVA_NATIVERECORDERINJAVAOBJ_FIELD_NAME "mNativeRecorderInJavaObj"
#define JAVA_NATIVECALLBACKINFO_FIELD_NAME "mNativeCallbackCookie"
+#define JAVA_NATIVEDEVICECALLBACK_FIELD_NAME "mNativeDeviceCallback"
// ----------------------------------------------------------------------------
int register_android_media_AudioRecord(JNIEnv *env)
@@ -641,6 +729,7 @@ int register_android_media_AudioRecord(JNIEnv *env)
javaAudioRecordFields.postNativeEventInJava = NULL;
javaAudioRecordFields.nativeRecorderInJavaObj = NULL;
javaAudioRecordFields.nativeCallbackCookie = NULL;
+ javaAudioRecordFields.nativeDeviceCallback = NULL;
// Get the AudioRecord class
@@ -658,6 +747,9 @@ int register_android_media_AudioRecord(JNIEnv *env)
javaAudioRecordFields.nativeCallbackCookie = GetFieldIDOrDie(env,
audioRecordClass, JAVA_NATIVECALLBACKINFO_FIELD_NAME, "J");
+ javaAudioRecordFields.nativeDeviceCallback = GetFieldIDOrDie(env,
+ audioRecordClass, JAVA_NATIVEDEVICECALLBACK_FIELD_NAME, "J");
+
// Get the AudioAttributes class and fields
jclass audioAttrClass = FindClassOrDie(env, kAudioAttributesClassPathName);
javaAudioAttrFields.fieldRecSource = GetFieldIDOrDie(env, audioAttrClass, "mSource", "I");
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 3655adc..eab5668 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -937,7 +937,8 @@ static jint convertAudioPortFromNative(JNIEnv *env,
} else if (nAudioPort->type == AUDIO_PORT_TYPE_MIX) {
ALOGV("convertAudioPortFromNative is a mix");
*jAudioPort = env->NewObject(gAudioMixPortClass, gAudioMixPortCstor,
- jHandle, nAudioPort->role, jDeviceName,
+ jHandle, nAudioPort->ext.mix.handle,
+ nAudioPort->role, jDeviceName,
jSamplingRates, jChannelMasks,
jFormats, jGains);
} else {
@@ -1670,7 +1671,7 @@ int register_android_media_AudioSystem(JNIEnv *env)
jclass audioMixPortClass = FindClassOrDie(env, "android/media/AudioMixPort");
gAudioMixPortClass = MakeGlobalRefOrDie(env, audioMixPortClass);
gAudioMixPortCstor = GetMethodIDOrDie(env, audioMixPortClass, "<init>",
- "(Landroid/media/AudioHandle;ILjava/lang/String;[I[I[I[Landroid/media/AudioGain;)V");
+ "(Landroid/media/AudioHandle;IILjava/lang/String;[I[I[I[Landroid/media/AudioGain;)V");
jclass audioGainClass = FindClassOrDie(env, "android/media/AudioGain");
gAudioGainClass = MakeGlobalRefOrDie(env, audioGainClass);
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 26b82c5..662ecd3 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -36,6 +36,7 @@
#include "android_media_AudioFormat.h"
#include "android_media_AudioErrors.h"
#include "android_media_PlaybackSettings.h"
+#include "android_media_DeviceCallback.h"
// ----------------------------------------------------------------------------
@@ -79,6 +80,7 @@ class AudioTrackJniStorage {
sp<MemoryHeapBase> mMemHeap;
sp<MemoryBase> mMemBase;
audiotrack_callback_cookie mCallbackData;
+ sp<JNIDeviceCallback> mDeviceCallback;
AudioTrackJniStorage() {
mCallbackData.audioTrack_class = 0;
@@ -977,6 +979,51 @@ static jboolean android_media_AudioTrack_setOutputDevice(
return lpTrack->setOutputDevice(device_id) == NO_ERROR;
}
+static jint android_media_AudioTrack_getRoutedDeviceId(
+ JNIEnv *env, jobject thiz) {
+
+ sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
+ if (lpTrack == NULL) {
+ return 0;
+ }
+ return (jint)lpTrack->getRoutedDeviceId();
+}
+
+static void android_media_AudioTrack_enableDeviceCallback(
+ JNIEnv *env, jobject thiz) {
+
+ sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
+ if (lpTrack == NULL) {
+ return;
+ }
+ AudioTrackJniStorage* pJniStorage = (AudioTrackJniStorage *)env->GetLongField(
+ thiz, javaAudioTrackFields.jniData);
+ if (pJniStorage == NULL || pJniStorage->mDeviceCallback != 0) {
+ return;
+ }
+ pJniStorage->mDeviceCallback =
+ new JNIDeviceCallback(env, thiz, pJniStorage->mCallbackData.audioTrack_ref,
+ javaAudioTrackFields.postNativeEventInJava);
+ lpTrack->addAudioDeviceCallback(pJniStorage->mDeviceCallback);
+}
+
+static void android_media_AudioTrack_disableDeviceCallback(
+ JNIEnv *env, jobject thiz) {
+
+ sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
+ if (lpTrack == NULL) {
+ return;
+ }
+ AudioTrackJniStorage* pJniStorage = (AudioTrackJniStorage *)env->GetLongField(
+ thiz, javaAudioTrackFields.jniData);
+ if (pJniStorage == NULL || pJniStorage->mDeviceCallback == 0) {
+ return;
+ }
+ lpTrack->removeAudioDeviceCallback(pJniStorage->mDeviceCallback);
+ pJniStorage->mDeviceCallback.clear();
+}
+
+
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
static JNINativeMethod gMethods[] = {
@@ -1030,6 +1077,9 @@ static JNINativeMethod gMethods[] = {
"(I)I", (void *)android_media_AudioTrack_attachAuxEffect},
{"native_setOutputDevice", "(I)Z",
(void *)android_media_AudioTrack_setOutputDevice},
+ {"native_getRoutedDeviceId", "()I", (void *)android_media_AudioTrack_getRoutedDeviceId},
+ {"native_enableDeviceCallback", "()V", (void *)android_media_AudioTrack_enableDeviceCallback},
+ {"native_disableDeviceCallback", "()V", (void *)android_media_AudioTrack_disableDeviceCallback},
};
diff --git a/core/jni/android_media_DeviceCallback.cpp b/core/jni/android_media_DeviceCallback.cpp
new file mode 100644
index 0000000..e159373
--- /dev/null
+++ b/core/jni/android_media_DeviceCallback.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+//#define LOG_NDEBUG 0
+
+#define LOG_TAG "AudioDeviceCallback-JNI"
+
+#include <utils/Log.h>
+#include <JNIHelp.h>
+#include <JniConstants.h>
+#include "core_jni_helpers.h"
+#include <media/AudioSystem.h>
+
+#include "android_media_DeviceCallback.h"
+
+
+// ----------------------------------------------------------------------------
+
+using namespace android;
+
+JNIDeviceCallback::JNIDeviceCallback(JNIEnv* env, jobject thiz, jobject weak_thiz,
+ jmethodID postEventFromNative)
+{
+
+ // Hold onto the AudioTrack/AudioRecord class for use in calling the static method
+ // that posts events to the application thread.
+ jclass clazz = env->GetObjectClass(thiz);
+ if (clazz == NULL) {
+ return;
+ }
+ mClass = (jclass)env->NewGlobalRef(clazz);
+
+ // We use a weak reference so the AudioTrack/AudioRecord object can be garbage collected.
+ // The reference is only used as a proxy for callbacks.
+ mObject = env->NewGlobalRef(weak_thiz);
+
+ mPostEventFromNative = postEventFromNative;
+}
+
+JNIDeviceCallback::~JNIDeviceCallback()
+{
+ // remove global references
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ if (env == NULL) {
+ return;
+ }
+ env->DeleteGlobalRef(mObject);
+ env->DeleteGlobalRef(mClass);
+}
+
+void JNIDeviceCallback::onAudioDeviceUpdate(audio_io_handle_t audioIo,
+ audio_port_handle_t deviceId)
+{
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ if (env == NULL) {
+ return;
+ }
+
+ ALOGV("%s audioIo %d deviceId %d", __FUNCTION__, audioIo, deviceId);
+ env->CallStaticVoidMethod(mClass,
+ mPostEventFromNative,
+ mObject,
+ AUDIO_NATIVE_EVENT_ROUTING_CHANGE, deviceId, 0, NULL);
+ if (env->ExceptionCheck()) {
+ ALOGW("An exception occurred while notifying an event.");
+ env->ExceptionClear();
+ }
+}
+
diff --git a/core/jni/android_media_DeviceCallback.h b/core/jni/android_media_DeviceCallback.h
new file mode 100644
index 0000000..7ae788e
--- /dev/null
+++ b/core/jni/android_media_DeviceCallback.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ANDROID_MEDIA_DEVICE_CALLBACK_H
+#define ANDROID_MEDIA_DEVICE_CALLBACK_H
+
+#include <system/audio.h>
+#include <media/AudioSystem.h>
+
+namespace android {
+
+// keep in sync with AudioSystem.java
+#define AUDIO_NATIVE_EVENT_ROUTING_CHANGE 1000
+
+class JNIDeviceCallback: public AudioSystem::AudioDeviceCallback
+{
+public:
+ JNIDeviceCallback(JNIEnv* env, jobject thiz, jobject weak_thiz, jmethodID postEventFromNative);
+ ~JNIDeviceCallback();
+
+ virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo,
+ audio_port_handle_t deviceId);
+
+private:
+ void sendEvent(int event);
+
+ jclass mClass; // Reference to AudioTrack/AudioRecord class
+ jobject mObject; // Weak ref to AudioTrack/AudioRecord Java object to call on
+ jmethodID mPostEventFromNative; // postEventFromNative method ID.
+};
+
+}; // namespace android
+
+#endif // ANDROID_MEDIA_DEVICE_CALLBACK_H
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a162b4a..e3930cd 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2451,7 +2451,8 @@
android:backupAgent="com.android.server.backup.SystemBackupAgent"
android:killAfterRestore="false"
android:icon="@drawable/ic_launcher_android"
- android:supportsRtl="true">
+ android:supportsRtl="true"
+ android:theme="@style/Theme.Material.DayNight.DarkActionBar">
<activity android:name="com.android.internal.app.ChooserActivity"
android:theme="@style/Theme.DeviceDefault.Resolver"
android:finishOnCloseSystemDialogs="true"
@@ -2484,7 +2485,7 @@
android:label="@string/managed_profile_label">
</activity-alias>
<activity android:name="com.android.internal.app.HeavyWeightSwitcherActivity"
- android:theme="@style/Theme.Material.Light.Dialog"
+ android:theme="@style/Theme.Material.DayNight.Dialog"
android:label="@string/heavy_weight_switcher_title"
android:finishOnCloseSystemDialogs="true"
android:excludeFromRecents="true"
@@ -2517,7 +2518,7 @@
<activity android:name="android.accounts.ChooseAccountActivity"
android:excludeFromRecents="true"
android:exported="true"
- android:theme="@style/Theme.Material.Light.Dialog"
+ android:theme="@style/Theme.Material.DayNight.Dialog"
android:label="@string/choose_account_label"
android:process=":ui">
</activity>
@@ -2525,14 +2526,14 @@
<activity android:name="android.accounts.ChooseTypeAndAccountActivity"
android:excludeFromRecents="true"
android:exported="true"
- android:theme="@style/Theme.Material.Light.Dialog"
+ android:theme="@style/Theme.Material.DayNight.Dialog"
android:label="@string/choose_account_label"
android:process=":ui">
</activity>
<activity android:name="android.accounts.ChooseAccountTypeActivity"
android:excludeFromRecents="true"
- android:theme="@style/Theme.Material.Light.Dialog"
+ android:theme="@style/Theme.Material.DayNight.Dialog"
android:label="@string/choose_account_label"
android:process=":ui">
</activity>
@@ -2540,19 +2541,19 @@
<activity android:name="android.accounts.CantAddAccountActivity"
android:excludeFromRecents="true"
android:exported="true"
- android:theme="@style/Theme.Material.Light.Dialog.NoActionBar"
+ android:theme="@style/Theme.Material.DayNight.Dialog.NoActionBar"
android:process=":ui">
</activity>
<activity android:name="android.accounts.GrantCredentialsPermissionActivity"
android:excludeFromRecents="true"
android:exported="true"
- android:theme="@style/Theme.Material.Light.DialogWhenLarge"
+ android:theme="@style/Theme.Material.DayNight.DialogWhenLarge"
android:process=":ui">
</activity>
<activity android:name="android.content.SyncActivityTooManyDeletes"
- android:theme="@style/Theme.Material.Light.Dialog"
+ android:theme="@style/Theme.Material.DayNight.Dialog"
android:label="@string/sync_too_many_deletes"
android:process=":ui">
</activity>
@@ -2572,13 +2573,13 @@
</activity>
<activity android:name="com.android.internal.app.NetInitiatedActivity"
- android:theme="@style/Theme.Material.Light.Dialog.Alert"
+ android:theme="@style/Theme.Material.DayNight.Dialog.Alert"
android:excludeFromRecents="true"
android:process=":ui">
</activity>
<activity android:name="com.android.internal.app.RestrictionsPinActivity"
- android:theme="@style/Theme.Material.Light.Dialog.Alert"
+ android:theme="@style/Theme.Material.DayNight.Dialog.Alert"
android:excludeFromRecents="true"
android:windowSoftInputMode="adjustPan"
android:process=":ui">
diff --git a/core/res/res/drawable/scroll_indicator_material.xml b/core/res/res/drawable/scroll_indicator_material.xml
new file mode 100644
index 0000000..63cd584
--- /dev/null
+++ b/core/res/res/drawable/scroll_indicator_material.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:tint="?attr/colorForeground">
+ <solid android:color="#1f000000" />
+ <size
+ android:height="1dp"
+ android:width="1dp" />
+</shape>
diff --git a/core/res/res/layout/alert_dialog_button_bar_material.xml b/core/res/res/layout/alert_dialog_button_bar_material.xml
index 1eea4e1..6e102f3 100644
--- a/core/res/res/layout/alert_dialog_button_bar_material.xml
+++ b/core/res/res/layout/alert_dialog_button_bar_material.xml
@@ -27,6 +27,7 @@
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:gravity="bottom"
+ android:allowStacking="@bool/allow_stacked_button_bar"
style="?attr/buttonBarStyle">
<Button
@@ -53,4 +54,4 @@
style="?attr/buttonBarPositiveButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
-</com.android.internal.widget.ButtonBarLayout> \ No newline at end of file
+</com.android.internal.widget.ButtonBarLayout>
diff --git a/core/res/res/layout/alert_dialog_material.xml b/core/res/res/layout/alert_dialog_material.xml
index bf1e383..95c2459 100644
--- a/core/res/res/layout/alert_dialog_material.xml
+++ b/core/res/res/layout/alert_dialog_material.xml
@@ -24,52 +24,51 @@
<include layout="@layout/alert_dialog_title_material" />
- <FrameLayout android:id="@+id/contentPanel"
+ <FrameLayout
+ android:id="@+id/contentPanel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:minHeight="48dp">
- <View android:id="@+id/scrollIndicatorUp"
- android:visibility="gone"
- android:layout_width="match_parent"
- android:layout_height="1dp"
- android:layout_gravity="top"
- android:background="@drawable/list_divider_material"/>
- <ScrollView android:id="@+id/scrollView"
+
+ <ScrollView
+ android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:paddingTop="@dimen/dialog_padding_top_material"
android:clipToPadding="false">
+
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
- <TextView android:id="@+id/message"
- style="@style/TextAppearance.Material.Subhead"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingStart="?attr/dialogPreferredPadding"
- android:paddingTop="@dimen/dialog_padding_top_material"
- android:paddingEnd="?attr/dialogPreferredPadding" />
- <Space android:id="@+id/textSpacerNoButtons"
- android:visibility="gone"
- android:layout_width="0dp"
- android:layout_height="@dimen/dialog_padding_top_material" />
+
+ <TextView
+ android:id="@+id/message"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingEnd="?attr/dialogPreferredPadding"
+ android:paddingStart="?attr/dialogPreferredPadding"
+ style="@style/TextAppearance.Material.Subhead" />
+
+ <Space
+ android:id="@+id/textSpacerNoButtons"
+ android:visibility="gone"
+ android:layout_width="0dp"
+ android:layout_height="@dimen/dialog_padding_top_material" />
</LinearLayout>
</ScrollView>
- <View android:id="@+id/scrollIndicatorDown"
- android:visibility="gone"
- android:layout_width="match_parent"
- android:layout_height="1dp"
- android:layout_gravity="bottom"
- android:background="@drawable/list_divider_material"/>
</FrameLayout>
- <FrameLayout android:id="@+id/customPanel"
+ <FrameLayout
+ android:id="@+id/customPanel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:minHeight="48dp">
- <FrameLayout android:id="@+id/custom"
+
+ <FrameLayout
+ android:id="@+id/custom"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</FrameLayout>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 2914817..1c4b5f7 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1998,6 +1998,13 @@
<attr name="needsDefaultBackgrounds" format="boolean" />
</declare-styleable>
+ <!-- @hide -->
+ <declare-styleable name="ButtonBarLayout">
+ <!-- Whether to automatically stack the buttons when there is not
+ enough space to lay them out side-by-side. -->
+ <attr name="allowStacking" format="boolean" />
+ </declare-styleable>
+
<!-- Fragment animation class attributes. -->
<declare-styleable name="FragmentAnimation">
<attr name="fragmentOpenEnterAnimation" format="reference" />
@@ -2715,6 +2722,28 @@
<enum name="add" value="16" />
</attr>
+ <!-- Defines which scroll indicators should be displayed when the view
+ can be scrolled. Multiple values may be combined using logical OR,
+ for example "top|bottom". -->
+ <attr name="scrollIndicators">
+ <!-- No scroll indicators are displayed. -->
+ <flag name="none" value="0x0000" />
+ <!-- Displays top scroll indicator when view can be scrolled up. -->
+ <flag name="top" value="0x0100" />
+ <!-- Displays bottom scroll indicator when vew can be scrolled down. -->
+ <flag name="bottom" value="0x0200" />
+ <!-- Displays left scroll indicator when vew can be scrolled left. -->
+ <flag name="left" value="0x0400" />
+ <!-- Displays right scroll indicator when vew can be scrolled right. -->
+ <flag name="right" value="0x0800" />
+ <!-- Displays right scroll indicator when vew can be scrolled in the
+ start direction. -->
+ <flag name="start" value="0x1000" />
+ <!-- Displays right scroll indicator when vew can be scrolled in the
+ end direction. -->
+ <flag name="end" value="0x2000" />
+ </attr>
+
</declare-styleable>
<!-- Attributes that can be assigned to a tag for a particular View. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 83ac6c1..297b302 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2623,7 +2623,6 @@
<public type="attr" name="fullBackupContent" />
<public type="style" name="Widget.Material.Button.Colored" />
-
<public type="style" name="Theme.Material.DayNight" />
<public type="style" name="Theme.Material.DayNight.DarkActionBar" />
<public type="style" name="Theme.Material.DayNight.Dialog" />
@@ -2686,4 +2685,5 @@
<public type="attr" name="assistBlocked" />
<public type="attr" name="stylusButtonPressable" />
<public type="attr" name="supportsLaunchVoiceAssistFromKeyguard" />
+ <public type="attr" name="scrollIndicators" />
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index a57b3b8..28ffbfa 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2180,8 +2180,6 @@
<java-symbol type="bool" name="config_defaultWindowFeatureContextMenu" />
<java-symbol type="layout" name="simple_account_item" />
- <java-symbol type="id" name="scrollIndicatorUp" />
- <java-symbol type="id" name="scrollIndicatorDown" />
<java-symbol type="array" name="config_sms_convert_destination_number_support" />
<java-symbol type="string" name="prohibit_manual_network_selection_in_gobal_mode" />
<java-symbol type="id" name="profile_button" />
@@ -2204,7 +2202,6 @@
<java-symbol type="string" name="usb_midi_peripheral_manufacturer_name" />
<java-symbol type="string" name="usb_midi_peripheral_product_name" />
- <java-symbol type="bool" name="allow_stacked_button_bar" />
<java-symbol type="id" name="spacer" />
<java-symbol type="xml" name="bookmarks" />
@@ -2258,4 +2255,5 @@
<java-symbol type="id" name="title_icon" />
<java-symbol type="id" name="day_picker_view_pager" />
<java-symbol type="layout" name="day_picker_content_material" />
+ <java-symbol type="drawable" name="scroll_indicator_material" />
</resources>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index e679e0a..f02fed1 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -207,8 +207,8 @@ please see themes_device_defaults.xml.
<!-- Scrollbar attributes -->
<item name="scrollbarFadeDuration">250</item>
- <item name="scrollbarDefaultDelayBeforeFade">300</item>
- <item name="scrollbarSize">10dip</item>
+ <item name="scrollbarDefaultDelayBeforeFade">400</item>
+ <item name="scrollbarSize">10dp</item>
<item name="scrollbarThumbHorizontal">@drawable/scrollbar_handle_material</item>
<item name="scrollbarThumbVertical">@drawable/scrollbar_handle_material</item>
<item name="scrollbarTrackHorizontal">@null</item>
@@ -563,8 +563,8 @@ please see themes_device_defaults.xml.
<!-- Scrollbar attributes -->
<item name="scrollbarFadeDuration">250</item>
- <item name="scrollbarDefaultDelayBeforeFade">300</item>
- <item name="scrollbarSize">10dip</item>
+ <item name="scrollbarDefaultDelayBeforeFade">400</item>
+ <item name="scrollbarSize">10dp</item>
<item name="scrollbarThumbHorizontal">@drawable/scrollbar_handle_material</item>
<item name="scrollbarThumbVertical">@drawable/scrollbar_handle_material</item>
<item name="scrollbarTrackHorizontal">@null</item>
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index b03fe3a..4a06805 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -295,9 +295,9 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
@Override
public void setHotspotBounds(int left, int top, int right, int bottom) {
if (mHotspotBounds == null) {
- mHotspotBounds = new Rect(left, top, bottom, right);
+ mHotspotBounds = new Rect(left, top, right, bottom);
} else {
- mHotspotBounds.set(left, top, bottom, right);
+ mHotspotBounds.set(left, top, right, bottom);
}
if (mCurrDrawable != null) {
diff --git a/keystore/java/android/security/AndroidKeyStoreProvider.java b/keystore/java/android/security/AndroidKeyStoreProvider.java
index 518067b..257ab54 100644
--- a/keystore/java/android/security/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/AndroidKeyStoreProvider.java
@@ -104,13 +104,13 @@ public class AndroidKeyStoreProvider extends Provider {
*
* <p>The following primitives are supported: {@link Cipher} and {@link Mac}.
*
- * @return KeyStore operation handle or {@code null} if the provided primitive's KeyStore
- * operation is not in progress.
+ * @return KeyStore operation handle or {@code 0} if the provided primitive's KeyStore operation
+ * is not in progress.
*
* @throws IllegalArgumentException if the provided primitive is not supported or is not backed
* by AndroidKeyStore provider.
*/
- public static Long getKeyStoreOperationHandle(Object cryptoPrimitive) {
+ public static long getKeyStoreOperationHandle(Object cryptoPrimitive) {
if (cryptoPrimitive == null) {
throw new NullPointerException();
}
diff --git a/keystore/java/android/security/KeyStoreCipherSpi.java b/keystore/java/android/security/KeyStoreCipherSpi.java
index 20dd524..094aa75 100644
--- a/keystore/java/android/security/KeyStoreCipherSpi.java
+++ b/keystore/java/android/security/KeyStoreCipherSpi.java
@@ -134,7 +134,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry
* error conditions in between.
*/
private IBinder mOperationToken;
- private Long mOperationHandle;
+ private long mOperationHandle;
private KeyStoreCryptoOperationChunkedStreamer mMainDataStreamer;
/**
@@ -247,7 +247,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry
mIvHasBeenUsed = false;
mAdditionalEntropyForBegin = null;
mOperationToken = null;
- mOperationHandle = null;
+ mOperationHandle = 0;
mMainDataStreamer = null;
mCachedException = null;
}
@@ -258,7 +258,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry
mOperationToken = null;
mKeyStore.abort(operationToken);
}
- mOperationHandle = null;
+ mOperationHandle = 0;
mMainDataStreamer = null;
mAdditionalEntropyForBegin = null;
mCachedException = null;
@@ -322,6 +322,9 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry
if (mOperationToken == null) {
throw new IllegalStateException("Keystore returned null operation token");
}
+ if (mOperationHandle == 0) {
+ throw new IllegalStateException("Keystore returned invalid operation handle");
+ }
loadAlgorithmSpecificParametersFromBeginResult(keymasterOutputArgs);
mFirstOperationInitiated = true;
@@ -471,7 +474,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry
}
@Override
- public Long getOperationHandle() {
+ public long getOperationHandle() {
return mOperationHandle;
}
diff --git a/keystore/java/android/security/KeyStoreCryptoOperation.java b/keystore/java/android/security/KeyStoreCryptoOperation.java
index 19abd05..c5cf211 100644
--- a/keystore/java/android/security/KeyStoreCryptoOperation.java
+++ b/keystore/java/android/security/KeyStoreCryptoOperation.java
@@ -25,7 +25,7 @@ public interface KeyStoreCryptoOperation {
/**
* Gets the KeyStore operation handle of this crypto operation.
*
- * @return handle or {@code null} if the KeyStore operation is not in progress.
+ * @return handle or {@code 0} if the KeyStore operation is not in progress.
*/
- Long getOperationHandle();
+ long getOperationHandle();
}
diff --git a/keystore/java/android/security/KeyStoreHmacSpi.java b/keystore/java/android/security/KeyStoreHmacSpi.java
index e993b50..0dbe788 100644
--- a/keystore/java/android/security/KeyStoreHmacSpi.java
+++ b/keystore/java/android/security/KeyStoreHmacSpi.java
@@ -75,7 +75,7 @@ public abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOp
// Fields below are reset when engineDoFinal succeeds.
private KeyStoreCryptoOperationChunkedStreamer mChunkedStreamer;
private IBinder mOperationToken;
- private Long mOperationHandle;
+ private long mOperationHandle;
protected KeyStoreHmacSpi(int keymasterDigest) {
mKeymasterDigest = keymasterDigest;
@@ -128,7 +128,7 @@ public abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOp
mOperationToken = null;
mKeyStore.abort(operationToken);
}
- mOperationHandle = null;
+ mOperationHandle = 0;
mChunkedStreamer = null;
}
@@ -138,7 +138,7 @@ public abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOp
mOperationToken = null;
mKeyStore.abort(operationToken);
}
- mOperationHandle = null;
+ mOperationHandle = 0;
mChunkedStreamer = null;
}
@@ -187,6 +187,9 @@ public abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOp
if (mOperationToken == null) {
throw new IllegalStateException("Keystore returned null operation token");
}
+ if (mOperationHandle == 0) {
+ throw new IllegalStateException("Keystore returned invalid operation handle");
+ }
mChunkedStreamer = new KeyStoreCryptoOperationChunkedStreamer(
new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
@@ -249,7 +252,7 @@ public abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOp
}
@Override
- public Long getOperationHandle() {
+ public long getOperationHandle() {
return mOperationHandle;
}
}
diff --git a/libs/hwui/tests/main.cpp b/libs/hwui/tests/main.cpp
index aca7c52..2f79c58 100644
--- a/libs/hwui/tests/main.cpp
+++ b/libs/hwui/tests/main.cpp
@@ -58,13 +58,20 @@ static void endRecording(DisplayListCanvas* renderer, RenderNode* node) {
class TreeContentAnimation {
public:
virtual ~TreeContentAnimation() {}
- virtual int getFrameCount() { return 150; }
+ int frameCount = 150;
+ virtual int getFrameCount() { return frameCount; }
+ virtual void setFrameCount(int fc) {
+ if (fc > 0) {
+ frameCount = fc;
+ }
+ }
virtual void createContent(int width, int height, DisplayListCanvas* renderer) = 0;
virtual void doFrame(int frameNr) = 0;
template <class T>
- static void run() {
+ static void run(int frameCount) {
T animation;
+ animation.setFrameCount(frameCount);
TestContext testContext;
@@ -137,9 +144,10 @@ public:
renderer->insertReorderBarrier(false);
}
void doFrame(int frameNr) override {
+ int curFrame = frameNr % 150;
for (size_t ci = 0; ci < cards.size(); ci++) {
- cards[ci]->mutateStagingProperties().setTranslationX(frameNr);
- cards[ci]->mutateStagingProperties().setTranslationY(frameNr);
+ cards[ci]->mutateStagingProperties().setTranslationX(curFrame);
+ cards[ci]->mutateStagingProperties().setTranslationY(curFrame);
cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
}
}
@@ -159,6 +167,47 @@ private:
}
};
+class ShadowGrid2Animation : public TreeContentAnimation {
+public:
+ std::vector< sp<RenderNode> > cards;
+ void createContent(int width, int height, DisplayListCanvas* renderer) override {
+ renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
+ renderer->insertReorderBarrier(true);
+
+ for (int x = dp(8); x < (width - dp(58)); x += dp(58)) {
+ for (int y = dp(8); y < (height - dp(58)); y += dp(58)) {
+ sp<RenderNode> card = createCard(x, y, dp(50), dp(50));
+ renderer->drawRenderNode(card.get());
+ cards.push_back(card);
+ }
+ }
+
+ renderer->insertReorderBarrier(false);
+ }
+ void doFrame(int frameNr) override {
+ int curFrame = frameNr % 150;
+ for (size_t ci = 0; ci < cards.size(); ci++) {
+ cards[ci]->mutateStagingProperties().setTranslationX(curFrame);
+ cards[ci]->mutateStagingProperties().setTranslationY(curFrame);
+ cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+ }
+ }
+private:
+ sp<RenderNode> createCard(int x, int y, int width, int height) {
+ sp<RenderNode> node = new RenderNode();
+ node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height);
+ node->mutateStagingProperties().setElevation(dp(16));
+ node->mutateStagingProperties().mutableOutline().setRoundRect(0, 0, width, height, dp(6), 1);
+ node->mutateStagingProperties().mutableOutline().setShouldClip(true);
+ node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y | RenderNode::Z);
+
+ DisplayListCanvas* renderer = startRecording(node.get());
+ renderer->drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
+ endRecording(renderer, node.get());
+ return node;
+ }
+};
+
class RectGridAnimation : public TreeContentAnimation {
public:
sp<RenderNode> card;
@@ -172,8 +221,9 @@ public:
renderer->insertReorderBarrier(false);
}
void doFrame(int frameNr) override {
- card->mutateStagingProperties().setTranslationX(frameNr);
- card->mutateStagingProperties().setTranslationY(frameNr);
+ int curFrame = frameNr % 150;
+ card->mutateStagingProperties().setTranslationX(curFrame);
+ card->mutateStagingProperties().setTranslationY(curFrame);
card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
}
private:
@@ -220,8 +270,9 @@ public:
}
void doFrame(int frameNr) override {
- card->mutateStagingProperties().setTranslationX(frameNr);
- card->mutateStagingProperties().setTranslationY(frameNr);
+ int curFrame = frameNr % 150;
+ card->mutateStagingProperties().setTranslationX(curFrame);
+ card->mutateStagingProperties().setTranslationY(curFrame);
card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
}
private:
@@ -248,10 +299,11 @@ struct cstr_cmp {
}
};
-typedef void (*testProc)();
+typedef void (*testProc)(int);
std::map<const char*, testProc, cstr_cmp> gTestMap {
{"shadowgrid", TreeContentAnimation::run<ShadowGridAnimation>},
+ {"shadowgrid2", TreeContentAnimation::run<ShadowGrid2Animation>},
{"rectgrid", TreeContentAnimation::run<RectGridAnimation> },
{"oval", TreeContentAnimation::run<OvalAnimation> },
};
@@ -263,7 +315,28 @@ int main(int argc, char* argv[]) {
printf("Error: couldn't find test %s\n", testName);
return 1;
}
- proc();
+ int loopCount = 1;
+ if (argc > 2) {
+ loopCount = atoi(argv[2]);
+ if (!loopCount) {
+ printf("Invalid loop count!\n");
+ return 1;
+ }
+ }
+ int frameCount = 150;
+ if (argc > 3) {
+ frameCount = atoi(argv[3]);
+ if (frameCount < 1) {
+ printf("Invalid frame count!\n");
+ return 1;
+ }
+ }
+ if (loopCount < 0) {
+ loopCount = INT_MAX;
+ }
+ for (int i = 0; i < loopCount; i++) {
+ proc(frameCount);
+ }
printf("Success!\n");
return 0;
}
diff --git a/media/java/android/media/AudioDevicePort.java b/media/java/android/media/AudioDevicePort.java
index 82da27d..c078260 100644
--- a/media/java/android/media/AudioDevicePort.java
+++ b/media/java/android/media/AudioDevicePort.java
@@ -83,6 +83,16 @@ public class AudioDevicePort extends AudioPort {
if (o == null || !(o instanceof AudioDevicePort)) {
return false;
}
+ AudioDevicePort other = (AudioDevicePort)o;
+ if (mType != other.type()) {
+ return false;
+ }
+ if (mAddress == null && other.address() != null) {
+ return false;
+ }
+ if (!mAddress.equals(other.address())) {
+ return false;
+ }
return super.equals(o);
}
diff --git a/media/java/android/media/AudioDevicesManager.java b/media/java/android/media/AudioDevicesManager.java
index ca238d7..8b83c17 100644
--- a/media/java/android/media/AudioDevicesManager.java
+++ b/media/java/android/media/AudioDevicesManager.java
@@ -96,7 +96,7 @@ public class AudioDevicesManager {
* @param flags A set of bitflags specifying the criteria to test.
* @see {@link LIST_DEVICES_OUTPUTS} and {@link LIST_DEVICES_INPUTS}
**/
- private boolean checkFlags(AudioDevicePort port, int flags) {
+ private static boolean checkFlags(AudioDevicePort port, int flags) {
return port.role() == AudioPort.ROLE_SINK && (flags & LIST_DEVICES_OUTPUTS) != 0 ||
port.role() == AudioPort.ROLE_SOURCE && (flags & LIST_DEVICES_INPUTS) != 0;
}
@@ -110,8 +110,21 @@ public class AudioDevicesManager {
* @return A (possibly zero-length) array of AudioDeviceInfo objects.
*/
public AudioDeviceInfo[] listDevices(int flags) {
+ return listDevicesStatic(flags);
+ }
+
+ /**
+ * Generates a list of AudioDeviceInfo objects corresponding to the audio devices currently
+ * connected to the system and meeting the criteria specified in the <code>flags</code>
+ * parameter.
+ * @param flags A set of bitflags specifying the criteria to test.
+ * @see {@link LIST_DEVICES_OUTPUTS}, {@link LIST_DEVICES_INPUTS} and {@link LIST_DEVICES_ALL}.
+ * @return A (possibly zero-length) array of AudioDeviceInfo objects.
+ * @hide
+ */
+ public static AudioDeviceInfo[] listDevicesStatic(int flags) {
ArrayList<AudioDevicePort> ports = new ArrayList<AudioDevicePort>();
- int status = mAudioManager.listAudioDevicePorts(ports);
+ int status = AudioManager.listAudioDevicePorts(ports);
if (status != AudioManager.SUCCESS) {
// fail and bail!
return new AudioDeviceInfo[0];
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 6eaf812..19900d0 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3401,7 +3401,7 @@ public class AudioManager {
* @param ports An AudioPort ArrayList where the list will be returned.
* @hide
*/
- public int listAudioPorts(ArrayList<AudioPort> ports) {
+ public static int listAudioPorts(ArrayList<AudioPort> ports) {
return updateAudioPortCache(ports, null);
}
@@ -3410,7 +3410,7 @@ public class AudioManager {
* @see listAudioPorts(ArrayList<AudioPort>)
* @hide
*/
- public int listAudioDevicePorts(ArrayList<AudioDevicePort> devices) {
+ public static int listAudioDevicePorts(ArrayList<AudioDevicePort> devices) {
ArrayList<AudioPort> ports = new ArrayList<AudioPort>();
int status = updateAudioPortCache(ports, null);
if (status == SUCCESS) {
@@ -3447,7 +3447,7 @@ public class AudioManager {
* patch[0] contains the newly created patch
* @hide
*/
- public int createAudioPatch(AudioPatch[] patch,
+ public static int createAudioPatch(AudioPatch[] patch,
AudioPortConfig[] sources,
AudioPortConfig[] sinks) {
return AudioSystem.createAudioPatch(patch, sources, sinks);
@@ -3464,7 +3464,7 @@ public class AudioManager {
* - {@link #ERROR} if patch cannot be released for any other reason.
* @hide
*/
- public int releaseAudioPatch(AudioPatch patch) {
+ public static int releaseAudioPatch(AudioPatch patch) {
return AudioSystem.releaseAudioPatch(patch);
}
@@ -3473,7 +3473,7 @@ public class AudioManager {
* @param patches An AudioPatch array where the list will be returned.
* @hide
*/
- public int listAudioPatches(ArrayList<AudioPatch> patches) {
+ public static int listAudioPatches(ArrayList<AudioPatch> patches) {
return updateAudioPortCache(null, patches);
}
@@ -3482,7 +3482,7 @@ public class AudioManager {
* AudioGain.buildConfig()
* @hide
*/
- public int setAudioPortGain(AudioPort port, AudioGainConfig gain) {
+ public static int setAudioPortGain(AudioPort port, AudioGainConfig gain) {
if (port == null || gain == null) {
return ERROR_BAD_VALUE;
}
diff --git a/media/java/android/media/AudioMixPort.java b/media/java/android/media/AudioMixPort.java
index 9fac8d1..ab55c8d 100644
--- a/media/java/android/media/AudioMixPort.java
+++ b/media/java/android/media/AudioMixPort.java
@@ -20,16 +20,21 @@ package android.media;
* The AudioMixPort is a specialized type of AudioPort
* describing an audio mix or stream at an input or output stream of the audio
* framework.
+ * In addition to base audio port attributes, the mix descriptor contains:
+ * - the unique audio I/O handle assigned by AudioFlinger to this mix.
* @see AudioPort
* @hide
*/
public class AudioMixPort extends AudioPort {
- AudioMixPort(AudioHandle handle, int role, String deviceName,
+ private final int mIoHandle;
+
+ AudioMixPort(AudioHandle handle, int ioHandle, int role, String deviceName,
int[] samplingRates, int[] channelMasks,
int[] formats, AudioGain[] gains) {
super(handle, role, deviceName, samplingRates, channelMasks, formats, gains);
+ mIoHandle = ioHandle;
}
/**
@@ -41,11 +46,23 @@ public class AudioMixPort extends AudioPort {
return new AudioMixPortConfig(this, samplingRate, channelMask, format, gain);
}
+ /**
+ * Get the device type (e.g AudioManager.DEVICE_OUT_SPEAKER)
+ */
+ public int ioHandle() {
+ return mIoHandle;
+ }
+
@Override
public boolean equals(Object o) {
if (o == null || !(o instanceof AudioMixPort)) {
return false;
}
+ AudioMixPort other = (AudioMixPort)o;
+ if (mIoHandle != other.ioHandle()) {
+ return false;
+ }
+
return super.equals(o);
}
diff --git a/media/java/android/media/AudioPort.java b/media/java/android/media/AudioPort.java
index 88e784a..7328d7a 100644
--- a/media/java/android/media/AudioPort.java
+++ b/media/java/android/media/AudioPort.java
@@ -93,6 +93,14 @@ public class AudioPort {
}
/**
+ * Get the system unique device ID.
+ */
+ public int id() {
+ return mHandle.id();
+ }
+
+
+ /**
* Get the audio port role
*/
public int role() {
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 472da02..11671d8 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -116,11 +116,6 @@ public class AudioRecord
*/
private static final int NATIVE_EVENT_NEW_POS = 3;
- /**
- * Event id denotes when the routing changes.
- */
- private final static int NATIVE_EVENT_ROUTING_CHANGE = 1000;
-
private final static String TAG = "android.media.AudioRecord";
/** @hide */
@@ -161,6 +156,12 @@ public class AudioRecord
@SuppressWarnings("unused")
private long mNativeCallbackCookie;
+ /**
+ * Accessed by native methods: provides access to the JNIDeviceCallback instance.
+ */
+ @SuppressWarnings("unused")
+ private long mNativeDeviceCallback;
+
//---------------------------------------------------------
// Member variables
@@ -1205,6 +1206,17 @@ public class AudioRecord
* Returns an {@link AudioDeviceInfo} identifying the current routing of this AudioRecord.
*/
public AudioDeviceInfo getRoutedDevice() {
+ int deviceId = native_getRoutedDeviceId();
+ if (deviceId == 0) {
+ return null;
+ }
+ AudioDeviceInfo[] devices =
+ AudioDevicesManager.listDevicesStatic(AudioDevicesManager.LIST_DEVICES_INPUTS);
+ for (int i = 0; i < devices.length; i++) {
+ if (devices[i].getId() == deviceId) {
+ return devices[i];
+ }
+ }
return null;
}
@@ -1224,6 +1236,9 @@ public class AudioRecord
android.os.Handler handler) {
if (listener != null && !mRoutingChangeListeners.containsKey(listener)) {
synchronized (mRoutingChangeListeners) {
+ if (mRoutingChangeListeners.size() == 0) {
+ native_enableDeviceCallback();
+ }
mRoutingChangeListeners.put(
listener, new NativeRoutingEventHandlerDelegate(this, listener, handler));
}
@@ -1238,6 +1253,9 @@ public class AudioRecord
synchronized (mRoutingChangeListeners) {
if (mRoutingChangeListeners.containsKey(listener)) {
mRoutingChangeListeners.remove(listener);
+ if (mRoutingChangeListeners.size() == 0) {
+ native_disableDeviceCallback();
+ }
}
}
}
@@ -1271,7 +1289,7 @@ public class AudioRecord
return;
}
switch(msg.what) {
- case NATIVE_EVENT_ROUTING_CHANGE:
+ case AudioSystem.NATIVE_EVENT_ROUTING_CHANGE:
if (listener != null) {
listener.onAudioRecordRouting(record);
}
@@ -1299,10 +1317,11 @@ public class AudioRecord
synchronized (mRoutingChangeListeners) {
values = mRoutingChangeListeners.values();
}
+ AudioManager.resetAudioPortGeneration();
for(NativeRoutingEventHandlerDelegate delegate : values) {
Handler handler = delegate.getHandler();
if (handler != null) {
- handler.sendEmptyMessage(NATIVE_EVENT_ROUTING_CHANGE);
+ handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE);
}
}
}
@@ -1341,10 +1360,14 @@ public class AudioRecord
return false;
}
- mPreferredDevice = deviceInfo;
- int preferredDeviceId = mPreferredDevice != null ? deviceInfo.getId() : 0;
-
- return native_setInputDevice(preferredDeviceId);
+ int preferredDeviceId = deviceInfo != null ? deviceInfo.getId() : 0;
+ boolean status = native_setInputDevice(preferredDeviceId);
+ if (status == true) {
+ synchronized (this) {
+ mPreferredDevice = deviceInfo;
+ }
+ }
+ return status;
}
/**
@@ -1352,7 +1375,9 @@ public class AudioRecord
* is not guarenteed to correspond to the actual device being used for recording.
*/
public AudioDeviceInfo getPreferredInputDevice() {
- return mPreferredDevice;
+ synchronized (this) {
+ return mPreferredDevice;
+ }
}
//---------------------------------------------------------
@@ -1435,6 +1460,11 @@ public class AudioRecord
return;
}
+ if (what == AudioSystem.NATIVE_EVENT_ROUTING_CHANGE) {
+ recorder.broadcastRoutingChange();
+ return;
+ }
+
if (recorder.mEventHandler != null) {
Message m =
recorder.mEventHandler.obtainMessage(what, arg1, arg2, obj);
@@ -1486,7 +1516,9 @@ public class AudioRecord
int sampleRateInHz, int channelCount, int audioFormat);
private native final boolean native_setInputDevice(int deviceId);
-
+ private native final int native_getRoutedDeviceId();
+ private native final void native_enableDeviceCallback();
+ private native final void native_disableDeviceCallback();
//---------------------------------------------------------
// Utility methods
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 3dae543..ee12374 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -721,5 +721,11 @@ public class AudioSystem
(1 << STREAM_RING) |
(1 << STREAM_NOTIFICATION) |
(1 << STREAM_SYSTEM);
+
+ /**
+ * Event posted by AudioTrack and AudioRecord JNI (JNIDeviceCallback) when routing changes.
+ * Keep in sync with core/jni/android_media_DeviceCallback.h.
+ */
+ final static int NATIVE_EVENT_ROUTING_CHANGE = 1000;
}
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index cb05cc5..a66a1e5 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -178,12 +178,6 @@ public class AudioTrack
*/
private static final int NATIVE_EVENT_NEW_POS = 4;
- /**
- * Event id denotes when the routing changes.
- */
- private final static int NATIVE_EVENT_ROUTING_CHANGE = 1000;
-
-
private final static String TAG = "android.media.AudioTrack";
@@ -2057,11 +2051,14 @@ public class AudioTrack
if (deviceInfo != null && !deviceInfo.isSink()) {
return false;
}
-
- mPreferredDevice = deviceInfo;
- int preferredDeviceId = mPreferredDevice != null ? deviceInfo.getId() : 0;
-
- return native_setOutputDevice(preferredDeviceId);
+ int preferredDeviceId = deviceInfo != null ? deviceInfo.getId() : 0;
+ boolean status = native_setOutputDevice(preferredDeviceId);
+ if (status == true) {
+ synchronized (this) {
+ mPreferredDevice = deviceInfo;
+ }
+ }
+ return status;
}
/**
@@ -2069,7 +2066,9 @@ public class AudioTrack
* is not guaranteed to correspond to the actual device being used for playback.
*/
public AudioDeviceInfo getPreferredOutputDevice() {
- return mPreferredDevice;
+ synchronized (this) {
+ return mPreferredDevice;
+ }
}
//--------------------------------------------------------------------------
@@ -2079,6 +2078,17 @@ public class AudioTrack
* Returns an {@link AudioDeviceInfo} identifying the current routing of this AudioTrack.
*/
public AudioDeviceInfo getRoutedDevice() {
+ int deviceId = native_getRoutedDeviceId();
+ if (deviceId == 0) {
+ return null;
+ }
+ AudioDeviceInfo[] devices =
+ AudioDevicesManager.listDevicesStatic(AudioDevicesManager.LIST_DEVICES_OUTPUTS);
+ for (int i = 0; i < devices.length; i++) {
+ if (devices[i].getId() == deviceId) {
+ return devices[i];
+ }
+ }
return null;
}
@@ -2098,6 +2108,9 @@ public class AudioTrack
android.os.Handler handler) {
if (listener != null && !mRoutingChangeListeners.containsKey(listener)) {
synchronized (mRoutingChangeListeners) {
+ if (mRoutingChangeListeners.size() == 0) {
+ native_enableDeviceCallback();
+ }
mRoutingChangeListeners.put(
listener, new NativeRoutingEventHandlerDelegate(this, listener, handler));
}
@@ -2113,6 +2126,9 @@ public class AudioTrack
if (mRoutingChangeListeners.containsKey(listener)) {
mRoutingChangeListeners.remove(listener);
}
+ if (mRoutingChangeListeners.size() == 0) {
+ native_disableDeviceCallback();
+ }
}
}
@@ -2124,10 +2140,11 @@ public class AudioTrack
synchronized (mRoutingChangeListeners) {
values = mRoutingChangeListeners.values();
}
+ AudioManager.resetAudioPortGeneration();
for(NativeRoutingEventHandlerDelegate delegate : values) {
Handler handler = delegate.getHandler();
if (handler != null) {
- handler.sendEmptyMessage(NATIVE_EVENT_ROUTING_CHANGE);
+ handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE);
}
}
}
@@ -2240,7 +2257,7 @@ public class AudioTrack
return;
}
switch(msg.what) {
- case NATIVE_EVENT_ROUTING_CHANGE:
+ case AudioSystem.NATIVE_EVENT_ROUTING_CHANGE:
if (listener != null) {
listener.onAudioTrackRouting(track);
}
@@ -2273,6 +2290,10 @@ public class AudioTrack
return;
}
+ if (what == AudioSystem.NATIVE_EVENT_ROUTING_CHANGE) {
+ track.broadcastRoutingChange();
+ return;
+ }
NativePositionEventHandlerDelegate delegate = track.mEventHandlerDelegate;
if (delegate != null) {
Handler handler = delegate.getHandler();
@@ -2281,7 +2302,6 @@ public class AudioTrack
handler.sendMessage(m);
}
}
-
}
@@ -2362,6 +2382,9 @@ public class AudioTrack
private native final int native_setAuxEffectSendLevel(float level);
private native final boolean native_setOutputDevice(int deviceId);
+ private native final int native_getRoutedDeviceId();
+ private native final void native_enableDeviceCallback();
+ private native final void native_disableDeviceCallback();
//---------------------------------------------------------
// Utility methods
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 8220a74..6f7b583 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -918,9 +918,9 @@ final public class MediaCodec {
}
/**
- * This indicates that no key has been set to perform the requested
- * decrypt operation. The operation can be retried after adding
- * a decryption key.
+ * This indicates that the requested key was not found when trying to
+ * perform a decrypt operation. The operation can be retried after adding
+ * the correct decryption key.
*/
public static final int ERROR_NO_KEY = 1;
diff --git a/packages/Keyguard/res/values/strings.xml b/packages/Keyguard/res/values/strings.xml
index e060b4a..49ce427 100644
--- a/packages/Keyguard/res/values/strings.xml
+++ b/packages/Keyguard/res/values/strings.xml
@@ -96,8 +96,6 @@
<string name="keyguard_widget_24_hours_format" translatable="false">kk\uee01mm</string>
<string name="keyguard_accessibility_pattern_unlock">Pattern unlock.</string>
- <!-- Accessibility description of the face unlock. [CHAR_LIMIT=none] -->
- <string name="keyguard_accessibility_face_unlock">Face unlock.</string>
<!-- Accessibility description of the pin lock. [CHAR_LIMIT=none] -->
<string name="keyguard_accessibility_pin_unlock">Pin unlock.</string>
<!-- Accessibility description of the password lock. [CHAR_LIMIT=none] -->
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
index 845d53a..929258d 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
@@ -162,7 +162,8 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView
switchImeButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mCallback.userActivity(); // Leave the screen on a bit longer
- mImm.showInputMethodPicker();
+ // Do not show auxiliary subtypes in password lock screen.
+ mImm.showInputMethodPicker(false /* showAuxiliarySubtypes */);
}
});
}
diff --git a/packages/PrintSpooler/res/values/themes.xml b/packages/PrintSpooler/res/values/themes.xml
index 532b01f..db319e9 100644
--- a/packages/PrintSpooler/res/values/themes.xml
+++ b/packages/PrintSpooler/res/values/themes.xml
@@ -16,10 +16,7 @@
<resources>
- <style name="PrintActivity" parent="@android:style/Theme.Material">
- <item name="android:colorPrimary">@*android:color/material_blue_grey_900</item>
- <item name="android:colorPrimaryDark">@*android:color/material_blue_grey_950</item>
- <item name="android:colorAccent">@*android:color/material_deep_teal_500</item>
+ <style name="PrintActivity" parent="@android:style/Theme.Material.Settings">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 4082bf5..b702e35 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -64,6 +64,8 @@
<string name="wifi_not_in_range">Not in range</string>
<!-- Summary for the remembered network but no internet connection was detected. -->
<string name="wifi_no_internet">No Internet Access Detected, won\'t automatically reconnect.</string>
+ <!-- Summary for saved networks -->
+ <string name="saved_network">Saved by <xliff:g id="name">%1$s</xliff:g></string>
<!-- Status message of Wi-Fi when it is connected by a Wi-Fi assistant application. [CHAR LIMIT=NONE] -->
<string name="connected_via_wfa">Connected via Wi\u2011Fi assistant</string>
@@ -71,6 +73,10 @@
<string name="connected_via_passpoint">Connected via %1$s</string>
<!-- Status message of Wi-Fi when network has matching passpoint credentials. [CHAR LIMIT=NONE] -->
<string name="available_via_passpoint">Available via %1$s</string>
+ <!-- Package name for Settings app-->
+ <string name="settings_package" translatable="false">com.android.settings</string>
+ <!-- Package name for Certinstaller app-->
+ <string name="certinstaller_package" translatable="false">com.android.certinstaller</string>
<!-- Summary for Connected wifi network without internet -->
<string name="wifi_connected_no_internet">Connected, no Internet</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 53e69e3..7eaa728 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -35,6 +35,12 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import android.util.LruCache;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.os.RemoteException;
+import android.app.AppGlobals;
import com.android.settingslib.R;
@@ -288,12 +294,28 @@ public class AccessPoint implements Comparable<AccessPoint> {
}
public String getSavedNetworkSummary() {
- // Update to new summary
- if (mConfig != null && mConfig.isPasspoint()) {
- return "";
- } else {
- return getSettingsSummary();
+ if (mConfig != null) {
+ PackageManager pm = mContext.getPackageManager();
+ String systemName = pm.getNameForUid(android.os.Process.SYSTEM_UID);
+ int userId = UserHandle.getUserId(mConfig.creatorUid);
+ ApplicationInfo appInfo = null;
+ if (mConfig.creatorName != null && mConfig.creatorName.equals(systemName)) {
+ appInfo = mContext.getApplicationInfo();
+ } else {
+ try {
+ IPackageManager ipm = AppGlobals.getPackageManager();
+ appInfo = ipm.getApplicationInfo(mConfig.creatorName, 0 /* flags */, userId);
+ } catch (RemoteException rex) {
+ }
+ }
+ if (appInfo != null &&
+ !appInfo.packageName.equals(mContext.getString(R.string.settings_package)) &&
+ !appInfo.packageName.equals(
+ mContext.getString(R.string.certinstaller_package))) {
+ return mContext.getString(R.string.saved_network, appInfo.loadLabel(pm));
+ }
}
+ return "";
}
public String getSummary() {
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 5b4b4fd..dda9358 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -121,7 +121,7 @@
<activity
android:name=".BugreportWarningActivity"
- android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
+ android:theme="@*android:style/Theme.Material.DayNight.Dialog.Alert"
android:finishOnCloseSystemDialogs="true"
android:excludeFromRecents="true"
android:exported="false" />
diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml
index 595c9ed..0264f3d 100644
--- a/packages/SystemUI/res/layout/zen_mode_panel.xml
+++ b/packages/SystemUI/res/layout/zen_mode_panel.xml
@@ -52,7 +52,7 @@
android:layout_alignParentEnd="true"
android:background="@drawable/btn_borderless_rect"
android:clickable="true"
- android:contentDescription="@string/accessibility_desc_confirm"
+ android:contentDescription="@string/accessibility_desc_close"
android:scaleType="center"
android:src="@drawable/ic_close"
android:tint="@android:color/white" />
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 8466a5a..8606a59 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -424,8 +424,8 @@
<string name="accessibility_desc_settings">Settings</string>
<!-- Content description for the recent apps panel (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_desc_recent_apps">Overview.</string>
- <!-- Content description for the confirm button in the zen mode panel introduction message. [CHAR LIMIT=NONE] -->
- <string name="accessibility_desc_confirm">Confirm</string>
+ <!-- Content description for the close button in the zen mode panel introduction message. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_desc_close">Close</string>
<!-- Content description of the user tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_user">User <xliff:g id="user" example="John Doe">%s</xliff:g>.</string>
diff --git a/packages/SystemUI/src/com/android/systemui/EventLogConstants.java b/packages/SystemUI/src/com/android/systemui/EventLogConstants.java
index c8af2d4..43a1be1 100644
--- a/packages/SystemUI/src/com/android/systemui/EventLogConstants.java
+++ b/packages/SystemUI/src/com/android/systemui/EventLogConstants.java
@@ -34,4 +34,10 @@ public class EventLogConstants {
public static final int SYSUI_LOCKSCREEN_GESTURE_TAP_LOCK = 6;
/** The user tapped a notification, needs to tap again to launch. */
public static final int SYSUI_LOCKSCREEN_GESTURE_TAP_NOTIFICATION_ACTIVATE = 7;
+ /** The user swiped down to open quick settings, from keyguard. */
+ public static final int SYSUI_LOCKSCREEN_GESTURE_SWIPE_DOWN_QS = 8;
+ /** The user swiped down to open quick settings, from shade. */
+ public static final int SYSUI_SHADE_GESTURE_SWIPE_DOWN_QS = 9;
+ /** The user tapped on the status bar to open quick settings, from shade. */
+ public static final int SYSUI_TAP_TO_OPEN_QS = 10;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index c62ad66..7077a17 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -144,7 +144,7 @@ public class NavigationBarView extends LinearLayout {
@Override
public void onClick(View view) {
((InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE))
- .showInputMethodPicker();
+ .showInputMethodPicker(true /* showAuxiliarySubtypes */);
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index c3ede75..f77ac4b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -39,6 +39,7 @@ import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import android.widget.TextView;
+import com.android.internal.logging.MetricsLogger;
import com.android.keyguard.KeyguardStatusView;
import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
@@ -73,6 +74,10 @@ public class NotificationPanelView extends PanelView implements
private static final float HEADER_RUBBERBAND_FACTOR = 2.05f;
private static final float LOCK_ICON_ACTIVE_SCALE = 1.2f;
+ private static final String COUNTER_PANEL_OPEN = "panel_open";
+ private static final String COUNTER_PANEL_OPEN_QS = "panel_open_qs";
+ private static final String COUNTER_PANEL_OPEN_PEEK = "panel_open_peek";
+
public static final long DOZE_ANIMATION_DURATION = 700;
private KeyguardAffordanceHelper mAfforanceHelper;
@@ -541,6 +546,8 @@ public class NotificationPanelView extends PanelView implements
initDownStates(event);
if (mHeadsUpTouchHelper.onInterceptTouchEvent(event)) {
mIsExpansionFromHeadsUp = true;
+ MetricsLogger.count(mContext, COUNTER_PANEL_OPEN, 1);
+ MetricsLogger.count(mContext, COUNTER_PANEL_OPEN_PEEK, 1);
return true;
}
if (!isFullyCollapsed() && onQsIntercept(event)) {
@@ -617,7 +624,7 @@ public class NotificationPanelView extends PanelView implements
case MotionEvent.ACTION_UP:
trackMovement(event);
if (mQsTracking) {
- flingQsWithCurrentVelocity(
+ flingQsWithCurrentVelocity(y,
event.getActionMasked() == MotionEvent.ACTION_CANCEL);
mQsTracking = false;
}
@@ -655,9 +662,24 @@ public class NotificationPanelView extends PanelView implements
super.requestDisallowInterceptTouchEvent(disallowIntercept);
}
- private void flingQsWithCurrentVelocity(boolean isCancelMotionEvent) {
+ private void flingQsWithCurrentVelocity(float y, boolean isCancelMotionEvent) {
+ float vel = getCurrentVelocity();
+ final boolean expandsQs = flingExpandsQs(vel);
+ if (expandsQs) {
+ logQsSwipeDown(y);
+ }
+ flingSettings(vel, expandsQs && !isCancelMotionEvent);
+ }
+
+ private void logQsSwipeDown(float y) {
float vel = getCurrentVelocity();
- flingSettings(vel, flingExpandsQs(vel) && !isCancelMotionEvent);
+ final int gesture = mStatusBarState == StatusBarState.KEYGUARD
+ ? EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_DOWN_QS
+ : EventLogConstants.SYSUI_SHADE_GESTURE_SWIPE_DOWN_QS;
+ EventLogTags.writeSysuiLockscreenGesture(
+ gesture,
+ (int) ((y - mInitialTouchY) / mStatusBar.getDisplayDensity()),
+ (int) (vel / mStatusBar.getDisplayDensity()));
}
private boolean flingExpandsQs(float vel) {
@@ -699,6 +721,7 @@ public class NotificationPanelView extends PanelView implements
return true;
}
if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isFullyCollapsed()) {
+ MetricsLogger.count(mContext, COUNTER_PANEL_OPEN, 1);
updateVerticalPanelPosition(event.getX());
}
super.onTouchEvent(event);
@@ -738,6 +761,7 @@ public class NotificationPanelView extends PanelView implements
if (mTwoFingerQsExpandPossible && event.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN
&& event.getPointerCount() == 2
&& event.getY(event.getActionIndex()) < mStatusBarMinHeight) {
+ MetricsLogger.count(mContext, COUNTER_PANEL_OPEN_QS, 1);
mQsExpandImmediate = true;
requestPanelHeightUpdate();
@@ -799,6 +823,7 @@ public class NotificationPanelView extends PanelView implements
}
final float y = event.getY(pointerIndex);
final float x = event.getX(pointerIndex);
+ final float h = y - mInitialTouchY;
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
@@ -826,7 +851,6 @@ public class NotificationPanelView extends PanelView implements
break;
case MotionEvent.ACTION_MOVE:
- final float h = y - mInitialTouchY;
setQsExpansion(h + mInitialHeightOnTouch);
if (h >= getFalsingThreshold()) {
mQsTouchAboveFalsingThreshold = true;
@@ -842,9 +866,10 @@ public class NotificationPanelView extends PanelView implements
float fraction = getQsExpansionFraction();
if ((fraction != 0f || y >= mInitialTouchY)
&& (fraction != 1f || y <= mInitialTouchY)) {
- flingQsWithCurrentVelocity(
+ flingQsWithCurrentVelocity(y,
event.getActionMasked() == MotionEvent.ACTION_CANCEL);
} else {
+ logQsSwipeDown(y);
mScrollYOverride = -1;
}
if (mVelocityTracker != null) {
@@ -1819,6 +1844,9 @@ public class NotificationPanelView extends PanelView implements
if (mQsExpanded) {
flingSettings(0 /* vel */, false /* expand */);
} else if (mQsExpansionEnabled) {
+ EventLogTags.writeSysuiLockscreenGesture(
+ EventLogConstants.SYSUI_TAP_TO_OPEN_QS,
+ 0, 0);
flingSettings(0 /* vel */, true /* expand */);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
index 23a65e8..ca32567 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
@@ -93,7 +93,7 @@ public class UsbResolverActivity extends ResolverActivity {
}
@Override
- protected void onTargetSelected(TargetInfo target, boolean alwaysCheck) {
+ protected boolean onTargetSelected(TargetInfo target, boolean alwaysCheck) {
final ResolveInfo ri = target.getResolveInfo();
try {
IBinder b = ServiceManager.getService(USB_SERVICE);
@@ -129,5 +129,6 @@ public class UsbResolverActivity extends ResolverActivity {
} catch (RemoteException e) {
Log.e(TAG, "onIntentSelected failed", e);
}
+ return true;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index 7115897..1e34663 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -788,6 +788,7 @@ public class VolumeDialog {
public void onConfigurationChanged() {
updateWindowWidthH();
mSpTexts.update();
+ mZenFooter.onConfigurationChanged();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
index 8aded45..ccb2b5a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
@@ -36,10 +36,11 @@ public class ZenFooter extends LinearLayout {
private static final String TAG = Util.logTag(ZenFooter.class);
private final Context mContext;
+ private final SpTexts mSpTexts;
private TextView mSummaryLine1;
private TextView mSummaryLine2;
- private View mEndNowButton;
+ private TextView mEndNowButton;
private int mZen = -1;
private ZenModeConfig mConfig;
private ZenModeController mController;
@@ -47,6 +48,7 @@ public class ZenFooter extends LinearLayout {
public ZenFooter(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
+ mSpTexts = new SpTexts(mContext);
setLayoutTransition(new LayoutTransition());
}
@@ -55,7 +57,10 @@ public class ZenFooter extends LinearLayout {
super.onFinishInflate();
mSummaryLine1 = (TextView) findViewById(R.id.volume_zen_summary_line_1);
mSummaryLine2 = (TextView) findViewById(R.id.volume_zen_summary_line_2);
- mEndNowButton = findViewById(R.id.volume_zen_end_now);
+ mEndNowButton = (TextView) findViewById(R.id.volume_zen_end_now);
+ mSpTexts.add(mSummaryLine1);
+ mSpTexts.add(mSummaryLine2);
+ mSpTexts.add(mEndNowButton);
}
public void init(final ZenModeController controller) {
@@ -122,4 +127,8 @@ public class ZenFooter extends LinearLayout {
Util.setText(mSummaryLine2, line2);
}
+ public void onConfigurationChanged() {
+ mSpTexts.update();
+ }
+
}
diff --git a/packages/VpnDialogs/AndroidManifest.xml b/packages/VpnDialogs/AndroidManifest.xml
index 375c5d8..32e1e6d 100644
--- a/packages/VpnDialogs/AndroidManifest.xml
+++ b/packages/VpnDialogs/AndroidManifest.xml
@@ -24,7 +24,7 @@
<application android:label="VpnDialogs"
android:allowBackup="false" >
<activity android:name=".ConfirmDialog"
- android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert">
+ android:theme="@*android:style/Theme.Material.DayNight.Dialog.Alert">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.DEFAULT"/>
@@ -32,7 +32,7 @@
</activity>
<activity android:name=".ManageDialog"
- android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
+ android:theme="@*android:style/Theme.Material.DayNight.Dialog.Alert"
android:noHistory="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
diff --git a/packages/WallpaperCropper/res/values/styles.xml b/packages/WallpaperCropper/res/values/styles.xml
index a34b25a..e438c84 100644
--- a/packages/WallpaperCropper/res/values/styles.xml
+++ b/packages/WallpaperCropper/res/values/styles.xml
@@ -15,13 +15,13 @@
-->
<resources>
- <style name="Theme.WallpaperCropper" parent="@android:style/Theme.DeviceDefault">
+ <style name="Theme.WallpaperCropper" parent="@android:style/Theme.Material.DayNight">
<item name="android:actionBarStyle">@style/WallpaperCropperActionBar</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowActionBarOverlay">true</item>
</style>
- <style name="WallpaperCropperActionBar" parent="android:style/Widget.DeviceDefault.ActionBar">
+ <style name="WallpaperCropperActionBar" parent="@android:style/Widget.Material.ActionBar">
<item name="android:displayOptions">showCustom</item>
<item name="android:background">#88000000</item>
</style>
diff --git a/rs/java/android/renderscript/Script.java b/rs/java/android/renderscript/Script.java
index 6a1efee..7cd6d09 100644
--- a/rs/java/android/renderscript/Script.java
+++ b/rs/java/android/renderscript/Script.java
@@ -182,9 +182,9 @@ public class Script extends BaseObj {
mRS.validateObject(ain);
mRS.validateObject(aout);
- if (ain == null && aout == null) {
+ if (ain == null && aout == null && sc == null) {
throw new RSIllegalArgumentException(
- "At least one of ain or aout is required to be non-null.");
+ "At least one of input allocation, output allocation, or LaunchOptions is required to be non-null.");
}
long[] in_ids = null;
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 80d6515..58d0fce 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define LOG_TAG "libRS_jni"
+#define LOG_TAG "RenderScript_jni"
#include <stdlib.h>
#include <stdio.h>
@@ -1857,7 +1857,7 @@ nScriptForEach(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot,
jintArray limits)
{
if (kLogApi) {
- ALOGD("nScriptForEach, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
+ ALOGD("nScriptForEach, con(%p), s(%p), slot(%i) ains(%p) aout(%lli)", (RsContext)con, (void *)script, slot, ains, aout);
}
jint in_len = 0;
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index bfe8b5c..6c1023c 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -9368,44 +9368,47 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
throw new SecurityException("No permission to restore other packages");
}
- // So far so good; we're allowed to try to restore this package. Now
- // check whether there is data for it in the current dataset, falling back
- // to the ancestral dataset if not.
- long token = getAvailableRestoreToken(packageName);
- if (DEBUG) Slog.v(TAG, "restorePackage pkg=" + packageName
- + " token=" + Long.toHexString(token));
-
- // If we didn't come up with a place to look -- no ancestral dataset and
- // the app has never been backed up from this device -- there's nothing
- // to do but return failure.
- if (token == 0) {
- if (DEBUG) Slog.w(TAG, "No data available for this package; not restoring");
- return -1;
- }
-
- String dirName;
+ // So far so good; we're allowed to try to restore this package.
+ long oldId = Binder.clearCallingIdentity();
try {
- dirName = mRestoreTransport.transportDirName();
- } catch (RemoteException e) {
- // Transport went AWOL; fail.
- Slog.e(TAG, "Unable to contact transport for restore");
- return -1;
- }
+ // Check whether there is data for it in the current dataset, falling back
+ // to the ancestral dataset if not.
+ long token = getAvailableRestoreToken(packageName);
+ if (DEBUG) Slog.v(TAG, "restorePackage pkg=" + packageName
+ + " token=" + Long.toHexString(token));
+
+ // If we didn't come up with a place to look -- no ancestral dataset and
+ // the app has never been backed up from this device -- there's nothing
+ // to do but return failure.
+ if (token == 0) {
+ if (DEBUG) Slog.w(TAG, "No data available for this package; not restoring");
+ return -1;
+ }
- // Stop the session timeout until we finalize the restore
- mBackupHandler.removeMessages(MSG_RESTORE_TIMEOUT);
+ String dirName;
+ try {
+ dirName = mRestoreTransport.transportDirName();
+ } catch (RemoteException e) {
+ // Transport went AWOL; fail.
+ Slog.e(TAG, "Unable to contact transport for restore");
+ return -1;
+ }
- // Ready to go: enqueue the restore request and claim success
- long oldId = Binder.clearCallingIdentity();
- mWakelock.acquire();
- if (MORE_DEBUG) {
- Slog.d(TAG, "restorePackage() : " + packageName);
+ // Stop the session timeout until we finalize the restore
+ mBackupHandler.removeMessages(MSG_RESTORE_TIMEOUT);
+
+ // Ready to go: enqueue the restore request and claim success
+ mWakelock.acquire();
+ if (MORE_DEBUG) {
+ Slog.d(TAG, "restorePackage() : " + packageName);
+ }
+ Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
+ msg.obj = new RestoreParams(mRestoreTransport, dirName,
+ observer, token, app, 0);
+ mBackupHandler.sendMessage(msg);
+ } finally {
+ Binder.restoreCallingIdentity(oldId);
}
- Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
- msg.obj = new RestoreParams(mRestoreTransport, dirName,
- observer, token, app, 0);
- mBackupHandler.sendMessage(msg);
- Binder.restoreCallingIdentity(oldId);
return 0;
}
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 45909db..759a6be 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -2238,7 +2238,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
@Override
- public void showInputMethodPickerFromClient(IInputMethodClient client) {
+ public void showInputMethodPickerFromClient(
+ IInputMethodClient client, int auxiliarySubtypeMode) {
if (!calledFromValidUser()) {
return;
}
@@ -2251,7 +2252,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
// Always call subtype picker, because subtype picker is a superset of input method
// picker.
- mHandler.sendEmptyMessage(MSG_SHOW_IM_SUBTYPE_PICKER);
+ mHandler.sendMessage(mCaller.obtainMessageI(
+ MSG_SHOW_IM_SUBTYPE_PICKER, auxiliarySubtypeMode));
}
}
@@ -2597,7 +2599,25 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
SomeArgs args;
switch (msg.what) {
case MSG_SHOW_IM_SUBTYPE_PICKER:
- showInputMethodMenu();
+ final boolean showAuxSubtypes;
+ switch (msg.arg1) {
+ case InputMethodManager.SHOW_IM_PICKER_MODE_AUTO:
+ // This is undocumented so far, but IMM#showInputMethodPicker() has been
+ // implemented so that auxiliary subtypes will be excluded when the soft
+ // keyboard is invisible.
+ showAuxSubtypes = mInputShown;
+ break;
+ case InputMethodManager.SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES:
+ showAuxSubtypes = true;
+ break;
+ case InputMethodManager.SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES:
+ showAuxSubtypes = false;
+ break;
+ default:
+ Slog.e(TAG, "Unknown subtype picker mode = " + msg.arg1);
+ return false;
+ }
+ showInputMethodMenu(showAuxSubtypes);
return true;
case MSG_SHOW_IM_SUBTYPE_ENABLER:
@@ -2880,8 +2900,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
&& mKeyguardManager.isKeyguardLocked() && mKeyguardManager.isKeyguardSecure();
}
- private void showInputMethodMenu() {
- if (DEBUG) Slog.v(TAG, "Show switching menu");
+ private void showInputMethodMenu(boolean showAuxSubtypes) {
+ if (DEBUG) Slog.v(TAG, "Show switching menu. showAuxSubtypes=" + showAuxSubtypes);
final Context context = mContext;
final boolean isScreenLocked = isScreenLocked();
@@ -2902,7 +2922,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
final List<ImeSubtypeListItem> imList =
mSwitchingController.getSortedInputMethodAndSubtypeListLocked(
- true /* showSubtypes */, mInputShown, isScreenLocked);
+ true /* showSubtypes */, showAuxSubtypes, isScreenLocked);
if (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID) {
final InputMethodSubtype currentSubtype = getCurrentInputMethodSubtypeLocked();
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 7cccef2..3dc282b 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -52,6 +52,7 @@ import android.content.pm.RegisteredServicesCache;
import android.content.pm.RegisteredServicesCacheListener;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
+import android.database.ContentObserver;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.BatteryStats;
@@ -99,6 +100,7 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
@@ -157,7 +159,19 @@ public class SyncManager {
/**
* How long to wait before considering an active sync to have timed-out, and cancelling it.
*/
- private static final long ACTIVE_SYNC_TIMEOUT_MILLIS = 30L * 60 * 1000; // 30 mins.
+ private static final long ACTIVE_SYNC_TIMEOUT_MILLIS = 30L * 60 * 1000; // 30 mins
+
+ /**
+ * How long to delay each queued {@link SyncHandler} message that may have occurred before boot
+ * or befor the device became provisioned.
+ */
+ private static final long PER_SYNC_BOOT_DELAY_MILLIS = 3000L; // 3 seconds
+
+ /**
+ * The maximum amount of time we're willing to delay syncs out of boot, after device has been
+ * provisioned, etc.
+ */
+ private static final long MAX_SYNC_BOOT_DELAY_MILLIS = 120000L; // 2 minutes
private static final String SYNC_WAKE_LOCK_PREFIX = "*sync*/";
private static final String HANDLE_SYNC_ALARM_WAKE_LOCK = "SyncManagerHandleSyncAlarm";
@@ -198,6 +212,9 @@ public class SyncManager {
// its accessor, getConnManager().
private ConnectivityManager mConnManagerDoNotUseDirectly;
+ /** Track whether the device has already been provisioned. */
+ private boolean mProvisioned;
+
protected SyncAdaptersCache mSyncAdapters;
private final AppIdleMonitor mAppIdleMonitor;
@@ -242,6 +259,7 @@ public class SyncManager {
private BroadcastReceiver mBootCompletedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
+ mBootCompleted = true;
mSyncHandler.onBootCompleted();
}
};
@@ -491,12 +509,41 @@ public class SyncManager {
mSyncStorageEngine.addStatusChangeListener(
ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, new ISyncStatusObserver.Stub() {
- @Override
- public void onStatusChanged(int which) {
- // force the sync loop to run if the settings change
- sendCheckAlarmsMessage();
+ @Override
+ public void onStatusChanged(int which) {
+ // force the sync loop to run if the settings change
+ sendCheckAlarmsMessage();
+ }
+ });
+
+ mProvisioned = isDeviceProvisioned();
+ if (!mProvisioned) {
+ final ContentResolver resolver = context.getContentResolver();
+ ContentObserver provisionedObserver =
+ new ContentObserver(null /* current thread */) {
+ public void onChange(boolean selfChange) {
+ mProvisioned |= isDeviceProvisioned();
+ if (mProvisioned) {
+ mSyncHandler.onDeviceProvisioned();
+ resolver.unregisterContentObserver(this);
+ }
+ }
+ };
+
+ synchronized (mSyncHandler) {
+ resolver.registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
+ false /* notifyForDescendents */,
+ provisionedObserver);
+
+ // The device *may* have been provisioned while we were registering above observer.
+ // Check again to make sure.
+ mProvisioned |= isDeviceProvisioned();
+ if (mProvisioned) {
+ resolver.unregisterContentObserver(provisionedObserver);
+ }
}
- });
+ }
if (!factoryTest) {
// Register for account list updates for all users
@@ -510,6 +557,10 @@ public class SyncManager {
mSyncRandomOffsetMillis = mSyncStorageEngine.getSyncRandomOffset() * 1000;
}
+ private boolean isDeviceProvisioned() {
+ final ContentResolver resolver = mContext.getContentResolver();
+ return (Settings.Global.getInt(resolver, Settings.Global.DEVICE_PROVISIONED, 0) != 0);
+ }
/**
* Return a random value v that satisfies minValue <= v < maxValue. The difference between
* maxValue and minValue must be less than Integer.MAX_VALUE.
@@ -2000,20 +2051,36 @@ public class SyncManager {
public final SyncTimeTracker mSyncTimeTracker = new SyncTimeTracker();
private final HashMap<String, PowerManager.WakeLock> mWakeLocks = Maps.newHashMap();
- private List<Message> mBootQueue = new ArrayList<Message>();
+ private List<Message> mUnreadyQueue = new ArrayList<Message>();
- public void onBootCompleted() {
+ void onBootCompleted() {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Boot completed, clearing boot queue.");
}
doDatabaseCleanup();
synchronized(this) {
// Dispatch any stashed messages.
- for (Message message : mBootQueue) {
- sendMessage(message);
+ maybeEmptyUnreadyQueueLocked();
+ }
+ }
+
+ void onDeviceProvisioned() {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "mProvisioned=" + mProvisioned);
+ }
+ synchronized (this) {
+ maybeEmptyUnreadyQueueLocked();
+ }
+ }
+
+ private void maybeEmptyUnreadyQueueLocked() {
+ if (mProvisioned && mBootCompleted) {
+ // Dispatch any stashed messages.
+ for (int i=0; i<mUnreadyQueue.size(); i++) {
+ sendMessageDelayed(mUnreadyQueue.get(i),
+ Math.max(PER_SYNC_BOOT_DELAY_MILLIS * i, MAX_SYNC_BOOT_DELAY_MILLIS));
}
- mBootQueue = null;
- mBootCompleted = true;
+ mUnreadyQueue = null;
}
}
@@ -2030,20 +2097,23 @@ public class SyncManager {
}
/**
- * Stash any messages that come to the handler before boot is complete.
- * {@link #onBootCompleted()} will disable this and dispatch all the messages collected.
+ * Stash any messages that come to the handler before boot is complete or before the device
+ * is properly provisioned (i.e. out of set-up wizard).
+ * {@link #onBootCompleted()} and {@link #onDeviceProvisioned(boolean)} both need to come
+ * in before we start syncing.
* @param msg Message to dispatch at a later point.
* @return true if a message was enqueued, false otherwise. This is to avoid losing the
* message if we manage to acquire the lock but by the time we do boot has completed.
*/
private boolean tryEnqueueMessageUntilReadyToRun(Message msg) {
synchronized (this) {
- if (!mBootCompleted) {
+ if (!mBootCompleted || !mProvisioned) {
// Need to copy the message bc looper will recycle it.
- mBootQueue.add(Message.obtain(msg));
+ mUnreadyQueue.add(Message.obtain(msg));
return true;
+ } else {
+ return false;
}
- return false;
}
}
@@ -2100,7 +2170,7 @@ public class SyncManager {
}
cancelActiveSync(expiredContext.mSyncOperation.target,
expiredContext.mSyncOperation.extras);
- nextPendingSyncTime = maybeStartNextSyncLocked();
+ nextPendingSyncTime = maybeStartNextSyncH();
break;
case SyncHandler.MESSAGE_CANCEL: {
@@ -2111,7 +2181,7 @@ public class SyncManager {
+ payload + " bundle: " + extras);
}
cancelActiveSyncLocked(payload, extras);
- nextPendingSyncTime = maybeStartNextSyncLocked();
+ nextPendingSyncTime = maybeStartNextSyncH();
break;
}
@@ -2120,17 +2190,17 @@ public class SyncManager {
Log.v(TAG, "handleSyncHandlerMessage: MESSAGE_SYNC_FINISHED");
}
SyncHandlerMessagePayload payload = (SyncHandlerMessagePayload) msg.obj;
- if (!isSyncStillActive(payload.activeSyncContext)) {
+ if (!isSyncStillActiveH(payload.activeSyncContext)) {
Log.d(TAG, "handleSyncHandlerMessage: dropping since the "
+ "sync is no longer active: "
+ payload.activeSyncContext);
break;
}
- runSyncFinishedOrCanceledLocked(payload.syncResult,
+ runSyncFinishedOrCanceledH(payload.syncResult,
payload.activeSyncContext);
// since a sync just finished check if it is time to start a new sync
- nextPendingSyncTime = maybeStartNextSyncLocked();
+ nextPendingSyncTime = maybeStartNextSyncH();
break;
case SyncHandler.MESSAGE_SERVICE_CONNECTED: {
@@ -2140,7 +2210,7 @@ public class SyncManager {
+ msgData.activeSyncContext);
}
// check that this isn't an old message
- if (isSyncStillActive(msgData.activeSyncContext)) {
+ if (isSyncStillActiveH(msgData.activeSyncContext)) {
runBoundToAdapter(
msgData.activeSyncContext,
msgData.adapter);
@@ -2156,7 +2226,7 @@ public class SyncManager {
+ currentSyncContext);
}
// check that this isn't an old message
- if (isSyncStillActive(currentSyncContext)) {
+ if (isSyncStillActiveH(currentSyncContext)) {
// cancel the sync if we have a syncadapter, which means one is
// outstanding
try {
@@ -2174,10 +2244,10 @@ public class SyncManager {
// which is a soft error
SyncResult syncResult = new SyncResult();
syncResult.stats.numIoExceptions++;
- runSyncFinishedOrCanceledLocked(syncResult, currentSyncContext);
+ runSyncFinishedOrCanceledH(syncResult, currentSyncContext);
// since a sync just finished check if it is time to start a new sync
- nextPendingSyncTime = maybeStartNextSyncLocked();
+ nextPendingSyncTime = maybeStartNextSyncH();
}
break;
@@ -2190,7 +2260,7 @@ public class SyncManager {
}
mAlarmScheduleTime = null;
try {
- nextPendingSyncTime = maybeStartNextSyncLocked();
+ nextPendingSyncTime = maybeStartNextSyncH();
} finally {
mHandleAlarmWakeLock.release();
}
@@ -2201,7 +2271,7 @@ public class SyncManager {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "handleSyncHandlerMessage: MESSAGE_CHECK_ALARMS");
}
- nextPendingSyncTime = maybeStartNextSyncLocked();
+ nextPendingSyncTime = maybeStartNextSyncH();
break;
}
} finally {
@@ -2393,7 +2463,7 @@ public class SyncManager {
0 : (earliestFuturePollTime - nowAbsolute));
}
- private long maybeStartNextSyncLocked() {
+ private long maybeStartNextSyncH() {
final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
if (isLoggable) Log.v(TAG, "maybeStartNextSync");
@@ -2612,7 +2682,7 @@ public class SyncManager {
}
if (toReschedule != null) {
- runSyncFinishedOrCanceledLocked(null, toReschedule);
+ runSyncFinishedOrCanceledH(null, toReschedule);
scheduleSyncOperation(toReschedule.mSyncOperation);
}
synchronized (mSyncQueue) {
@@ -2845,14 +2915,14 @@ public class SyncManager {
false /* no config settings */)) {
continue;
}
- runSyncFinishedOrCanceledLocked(null /* no result since this is a cancel */,
+ runSyncFinishedOrCanceledH(null /* no result since this is a cancel */,
activeSyncContext);
}
}
}
- private void runSyncFinishedOrCanceledLocked(SyncResult syncResult,
- ActiveSyncContext activeSyncContext) {
+ private void runSyncFinishedOrCanceledH(SyncResult syncResult,
+ ActiveSyncContext activeSyncContext) {
boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
final SyncOperation syncOperation = activeSyncContext.mSyncOperation;
@@ -3257,7 +3327,7 @@ public class SyncManager {
}
}
- private boolean isSyncStillActive(ActiveSyncContext activeSyncContext) {
+ private boolean isSyncStillActiveH(ActiveSyncContext activeSyncContext) {
for (ActiveSyncContext sync : mActiveSyncContexts) {
if (sync == activeSyncContext) {
return true;
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 5ac027d..e650456 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -486,6 +486,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
HdmiLogger.debug("Input not ready for device: %X; buffering the command", info.getId());
mDelayedMessageBuffer.add(message);
} else {
+ updateDevicePowerStatus(logicalAddress, HdmiControlManager.POWER_STATUS_ON);
ActiveSource activeSource = ActiveSource.of(logicalAddress, physicalAddress);
ActiveSourceHandler.create(this, null).process(activeSource, info.getDeviceType());
}
@@ -1613,6 +1614,8 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
super.disableDevice(initiatedByCec, callback);
clearDeviceInfoList();
+ getActiveSource().invalidate();
+ setActivePath(Constants.INVALID_PHYSICAL_ADDRESS);
checkIfPendingActionsCleared();
}
diff --git a/services/core/java/com/android/server/notification/CalendarTracker.java b/services/core/java/com/android/server/notification/CalendarTracker.java
index c82df48..28da73c 100644
--- a/services/core/java/com/android/server/notification/CalendarTracker.java
+++ b/services/core/java/com/android/server/notification/CalendarTracker.java
@@ -47,6 +47,7 @@ public class CalendarTracker {
Instances.EVENT_ID,
Instances.OWNER_ACCOUNT,
Instances.CALENDAR_ID,
+ Instances.AVAILABILITY,
};
private static final String INSTANCE_ORDER_BY = Instances.BEGIN + " ASC";
@@ -143,11 +144,14 @@ public class CalendarTracker {
final int eventId = cursor.getInt(4);
final String owner = cursor.getString(5);
final long calendarId = cursor.getLong(6);
- if (DEBUG) Log.d(TAG, String.format("%s %s-%s v=%s eid=%s o=%s cid=%s", title,
- new Date(begin), new Date(end), visible, eventId, owner, calendarId));
+ final int availability = cursor.getInt(7);
+ if (DEBUG) Log.d(TAG, String.format("%s %s-%s v=%s a=%s eid=%s o=%s cid=%s", title,
+ new Date(begin), new Date(end), visible, availabilityToString(availability),
+ eventId, owner, calendarId));
final boolean meetsTime = time >= begin && time < end;
final boolean meetsCalendar = visible
- && (filter.calendar == 0 || filter.calendar == calendarId);
+ && (filter.calendar == 0 || filter.calendar == calendarId)
+ && availability != Instances.AVAILABILITY_FREE;
if (meetsCalendar) {
if (DEBUG) Log.d(TAG, " MEETS CALENDAR");
final boolean meetsAttendee = meetsAttendee(filter, eventId, owner);
@@ -228,6 +232,15 @@ public class CalendarTracker {
}
}
+ private static String availabilityToString(int availability) {
+ switch (availability) {
+ case Instances.AVAILABILITY_BUSY: return "AVAILABILITY_BUSY";
+ case Instances.AVAILABILITY_FREE: return "AVAILABILITY_FREE";
+ case Instances.AVAILABILITY_TENTATIVE: return "AVAILABILITY_TENTATIVE";
+ default: return "AVAILABILITY_UNKNOWN_" + availability;
+ }
+ }
+
private static boolean meetsReply(int reply, int attendeeStatus) {
switch (reply) {
case EventInfo.REPLY_YES:
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index a8ec867..6f01ca0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -161,7 +161,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
private static final String TAG_STATUS_BAR = "statusbar";
- private static final String ATTR_ENABLED = "enabled";
+ private static final String ATTR_DISABLED = "disabled";
private static final String DO_NOT_ASK_CREDENTIALS_ON_BOOT_XML =
"do-not-ask-credentials-on-boot";
@@ -313,7 +313,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// This is the list of component allowed to start lock task mode.
List<String> mLockTaskPackages = new ArrayList<>();
- boolean mStatusBarEnabledState = true;
+ boolean mStatusBarDisabled = false;
ComponentName mRestrictionsProvider;
@@ -1476,9 +1476,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
out.endTag(null, TAG_LOCK_TASK_COMPONENTS);
}
- if (!policy.mStatusBarEnabledState) {
+ if (policy.mStatusBarDisabled) {
out.startTag(null, TAG_STATUS_BAR);
- out.attribute(null, ATTR_ENABLED, Boolean.toString(policy.mStatusBarEnabledState));
+ out.attribute(null, ATTR_DISABLED, Boolean.toString(policy.mStatusBarDisabled));
out.endTag(null, TAG_STATUS_BAR);
}
@@ -1615,8 +1615,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} else if (TAG_LOCK_TASK_COMPONENTS.equals(tag)) {
policy.mLockTaskPackages.add(parser.getAttributeValue(null, "name"));
} else if (TAG_STATUS_BAR.equals(tag)) {
- policy.mStatusBarEnabledState = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_ENABLED));
+ policy.mStatusBarDisabled = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_DISABLED));
} else if (DO_NOT_ASK_CREDENTIALS_ON_BOOT_XML.equals(tag)) {
policy.doNotAskCredentialsOnBoot = true;
} else {
@@ -1678,8 +1678,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
updateMaximumTimeToLockLocked(policy);
addDeviceInitializerToLockTaskPackagesLocked(userHandle);
updateLockTaskPackagesLocked(policy.mLockTaskPackages, userHandle);
- if (!policy.mStatusBarEnabledState) {
- setStatusBarEnabledStateInternal(policy.mStatusBarEnabledState, userHandle);
+ if (policy.mStatusBarDisabled) {
+ setStatusBarDisabledInternal(policy.mStatusBarDisabled, userHandle);
}
updatePreferredSetupActivityLocked(userHandle);
}
@@ -4275,7 +4275,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DevicePolicyData policy = getUserData(userId);
policy.mPermissionPolicy = DevicePolicyManager.PERMISSION_POLICY_PROMPT;
policy.mDelegatedCertInstallerPackage = null;
- policy.mStatusBarEnabledState = true;
+ policy.mStatusBarDisabled = false;
saveSettingsLocked(userId);
long ident = Binder.clearCallingIdentity();
@@ -6026,7 +6026,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
@Override
- public boolean setKeyguardEnabledState(ComponentName who, boolean enabled) {
+ public boolean setKeyguardDisabled(ComponentName who, boolean disabled) {
Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
@@ -6037,10 +6037,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
long ident = Binder.clearCallingIdentity();
try {
// disallow disabling the keyguard if a password is currently set
- if (!enabled && utils.isSecure(userId)) {
+ if (disabled && utils.isSecure(userId)) {
return false;
}
- utils.setLockScreenDisabled(!enabled, userId);
+ utils.setLockScreenDisabled(disabled, userId);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -6048,35 +6048,40 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
@Override
- public void setStatusBarEnabledState(ComponentName who, boolean enabled) {
+ public boolean setStatusBarDisabled(ComponentName who, boolean disabled) {
int userId = UserHandle.getCallingUserId();
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
DevicePolicyData policy = getUserData(userId);
- if (policy.mStatusBarEnabledState != enabled) {
- policy.mStatusBarEnabledState = enabled;
- setStatusBarEnabledStateInternal(enabled, userId);
+ if (policy.mStatusBarDisabled != disabled) {
+ if (!setStatusBarDisabledInternal(disabled, userId)) {
+ return false;
+ }
+ policy.mStatusBarDisabled = disabled;
saveSettingsLocked(userId);
}
}
+ return true;
}
- private void setStatusBarEnabledStateInternal(boolean enabled, int userId) {
+ private boolean setStatusBarDisabledInternal(boolean disabled, int userId) {
long ident = Binder.clearCallingIdentity();
try {
IStatusBarService statusBarService = IStatusBarService.Stub.asInterface(
ServiceManager.checkService(Context.STATUS_BAR_SERVICE));
if (statusBarService != null) {
- int flags1 = enabled ? StatusBarManager.DISABLE_NONE : STATUS_BAR_DISABLE_MASK;
- int flags2 = enabled ? StatusBarManager.DISABLE2_NONE : STATUS_BAR_DISABLE2_MASK;
+ int flags1 = disabled ? STATUS_BAR_DISABLE_MASK : StatusBarManager.DISABLE_NONE;
+ int flags2 = disabled ? STATUS_BAR_DISABLE2_MASK : StatusBarManager.DISABLE2_NONE;
statusBarService.disableForUser(flags1, mToken, mContext.getPackageName(), userId);
statusBarService.disable2ForUser(flags2, mToken, mContext.getPackageName(), userId);
+ return true;
}
} catch (RemoteException e) {
Slog.e(LOG_TAG, "Failed to disable the status bar", e);
} finally {
Binder.restoreCallingIdentity(ident);
}
+ return false;
}
/**
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index fee6495..adab00b 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -1000,9 +1000,9 @@ public final class Call {
}
boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged() &&
- !Objects.equals(mVideoCall, parcelableCall.getVideoCall());
+ !Objects.equals(mVideoCall, parcelableCall.getVideoCall(this));
if (videoCallChanged) {
- mVideoCall = parcelableCall.getVideoCall();
+ mVideoCall = parcelableCall.getVideoCall(this);
}
int state = parcelableCall.getState();
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 3060f40..4bc639b 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -16,6 +16,7 @@
package android.telecom;
+import com.android.internal.os.SomeArgs;
import com.android.internal.telecom.IVideoCallback;
import com.android.internal.telecom.IVideoProvider;
@@ -471,9 +472,16 @@ public abstract class Connection implements Conferenceable {
case MSG_SET_ZOOM:
onSetZoom((Float) msg.obj);
break;
- case MSG_SEND_SESSION_MODIFY_REQUEST:
- onSendSessionModifyRequest((VideoProfile) msg.obj);
+ case MSG_SEND_SESSION_MODIFY_REQUEST: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ onSendSessionModifyRequest((VideoProfile) args.arg1,
+ (VideoProfile) args.arg2);
+ } finally {
+ args.recycle();
+ }
break;
+ }
case MSG_SEND_SESSION_MODIFY_RESPONSE:
onSendSessionModifyResponse((VideoProfile) msg.obj);
break;
@@ -527,9 +535,11 @@ public abstract class Connection implements Conferenceable {
mMessageHandler.obtainMessage(MSG_SET_ZOOM, value).sendToTarget();
}
- public void sendSessionModifyRequest(VideoProfile requestProfile) {
- mMessageHandler.obtainMessage(
- MSG_SEND_SESSION_MODIFY_REQUEST, requestProfile).sendToTarget();
+ public void sendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = fromProfile;
+ args.arg2 = toProfile;
+ mMessageHandler.obtainMessage(MSG_SEND_SESSION_MODIFY_REQUEST, args).sendToTarget();
}
public void sendSessionModifyResponse(VideoProfile responseProfile) {
@@ -606,9 +616,11 @@ public abstract class Connection implements Conferenceable {
* Some examples of session modification requests: upgrade connection from audio to video,
* downgrade connection from video to audio, pause video.
*
- * @param requestProfile The requested connection video properties.
+ * @param fromProfile The video properties prior to the request.
+ * @param toProfile The video properties with the requested changes made.
*/
- public abstract void onSendSessionModifyRequest(VideoProfile requestProfile);
+ public abstract void onSendSessionModifyRequest(VideoProfile fromProfile,
+ VideoProfile toProfile);
/**te
* Provides a response to a request to change the current connection session video
diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java
index 1a30910..bb65ce9 100644
--- a/telecomm/java/android/telecom/ParcelableCall.java
+++ b/telecomm/java/android/telecom/ParcelableCall.java
@@ -178,10 +178,10 @@ public final class ParcelableCall implements Parcelable {
* Returns an object for remotely communicating through the video call provider's binder.
* @return The video call.
*/
- public InCallService.VideoCall getVideoCall() {
+ public InCallService.VideoCall getVideoCall(Call call) {
if (mVideoCall == null && mVideoCallProvider != null) {
try {
- mVideoCall = new VideoCallImpl(mVideoCallProvider);
+ mVideoCall = new VideoCallImpl(mVideoCallProvider, call);
} catch (RemoteException ignored) {
// Ignore RemoteException.
}
diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java
index 1493b20..9ca9f31 100644
--- a/telecomm/java/android/telecom/RemoteConnection.java
+++ b/telecomm/java/android/telecom/RemoteConnection.java
@@ -350,9 +350,9 @@ public final class RemoteConnection {
}
}
- public void sendSessionModifyRequest(VideoProfile reqProfile) {
+ public void sendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile) {
try {
- mVideoProviderBinder.sendSessionModifyRequest(reqProfile);
+ mVideoProviderBinder.sendSessionModifyRequest(fromProfile, toProfile);
} catch (RemoteException e) {
}
}
diff --git a/telecomm/java/android/telecom/VideoCallImpl.java b/telecomm/java/android/telecom/VideoCallImpl.java
index 7a82c1b..331f57e 100644
--- a/telecomm/java/android/telecom/VideoCallImpl.java
+++ b/telecomm/java/android/telecom/VideoCallImpl.java
@@ -40,6 +40,8 @@ public class VideoCallImpl extends VideoCall {
private final IVideoProvider mVideoProvider;
private final VideoCallListenerBinder mBinder;
private VideoCall.Callback mCallback;
+ private int mVideoQuality = VideoProfile.QUALITY_UNKNOWN;
+ private Call mCall;
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
@Override
@@ -161,6 +163,7 @@ public class VideoCallImpl extends VideoCall {
(CameraCapabilities) msg.obj);
break;
case MSG_CHANGE_VIDEO_QUALITY:
+ mVideoQuality = msg.arg1;
mCallback.onVideoQualityChanged(msg.arg1);
break;
default:
@@ -171,12 +174,13 @@ public class VideoCallImpl extends VideoCall {
private Handler mHandler;
- VideoCallImpl(IVideoProvider videoProvider) throws RemoteException {
+ VideoCallImpl(IVideoProvider videoProvider, Call call) throws RemoteException {
mVideoProvider = videoProvider;
mVideoProvider.asBinder().linkToDeath(mDeathRecipient, 0);
mBinder = new VideoCallListenerBinder();
mVideoProvider.addVideoCallback(mBinder);
+ mCall = call;
}
public void destroy() {
@@ -251,10 +255,24 @@ public class VideoCallImpl extends VideoCall {
}
}
- /** {@inheritDoc} */
+ /**
+ * Sends a session modification request to the video provider.
+ * <p>
+ * The {@link InCallService} will create the {@code requestProfile} based on the current
+ * video state (i.e. {@link Call.Details#getVideoState()}). It is, however, possible that the
+ * video state maintained by the {@link InCallService} could get out of sync with what is known
+ * by the {@link android.telecom.Connection.VideoProvider}. To remove ambiguity, the
+ * {@link VideoCallImpl} passes along the pre-modify video profile to the {@code VideoProvider}
+ * to ensure it has full context of the requested change.
+ *
+ * @param requestProfile The requested video profile.
+ */
public void sendSessionModifyRequest(VideoProfile requestProfile) {
try {
- mVideoProvider.sendSessionModifyRequest(requestProfile);
+ VideoProfile originalProfile = new VideoProfile(mCall.getDetails().getVideoState(),
+ mVideoQuality);
+
+ mVideoProvider.sendSessionModifyRequest(originalProfile, requestProfile);
} catch (RemoteException e) {
}
}
diff --git a/telecomm/java/com/android/internal/telecom/IVideoProvider.aidl b/telecomm/java/com/android/internal/telecom/IVideoProvider.aidl
index bff3865..d095744 100644
--- a/telecomm/java/com/android/internal/telecom/IVideoProvider.aidl
+++ b/telecomm/java/com/android/internal/telecom/IVideoProvider.aidl
@@ -39,7 +39,7 @@ oneway interface IVideoProvider {
void setZoom(float value);
- void sendSessionModifyRequest(in VideoProfile reqProfile);
+ void sendSessionModifyRequest(in VideoProfile fromProfile, in VideoProfile toProfile);
void sendSessionModifyResponse(in VideoProfile responseProfile);
diff --git a/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl b/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl
index 1fd88e7..4ff0b43 100644
--- a/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl
+++ b/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl
@@ -52,7 +52,7 @@ oneway interface IImsVideoCallProvider {
void setZoom(float value);
- void sendSessionModifyRequest(in VideoProfile reqProfile);
+ void sendSessionModifyRequest(in VideoProfile fromProfile, in VideoProfile toProfile);
void sendSessionModifyResponse(in VideoProfile responseProfile);