diff options
99 files changed, 2117 insertions, 584 deletions
| diff --git a/api/current.txt b/api/current.txt index 8716381d8794..0ef476632ee3 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 f11e11352df8..3aa6ca0cd473 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/Application.java b/core/java/android/app/Application.java index 75e4babeb524..1174387d410f 100644 --- a/core/java/android/app/Application.java +++ b/core/java/android/app/Application.java @@ -18,6 +18,7 @@ package android.app;  import java.util.ArrayList; +import android.annotation.CallSuper;  import android.content.ComponentCallbacks;  import android.content.ComponentCallbacks2;  import android.content.Context; @@ -89,6 +90,7 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 {       * service, or receiver in a process.       * If you override this method, be sure to call super.onCreate().       */ +    @CallSuper      public void onCreate() {      } @@ -98,9 +100,11 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 {       * removed by simply killing them; no user code (including this callback)       * is executed when doing so.       */ +    @CallSuper      public void onTerminate() {      } +    @CallSuper      public void onConfigurationChanged(Configuration newConfig) {          Object[] callbacks = collectComponentCallbacks();          if (callbacks != null) { @@ -110,6 +114,7 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 {          }      } +    @CallSuper      public void onLowMemory() {          Object[] callbacks = collectComponentCallbacks();          if (callbacks != null) { @@ -119,6 +124,7 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 {          }      } +    @CallSuper      public void onTrimMemory(int level) {          Object[] callbacks = collectComponentCallbacks();          if (callbacks != null) { diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java index b1a5d214c2b9..fa11221cc841 100644 --- a/core/java/android/app/SearchDialog.java +++ b/core/java/android/app/SearchDialog.java @@ -165,8 +165,6 @@ public class SearchDialog extends Dialog {          setContentView(com.android.internal.R.layout.search_bar);          // get the view elements for local access -        SearchBar searchBar = (SearchBar) findViewById(com.android.internal.R.id.search_bar); -        searchBar.setSearchDialog(this);          mSearchView = (SearchView) findViewById(com.android.internal.R.id.search_view);          mSearchView.setIconified(false);          mSearchView.setOnCloseListener(mOnCloseListener); @@ -618,8 +616,6 @@ public class SearchDialog extends Dialog {       */      public static class SearchBar extends LinearLayout { -        private SearchDialog mSearchDialog; -          public SearchBar(Context context, AttributeSet attrs) {              super(context, attrs);          } @@ -628,18 +624,6 @@ public class SearchDialog extends Dialog {              super(context);          } -        public void setSearchDialog(SearchDialog searchDialog) { -            mSearchDialog = searchDialog; -        } - -        /** -         * Don't allow action modes in a SearchBar, it looks silly. -         */ -        @Override -        public ActionMode startActionModeForChild(View child, ActionMode.Callback callback) { -            return null; -        } -          @Override          public ActionMode startActionModeForChild(                  View child, ActionMode.Callback callback, int type) { diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 4b72dc37fa9d..8009b6c6ce4d 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 833bc0063e51..e81e7c14af04 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 54fe7860219d..d0298cdc7ff9 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 a4d6be091bc5..691798f71991 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 451abea951d6..59c7c6d34eb8 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 75dc0a2d1509..f62e6a2f1449 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 f240fd6ad2a4..babb4e9066be 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 78604bfa294c..040fd371cb02 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 8d35b837083c..712fdba6dd25 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 310412f9ba02..05866f07f9a9 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 c3ac278760f8..b4cbf35ac60e 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 b8110e3a3ac8..61ee00c55fe0 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 e347faa48fb9..62ca1f0f3935 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 8dd7836a6bf6..204866432000 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 52485ddb7fa7..ce94727cd9f5 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/os/MobileRadioPowerCalculator.java b/core/java/com/android/internal/os/MobileRadioPowerCalculator.java index 9711c3bd37a1..8586d76a75ee 100644 --- a/core/java/com/android/internal/os/MobileRadioPowerCalculator.java +++ b/core/java/com/android/internal/os/MobileRadioPowerCalculator.java @@ -52,7 +52,7 @@ public class MobileRadioPowerCalculator extends PowerCalculator {      public MobileRadioPowerCalculator(PowerProfile profile, BatteryStats stats) {          mPowerRadioOn = profile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE);          for (int i = 0; i < mPowerBins.length; i++) { -            mPowerBins[i] = profile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE, i); +            mPowerBins[i] = profile.getAveragePower(PowerProfile.POWER_RADIO_ON, i);          }          mPowerScan = profile.getAveragePower(PowerProfile.POWER_RADIO_SCANNING);          mStats = stats; @@ -128,7 +128,9 @@ public class MobileRadioPowerCalculator extends PowerCalculator {          }          if (power != 0) { -            app.noCoveragePercent = noCoverageTimeMs * 100.0 / signalTimeMs; +            if (signalTimeMs != 0) { +                app.noCoveragePercent = noCoverageTimeMs * 100.0 / signalTimeMs; +            }              app.mobileActive = remainingActiveTimeMs;              app.mobileActiveCount = stats.getMobileRadioActiveUnknownCount(statsType);              app.mobileRadioPowerMah = power; diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index 6f104dd0eb24..60c5e420d24f 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 64e6c69e3b12..f58ab03bc7dd 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 bbdd860d418e..5448214aefb4 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 8b65fd1db25a..87b81d5fcad2 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 3655adcede6a..eab56689bbf5 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 26b82c5166ad..662ecd332502 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 000000000000..e159373602c3 --- /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 000000000000..7ae788eaf058 --- /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 a162b4a1c1c2..e3930cdbdf8a 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/anim/ic_checkbox_unchecked_box_inner_merged_animation.xml b/core/res/res/anim/ic_checkbox_to_checked_box_inner_merged_animation.xml index b5ad5e9d444c..e522453162aa 100644 --- a/core/res/res/anim/ic_checkbox_unchecked_box_inner_merged_animation.xml +++ b/core/res/res/anim/ic_checkbox_to_checked_box_inner_merged_animation.xml @@ -1,6 +1,5 @@  <?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2015 The Android Open Source Project +<!-- 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. @@ -15,8 +14,7 @@       limitations under the License.  --> -<set -    xmlns:android="http://schemas.android.com/apk/res/android" > +<set xmlns:android="http://schemas.android.com/apk/res/android">      <objectAnimator          android:duration="166"          android:propertyName="pathData" @@ -24,8 +22,7 @@          android:valueTo="M 0.0,-0.05 l 0.0,0.0 c 0.02761423749,0.0 0.05,0.02238576251 0.05,0.05 l 0.0,0.0 c 0.0,0.02761423749 -0.02238576251,0.05 -0.05,0.05 l 0.0,0.0 c -0.02761423749,0.0 -0.05,-0.02238576251 -0.05,-0.05 l 0.0,0.0 c 0.0,-0.02761423749 0.02238576251,-0.05 0.05,-0.05 Z M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"          android:valueType="pathType"          android:interpolator="@interpolator/ic_checkbox_unchecked_animation_interpolator_1" /> -    <set -        android:ordering="sequentially" > +    <set android:ordering="sequentially">          <objectAnimator              android:duration="166"              android:propertyName="fillAlpha" diff --git a/core/res/res/anim/ic_checkbox_unchecked_box_outer_merged_animation.xml b/core/res/res/anim/ic_checkbox_to_checked_box_outer_merged_animation.xml index 066971a146a4..628e9674d724 100644 --- a/core/res/res/anim/ic_checkbox_unchecked_box_outer_merged_animation.xml +++ b/core/res/res/anim/ic_checkbox_to_checked_box_outer_merged_animation.xml @@ -1,6 +1,5 @@  <?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2015 The Android Open Source Project +<!-- 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. @@ -15,10 +14,8 @@       limitations under the License.  --> -<set -    xmlns:android="http://schemas.android.com/apk/res/android" > -    <set -        android:ordering="sequentially" > +<set xmlns:android="http://schemas.android.com/apk/res/android"> +    <set android:ordering="sequentially">          <objectAnimator              android:duration="200"              android:propertyName="pathData" @@ -34,8 +31,7 @@              android:valueType="pathType"              android:interpolator="@interpolator/ic_checkbox_unchecked_animation_interpolator_1" />      </set> -    <set -        android:ordering="sequentially" > +    <set android:ordering="sequentially">          <objectAnimator              android:duration="166"              android:propertyName="fillAlpha" diff --git a/core/res/res/anim/ic_checkbox_unchecked_icon_null_animation.xml b/core/res/res/anim/ic_checkbox_to_checked_icon_null_animation.xml index fc40d476c8b4..6fa3fd520aa5 100644 --- a/core/res/res/anim/ic_checkbox_unchecked_icon_null_animation.xml +++ b/core/res/res/anim/ic_checkbox_to_checked_icon_null_animation.xml @@ -1,6 +1,5 @@  <?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2015 The Android Open Source Project +<!-- 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. @@ -15,10 +14,8 @@       limitations under the License.  --> -<set -    xmlns:android="http://schemas.android.com/apk/res/android" > -    <set -        android:ordering="sequentially" > +<set xmlns:android="http://schemas.android.com/apk/res/android"> +    <set android:ordering="sequentially">          <objectAnimator              android:duration="200"              android:propertyName="scaleX" @@ -32,8 +29,7 @@              android:valueTo="0.2"              android:interpolator="@interpolator/ic_checkbox_unchecked_animation_interpolator_1" />      </set> -    <set -        android:ordering="sequentially" > +    <set android:ordering="sequentially">          <objectAnimator              android:duration="200"              android:propertyName="scaleY" diff --git a/core/res/res/anim/ic_checkbox_checked_box_inner_merged_animation.xml b/core/res/res/anim/ic_checkbox_to_unchecked_box_inner_merged_animation.xml index 7be32afd424c..d35b42633ce8 100644 --- a/core/res/res/anim/ic_checkbox_checked_box_inner_merged_animation.xml +++ b/core/res/res/anim/ic_checkbox_to_unchecked_box_inner_merged_animation.xml @@ -1,6 +1,5 @@  <?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2015 The Android Open Source Project +<!-- 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. @@ -15,10 +14,8 @@       limitations under the License.  --> -<set -    xmlns:android="http://schemas.android.com/apk/res/android" > -    <set -        android:ordering="sequentially" > +<set xmlns:android="http://schemas.android.com/apk/res/android"> +    <set android:ordering="sequentially">          <objectAnimator              android:duration="166"              android:propertyName="pathData" @@ -34,8 +31,7 @@              android:valueType="pathType"              android:interpolator="@interpolator/ic_checkbox_checked_animation_interpolator_1" />      </set> -    <set -        android:ordering="sequentially" > +    <set android:ordering="sequentially">          <objectAnimator              android:duration="133"              android:propertyName="fillAlpha" diff --git a/core/res/res/anim/ic_checkbox_checked_check_path_merged_animation.xml b/core/res/res/anim/ic_checkbox_to_unchecked_check_path_merged_animation.xml index fcba2c83f0e3..a5d814e32642 100644 --- a/core/res/res/anim/ic_checkbox_checked_check_path_merged_animation.xml +++ b/core/res/res/anim/ic_checkbox_to_unchecked_check_path_merged_animation.xml @@ -1,6 +1,5 @@  <?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2015 The Android Open Source Project +<!-- 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. @@ -15,8 +14,7 @@       limitations under the License.  --> -<set -    xmlns:android="http://schemas.android.com/apk/res/android" > +<set xmlns:android="http://schemas.android.com/apk/res/android">      <objectAnimator          android:duration="166"          android:propertyName="pathData" @@ -24,8 +22,7 @@          android:valueTo="M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M 0.0,1.42500305176 c 0.0,0.0 -1.4234161377,-1.40159606934 -1.4234161377,-1.40159606934 c 0.0,0.0 1.41409301758,-1.41409301758 1.41409301758,-1.41409301758 c 0.0,0.0 0.00932312011719,-0.0124053955078 0.00932312011719,-0.0124053955078 c 0.0,0.0 0.0234069824219,-0.0235137939453 0.0234069824219,-0.0235137939453 c 0.0,0.0 1.41409301758,1.41409301758 1.41409301758,1.41409301758 c 0.0,0.0 -1.4375,1.43751525879 -1.4375,1.43751525879 Z"          android:valueType="pathType"          android:interpolator="@interpolator/ic_checkbox_checked_animation_interpolator_1" /> -    <set -        android:ordering="sequentially" > +    <set android:ordering="sequentially" >          <objectAnimator              android:duration="133"              android:propertyName="fillAlpha" diff --git a/core/res/res/anim/ic_checkbox_checked_icon_null_animation.xml b/core/res/res/anim/ic_checkbox_to_unchecked_icon_null_animation.xml index 312003f1002b..0f07b0e070fb 100644 --- a/core/res/res/anim/ic_checkbox_checked_icon_null_animation.xml +++ b/core/res/res/anim/ic_checkbox_to_unchecked_icon_null_animation.xml @@ -1,6 +1,5 @@  <?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2015 The Android Open Source Project +<!-- 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. @@ -15,10 +14,8 @@       limitations under the License.  --> -<set -    xmlns:android="http://schemas.android.com/apk/res/android" > -    <set -        android:ordering="sequentially" > +<set xmlns:android="http://schemas.android.com/apk/res/android"> +    <set android:ordering="sequentially">          <objectAnimator              android:duration="166"              android:propertyName="scaleX" @@ -32,8 +29,7 @@              android:valueTo="0.2"              android:interpolator="@interpolator/ic_checkbox_checked_animation_interpolator_1" />      </set> -    <set -        android:ordering="sequentially" > +    <set android:ordering="sequentially">          <objectAnimator              android:duration="166"              android:propertyName="scaleY" diff --git a/core/res/res/drawable/btn_check_material_anim.xml b/core/res/res/drawable/btn_check_material_anim.xml index 7cb1b89904b6..710a29116469 100644 --- a/core/res/res/drawable/btn_check_material_anim.xml +++ b/core/res/res/drawable/btn_check_material_anim.xml @@ -1,5 +1,5 @@  <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2014 The Android Open Source Project +<!-- 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. @@ -15,24 +15,19 @@  -->  <animated-selector xmlns:android="http://schemas.android.com/apk/res/android"> -      <item -        android:id="@+id/on" +        android:id="@+id/checked"          android:state_checked="true"          android:drawable="@drawable/ic_checkbox_checked" /> -      <item -        android:id="@+id/off" +        android:id="@+id/unchecked"          android:drawable="@drawable/ic_checkbox_unchecked" /> -      <transition -        android:fromId="@+id/off" -        android:toId="@+id/on" -        android:drawable="@drawable/ic_checkbox_unchecked_animation" /> - +        android:fromId="@+id/unchecked" +        android:toId="@+id/checked" +        android:drawable="@drawable/ic_checkbox_unchecked_to_checked_animation" />      <transition -        android:fromId="@+id/on" -        android:toId="@+id/off" -        android:drawable="@drawable/ic_checkbox_checked_animation" /> - +        android:fromId="@+id/checked" +        android:toId="@+id/unchecked" +        android:drawable="@drawable/ic_checkbox_checked_to_unchecked_animation" />  </animated-selector> diff --git a/core/res/res/drawable/ic_checkbox_checked.xml b/core/res/res/drawable/ic_checkbox_checked.xml index cc7b5df6fac4..ecde41443b8b 100644 --- a/core/res/res/drawable/ic_checkbox_checked.xml +++ b/core/res/res/drawable/ic_checkbox_checked.xml @@ -1,6 +1,5 @@  <?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2015 The Android Open Source Project +<!-- 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. @@ -15,24 +14,23 @@       limitations under the License.  --> -<vector -    xmlns:android="http://schemas.android.com/apk/res/android" -    android:name="ic_checkbox_checked" -    android:width="32dp" -    android:viewportWidth="48" -    android:height="32dp" -    android:viewportHeight="48" -    android:tint="?attr/colorControlActivated" > +<vector xmlns:android="http://schemas.android.com/apk/res/android" +        android:name="ic_checkbox_checked" +        android:width="32dp" +        android:viewportWidth="48" +        android:height="32dp" +        android:viewportHeight="48" +        android:tint="@color/control_checkable_material">      <group          android:name="icon_null"          android:translateX="24"          android:translateY="24"          android:scaleX="0.2" -        android:scaleY="0.2" > +        android:scaleY="0.2">          <group              android:name="check"              android:scaleX="7.5" -            android:scaleY="7.5" > +            android:scaleY="7.5">              <path                  android:name="check_path_merged"                  android:pathData="M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M -2.0,5.00001525879 c 0.0,0.0 -5.0,-5.00001525879 -5.0,-5.00001525879 c 0.0,0.0 1.41409301758,-1.41409301758 1.41409301758,-1.41409301758 c 0.0,0.0 3.58590698242,3.58601379395 3.58590698242,3.58601379395 c 0.0,0.0 7.58590698242,-7.58601379395 7.58590698242,-7.58601379395 c 0.0,0.0 1.41409301758,1.41409301758 1.41409301758,1.41409301758 c 0.0,0.0 -9.0,9.00001525879 -9.0,9.00001525879 Z" @@ -41,7 +39,7 @@          <group              android:name="box_dilate"              android:scaleX="7.5" -            android:scaleY="7.5" > +            android:scaleY="7.5">              <path                  android:name="box_inner_merged"                  android:pathData="M 0.0,-1.0 l 0.0,0.0 c 0.5522847498,0.0 1.0,0.4477152502 1.0,1.0 l 0.0,0.0 c 0.0,0.5522847498 -0.4477152502,1.0 -1.0,1.0 l 0.0,0.0 c -0.5522847498,0.0 -1.0,-0.4477152502 -1.0,-1.0 l 0.0,0.0 c 0.0,-0.5522847498 0.4477152502,-1.0 1.0,-1.0 Z M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" diff --git a/core/res/res/drawable/ic_checkbox_checked_animation.xml b/core/res/res/drawable/ic_checkbox_checked_to_unchecked_animation.xml index af5eeeea0968..fad2233fa7a2 100644 --- a/core/res/res/drawable/ic_checkbox_checked_animation.xml +++ b/core/res/res/drawable/ic_checkbox_checked_to_unchecked_animation.xml @@ -1,6 +1,5 @@  <?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2015 The Android Open Source Project +<!-- 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. @@ -15,16 +14,15 @@       limitations under the License.  --> -<animated-vector -    xmlns:android="http://schemas.android.com/apk/res/android" -    android:drawable="@drawable/ic_checkbox_checked" > +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" +                 android:drawable="@drawable/ic_checkbox_checked">      <target          android:name="icon_null" -        android:animation="@anim/ic_checkbox_checked_icon_null_animation" /> +        android:animation="@anim/ic_checkbox_to_unchecked_icon_null_animation" />      <target          android:name="check_path_merged" -        android:animation="@anim/ic_checkbox_checked_check_path_merged_animation" /> +        android:animation="@anim/ic_checkbox_to_unchecked_check_path_merged_animation" />      <target          android:name="box_inner_merged" -        android:animation="@anim/ic_checkbox_checked_box_inner_merged_animation" /> +        android:animation="@anim/ic_checkbox_to_unchecked_box_inner_merged_animation" />  </animated-vector> diff --git a/core/res/res/drawable/ic_checkbox_unchecked.xml b/core/res/res/drawable/ic_checkbox_unchecked.xml index 410f0bcc901e..3329b46f5a40 100644 --- a/core/res/res/drawable/ic_checkbox_unchecked.xml +++ b/core/res/res/drawable/ic_checkbox_unchecked.xml @@ -1,6 +1,5 @@  <?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2015 The Android Open Source Project +<!-- 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. @@ -15,24 +14,23 @@       limitations under the License.  --> -<vector -    xmlns:android="http://schemas.android.com/apk/res/android" -    android:name="ic_checkbox_unchecked" -    android:width="32dp" -    android:viewportWidth="48" -    android:height="32dp" -    android:viewportHeight="48" -    android:tint="?attr/colorControlNormal" > +<vector xmlns:android="http://schemas.android.com/apk/res/android" +        android:name="ic_checkbox_unchecked" +        android:width="32dp" +        android:viewportWidth="48" +        android:height="32dp" +        android:viewportHeight="48" +        android:tint="@color/control_checkable_material">      <group          android:name="icon_null"          android:translateX="24"          android:translateY="24"          android:scaleX="0.2" -        android:scaleY="0.2" > +        android:scaleY="0.2">          <group              android:name="check"              android:scaleX="7.5" -            android:scaleY="7.5" > +            android:scaleY="7.5">              <path                  android:name="box_outer_merged"                  android:pathData="M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M -2.0,5.00001525879 c 0.0,0.0 -1.4234161377,-1.40159606934 -1.4234161377,-1.40159606934 c 0.0,0.0 1.41409301758,-1.41409301758 1.41409301758,-1.41409301758 c 0.0,0.0 0.00932312011719,-0.0124053955078 0.00932312011719,-0.0124053955078 c 0.0,0.0 0.0234069824219,-0.0235137939453 0.0234069824219,-0.0235137939453 c 0.0,0.0 1.41409301758,1.41409301758 1.41409301758,1.41409301758 c 0.0,0.0 -1.4375,1.43751525879 -1.4375,1.43751525879 Z" @@ -42,7 +40,7 @@          <group              android:name="box_dilate"              android:scaleX="7.5" -            android:scaleY="7.5" > +            android:scaleY="7.5">              <path                  android:name="box_inner_merged"                  android:pathData="M -7.0,-7.0 l 14.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,14.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l -14.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-14.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" diff --git a/core/res/res/drawable/ic_checkbox_unchecked_animation.xml b/core/res/res/drawable/ic_checkbox_unchecked_to_checked_animation.xml index 605fce117523..68351701533a 100644 --- a/core/res/res/drawable/ic_checkbox_unchecked_animation.xml +++ b/core/res/res/drawable/ic_checkbox_unchecked_to_checked_animation.xml @@ -1,6 +1,5 @@  <?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2015 The Android Open Source Project +<!-- 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. @@ -15,16 +14,15 @@       limitations under the License.  --> -<animated-vector -    xmlns:android="http://schemas.android.com/apk/res/android" -    android:drawable="@drawable/ic_checkbox_unchecked" > +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" +                 android:drawable="@drawable/ic_checkbox_unchecked">      <target          android:name="icon_null" -        android:animation="@anim/ic_checkbox_unchecked_icon_null_animation" /> +        android:animation="@anim/ic_checkbox_to_checked_icon_null_animation" />      <target          android:name="box_outer_merged" -        android:animation="@anim/ic_checkbox_unchecked_box_outer_merged_animation" /> +        android:animation="@anim/ic_checkbox_to_checked_box_outer_merged_animation" />      <target          android:name="box_inner_merged" -        android:animation="@anim/ic_checkbox_unchecked_box_inner_merged_animation" /> +        android:animation="@anim/ic_checkbox_to_checked_box_inner_merged_animation" />  </animated-vector> 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 000000000000..63cd584ef2b7 --- /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 1eea4e124af3..6e102f35b2b8 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 bf1e383ed72f..95c24599a738 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 291481782684..1c4b5f7ec7c8 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 83ac6c1c038b..297b30272d7e 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 a57b3b80e347..28ffbfa18352 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 e679e0a7fd83..f02fed150460 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/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd index fc7997071b50..b06da5643f86 100644 --- a/docs/html/guide/topics/resources/providing-resources.jd +++ b/docs/html/guide/topics/resources/providing-resources.jd @@ -129,7 +129,7 @@ are compiled into the following drawable resource subtypes:</p>      <td><code>mipmap/</code></td>      <td>Drawable files for different launcher icon densities. For more information on managing      launcher icons with {@code mipmap/} folders, see -    <a href="{@docRoot}tools/project/index.html#mipmap">Managing Projects Overview</a>.</td> +    <a href="{@docRoot}tools/projects/index.html#mipmap">Managing Projects Overview</a>.</td>    </tr>    <tr> diff --git a/docs/html/tools/building/multidex.jd b/docs/html/tools/building/multidex.jd index 49cde8ccddce..e441a7c63bd3 100644 --- a/docs/html/tools/building/multidex.jd +++ b/docs/html/tools/building/multidex.jd @@ -415,30 +415,40 @@ dependencies {  <h2 id="testing">Testing Multidex Apps</h2>  <p> -  Testing apps that use multidex configuration require some additional steps and configuration. -  Since the location of code for classes is not within a single DEX file, instrumentation tests do -  not run properly unless configured for multidex. +  When using instrumentation tests with multidex apps, additional configuration is required to +  enable the test instrumentation. Because the location of code for classes in multidex apps is not +  within a single DEX file, instrumentation tests do not run properly unless configured for +  multidex.  </p>  <p> -  When testing a multidex app with instrumentation tests, use +  To test a multidex app with instrumentation tests, configure the    <a href="{@docRoot}reference/com/android/test/runner/MultiDexTestRunner.html">    MultiDexTestRunner</a> from the multidex testing support library. The following sample -  {@code build.gradle} file, demonstrates how to configure your build to use this test runner: +  {@code build.gradle} file demonstrates how to configure your build to use this test runner:  </p>  <pre>  android {    defaultConfig {        ... -      testInstrumentationRunner "android.support.multidex.MultiDexTestRunner" +      testInstrumentationRunner "com.android.test.runner.MultiDexTestRunner"    }  } +</pre> +<p class="note"> +  <strong>Note:</strong> With Android Plugin for Gradle versions lower than 1.1, you need to add +  the following dependency for <code>multidex-instrumentation</code>: +<pre>  dependencies { -    androidTestCompile 'com.android.support:multidex-instrumentation:1.0.0' +    androidTestCompile('com.android.support:multidex-instrumentation:1.0.1') { +         exclude group: 'com.android.support', module: 'multidex' +    }         }  </pre> +</p> +  <p>    You may use the instrumentation test runner class directly or extend it to fit your testing @@ -455,4 +465,4 @@ public void onCreate(Bundle arguments) {  <p class="note">    <strong>Note:</strong> Use of multidex for creating a test APK is not currently supported. -</p>
\ No newline at end of file +</p> diff --git a/docs/html/tools/revisions/studio.jd b/docs/html/tools/revisions/studio.jd index 4f153e30703b..f530a5f28fdc 100644 --- a/docs/html/tools/revisions/studio.jd +++ b/docs/html/tools/revisions/studio.jd @@ -50,7 +50,7 @@ Android Studio, as denoted by revision number. </p>      <p>Various fixes and enhancements:</p>      <ul>        <li>Updated the Android runtime window to include the -        <a href="{@docRoot}tools/studio/index.html#memory-monitor">Memory Monitor</a> tool +        <a href="{@docRoot}tools/studio/index.html#mem-cpu">Memory Monitor</a> tool          and added a tab for CPU performance monitoring.</li>        <li>Added a <em>Captures</em> tab in the left margin to display the captured memory and CPU          performance data files, such as CPU method tracking and memory heap snapshots.</li> diff --git a/docs/html/tools/studio/index.jd b/docs/html/tools/studio/index.jd index 95cdb76ff9b2..13a2fead0394 100644 --- a/docs/html/tools/studio/index.jd +++ b/docs/html/tools/studio/index.jd @@ -53,7 +53,8 @@ Studio features.</p>  "{@docRoot}tools/workflow/index.html">Workflow</a> section, such as <a href=  "{@docRoot}tools/projects/projects-studio.html">Managing Projects from Android Studio</a> and  <a href="{@docRoot}tools/building/building-studio.html">Building and Running from Android -Studio</a>.</p> +Studio</a>. For a summary of the latest changes to Android Studio, see the +<a href="{@docRoot}tools/revisions/studio.html">Android Studio Release Notes</a>.</p> @@ -282,13 +283,6 @@ device or emulator, click the <strong>Android</strong> tab in the lower left cor  runtime window to launch the Android runtime window. Click the <strong>Memory</strong> or  <strong>CPU</strong> tab. </p> - -<h3 id="memory-monitor">Memory Monitor</h3> -<p>Android Studio provides a memory monitor view so you can more easily monitor your -app's memory usage to find deallocated objects, locate memory leaks and track the amount of -memory the connected device is using. With your app running on a device or emulator, click the -<strong>Memory Monitor</strong> tab in the lower right corner to launch the memory monitor. </p> -  <img src="{@docRoot}images/tools/studio-memory-monitor.png" srcset="{@docRoot}images/tools/studio-memory-monitor_2x.png 2x" width"635" height="171" alt="" />      <p class="img-caption"><strong>Figure 4.</strong> Monitor memory and CPU usage.</p> @@ -722,10 +716,7 @@ SDK Manager page. </p>  a variety of locales to the app's translation file. With  <a href="https://tools.ietf.org/html/bcp47">BCP 47</a> support, the editor combines language and  region codes into a single selection for targeted localizations. Color codes indicate whether a -locale is complete or still missing string translations. You can also use the plugin to export -your strings to the -<a href="{@docRoot}distribute/googleplay/developer-console.html">Google Play Developer Console</a> -for translation, then download and import your translations back into your project. </p> +locale is complete or still missing string translations. </p>  <p>To access the Translations Editor, open a <code>strings.xml</code> file and click the  <strong>Open Editor</strong> link.  </p> diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java index b03fe3a10328..4a06805cfb9d 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 518067b1c738..257ab54c9495 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 20dd52435dca..094aa75bf4b2 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 19abd05553bf..c5cf211a6f2d 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 e993b50edad4..0dbe78848813 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 aca7c526c323..2f79c5875e37 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 82da27dc9509..c0782608d9e0 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 ca238d77dc6b..8b83c17f9f3b 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 6eaf812aea71..19900d001683 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 9fac8d131d0c..ab55c8d841d3 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 88e784a9fa2c..7328d7a5fd4d 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 472da0262ebd..11671d8f30b0 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 3dae5438cb8f..ee12374094de 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 cb05cc561d7a..a66a1e5272c7 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 8220a744794e..6f7b58348758 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 e060b4a39e8d..49ce4279f684 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 845d53a19213..929258d5937a 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 532b01f7431b..db319e96dc8a 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 4082bf5adb27..b702e3508d0b 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 53e69e316c94..7eaa728e61d1 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 5b4b4fd00b76..dda9358a8940 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 595c9ede07a7..0264f3d056ba 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 8466a5a462f0..8606a599c97a 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 c8af2d44ec58..43a1be1d0642 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 c62ad663da3d..7077a17f00df 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 c3ede75eb6fa..f77ac4b0c4db 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 23a65e8ca4a3..ca325675e5e5 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 71158975bf65..1e34663769d6 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 8aded45b8d25..ccb2b5aa0549 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 375c5d8aeda9..32e1e6de687f 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 a34b25a8dc31..e438c84027db 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 6a1efee4f1be..7cd6d09e2812 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 80d65154e5ea..58d0fce9604f 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 bfe8b5c99629..6c1023c5671d 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 45909db9255b..759a6bea345c 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/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index a07591c94110..ac55292bbd30 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -488,7 +488,8 @@ public class Vpn {          try {              // Restricted users are not allowed to create VPNs, they are tied to Owner              UserInfo user = mgr.getUserInfo(mUserHandle); -            if (user.isRestricted() || mgr.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) { +            if (user.isRestricted() || mgr.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN, +                    new UserHandle(mUserHandle))) {                  throw new SecurityException("Restricted users cannot establish VPNs");              } @@ -896,7 +897,8 @@ public class Vpn {          }          UserManager mgr = UserManager.get(mContext);          UserInfo user = mgr.getUserInfo(mUserHandle); -        if (user.isRestricted() || mgr.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) { +        if (user.isRestricted() || mgr.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN, +                    new UserHandle(mUserHandle))) {              throw new SecurityException("Restricted users cannot establish VPNs");          } diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index 7cccef2e8fcf..3dc282bb7d81 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 5ac027dc54ab..e650456c0bf9 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 c82df4827f53..28da73ccb3ed 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 a8ec8672bd6f..6f01ca02b580 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 fee64951e3e3..adab00bb1e25 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 3060f40602ad..4bc639b7b101 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 1a3091011b01..bb65ce9aa63f 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 1493b208ad69..9ca9f316cd35 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/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index 1431eb8be125..ebd3f12d0fc7 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -1143,8 +1143,12 @@ public class TelecomManager {      public void placeCall(Uri address, Bundle extras) {          ITelecomService service = getTelecomService();          if (service != null) { +            if (address == null) { +                Log.w(TAG, "Cannot place call to empty address."); +            }              try { -                service.placeCall(address, extras, mContext.getOpPackageName()); +                service.placeCall(address, extras == null ? new Bundle() : extras, +                        mContext.getOpPackageName());              } catch (RemoteException e) {                  Log.e(TAG, "Error calling ITelecomService#placeCall", e);              } diff --git a/telecomm/java/android/telecom/VideoCallImpl.java b/telecomm/java/android/telecom/VideoCallImpl.java index 7a82c1bb3e3d..331f57ed8a54 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 bff3865e8840..d095744b6b34 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 1fd88e701eb3..4ff0b4367ea5 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); |