Merge "Fix "@null" resource values in LayoutLib." into lmp-dev
diff --git a/Android.mk b/Android.mk
index b419231..1cdc709 100644
--- a/Android.mk
+++ b/Android.mk
@@ -329,6 +329,7 @@
media/java/android/media/projection/IMediaProjection.aidl \
media/java/android/media/projection/IMediaProjectionCallback.aidl \
media/java/android/media/projection/IMediaProjectionManager.aidl \
+ media/java/android/media/projection/IMediaProjectionWatcherCallback.aidl \
media/java/android/media/routing/IMediaRouteService.aidl \
media/java/android/media/routing/IMediaRouteClientCallback.aidl \
media/java/android/media/routing/IMediaRouter.aidl \
diff --git a/api/current.txt b/api/current.txt
index 0154dd2..368dcef 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2047,6 +2047,8 @@
field public static final int TextAppearance_Material_Widget_TextView = 16974381; // 0x103022d
field public static final int TextAppearance_Material_Widget_TextView_PopupMenu = 16974382; // 0x103022e
field public static final int TextAppearance_Material_Widget_TextView_SpinnerItem = 16974383; // 0x103022f
+ field public static final int TextAppearance_Material_Widget_Toolbar_Subtitle = 16974569; // 0x10302e9
+ field public static final int TextAppearance_Material_Widget_Toolbar_Title = 16974568; // 0x10302e8
field public static final int TextAppearance_Material_WindowTitle = 16974361; // 0x1030219
field public static final int TextAppearance_Medium = 16973892; // 0x1030044
field public static final int TextAppearance_Medium_Inverse = 16973893; // 0x1030045
@@ -8595,19 +8597,26 @@
}
public class LauncherApps {
+ method public void addCallback(android.content.pm.LauncherApps.Callback);
+ method public void addCallback(android.content.pm.LauncherApps.Callback, android.os.Handler);
method public void addOnAppsChangedCallback(android.content.pm.LauncherApps.OnAppsChangedCallback);
method public void addOnAppsChangedCallback(android.content.pm.LauncherApps.OnAppsChangedCallback, android.os.Handler);
method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
+ method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
method public boolean isActivityEnabledForProfile(android.content.ComponentName, android.os.UserHandle);
+ method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle);
method public boolean isPackageEnabledForProfile(java.lang.String, android.os.UserHandle);
+ method public void removeCallback(android.content.pm.LauncherApps.Callback);
method public void removeOnAppsChangedCallback(android.content.pm.LauncherApps.OnAppsChangedCallback);
method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle);
method public void showAppDetailsForProfile(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
method public void startActivityForProfile(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
+ method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
+ method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
}
- public static abstract class LauncherApps.OnAppsChangedCallback {
- ctor public LauncherApps.OnAppsChangedCallback();
+ public static abstract class LauncherApps.Callback {
+ ctor public LauncherApps.Callback();
method public abstract void onPackageAdded(java.lang.String, android.os.UserHandle);
method public abstract void onPackageChanged(java.lang.String, android.os.UserHandle);
method public abstract void onPackageRemoved(java.lang.String, android.os.UserHandle);
@@ -8615,6 +8624,10 @@
method public abstract void onPackagesUnavailable(java.lang.String[], android.os.UserHandle, boolean);
}
+ public static abstract class LauncherApps.OnAppsChangedCallback extends android.content.pm.LauncherApps.Callback {
+ ctor public LauncherApps.OnAppsChangedCallback();
+ }
+
public class PackageInfo implements android.os.Parcelable {
ctor public PackageInfo();
method public int describeContents();
@@ -13304,85 +13317,6 @@
}
-package android.hardware.location {
-
- public final class GeofenceHardware {
- method public boolean addGeofence(int, int, android.hardware.location.GeofenceHardwareRequest, android.hardware.location.GeofenceHardwareCallback);
- method public int[] getMonitoringTypes();
- method public int getStatusOfMonitoringType(int);
- method public boolean pauseGeofence(int, int);
- method public boolean registerForMonitorStateChangeCallback(int, android.hardware.location.GeofenceHardwareMonitorCallback);
- method public boolean removeGeofence(int, int);
- method public boolean resumeGeofence(int, int, int);
- method public boolean unregisterForMonitorStateChangeCallback(int, android.hardware.location.GeofenceHardwareMonitorCallback);
- field public static final int GEOFENCE_ENTERED = 1; // 0x1
- field public static final int GEOFENCE_ERROR_ID_EXISTS = 2; // 0x2
- field public static final int GEOFENCE_ERROR_ID_UNKNOWN = 3; // 0x3
- field public static final int GEOFENCE_ERROR_INSUFFICIENT_MEMORY = 6; // 0x6
- field public static final int GEOFENCE_ERROR_INVALID_TRANSITION = 4; // 0x4
- field public static final int GEOFENCE_ERROR_TOO_MANY_GEOFENCES = 1; // 0x1
- field public static final int GEOFENCE_EXITED = 2; // 0x2
- field public static final int GEOFENCE_FAILURE = 5; // 0x5
- field public static final int GEOFENCE_SUCCESS = 0; // 0x0
- field public static final int GEOFENCE_UNCERTAIN = 4; // 0x4
- field public static final int MONITORING_TYPE_FUSED_HARDWARE = 1; // 0x1
- field public static final int MONITORING_TYPE_GPS_HARDWARE = 0; // 0x0
- field public static final int MONITOR_CURRENTLY_AVAILABLE = 0; // 0x0
- field public static final int MONITOR_CURRENTLY_UNAVAILABLE = 1; // 0x1
- field public static final int MONITOR_UNSUPPORTED = 2; // 0x2
- field public static final int SOURCE_TECHNOLOGY_BLUETOOTH = 16; // 0x10
- field public static final int SOURCE_TECHNOLOGY_CELL = 8; // 0x8
- field public static final int SOURCE_TECHNOLOGY_GNSS = 1; // 0x1
- field public static final int SOURCE_TECHNOLOGY_SENSORS = 4; // 0x4
- field public static final int SOURCE_TECHNOLOGY_WIFI = 2; // 0x2
- }
-
- public abstract class GeofenceHardwareCallback {
- ctor public GeofenceHardwareCallback();
- method public void onGeofenceAdd(int, int);
- method public void onGeofencePause(int, int);
- method public void onGeofenceRemove(int, int);
- method public void onGeofenceResume(int, int);
- method public void onGeofenceTransition(int, int, android.location.Location, long, int);
- }
-
- public abstract class GeofenceHardwareMonitorCallback {
- ctor public GeofenceHardwareMonitorCallback();
- method public deprecated void onMonitoringSystemChange(int, boolean, android.location.Location);
- method public void onMonitoringSystemChange(android.hardware.location.GeofenceHardwareMonitorEvent);
- }
-
- public class GeofenceHardwareMonitorEvent implements android.os.Parcelable {
- ctor public GeofenceHardwareMonitorEvent(int, int, int, android.location.Location);
- method public int describeContents();
- method public android.location.Location getLocation();
- method public int getMonitoringStatus();
- method public int getMonitoringType();
- method public int getSourceTechnologies();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator CREATOR;
- }
-
- public final class GeofenceHardwareRequest {
- ctor public GeofenceHardwareRequest();
- method public static android.hardware.location.GeofenceHardwareRequest createCircularGeofence(double, double, double);
- method public int getLastTransition();
- method public double getLatitude();
- method public double getLongitude();
- method public int getMonitorTransitions();
- method public int getNotificationResponsiveness();
- method public double getRadius();
- method public int getSourceTechnologies();
- method public int getUnknownTimer();
- method public void setLastTransition(int);
- method public void setMonitorTransitions(int);
- method public void setNotificationResponsiveness(int);
- method public void setSourceTechnologies(int);
- method public void setUnknownTimer(int);
- }
-
-}
-
package android.hardware.usb {
public class UsbAccessory implements android.os.Parcelable {
@@ -16691,33 +16625,41 @@
method public void adjustVolume(int, int);
method public android.media.routing.MediaRouter.Delegate createMediaRouterDelegate();
method public boolean dispatchMediaButtonEvent(android.view.KeyEvent);
+ method public android.media.session.MediaController.AudioInfo getAudioInfo();
method public android.os.Bundle getExtras();
method public long getFlags();
method public android.app.PendingIntent getLaunchActivity();
method public android.media.MediaMetadata getMetadata();
method public java.lang.String getPackageName();
method public android.media.session.PlaybackState getPlaybackState();
- method public java.util.List<android.media.session.MediaSession.Track> getQueue();
+ method public java.util.List<android.media.session.MediaSession.Item> getQueue();
method public java.lang.CharSequence getQueueTitle();
method public int getRatingType();
method public android.media.session.MediaSession.Token getSessionToken();
method public android.media.session.MediaController.TransportControls getTransportControls();
- method public android.media.session.MediaController.VolumeInfo getVolumeInfo();
method public void removeCallback(android.media.session.MediaController.Callback);
method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
method public void setVolumeTo(int, int);
}
+ public static final class MediaController.AudioInfo {
+ method public android.media.AudioAttributes getAudioAttributes();
+ method public int getCurrentVolume();
+ method public int getMaxVolume();
+ method public int getVolumeControl();
+ method public int getVolumeType();
+ }
+
public static abstract class MediaController.Callback {
ctor public MediaController.Callback();
+ method public void onAudioInfoChanged(android.media.session.MediaController.AudioInfo);
method public void onExtrasChanged(android.os.Bundle);
method public void onMetadataChanged(android.media.MediaMetadata);
method public void onPlaybackStateChanged(android.media.session.PlaybackState);
- method public void onQueueChanged(java.util.List<android.media.session.MediaSession.Track>);
+ method public void onQueueChanged(java.util.List<android.media.session.MediaSession.Item>);
method public void onQueueTitleChanged(java.lang.CharSequence);
method public void onSessionDestroyed();
method public void onSessionEvent(java.lang.String, android.os.Bundle);
- method public void onVolumeInfoChanged(android.media.session.MediaController.VolumeInfo);
}
public final class MediaController.TransportControls {
@@ -16731,20 +16673,12 @@
method public void sendCustomAction(android.media.session.PlaybackState.CustomAction, android.os.Bundle);
method public void sendCustomAction(java.lang.String, android.os.Bundle);
method public void setRating(android.media.Rating);
+ method public void skipToItem(long);
method public void skipToNext();
method public void skipToPrevious();
- method public void skipToTrack(long);
method public void stop();
}
- public static final class MediaController.VolumeInfo {
- method public android.media.AudioAttributes getAudioAttributes();
- method public int getCurrentVolume();
- method public int getMaxVolume();
- method public int getVolumeControl();
- method public int getVolumeType();
- }
-
public final class MediaSession {
ctor public MediaSession(android.content.Context, java.lang.String);
method public android.media.session.MediaController getController();
@@ -16764,7 +16698,7 @@
method public void setPlaybackState(android.media.session.PlaybackState);
method public void setPlaybackToLocal(android.media.AudioAttributes);
method public void setPlaybackToRemote(android.media.VolumeProvider);
- method public void setQueue(java.util.List<android.media.session.MediaSession.Track>);
+ method public void setQueue(java.util.List<android.media.session.MediaSession.Item>);
method public void setQueueTitle(java.lang.CharSequence);
field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
@@ -16785,19 +16719,13 @@
method public void onRewind();
method public void onSeekTo(long);
method public void onSetRating(android.media.Rating);
+ method public void onSkipToItem(long);
method public void onSkipToNext();
method public void onSkipToPrevious();
- method public void onSkipToTrack(long);
method public void onStop();
}
- public static final class MediaSession.Token implements android.os.Parcelable {
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator CREATOR;
- }
-
- public static final class MediaSession.Track implements android.os.Parcelable {
+ public static final class MediaSession.Item implements android.os.Parcelable {
method public int describeContents();
method public android.os.Bundle getExtras();
method public long getId();
@@ -16808,20 +16736,25 @@
field public static final int UNKNOWN_ID = -1; // 0xffffffff
}
- public static final class MediaSession.Track.Builder {
- ctor public MediaSession.Track.Builder(android.media.MediaMetadata, long, android.net.Uri);
- method public android.media.session.MediaSession.Track build();
- method public android.media.session.MediaSession.Track.Builder setExtras(android.os.Bundle);
+ public static final class MediaSession.Item.Builder {
+ ctor public MediaSession.Item.Builder(android.media.MediaMetadata, long, android.net.Uri);
+ method public android.media.session.MediaSession.Item build();
+ method public android.media.session.MediaSession.Item.Builder setExtras(android.os.Bundle);
+ }
+
+ public static final class MediaSession.Token implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
}
public final class MediaSessionManager {
- method public void addActiveSessionsListener(android.media.session.MediaSessionManager.SessionListener, android.content.ComponentName);
+ method public void addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName);
method public java.util.List<android.media.session.MediaController> getActiveSessions(android.content.ComponentName);
- method public void removeActiveSessionsListener(android.media.session.MediaSessionManager.SessionListener);
+ method public void removeOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener);
}
- public static abstract class MediaSessionManager.SessionListener {
- ctor public MediaSessionManager.SessionListener(android.content.Context);
+ public static abstract interface MediaSessionManager.OnActiveSessionsChangedListener {
method public abstract void onActiveSessionsChanged(java.util.List<android.media.session.MediaController>);
}
@@ -16845,9 +16778,9 @@
field public static final long ACTION_REWIND = 8L; // 0x8L
field public static final long ACTION_SEEK_TO = 256L; // 0x100L
field public static final long ACTION_SET_RATING = 128L; // 0x80L
+ field public static final long ACTION_SKIP_TO_ITEM = 4096L; // 0x1000L
field public static final long ACTION_SKIP_TO_NEXT = 32L; // 0x20L
field public static final long ACTION_SKIP_TO_PREVIOUS = 16L; // 0x10L
- field public static final long ACTION_SKIP_TO_TRACK = 4096L; // 0x1000L
field public static final long ACTION_STOP = 1L; // 0x1L
field public static final android.os.Parcelable.Creator CREATOR;
field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL
@@ -16871,7 +16804,7 @@
method public android.media.session.PlaybackState.Builder addCustomAction(android.media.session.PlaybackState.CustomAction);
method public android.media.session.PlaybackState build();
method public android.media.session.PlaybackState.Builder setActions(long);
- method public android.media.session.PlaybackState.Builder setActiveTrack(long);
+ method public android.media.session.PlaybackState.Builder setActiveItem(long);
method public android.media.session.PlaybackState.Builder setBufferPosition(long);
method public android.media.session.PlaybackState.Builder setErrorMessage(java.lang.CharSequence);
method public android.media.session.PlaybackState.Builder setState(int, long, float, long);
@@ -17175,8 +17108,6 @@
method public void setStreamVolume(float);
method public void setTvInputListener(android.media.tv.TvView.TvInputListener);
method public void tune(java.lang.String, android.net.Uri);
- field public static final int ERROR_INPUT_DISCONNECTED = 1; // 0x1
- field public static final int ERROR_INPUT_NOT_CONNECTED = 0; // 0x0
}
public static abstract interface TvView.OnUnhandledInputEventListener {
@@ -17186,9 +17117,10 @@
public static abstract class TvView.TvInputListener {
ctor public TvView.TvInputListener();
method public void onChannelRetuned(java.lang.String, android.net.Uri);
+ method public void onConnectionFailed(java.lang.String);
method public void onContentAllowed(java.lang.String);
method public void onContentBlocked(java.lang.String, android.media.tv.TvContentRating);
- method public void onError(java.lang.String, int);
+ method public void onDisconnected(java.lang.String);
method public void onTrackSelected(java.lang.String, int, java.lang.String);
method public void onTracksChanged(java.lang.String, java.util.List<android.media.tv.TvTrackInfo>);
method public void onVideoAvailable(java.lang.String);
@@ -28897,12 +28829,10 @@
method public final void setAudioModeIsVoip(boolean);
method public final void setCallCapabilities(int);
method public final void setCallerDisplayName(java.lang.String, int);
- method public final void setCanceled();
method public final void setConferenceableConnections(java.util.List<android.telecomm.Connection>);
method public final void setConnectionService(android.telecomm.ConnectionService);
method public final void setDialing();
method public final void setDisconnected(int, java.lang.String);
- method public final void setFailed(int, java.lang.String);
method public final void setHandle(android.net.Uri, int);
method public final void setInitialized();
method public final void setInitializing();
@@ -28916,10 +28846,8 @@
method public final void startActivityFromInCall(android.app.PendingIntent);
method public static java.lang.String stateToString(int);
field public static final int STATE_ACTIVE = 4; // 0x4
- field public static final int STATE_CANCELED = 8; // 0x8
field public static final int STATE_DIALING = 3; // 0x3
field public static final int STATE_DISCONNECTED = 6; // 0x6
- field public static final int STATE_FAILED = 7; // 0x7
field public static final int STATE_HOLDING = 5; // 0x5
field public static final int STATE_INITIALIZING = 0; // 0x0
field public static final int STATE_NEW = 1; // 0x1
@@ -29709,6 +29637,7 @@
method public int hasCarrierPrivileges();
method public boolean hasIccCard();
method public boolean iccCloseLogicalChannel(int);
+ method public byte[] iccExchangeSimIO(int, int, int, int, int, java.lang.String);
method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String);
method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String);
method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
@@ -32310,6 +32239,8 @@
method public void captureEndValues(android.transition.TransitionValues);
method public void captureStartValues(android.transition.TransitionValues);
method public int getOrdering();
+ method public android.transition.Transition getTransitionAt(int);
+ method public int getTransitionCount();
method public android.transition.TransitionSet removeTransition(android.transition.Transition);
method public android.transition.TransitionSet setOrdering(int);
field public static final int ORDERING_SEQUENTIAL = 1; // 0x1
diff --git a/cmds/appops/Android.mk b/cmds/appops/Android.mk
new file mode 100644
index 0000000..1e15204
--- /dev/null
+++ b/cmds/appops/Android.mk
@@ -0,0 +1,16 @@
+# Copyright 2014 The Android Open Source Project
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_MODULE := appops
+include $(BUILD_JAVA_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := appops
+LOCAL_SRC_FILES := appops
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_PREBUILT)
+
diff --git a/cmds/appops/MODULE_LICENSE_APACHE2 b/cmds/appops/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cmds/appops/MODULE_LICENSE_APACHE2
diff --git a/cmds/appops/NOTICE b/cmds/appops/NOTICE
new file mode 100644
index 0000000..06a9081
--- /dev/null
+++ b/cmds/appops/NOTICE
@@ -0,0 +1,190 @@
+
+ Copyright (c) 2005-2014, The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+
+ 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.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/cmds/appops/appops b/cmds/appops/appops
new file mode 100755
index 0000000..407e551
--- /dev/null
+++ b/cmds/appops/appops
@@ -0,0 +1,5 @@
+# Script to start "appwidget" on the device, which has a very rudimentary shell.
+base=/system
+export CLASSPATH=$base/framework/appops.jar
+exec app_process $base/bin com.android.commands.appops.AppOpsCommand "$@"
+
diff --git a/cmds/appops/src/com/android/commands/appops/AppOpsCommand.java b/cmds/appops/src/com/android/commands/appops/AppOpsCommand.java
new file mode 100644
index 0000000..c414f58
--- /dev/null
+++ b/cmds/appops/src/com/android/commands/appops/AppOpsCommand.java
@@ -0,0 +1,137 @@
+/*
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package com.android.commands.appops;
+
+import android.app.ActivityManager;
+import android.app.ActivityThread;
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.IPackageManager;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+
+import com.android.internal.app.IAppOpsService;
+import com.android.internal.os.BaseCommand;
+
+import java.io.PrintStream;
+
+/**
+ * This class is a command line utility for manipulating AppOps permissions.
+ */
+public class AppOpsCommand extends BaseCommand {
+
+ public static void main(String[] args) {
+ new AppOpsCommand().run(args);
+ }
+
+ @Override
+ public void onShowUsage(PrintStream out) {
+ out.println("usage: adb shell appops set <PACKAGE> <OP> "
+ + "<allow|ignore|deny|default> [--user <USER_ID>]\n"
+ + " <PACKAGE> an Android package name.\n"
+ + " <OP> an AppOps operation.\n"
+ + " <USER_ID> the user id under which the package is installed. If --user is not\n"
+ + " specified, the current user is assumed.\n");
+ }
+
+ private static final String COMMAND_SET = "set";
+
+ @Override
+ public void onRun() throws Exception {
+ String command = nextArgRequired();
+ switch (command) {
+ case COMMAND_SET:
+ runSet();
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown command '" + command + "'.");
+ }
+ }
+
+ private static final String ARGUMENT_USER = "--user";
+
+ // Modes
+ private static final String MODE_ALLOW = "allow";
+ private static final String MODE_DENY = "deny";
+ private static final String MODE_IGNORE = "ignore";
+ private static final String MODE_DEFAULT = "default";
+
+ private void runSet() throws Exception {
+ String packageName = null;
+ String op = null;
+ String mode = null;
+ int userId = UserHandle.USER_CURRENT;
+ for (String argument; (argument = nextArg()) != null;) {
+ if (ARGUMENT_USER.equals(argument)) {
+ userId = Integer.parseInt(nextArgRequired());
+ } else {
+ if (packageName == null) {
+ packageName = argument;
+ } else if (op == null) {
+ op = argument;
+ } else if (mode == null) {
+ mode = argument;
+ } else {
+ throw new IllegalArgumentException("Unsupported argument: " + argument);
+ }
+ }
+ }
+
+ if (packageName == null) {
+ throw new IllegalArgumentException("Package name not specified.");
+ } else if (op == null) {
+ throw new IllegalArgumentException("Operation not specified.");
+ } else if (mode == null) {
+ throw new IllegalArgumentException("Mode not specified.");
+ }
+
+ final int opInt = AppOpsManager.strOpToOp(op);
+ final int modeInt;
+ switch (mode) {
+ case MODE_ALLOW:
+ modeInt = AppOpsManager.MODE_ALLOWED;
+ break;
+ case MODE_DENY:
+ modeInt = AppOpsManager.MODE_ERRORED;
+ break;
+ case MODE_IGNORE:
+ modeInt = AppOpsManager.MODE_IGNORED;
+ break;
+ case MODE_DEFAULT:
+ modeInt = AppOpsManager.MODE_DEFAULT;
+ break;
+ default:
+ throw new IllegalArgumentException("Mode is invalid.");
+ }
+
+ // Parsing complete, let's execute the command.
+
+ if (userId == UserHandle.USER_CURRENT) {
+ userId = ActivityManager.getCurrentUser();
+ }
+
+ final IPackageManager pm = ActivityThread.getPackageManager();
+ final IAppOpsService appOpsService = IAppOpsService.Stub.asInterface(
+ ServiceManager.getService(Context.APP_OPS_SERVICE));
+ final int uid = pm.getPackageUid(packageName, userId);
+ if (uid < 0) {
+ throw new Exception("No UID for " + packageName + " for user " + userId);
+ }
+ appOpsService.setMode(opInt, uid, packageName, modeInt);
+ }
+}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index d9ea671..2136209 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3494,6 +3494,20 @@
synchronized (mResourcesManager) {
mCoreSettings = coreSettings;
}
+ onCoreSettingsChange();
+ }
+
+ private void onCoreSettingsChange() {
+ boolean debugViewAttributes =
+ mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0;
+ if (debugViewAttributes != View.mDebugViewAttributes) {
+ View.mDebugViewAttributes = debugViewAttributes;
+
+ // request all activities to relaunch for the changes to take place
+ for (Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) {
+ requestRelaunchActivity(entry.getKey(), null, null, 0, false, null, false);
+ }
+ }
}
private void handleUpdatePackageCompatibilityInfo(UpdateCompatibilityData data) {
@@ -4324,6 +4338,9 @@
final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24));
DateFormat.set24HourTimePref(is24Hr);
+ View.mDebugViewAttributes =
+ mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0;
+
/**
* For system applications on userdebug/eng builds, log stack
* traces of disk and network access to dropbox for analysis.
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index a6b3608..0d2ad08 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1046,7 +1046,10 @@
return packageName + " from uid " + uid + " not allowed to perform " + sOpNames[op];
}
- private int strOpToOp(String op) {
+ /**
+ * {@hide}
+ */
+ public static int strOpToOp(String op) {
Integer val = sOpStrToOp.get(op);
if (val == null) {
throw new IllegalArgumentException("Unknown operation string: " + op);
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 0ca800f..b13792b 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1612,7 +1612,7 @@
* @see #requestSync(android.accounts.Account, String, android.os.Bundle)
*/
public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
- notifyChange(uri, observer, syncToNetwork, UserHandle.getCallingUserId());
+ notifyChange(uri, observer, syncToNetwork, UserHandle.myUserId());
}
/**
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 5f046c5..a13a928 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -45,6 +45,7 @@
import android.util.AttributeSet;
import android.view.DisplayAdjustments;
import android.view.Display;
+import android.view.ViewDebug;
import android.view.WindowManager;
import java.io.File;
@@ -420,6 +421,7 @@
/**
* Return the Theme object associated with this Context.
*/
+ @ViewDebug.ExportedProperty(deepExport = true)
public abstract Resources.Theme getTheme();
/**
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 268919c..f9370b3 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -64,7 +64,7 @@
/**
* Callbacks for package changes to this and related managed profiles.
*/
- public static abstract class OnAppsChangedCallback {
+ public static abstract class Callback {
/**
* Indicates that a package was removed from the specified profile.
*
@@ -207,17 +207,17 @@
}
/**
- * Starts an activity in the specified profile.
+ * Starts a Main activity in the specified profile.
*
* @param component The ComponentName of the activity to launch
* @param user The UserHandle of the profile
* @param sourceBounds The Rect containing the source bounds of the clicked icon
* @param opts Options to pass to startActivity
*/
- public void startActivityForProfile(ComponentName component, UserHandle user, Rect sourceBounds,
+ public void startMainActivity(ComponentName component, UserHandle user, Rect sourceBounds,
Bundle opts) {
if (DEBUG) {
- Log.i(TAG, "StartActivityForProfile " + component + " " + user.getIdentifier());
+ Log.i(TAG, "StartMainActivity " + component + " " + user.getIdentifier());
}
try {
mService.startActivityAsUser(component, sourceBounds, opts, user);
@@ -235,7 +235,7 @@
* @param sourceBounds The Rect containing the source bounds of the clicked icon
* @param opts Options to pass to startActivity
*/
- public void showAppDetailsForProfile(ComponentName component, UserHandle user,
+ public void startAppDetailsActivity(ComponentName component, UserHandle user,
Rect sourceBounds, Bundle opts) {
try {
mService.showAppDetailsAsUser(component, sourceBounds, opts, user);
@@ -252,7 +252,7 @@
*
* @return true if the package exists and is enabled.
*/
- public boolean isPackageEnabledForProfile(String packageName, UserHandle user) {
+ public boolean isPackageEnabled(String packageName, UserHandle user) {
try {
return mService.isPackageEnabled(packageName, user);
} catch (RemoteException re) {
@@ -268,7 +268,7 @@
*
* @return true if the activity exists and is enabled.
*/
- public boolean isActivityEnabledForProfile(ComponentName component, UserHandle user) {
+ public boolean isActivityEnabled(ComponentName component, UserHandle user) {
try {
return mService.isActivityEnabled(component, user);
} catch (RemoteException re) {
@@ -282,8 +282,8 @@
*
* @param callback The callback to add.
*/
- public void addOnAppsChangedCallback(OnAppsChangedCallback callback) {
- addOnAppsChangedCallback(callback, null);
+ public void addCallback(Callback callback) {
+ addCallback(callback, null);
}
/**
@@ -292,7 +292,7 @@
* @param callback The callback to add.
* @param handler that should be used to post callbacks on, may be null.
*/
- public void addOnAppsChangedCallback(OnAppsChangedCallback callback, Handler handler) {
+ public void addCallback(Callback callback, Handler handler) {
synchronized (this) {
if (callback != null && !mCallbacks.contains(callback)) {
boolean addedFirstCallback = mCallbacks.size() == 0;
@@ -311,9 +311,9 @@
* Removes a callback that was previously added.
*
* @param callback The callback to remove.
- * @see #addOnAppsChangedListener(OnAppsChangedCallback)
+ * @see #addCallback(Callback)
*/
- public void removeOnAppsChangedCallback(OnAppsChangedCallback callback) {
+ public void removeCallback(Callback callback) {
synchronized (this) {
removeCallbackLocked(callback);
if (mCallbacks.size() == 0) {
@@ -325,7 +325,7 @@
}
}
- private void removeCallbackLocked(OnAppsChangedCallback callback) {
+ private void removeCallbackLocked(Callback callback) {
if (callback == null) {
throw new IllegalArgumentException("Callback cannot be null");
}
@@ -338,7 +338,7 @@
}
}
- private void addCallbackLocked(OnAppsChangedCallback callback, Handler handler) {
+ private void addCallbackLocked(Callback callback, Handler handler) {
// Remove if already present.
removeCallbackLocked(callback);
if (handler == null) {
@@ -421,7 +421,7 @@
private static final int MSG_AVAILABLE = 4;
private static final int MSG_UNAVAILABLE = 5;
- private OnAppsChangedCallback mCallback;
+ private LauncherApps.Callback mCallback;
private static class CallbackInfo {
String[] packageNames;
@@ -430,7 +430,7 @@
UserHandle user;
}
- public CallbackMessageHandler(Looper looper, OnAppsChangedCallback callback) {
+ public CallbackMessageHandler(Looper looper, LauncherApps.Callback callback) {
super(looper, null, true);
mCallback = callback;
}
@@ -499,4 +499,45 @@
obtainMessage(MSG_UNAVAILABLE, info).sendToTarget();
}
}
+
+ /** Remove after unbundled apps have migrated STOP SHIP */
+ public static abstract class OnAppsChangedCallback extends Callback {
+ }
+
+ /** Remove after unbundled apps have migrated STOP SHIP */
+ public void addOnAppsChangedCallback(OnAppsChangedCallback callback) {
+ addCallback(callback, null);
+ }
+
+ /** Remove after unbundled apps have migrated STOP SHIP */
+ public void addOnAppsChangedCallback(OnAppsChangedCallback callback, Handler handler) {
+ addCallback(callback, handler);
+ }
+
+ /** Remove after unbundled apps have migrated STOP SHIP */
+ public void removeOnAppsChangedCallback(OnAppsChangedCallback callback) {
+ removeCallback(callback);
+ }
+
+ /** Remove after unbundled apps have migrated STOP SHIP */
+ public void startActivityForProfile(ComponentName component, UserHandle user, Rect sourceBounds,
+ Bundle opts) {
+ startMainActivity(component, user, sourceBounds, opts);
+ }
+
+ /** Remove after unbundled apps have migrated STOP SHIP */
+ public void showAppDetailsForProfile(ComponentName component, UserHandle user,
+ Rect sourceBounds, Bundle opts) {
+ startAppDetailsActivity(component, user, sourceBounds, opts);
+ }
+
+ /** Remove after unbundled apps have migrated STOP SHIP */
+ public boolean isPackageEnabledForProfile(String packageName, UserHandle user) {
+ return isPackageEnabled(packageName, user);
+ }
+
+ /** Remove after unbundled apps have migrated STOP SHIP */
+ public boolean isActivityEnabledForProfile(ComponentName component, UserHandle user) {
+ return isActivityEnabled(component, user);
+ }
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index fff21aa..31813c10 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -16,6 +16,7 @@
package android.content.res;
+import android.view.ViewDebug;
import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
@@ -1638,12 +1639,41 @@
/*package*/ String getKey() {
return mKey;
}
+
+ private String getResourceNameFromHexString(String hexString) {
+ return getResourceName(Integer.parseInt(hexString, 16));
+ }
+
+ /**
+ * Parses {@link #mKey} and returns a String array that holds pairs of adjacent Theme data:
+ * resource name followed by whether or not it was forced, as specified by
+ * {@link #applyStyle(int, boolean)}.
+ *
+ * @hide
+ */
+ @ViewDebug.ExportedProperty(category = "theme", hasAdjacentMapping = true)
+ public String[] getTheme() {
+ String[] themeData = mKey.split(" ");
+ String[] themes = new String[themeData.length * 2];
+ String theme;
+ boolean forced;
+
+ for (int i = 0, j = themeData.length - 1; i < themes.length; i += 2, --j) {
+ theme = themeData[j];
+ forced = theme.endsWith("!");
+ themes[i] = forced ?
+ getResourceNameFromHexString(theme.substring(0, theme.length() - 1)) :
+ getResourceNameFromHexString(theme);
+ themes[i + 1] = forced ? "forced" : "not forced";
+ }
+ return themes;
+ }
}
/**
* Generate a new Theme object for this set of Resources. It initially
* starts out empty.
- *
+ *
* @return Theme The newly created Theme container.
*/
public final Theme newTheme() {
@@ -1653,7 +1683,7 @@
/**
* Retrieve a set of basic attribute values from an AttributeSet, not
* performing styling of them using a theme and/or style resources.
- *
+ *
* @param set The current attribute values to retrieve.
* @param attrs The specific attributes to be retrieved.
* @return Returns a TypedArray holding an array of the attribute values.
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index eadfa73..310ab76 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -1558,6 +1558,26 @@
return _enableShutterSound(enabled);
}
+ /**
+ * Disable the shutter sound unconditionally.
+ *
+ * <p>
+ * This is only guaranteed to work for legacy cameras
+ * (i.e. initialized with {@link #cameraInitUnspecified}). Trying to call this on
+ * a regular camera will force a conditional check in the camera service.
+ * </p>
+ *
+ * @return {@code true} if the shutter sound state was successfully
+ * changed. {@code false} if the shutter sound state could not be
+ * changed. {@code true} is also returned if shutter sound playback
+ * is already set to the requested state.
+ *
+ * @hide
+ */
+ public final boolean disableShutterSound() {
+ return _enableShutterSound(/*enabled*/false);
+ }
+
private native final boolean _enableShutterSound(boolean enabled);
/**
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
index c68d8c3..5cbf109 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -56,6 +56,7 @@
* Keep up to date with ICameraDeviceUser.aidl.
* </p>
*/
+@SuppressWarnings("deprecation")
public class CameraDeviceUserShim implements ICameraDeviceUser {
private static final String TAG = "CameraDeviceUserShim";
@@ -259,6 +260,7 @@
super(l);
}
+ @Override
public void handleMessage(Message msg) {
try {
switch (msg.what) {
@@ -320,6 +322,9 @@
// Check errors old HAL initialization
CameraBinderDecorator.throwOnError(initErrors);
+ // Disable shutter sounds (this will work unconditionally) for api2 clients
+ legacyCamera.disableShutterSound();
+
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(cameraId, info);
diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
index fbe26e5..ee0ca9c 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
@@ -1207,6 +1207,9 @@
m.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, bestRange);
}
+ // control.sceneMode -- DISABLED is always available
+ m.set(CaptureRequest.CONTROL_SCENE_MODE, CONTROL_SCENE_MODE_DISABLED);
+
/*
* statistics.*
*/
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index 2e6b9ae..c0b7967 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -339,6 +339,11 @@
* @see #isOutputSupportedFor(Class)
*/
public <T> Size[] getOutputSizes(Class<T> klass) {
+ // Image reader is "supported", but never for implementation-defined formats; return empty
+ if (android.media.ImageReader.class.isAssignableFrom(klass)) {
+ return new Size[0];
+ }
+
if (isOutputSupportedFor(klass) == false) {
return null;
}
diff --git a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
index 97da3a2..d8da80e 100644
--- a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
+++ b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
@@ -230,7 +230,7 @@
mDeviceType = DEVICE_RESERVED;
mVendorId = 0;
mDevicePowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN;
- mDisplayName = "MHL";
+ mDisplayName = "Mobile";
mDeviceId = adopterId;
mAdopterId = deviceId;
diff --git a/core/java/android/hardware/location/GeofenceHardware.java b/core/java/android/hardware/location/GeofenceHardware.java
index 2d82cba..7dd105a 100644
--- a/core/java/android/hardware/location/GeofenceHardware.java
+++ b/core/java/android/hardware/location/GeofenceHardware.java
@@ -15,6 +15,7 @@
*/
package android.hardware.location;
+import android.annotation.SystemApi;
import android.location.Location;
import android.os.Build;
import android.os.RemoteException;
@@ -43,7 +44,10 @@
* an appropriate transition would be triggered. The "reasonably confident" parameter
* depends on the hardware system and the positioning algorithms used.
* For instance, {@link #MONITORING_TYPE_GPS_HARDWARE} uses 95% as a confidence level.
+ *
+ * @hide
*/
+@SystemApi
public final class GeofenceHardware {
private IGeofenceHardware mService;
@@ -162,9 +166,7 @@
private HashMap<GeofenceHardwareMonitorCallback, GeofenceHardwareMonitorCallbackWrapper>
mMonitorCallbacks = new HashMap<GeofenceHardwareMonitorCallback,
GeofenceHardwareMonitorCallbackWrapper>();
- /**
- * @hide
- */
+
public GeofenceHardware(IGeofenceHardware service) {
mService = service;
}
diff --git a/core/java/android/hardware/location/GeofenceHardwareCallback.java b/core/java/android/hardware/location/GeofenceHardwareCallback.java
index 6cad3da..a2a7ed0 100644
--- a/core/java/android/hardware/location/GeofenceHardwareCallback.java
+++ b/core/java/android/hardware/location/GeofenceHardwareCallback.java
@@ -16,11 +16,15 @@
package android.hardware.location;
+import android.annotation.SystemApi;
import android.location.Location;
/**
* The callback class associated with the APIs in {@link GeofenceHardware}
+ *
+ * @hide
*/
+@SystemApi
public abstract class GeofenceHardwareCallback {
/**
* The callback called when there is a transition to report for the specific
diff --git a/core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java b/core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java
index f927027..d7daa10 100644
--- a/core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java
+++ b/core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java
@@ -16,12 +16,16 @@
package android.hardware.location;
+import android.annotation.SystemApi;
import android.location.Location;
/**
* The callback class associated with the status change of hardware monitors
* in {@link GeofenceHardware}
+ *
+ * @hide
*/
+@SystemApi
public abstract class GeofenceHardwareMonitorCallback {
/**
* The callback called when the state of a monitoring system changes.
diff --git a/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java b/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java
index 9c460d2..7079237 100644
--- a/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java
+++ b/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java
@@ -16,13 +16,17 @@
package android.hardware.location;
+import android.annotation.SystemApi;
import android.location.Location;
import android.os.Parcel;
import android.os.Parcelable;
/**
* A class that represents an event for each change in the state of a monitoring system.
+ *
+ * @hide
*/
+@SystemApi
public class GeofenceHardwareMonitorEvent implements Parcelable {
private final int mMonitoringType;
private final int mMonitoringStatus;
diff --git a/core/java/android/hardware/location/GeofenceHardwareRequest.java b/core/java/android/hardware/location/GeofenceHardwareRequest.java
index 887c4ad..68545a8 100644
--- a/core/java/android/hardware/location/GeofenceHardwareRequest.java
+++ b/core/java/android/hardware/location/GeofenceHardwareRequest.java
@@ -16,12 +16,16 @@
package android.hardware.location;
+import android.annotation.SystemApi;
+
/**
* This class represents the characteristics of the geofence.
*
* <p> Use this in conjunction with {@link GeofenceHardware} APIs.
+ *
+ * @hide
*/
-
+@SystemApi
public final class GeofenceHardwareRequest {
static final int GEOFENCE_TYPE_CIRCLE = 0;
private int mType;
diff --git a/core/java/android/net/DhcpResults.java b/core/java/android/net/DhcpResults.java
index 49a307e..71df60a 100644
--- a/core/java/android/net/DhcpResults.java
+++ b/core/java/android/net/DhcpResults.java
@@ -16,13 +16,15 @@
package android.net;
+import android.net.NetworkUtils;
import android.os.Parcelable;
import android.os.Parcel;
import android.text.TextUtils;
import android.util.Log;
import java.net.InetAddress;
-import java.net.UnknownHostException;
+import java.net.Inet4Address;
+import java.util.Objects;
/**
* A simple object for retrieving the results of a DHCP request.
@@ -30,38 +32,34 @@
* TODO - remove when DhcpInfo is deprecated. Move the remaining api to LinkProperties.
* @hide
*/
-public class DhcpResults implements Parcelable {
+public class DhcpResults extends StaticIpConfiguration {
private static final String TAG = "DhcpResults";
- public final LinkProperties linkProperties;
-
public InetAddress serverAddress;
- /**
- * Vendor specific information (from RFC 2132).
- */
+ /** Vendor specific information (from RFC 2132). */
public String vendorInfo;
public int leaseDuration;
public DhcpResults() {
- linkProperties = new LinkProperties();
+ super();
+ }
+
+ public DhcpResults(StaticIpConfiguration source) {
+ super(source);
}
/** copy constructor */
public DhcpResults(DhcpResults source) {
- if (source != null) {
- linkProperties = new LinkProperties(source.linkProperties);
- serverAddress = source.serverAddress;
- leaseDuration = source.leaseDuration;
- vendorInfo = source.vendorInfo;
- } else {
- linkProperties = new LinkProperties();
- }
- }
+ super(source);
- public DhcpResults(LinkProperties lp) {
- linkProperties = new LinkProperties(lp);
+ if (source != null) {
+ // All these are immutable, so no need to make copies.
+ serverAddress = source.serverAddress;
+ vendorInfo = source.vendorInfo;
+ leaseDuration = source.leaseDuration;
+ }
}
/**
@@ -70,14 +68,10 @@
* being empty.
*/
public void updateFromDhcpRequest(DhcpResults orig) {
- if (orig == null || orig.linkProperties == null) return;
- if (linkProperties.getRoutes().size() == 0) {
- for (RouteInfo r : orig.linkProperties.getRoutes()) linkProperties.addRoute(r);
- }
- if (linkProperties.getDnsServers().size() == 0) {
- for (InetAddress d : orig.linkProperties.getDnsServers()) {
- linkProperties.addDnsServer(d);
- }
+ if (orig == null) return;
+ if (gateway == null) gateway = orig.gateway;
+ if (dnsServers.size() == 0) {
+ dnsServers.addAll(orig.dnsServers);
}
}
@@ -94,15 +88,14 @@
}
public void clear() {
- linkProperties.clear();
- serverAddress = null;
+ super.clear();
vendorInfo = null;
leaseDuration = 0;
}
@Override
public String toString() {
- StringBuffer str = new StringBuffer(linkProperties.toString());
+ StringBuffer str = new StringBuffer(super.toString());
str.append(" DHCP server ").append(serverAddress);
str.append(" Vendor info ").append(vendorInfo);
@@ -119,58 +112,19 @@
DhcpResults target = (DhcpResults)obj;
- if (linkProperties == null) {
- if (target.linkProperties != null) return false;
- } else if (!linkProperties.equals(target.linkProperties)) return false;
- if (serverAddress == null) {
- if (target.serverAddress != null) return false;
- } else if (!serverAddress.equals(target.serverAddress)) return false;
- if (vendorInfo == null) {
- if (target.vendorInfo != null) return false;
- } else if (!vendorInfo.equals(target.vendorInfo)) return false;
- if (leaseDuration != target.leaseDuration) return false;
-
- return true;
- }
-
- /** Implement the Parcelable interface */
- public int describeContents() {
- return 0;
- }
-
- /** Implement the Parcelable interface */
- public void writeToParcel(Parcel dest, int flags) {
- linkProperties.writeToParcel(dest, flags);
-
- dest.writeInt(leaseDuration);
-
- if (serverAddress != null) {
- dest.writeByte((byte)1);
- dest.writeByteArray(serverAddress.getAddress());
- } else {
- dest.writeByte((byte)0);
- }
-
- dest.writeString(vendorInfo);
+ return super.equals((StaticIpConfiguration) obj) &&
+ Objects.equals(serverAddress, target.serverAddress) &&
+ Objects.equals(vendorInfo, target.vendorInfo) &&
+ leaseDuration == target.leaseDuration;
}
/** Implement the Parcelable interface */
public static final Creator<DhcpResults> CREATOR =
new Creator<DhcpResults>() {
public DhcpResults createFromParcel(Parcel in) {
- DhcpResults prop = new DhcpResults((LinkProperties)in.readParcelable(null));
-
- prop.leaseDuration = in.readInt();
-
- if (in.readByte() == 1) {
- try {
- prop.serverAddress = InetAddress.getByAddress(in.createByteArray());
- } catch (UnknownHostException e) {}
- }
-
- prop.vendorInfo = in.readString();
-
- return prop;
+ DhcpResults dhcpResults = new DhcpResults();
+ readFromParcel(dhcpResults, in);
+ return dhcpResults;
}
public DhcpResults[] newArray(int size) {
@@ -178,33 +132,39 @@
}
};
- // Utils for jni population - false on success
- public void setInterfaceName(String interfaceName) {
- linkProperties.setInterfaceName(interfaceName);
+ /** Implement the Parcelable interface */
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(leaseDuration);
+ NetworkUtils.parcelInetAddress(dest, serverAddress, flags);
+ dest.writeString(vendorInfo);
}
- public boolean addLinkAddress(String addrString, int prefixLength) {
- InetAddress addr;
+ private static void readFromParcel(DhcpResults dhcpResults, Parcel in) {
+ StaticIpConfiguration.readFromParcel(dhcpResults, in);
+ dhcpResults.leaseDuration = in.readInt();
+ dhcpResults.serverAddress = NetworkUtils.unparcelInetAddress(in);
+ dhcpResults.vendorInfo = in.readString();
+ }
+
+ // Utils for jni population - false on success
+ // Not part of the superclass because they're only used by the JNI iterface to the DHCP daemon.
+ public boolean setIpAddress(String addrString, int prefixLength) {
try {
- addr = NetworkUtils.numericToInetAddress(addrString);
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "addLinkAddress failed with addrString " + addrString);
+ Inet4Address addr = (Inet4Address) NetworkUtils.numericToInetAddress(addrString);
+ ipAddress = new LinkAddress(addr, prefixLength);
+ } catch (IllegalArgumentException|ClassCastException e) {
+ Log.e(TAG, "setIpAddress failed with addrString " + addrString + "/" + prefixLength);
return true;
}
-
- LinkAddress linkAddress = new LinkAddress(addr, prefixLength);
- linkProperties.addLinkAddress(linkAddress);
-
- RouteInfo routeInfo = new RouteInfo(linkAddress);
- linkProperties.addRoute(routeInfo);
return false;
}
- public boolean addGateway(String addrString) {
+ public boolean setGateway(String addrString) {
try {
- linkProperties.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(addrString)));
+ gateway = NetworkUtils.numericToInetAddress(addrString);
} catch (IllegalArgumentException e) {
- Log.e(TAG, "addGateway failed with addrString " + addrString);
+ Log.e(TAG, "setGateway failed with addrString " + addrString);
return true;
}
return false;
@@ -213,7 +173,7 @@
public boolean addDns(String addrString) {
if (TextUtils.isEmpty(addrString) == false) {
try {
- linkProperties.addDnsServer(NetworkUtils.numericToInetAddress(addrString));
+ dnsServers.add(NetworkUtils.numericToInetAddress(addrString));
} catch (IllegalArgumentException e) {
Log.e(TAG, "addDns failed with addrString " + addrString);
return true;
@@ -241,6 +201,6 @@
}
public void setDomains(String domains) {
- linkProperties.setDomains(domains);
+ domains = domains;
}
}
diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index 608ca28..d965f27 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -21,7 +21,6 @@
import android.net.IpConfiguration;
import android.net.IpConfiguration.IpAssignment;
import android.net.IpConfiguration.ProxySettings;
-import android.net.LinkProperties;
import android.os.RemoteException;
/**
@@ -52,16 +51,12 @@
*/
public IpConfiguration getConfiguration() {
if (mService == null) {
- return new IpConfiguration(IpAssignment.UNASSIGNED,
- ProxySettings.UNASSIGNED,
- new LinkProperties());
+ return new IpConfiguration();
}
try {
return mService.getConfiguration();
} catch (RemoteException e) {
- return new IpConfiguration(IpAssignment.UNASSIGNED,
- ProxySettings.UNASSIGNED,
- new LinkProperties());
+ return new IpConfiguration();
}
}
diff --git a/core/java/android/net/IpConfiguration.java b/core/java/android/net/IpConfiguration.java
index 4730bab..fe69f296 100644
--- a/core/java/android/net/IpConfiguration.java
+++ b/core/java/android/net/IpConfiguration.java
@@ -16,7 +16,7 @@
package android.net;
-import android.net.LinkProperties;
+import android.net.StaticIpConfiguration;
import android.os.Parcel;
import android.os.Parcelable;
@@ -31,7 +31,7 @@
public enum IpAssignment {
/* Use statically configured IP settings. Configuration can be accessed
- * with linkProperties */
+ * with staticIpConfiguration */
STATIC,
/* Use dynamically configured IP settigns */
DHCP,
@@ -42,12 +42,14 @@
public IpAssignment ipAssignment;
+ public StaticIpConfiguration staticIpConfiguration;
+
public enum ProxySettings {
/* No proxy is to be used. Any existing proxy settings
* should be cleared. */
NONE,
/* Use statically configured proxy. Configuration can be accessed
- * with linkProperties */
+ * with httpProxy. */
STATIC,
/* no proxy details are assigned, this is used to indicate
* that any existing proxy settings should be retained */
@@ -59,30 +61,69 @@
public ProxySettings proxySettings;
- public LinkProperties linkProperties;
+ public ProxyInfo httpProxy;
- public IpConfiguration(IpConfiguration source) {
- if (source != null) {
- ipAssignment = source.ipAssignment;
- proxySettings = source.proxySettings;
- linkProperties = new LinkProperties(source.linkProperties);
- } else {
- ipAssignment = IpAssignment.UNASSIGNED;
- proxySettings = ProxySettings.UNASSIGNED;
- linkProperties = new LinkProperties();
- }
+ private void init(IpAssignment ipAssignment,
+ ProxySettings proxySettings,
+ StaticIpConfiguration staticIpConfiguration,
+ ProxyInfo httpProxy) {
+ this.ipAssignment = ipAssignment;
+ this.proxySettings = proxySettings;
+ this.staticIpConfiguration = (staticIpConfiguration == null) ?
+ null : new StaticIpConfiguration(staticIpConfiguration);
+ this.httpProxy = (httpProxy == null) ?
+ null : new ProxyInfo(httpProxy);
}
public IpConfiguration() {
- this(null);
+ init(IpAssignment.UNASSIGNED, ProxySettings.UNASSIGNED, null, null);
}
public IpConfiguration(IpAssignment ipAssignment,
ProxySettings proxySettings,
- LinkProperties linkProperties) {
+ StaticIpConfiguration staticIpConfiguration,
+ ProxyInfo httpProxy) {
+ init(ipAssignment, proxySettings, staticIpConfiguration, httpProxy);
+ }
+
+ public IpConfiguration(IpConfiguration source) {
+ this();
+ if (source != null) {
+ init(source.ipAssignment, source.proxySettings,
+ source.staticIpConfiguration, source.httpProxy);
+ }
+ }
+
+ public IpAssignment getIpAssignment() {
+ return ipAssignment;
+ }
+
+ public void setIpAssignment(IpAssignment ipAssignment) {
this.ipAssignment = ipAssignment;
+ }
+
+ public StaticIpConfiguration getStaticIpConfiguration() {
+ return staticIpConfiguration;
+ }
+
+ public void setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration) {
+ this.staticIpConfiguration = staticIpConfiguration;
+ }
+
+ public ProxySettings getProxySettings() {
+ return proxySettings;
+ }
+
+ public void setProxySettings(ProxySettings proxySettings) {
this.proxySettings = proxySettings;
- this.linkProperties = new LinkProperties(linkProperties);
+ }
+
+ public ProxyInfo getHttpProxy() {
+ return httpProxy;
+ }
+
+ public void setHttpProxy(ProxyInfo httpProxy) {
+ this.httpProxy = httpProxy;
}
@Override
@@ -90,10 +131,16 @@
StringBuilder sbuf = new StringBuilder();
sbuf.append("IP assignment: " + ipAssignment.toString());
sbuf.append("\n");
+ if (staticIpConfiguration != null) {
+ sbuf.append("Static configuration: " + staticIpConfiguration.toString());
+ sbuf.append("\n");
+ }
sbuf.append("Proxy settings: " + proxySettings.toString());
sbuf.append("\n");
- sbuf.append(linkProperties.toString());
- sbuf.append("\n");
+ if (httpProxy != null) {
+ sbuf.append("HTTP proxy: " + httpProxy.toString());
+ sbuf.append("\n");
+ }
return sbuf.toString();
}
@@ -111,14 +158,16 @@
IpConfiguration other = (IpConfiguration) o;
return this.ipAssignment == other.ipAssignment &&
this.proxySettings == other.proxySettings &&
- Objects.equals(this.linkProperties, other.linkProperties);
+ Objects.equals(this.staticIpConfiguration, other.staticIpConfiguration) &&
+ Objects.equals(this.httpProxy, other.httpProxy);
}
@Override
public int hashCode() {
- return 13 + (linkProperties != null ? linkProperties.hashCode() : 0) +
+ return 13 + (staticIpConfiguration != null ? staticIpConfiguration.hashCode() : 0) +
17 * ipAssignment.ordinal() +
- 47 * proxySettings.ordinal();
+ 47 * proxySettings.ordinal() +
+ 83 * httpProxy.hashCode();
}
/** Implement the Parcelable interface */
@@ -130,7 +179,8 @@
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(ipAssignment.name());
dest.writeString(proxySettings.name());
- dest.writeParcelable(linkProperties, flags);
+ dest.writeParcelable(staticIpConfiguration, flags);
+ dest.writeParcelable(httpProxy, flags);
}
/** Implement the Parcelable interface */
@@ -140,7 +190,8 @@
IpConfiguration config = new IpConfiguration();
config.ipAssignment = IpAssignment.valueOf(in.readString());
config.proxySettings = ProxySettings.valueOf(in.readString());
- config.linkProperties = in.readParcelable(null);
+ config.staticIpConfiguration = in.readParcelable(null);
+ config.httpProxy = in.readParcelable(null);
return config;
}
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 663aa15..54d8676 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -23,6 +23,7 @@
import java.util.Collection;
import java.util.Locale;
+import android.os.Parcel;
import android.util.Log;
import android.util.Pair;
@@ -203,6 +204,32 @@
}
/**
+ * Writes an InetAddress to a parcel. The address may be null. This is likely faster than
+ * calling writeSerializable.
+ */
+ protected static void parcelInetAddress(Parcel parcel, InetAddress address, int flags) {
+ byte[] addressArray = (address != null) ? address.getAddress() : null;
+ parcel.writeByteArray(addressArray);
+ }
+
+ /**
+ * Reads an InetAddress from a parcel. Returns null if the address that was written was null
+ * or if the data is invalid.
+ */
+ protected static InetAddress unparcelInetAddress(Parcel in) {
+ byte[] addressArray = in.createByteArray();
+ if (addressArray == null) {
+ return null;
+ }
+ try {
+ return InetAddress.getByAddress(addressArray);
+ } catch (UnknownHostException e) {
+ return null;
+ }
+ }
+
+
+ /**
* Masks a raw IP address byte array with the specified prefix length.
*/
public static void maskRawAddress(byte[] array, int prefixLength) {
diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java
new file mode 100644
index 0000000..5a273cf
--- /dev/null
+++ b/core/java/android/net/StaticIpConfiguration.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.net.LinkAddress;
+import android.os.Parcelable;
+import android.os.Parcel;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Class that describes static IP configuration.
+ *
+ * This class is different from LinkProperties because it represents
+ * configuration intent. The general contract is that if we can represent
+ * a configuration here, then we should be able to configure it on a network.
+ * The intent is that it closely match the UI we have for configuring networks.
+ *
+ * In contrast, LinkProperties represents current state. It is much more
+ * expressive. For example, it supports multiple IP addresses, multiple routes,
+ * stacked interfaces, and so on. Because LinkProperties is so expressive,
+ * using it to represent configuration intent as well as current state causes
+ * problems. For example, we could unknowingly save a configuration that we are
+ * not in fact capable of applying, or we could save a configuration that the
+ * UI cannot display, which has the potential for malicious code to hide
+ * hostile or unexpected configuration from the user: see, for example,
+ * http://b/12663469 and http://b/16893413 .
+ *
+ * @hide
+ */
+public class StaticIpConfiguration implements Parcelable {
+ public LinkAddress ipAddress;
+ public InetAddress gateway;
+ public final ArrayList<InetAddress> dnsServers;
+ public String domains;
+
+ public StaticIpConfiguration() {
+ dnsServers = new ArrayList<InetAddress>();
+ }
+
+ public StaticIpConfiguration(StaticIpConfiguration source) {
+ this();
+ if (source != null) {
+ // All of these except dnsServers are immutable, so no need to make copies.
+ ipAddress = source.ipAddress;
+ gateway = source.gateway;
+ dnsServers.addAll(source.dnsServers);
+ domains = source.domains;
+ }
+ }
+
+ public void clear() {
+ ipAddress = null;
+ gateway = null;
+ dnsServers.clear();
+ domains = null;
+ }
+
+ /**
+ * Returns the network routes specified by this object. Will typically include a
+ * directly-connected route for the IP address's local subnet and a default route.
+ */
+ public List<RouteInfo> getRoutes(String iface) {
+ List<RouteInfo> routes = new ArrayList<RouteInfo>(2);
+ if (ipAddress != null) {
+ routes.add(new RouteInfo(ipAddress, null, iface));
+ }
+ if (gateway != null) {
+ routes.add(new RouteInfo((LinkAddress) null, gateway, iface));
+ }
+ return routes;
+ }
+
+ /**
+ * Returns a LinkProperties object expressing the data in this object. Note that the information
+ * contained in the LinkProperties will not be a complete picture of the link's configuration,
+ * because any configuration information that is obtained dynamically by the network (e.g.,
+ * IPv6 configuration) will not be included.
+ */
+ public LinkProperties toLinkProperties(String iface) {
+ LinkProperties lp = new LinkProperties();
+ lp.setInterfaceName(iface);
+ if (ipAddress != null) {
+ lp.addLinkAddress(ipAddress);
+ }
+ for (RouteInfo route : getRoutes(iface)) {
+ lp.addRoute(route);
+ }
+ for (InetAddress dns : dnsServers) {
+ lp.addDnsServer(dns);
+ }
+ return lp;
+ }
+
+ public String toString() {
+ StringBuffer str = new StringBuffer();
+
+ str.append("IP address ");
+ if (ipAddress != null ) str.append(ipAddress).append(" ");
+
+ str.append("Gateway ");
+ if (gateway != null) str.append(gateway.getHostAddress()).append(" ");
+
+ str.append(" DNS servers: [");
+ for (InetAddress dnsServer : dnsServers) {
+ str.append(" ").append(dnsServer.getHostAddress());
+ }
+
+ str.append(" ] Domains");
+ if (domains != null) str.append(domains);
+ return str.toString();
+ }
+
+ public int hashCode() {
+ int result = 13;
+ result = 47 * result + (ipAddress == null ? 0 : ipAddress.hashCode());
+ result = 47 * result + (gateway == null ? 0 : gateway.hashCode());
+ result = 47 * result + (domains == null ? 0 : domains.hashCode());
+ result = 47 * result + dnsServers.hashCode();
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+
+ if (!(obj instanceof StaticIpConfiguration)) return false;
+
+ StaticIpConfiguration other = (StaticIpConfiguration) obj;
+
+ return other != null &&
+ Objects.equals(ipAddress, other.ipAddress) &&
+ Objects.equals(gateway, other.gateway) &&
+ dnsServers.equals(other.dnsServers) &&
+ Objects.equals(domains, other.domains);
+ }
+
+ /** Implement the Parcelable interface */
+ public static Creator<StaticIpConfiguration> CREATOR =
+ new Creator<StaticIpConfiguration>() {
+ public StaticIpConfiguration createFromParcel(Parcel in) {
+ StaticIpConfiguration s = new StaticIpConfiguration();
+ readFromParcel(s, in);
+ return s;
+ }
+
+ public StaticIpConfiguration[] newArray(int size) {
+ return new StaticIpConfiguration[size];
+ }
+ };
+
+ /** Implement the Parcelable interface */
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface */
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(ipAddress, flags);
+ NetworkUtils.parcelInetAddress(dest, gateway, flags);
+ dest.writeInt(dnsServers.size());
+ for (InetAddress dnsServer : dnsServers) {
+ NetworkUtils.parcelInetAddress(dest, dnsServer, flags);
+ }
+ }
+
+ protected static void readFromParcel(StaticIpConfiguration s, Parcel in) {
+ s.ipAddress = in.readParcelable(null);
+ s.gateway = NetworkUtils.unparcelInetAddress(in);
+ s.dnsServers.clear();
+ int size = in.readInt();
+ for (int i = 0; i < size; i++) {
+ s.dnsServers.add(NetworkUtils.unparcelInetAddress(in));
+ }
+ }
+}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index be46bc7..fe9f79b 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -3065,7 +3065,7 @@
"partial", which, linePrefix);
linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime,
"window", which, linePrefix);
- if (!linePrefix.equals(": ")) {
+ if (true || !linePrefix.equals(": ")) {
sb.append(" realtime");
// Only print out wake locks that were held
pw.println(sb.toString());
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 20e26e6..5e77d28 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3546,6 +3546,13 @@
public static final String DISABLED_SYSTEM_INPUT_METHODS = "disabled_system_input_methods";
/**
+ * Whether to show the IME when a hard keyboard is connected. This is a boolean that
+ * determines if the IME should be shown when a hard keyboard is attached.
+ * @hide
+ */
+ public static final String SHOW_IME_WITH_HARD_KEYBOARD = "show_ime_with_hard_keyboard";
+
+ /**
* Host name and port for global http proxy. Uses ':' seperator for
* between host and port.
*
@@ -5183,6 +5190,12 @@
public static final String ADB_ENABLED = "adb_enabled";
/**
+ * Whether Views are allowed to save their attribute data.
+ * @hide
+ */
+ public static final String DEBUG_VIEW_ATTRIBUTES = "debug_view_attributes";
+
+ /**
* Whether assisted GPS should be enabled or not.
* @hide
*/
diff --git a/core/java/android/transition/ChangeBounds.java b/core/java/android/transition/ChangeBounds.java
index efcbdb3..6246cbe 100644
--- a/core/java/android/transition/ChangeBounds.java
+++ b/core/java/android/transition/ChangeBounds.java
@@ -16,13 +16,11 @@
package android.transition;
-import android.animation.TypeConverter;
import android.content.Context;
import android.graphics.PointF;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.RectEvaluator;
@@ -119,9 +117,11 @@
values.values.put(PROPNAME_BOUNDS, new Rect(view.getLeft(), view.getTop(),
view.getRight(), view.getBottom()));
values.values.put(PROPNAME_PARENT, values.view.getParent());
- values.view.getLocationInWindow(tempLocation);
- values.values.put(PROPNAME_WINDOW_X, tempLocation[0]);
- values.values.put(PROPNAME_WINDOW_Y, tempLocation[1]);
+ if (mReparent) {
+ values.view.getLocationInWindow(tempLocation);
+ values.values.put(PROPNAME_WINDOW_X, tempLocation[0]);
+ values.values.put(PROPNAME_WINDOW_Y, tempLocation[1]);
+ }
}
@Override
@@ -134,6 +134,19 @@
captureValues(transitionValues);
}
+ private boolean parentMatches(View startParent, View endParent) {
+ boolean parentMatches = true;
+ if (mReparent) {
+ TransitionValues endValues = getMatchedTransitionValues(startParent, true);
+ if (endValues == null) {
+ parentMatches = startParent == endParent;
+ } else {
+ parentMatches = endParent == endValues.view;
+ }
+ }
+ return parentMatches;
+ }
+
@Override
public Animator createAnimator(final ViewGroup sceneRoot, TransitionValues startValues,
TransitionValues endValues) {
@@ -148,13 +161,7 @@
return null;
}
final View view = endValues.view;
- boolean parentsEqual = (startParent == endParent) ||
- (startParent.getId() == endParent.getId());
- // TODO: Might want reparenting to be separate/subclass transition, or at least
- // triggered by a property on ChangeBounds. Otherwise, we're forcing the requirement that
- // all parents in layouts have IDs to avoid layout-inflation resulting in a side-effect
- // of reparenting the views.
- if (!mReparent || parentsEqual) {
+ if (parentMatches(startParent, endParent)) {
Rect startBounds = (Rect) startValues.values.get(PROPNAME_BOUNDS);
Rect endBounds = (Rect) endValues.values.get(PROPNAME_BOUNDS);
int startLeft = startBounds.left;
diff --git a/core/java/android/transition/ChangeImageTransform.java b/core/java/android/transition/ChangeImageTransform.java
index 2b26756..4b230eb 100644
--- a/core/java/android/transition/ChangeImageTransform.java
+++ b/core/java/android/transition/ChangeImageTransform.java
@@ -182,6 +182,7 @@
if (endMatrix == null) {
endMatrix = Matrix.IDENTITY_MATRIX;
}
+ ANIMATED_TRANSFORM_PROPERTY.set(imageView, startMatrix);
animator = createMatrixAnimator(imageView, startMatrix, endMatrix);
}
return animator;
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index 2fa8d2a..0d32d40 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -192,6 +192,8 @@
private TransitionValuesMaps mEndValues = new TransitionValuesMaps();
TransitionSet mParent = null;
private int[] mMatchOrder = DEFAULT_MATCH_ORDER;
+ ArrayList<TransitionValues> mStartValuesList; // only valid after playTransition starts
+ ArrayList<TransitionValues> mEndValuesList; // only valid after playTransitions starts
// Per-animator information used for later canceling when future transitions overlap
private static ThreadLocal<ArrayMap<Animator, AnimationInfo>> sRunningAnimators =
@@ -518,32 +520,28 @@
}
/**
- * Match start/end values by View instance. Adds matched values to startValuesList
- * and endValuesList and removes them from unmatchedStart and unmatchedEnd.
+ * Match start/end values by View instance. Adds matched values to mStartValuesList
+ * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd.
*/
- private void matchInstances(ArrayList<TransitionValues> startValuesList,
- ArrayList<TransitionValues> endValuesList,
- ArrayMap<View, TransitionValues> unmatchedStart,
+ private void matchInstances(ArrayMap<View, TransitionValues> unmatchedStart,
ArrayMap<View, TransitionValues> unmatchedEnd) {
for (int i = unmatchedStart.size() - 1; i >= 0; i--) {
View view = unmatchedStart.keyAt(i);
TransitionValues end = unmatchedEnd.remove(view);
if (end != null) {
TransitionValues start = unmatchedStart.removeAt(i);
- startValuesList.add(start);
- endValuesList.add(end);
+ mStartValuesList.add(start);
+ mEndValuesList.add(end);
}
}
}
/**
- * Match start/end values by Adapter item ID. Adds matched values to startValuesList
- * and endValuesList and removes them from unmatchedStart and unmatchedEnd, using
+ * Match start/end values by Adapter item ID. Adds matched values to mStartValuesList
+ * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd, using
* startItemIds and endItemIds as a guide for which Views have unique item IDs.
*/
- private void matchItemIds(ArrayList<TransitionValues> startValuesList,
- ArrayList<TransitionValues> endValuesList,
- ArrayMap<View, TransitionValues> unmatchedStart,
+ private void matchItemIds(ArrayMap<View, TransitionValues> unmatchedStart,
ArrayMap<View, TransitionValues> unmatchedEnd,
LongSparseArray<View> startItemIds, LongSparseArray<View> endItemIds) {
int numStartIds = startItemIds.size();
@@ -555,8 +553,8 @@
TransitionValues startValues = unmatchedStart.get(startView);
TransitionValues endValues = unmatchedEnd.get(endView);
if (startValues != null && endValues != null) {
- startValuesList.add(startValues);
- endValuesList.add(endValues);
+ mStartValuesList.add(startValues);
+ mEndValuesList.add(endValues);
unmatchedStart.remove(startView);
unmatchedEnd.remove(endView);
}
@@ -566,13 +564,11 @@
}
/**
- * Match start/end values by Adapter view ID. Adds matched values to startValuesList
- * and endValuesList and removes them from unmatchedStart and unmatchedEnd, using
+ * Match start/end values by Adapter view ID. Adds matched values to mStartValuesList
+ * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd, using
* startIds and endIds as a guide for which Views have unique IDs.
*/
- private void matchIds(ArrayList<TransitionValues> startValuesList,
- ArrayList<TransitionValues> endValuesList,
- ArrayMap<View, TransitionValues> unmatchedStart,
+ private void matchIds(ArrayMap<View, TransitionValues> unmatchedStart,
ArrayMap<View, TransitionValues> unmatchedEnd,
SparseArray<View> startIds, SparseArray<View> endIds) {
int numStartIds = startIds.size();
@@ -584,8 +580,8 @@
TransitionValues startValues = unmatchedStart.get(startView);
TransitionValues endValues = unmatchedEnd.get(endView);
if (startValues != null && endValues != null) {
- startValuesList.add(startValues);
- endValuesList.add(endValues);
+ mStartValuesList.add(startValues);
+ mEndValuesList.add(endValues);
unmatchedStart.remove(startView);
unmatchedEnd.remove(endView);
}
@@ -595,13 +591,11 @@
}
/**
- * Match start/end values by Adapter transitionName. Adds matched values to startValuesList
- * and endValuesList and removes them from unmatchedStart and unmatchedEnd, using
+ * Match start/end values by Adapter transitionName. Adds matched values to mStartValuesList
+ * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd, using
* startNames and endNames as a guide for which Views have unique transitionNames.
*/
- private void matchNames(ArrayList<TransitionValues> startValuesList,
- ArrayList<TransitionValues> endValuesList,
- ArrayMap<View, TransitionValues> unmatchedStart,
+ private void matchNames(ArrayMap<View, TransitionValues> unmatchedStart,
ArrayMap<View, TransitionValues> unmatchedEnd,
ArrayMap<String, View> startNames, ArrayMap<String, View> endNames) {
int numStartNames = startNames.size();
@@ -613,8 +607,8 @@
TransitionValues startValues = unmatchedStart.get(startView);
TransitionValues endValues = unmatchedEnd.get(endView);
if (startValues != null && endValues != null) {
- startValuesList.add(startValues);
- endValuesList.add(endValues);
+ mStartValuesList.add(startValues);
+ mEndValuesList.add(endValues);
unmatchedStart.remove(startView);
unmatchedEnd.remove(endView);
}
@@ -624,30 +618,26 @@
}
/**
- * Adds all values from unmatchedStart and unmatchedEnd to startValuesList and endValuesList,
+ * Adds all values from unmatchedStart and unmatchedEnd to mStartValuesList and mEndValuesList,
* assuming that there is no match between values in the list.
*/
- private void addUnmatched(ArrayList<TransitionValues> startValuesList,
- ArrayList<TransitionValues> endValuesList,
- ArrayMap<View, TransitionValues> unmatchedStart,
+ private void addUnmatched(ArrayMap<View, TransitionValues> unmatchedStart,
ArrayMap<View, TransitionValues> unmatchedEnd) {
// Views that only exist in the start Scene
for (int i = 0; i < unmatchedStart.size(); i++) {
- startValuesList.add(unmatchedStart.valueAt(i));
- endValuesList.add(null);
+ mStartValuesList.add(unmatchedStart.valueAt(i));
+ mEndValuesList.add(null);
}
// Views that only exist in the end Scene
for (int i = 0; i < unmatchedEnd.size(); i++) {
- endValuesList.add(unmatchedEnd.valueAt(i));
- startValuesList.add(null);
+ mEndValuesList.add(unmatchedEnd.valueAt(i));
+ mStartValuesList.add(null);
}
}
private void matchStartAndEnd(TransitionValuesMaps startValues,
- TransitionValuesMaps endValues,
- ArrayList<TransitionValues> startValuesList,
- ArrayList<TransitionValues> endValuesList) {
+ TransitionValuesMaps endValues) {
ArrayMap<View, TransitionValues> unmatchedStart =
new ArrayMap<View, TransitionValues>(startValues.viewValues);
ArrayMap<View, TransitionValues> unmatchedEnd =
@@ -656,23 +646,23 @@
for (int i = 0; i < mMatchOrder.length; i++) {
switch (mMatchOrder[i]) {
case MATCH_INSTANCE:
- matchInstances(startValuesList, endValuesList, unmatchedStart, unmatchedEnd);
+ matchInstances(unmatchedStart, unmatchedEnd);
break;
case MATCH_NAME:
- matchNames(startValuesList, endValuesList, unmatchedStart, unmatchedEnd,
+ matchNames(unmatchedStart, unmatchedEnd,
startValues.nameValues, endValues.nameValues);
break;
case MATCH_ID:
- matchIds(startValuesList, endValuesList, unmatchedStart, unmatchedEnd,
+ matchIds(unmatchedStart, unmatchedEnd,
startValues.idValues, endValues.idValues);
break;
case MATCH_ITEM_ID:
- matchItemIds(startValuesList, endValuesList, unmatchedStart, unmatchedEnd,
+ matchItemIds(unmatchedStart, unmatchedEnd,
startValues.itemIdValues, endValues.itemIdValues);
break;
}
}
- addUnmatched(startValuesList, endValuesList, unmatchedStart, unmatchedEnd);
+ addUnmatched(unmatchedStart, unmatchedEnd);
}
/**
@@ -687,19 +677,17 @@
* @hide
*/
protected void createAnimators(ViewGroup sceneRoot, TransitionValuesMaps startValues,
- TransitionValuesMaps endValues) {
+ TransitionValuesMaps endValues, ArrayList<TransitionValues> startValuesList,
+ ArrayList<TransitionValues> endValuesList) {
if (DBG) {
Log.d(LOG_TAG, "createAnimators() for " + this);
}
- ArrayList<TransitionValues> startValuesList = new ArrayList<TransitionValues>();
- ArrayList<TransitionValues> endValuesList = new ArrayList<TransitionValues>();
- matchStartAndEnd(startValues, endValues, startValuesList, endValuesList);
-
ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
long minStartDelay = Long.MAX_VALUE;
int minAnimator = mAnimators.size();
SparseLongArray startDelays = new SparseLongArray();
- for (int i = 0; i < startValuesList.size(); ++i) {
+ int startValuesListCount = startValuesList.size();
+ for (int i = 0; i < startValuesListCount; ++i) {
TransitionValues start = startValuesList.get(i);
TransitionValues end = endValuesList.get(i);
// Only bother trying to animate with valid values that differ between start/end
@@ -1523,11 +1511,13 @@
mStartValues.idValues.clear();
mStartValues.itemIdValues.clear();
mStartValues.nameValues.clear();
+ mStartValuesList = null;
} else {
mEndValues.viewValues.clear();
mEndValues.idValues.clear();
mEndValues.itemIdValues.clear();
mEndValues.nameValues.clear();
+ mEndValuesList = null;
}
}
@@ -1613,6 +1603,45 @@
}
/**
+ * Find the matched start or end value for a given View. This is only valid
+ * after playTransition starts. For example, it will be valid in
+ * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)}, but not
+ * in {@link #captureStartValues(TransitionValues)}.
+ *
+ * @param view The view to find the match for.
+ * @param viewInStart Is View from the start values or end values.
+ * @return The matching TransitionValues for view in either start or end values, depending
+ * on viewInStart or null if there is no match for the given view.
+ */
+ TransitionValues getMatchedTransitionValues(View view, boolean viewInStart) {
+ if (mParent != null) {
+ return mParent.getMatchedTransitionValues(view, viewInStart);
+ }
+ ArrayList<TransitionValues> lookIn = viewInStart ? mStartValuesList : mEndValuesList;
+ if (lookIn == null) {
+ return null;
+ }
+ int count = lookIn.size();
+ int index = -1;
+ for (int i = 0; i < count; i++) {
+ TransitionValues values = lookIn.get(i);
+ if (values == null) {
+ return null;
+ }
+ if (values.view == view) {
+ index = i;
+ break;
+ }
+ }
+ TransitionValues values = null;
+ if (index >= 0) {
+ ArrayList<TransitionValues> matchIn = viewInStart ? mEndValuesList : mStartValuesList;
+ values = matchIn.get(index);
+ }
+ return values;
+ }
+
+ /**
* Pauses this transition, sending out calls to {@link
* TransitionListener#onTransitionPause(Transition)} to all listeners
* and pausing all running animators started by this transition.
@@ -1684,6 +1713,10 @@
* runAnimations() to actually start the animations.
*/
void playTransition(ViewGroup sceneRoot) {
+ mStartValuesList = new ArrayList<TransitionValues>();
+ mEndValuesList = new ArrayList<TransitionValues>();
+ matchStartAndEnd(mStartValues, mEndValues);
+
ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
int numOldAnims = runningAnimators.size();
WindowId windowId = sceneRoot.getWindowId();
@@ -1694,7 +1727,7 @@
if (oldInfo != null && oldInfo.view != null && oldInfo.windowId == windowId) {
TransitionValues oldValues = oldInfo.values;
View oldView = oldInfo.view;
- TransitionValues newValues = mEndValues.viewValues.get(oldView);
+ TransitionValues newValues = getMatchedTransitionValues(oldView, true);
boolean cancel = oldInfo.transition.areValuesChanged(oldValues, newValues);
if (cancel) {
if (anim.isRunning() || anim.isStarted()) {
@@ -1713,7 +1746,7 @@
}
}
- createAnimators(sceneRoot, mStartValues, mEndValues);
+ createAnimators(sceneRoot, mStartValues, mEndValues, mStartValuesList, mEndValuesList);
runAnimators();
}
@@ -2055,6 +2088,8 @@
clone.mAnimators = new ArrayList<Animator>();
clone.mStartValues = new TransitionValuesMaps();
clone.mEndValues = new TransitionValuesMaps();
+ clone.mStartValuesList = null;
+ clone.mEndValuesList = null;
} catch (CloneNotSupportedException e) {}
return clone;
diff --git a/core/java/android/transition/TransitionSet.java b/core/java/android/transition/TransitionSet.java
index 83c60af..f6499ae 100644
--- a/core/java/android/transition/TransitionSet.java
+++ b/core/java/android/transition/TransitionSet.java
@@ -151,6 +151,31 @@
}
/**
+ * Returns the number of child transitions in the TransitionSet.
+ *
+ * @return The number of child transitions in the TransitionSet.
+ * @see #addTransition(Transition)
+ * @see #getTransitionAt(int)
+ */
+ public int getTransitionCount() {
+ return mTransitions.size();
+ }
+
+ /**
+ * Returns the child Transition at the specified position in the TransitionSet.
+ *
+ * @param index The position of the Transition to retrieve.
+ * @see #addTransition(Transition)
+ * @see #getTransitionCount()
+ */
+ public Transition getTransitionAt(int index) {
+ if (index < 0 || index >= mTransitions.size()) {
+ return null;
+ }
+ return mTransitions.get(index);
+ }
+
+ /**
* Setting a non-negative duration on a TransitionSet causes all of the child
* transitions (current and future) to inherit this duration.
*
@@ -361,11 +386,13 @@
*/
@Override
protected void createAnimators(ViewGroup sceneRoot, TransitionValuesMaps startValues,
- TransitionValuesMaps endValues) {
+ TransitionValuesMaps endValues, ArrayList<TransitionValues> startValuesList,
+ ArrayList<TransitionValues> endValuesList) {
startValues = removeExcludes(startValues);
endValues = removeExcludes(endValues);
for (Transition childTransition : mTransitions) {
- childTransition.createAnimators(sceneRoot, startValues, endValues);
+ childTransition.createAnimators(sceneRoot, startValues, endValues, startValuesList,
+ endValuesList);
}
}
diff --git a/core/java/android/view/MenuItem.java b/core/java/android/view/MenuItem.java
index 2dfbcb5..e706c9c 100644
--- a/core/java/android/view/MenuItem.java
+++ b/core/java/android/view/MenuItem.java
@@ -258,8 +258,8 @@
/**
* Change both the numeric and alphabetic shortcut associated with this
* item. Note that the shortcut will be triggered when the key that
- * generates the given character is pressed alone or along with with the alt
- * key. Also note that case is not significant and that alphabetic shortcut
+ * generates the given character is pressed along with the ctrl key.
+ * Also note that case is not significant and that alphabetic shortcut
* characters will be displayed in lower case.
* <p>
* See {@link Menu} for the menu types that support shortcuts.
@@ -293,9 +293,9 @@
/**
* Change the alphabetic shortcut associated with this item. The shortcut
* will be triggered when the key that generates the given character is
- * pressed alone or along with with the alt key. Case is not significant and
- * shortcut characters will be displayed in lower case. Note that menu items
- * with the characters '\b' or '\n' as shortcuts will get triggered by the
+ * pressed along with the ctrl key. Case is not significant and shortcut
+ * characters will be displayed in lower case. Note that menu items with
+ * the characters '\b' or '\n' as shortcuts will get triggered by the
* Delete key or Carriage Return key, respectively.
* <p>
* See {@link Menu} for the menu types that support shortcuts.
@@ -596,4 +596,4 @@
* @return This menu item instance for call chaining
*/
public MenuItem setOnActionExpandListener(OnActionExpandListener listener);
-}
\ No newline at end of file
+}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index e56581b..3adc41a 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -700,6 +700,13 @@
public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
/**
+ * When set to true, this view will save its attribute data.
+ *
+ * @hide
+ */
+ public static boolean mDebugViewAttributes = false;
+
+ /**
* Used to mark a View that has no ID.
*/
public static final int NO_ID = -1;
@@ -3254,6 +3261,7 @@
* This field should be made private, so it is hidden from the SDK.
* {@hide}
*/
+ @ViewDebug.ExportedProperty(deepExport = true)
protected Context mContext;
private final Resources mResources;
@@ -3524,6 +3532,18 @@
GhostView mGhostView;
/**
+ * Holds pairs of adjacent attribute data: attribute name followed by its value.
+ * @hide
+ */
+ @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
+ public String[] mAttributes;
+
+ /**
+ * Maps a Resource id to its name.
+ */
+ private static SparseArray<String> mAttributeMap;
+
+ /**
* Simple constructor to use when creating a view from code.
*
* @param context The Context the view is running in, through which it can
@@ -3641,6 +3661,10 @@
final TypedArray a = context.obtainStyledAttributes(
attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
+ if (mDebugViewAttributes) {
+ saveAttributeData(attrs, a);
+ }
+
Drawable background = null;
int leftPadding = -1;
@@ -4136,6 +4160,51 @@
mRenderNode = RenderNode.create(getClass().getName());
}
+ private static SparseArray<String> getAttributeMap() {
+ if (mAttributeMap == null) {
+ mAttributeMap = new SparseArray<String>();
+ }
+ return mAttributeMap;
+ }
+
+ private void saveAttributeData(AttributeSet attrs, TypedArray a) {
+ int length = ((attrs == null ? 0 : attrs.getAttributeCount()) + a.getIndexCount()) * 2;
+ mAttributes = new String[length];
+
+ int i = 0;
+ if (attrs != null) {
+ for (i = 0; i < attrs.getAttributeCount(); i += 2) {
+ mAttributes[i] = attrs.getAttributeName(i);
+ mAttributes[i + 1] = attrs.getAttributeValue(i);
+ }
+
+ }
+
+ SparseArray<String> attributeMap = getAttributeMap();
+ for (int j = 0; j < a.length(); ++j) {
+ if (a.hasValue(j)) {
+ try {
+ int resourceId = a.getResourceId(j, 0);
+ if (resourceId == 0) {
+ continue;
+ }
+
+ String resourceName = attributeMap.get(resourceId);
+ if (resourceName == null) {
+ resourceName = a.getResources().getResourceName(resourceId);
+ attributeMap.put(resourceId, resourceName);
+ }
+
+ mAttributes[i] = resourceName;
+ mAttributes[i + 1] = a.getText(j).toString();
+ i += 2;
+ } catch (Resources.NotFoundException e) {
+ // if we can't get the resource name, we just ignore it
+ }
+ }
+ }
+ }
+
public String toString() {
StringBuilder out = new StringBuilder(128);
out.append(getClass().getName());
@@ -13762,6 +13831,7 @@
} else {
draw(canvas);
}
+ drawAccessibilityFocus(canvas);
}
} finally {
renderNode.end(canvas);
@@ -14056,6 +14126,7 @@
} else {
draw(canvas);
}
+ drawAccessibilityFocus(canvas);
canvas.restoreToCount(restoreCount);
canvas.setBitmap(null);
@@ -14130,6 +14201,7 @@
} else {
draw(canvas);
}
+ drawAccessibilityFocus(canvas);
mPrivateFlags = flags;
@@ -14723,9 +14795,13 @@
if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
mPrivateFlags &= ~PFLAG_DIRTY_MASK;
dispatchDraw(canvas);
+ if (mOverlay != null && !mOverlay.isEmpty()) {
+ mOverlay.getOverlayView().draw(canvas);
+ }
} else {
draw(canvas);
}
+ drawAccessibilityFocus(canvas);
} else {
mPrivateFlags &= ~PFLAG_DIRTY_MASK;
((HardwareCanvas) canvas).drawRenderNode(renderNode, null, flags);
@@ -14977,6 +15053,45 @@
}
/**
+ * Draws the accessibility focus rect onto the specified canvas.
+ *
+ * @param canvas Canvas on which to draw the focus rect
+ */
+ private void drawAccessibilityFocus(Canvas canvas) {
+ if (mAttachInfo == null) {
+ return;
+ }
+
+ final Rect bounds = mAttachInfo.mTmpInvalRect;
+ final ViewRootImpl viewRoot = getViewRootImpl();
+ if (viewRoot == null || viewRoot.getAccessibilityFocusedHost() != this) {
+ return;
+ }
+
+ final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
+ if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
+ return;
+ }
+
+ final Drawable drawable = viewRoot.getAccessibilityFocusedDrawable();
+ if (drawable == null) {
+ return;
+ }
+
+ final AccessibilityNodeInfo virtualView = viewRoot.getAccessibilityFocusedVirtualView();
+ if (virtualView != null) {
+ virtualView.getBoundsInParent(bounds);
+ } else {
+ bounds.set(0, 0, mRight - mLeft, mBottom - mTop);
+ }
+
+ canvas.translate(mScrollX, mScrollY);
+ drawable.setBounds(bounds);
+ drawable.draw(canvas);
+ canvas.translate(-mScrollX, -mScrollY);
+ }
+
+ /**
* Draws the background onto the specified canvas.
*
* @param canvas Canvas on which to draw the background
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 4d9a8cc..6c66eb0 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -187,6 +187,15 @@
* @return true if the supported values should be formatted as a hex string.
*/
boolean formatToHexString() default false;
+
+ /**
+ * Indicates whether or not the key to value mappings are held in adjacent indices.
+ *
+ * Note: Applies only to fields and methods that return String[].
+ *
+ * @return true if the key to value mappings are held in adjacent indices.
+ */
+ boolean hasAdjacentMapping() default false;
}
/**
@@ -1056,7 +1065,6 @@
Class<?> klass, String prefix) throws IOException {
final Method[] methods = getExportedPropertyMethods(klass);
-
int count = methods.length;
for (int i = 0; i < count; i++) {
final Method method = methods[i];
@@ -1108,6 +1116,19 @@
exportUnrolledArray(context, out, property, array, valuePrefix, suffix);
continue;
+ } else if (returnType == String[].class) {
+ final String[] array = (String[]) methodValue;
+ if (property.hasAdjacentMapping() && array != null) {
+ for (int j = 0; j < array.length; j += 2) {
+ if (array[j] != null) {
+ writeEntry(out, categoryPrefix + prefix, array[j], "()",
+ array[j + 1] == null ? "null" : array[j + 1]);
+ }
+
+ }
+ }
+
+ continue;
} else if (!returnType.isPrimitive()) {
if (property.deepExport()) {
dumpViewProperties(context, methodValue, out, prefix + property.prefix());
@@ -1187,6 +1208,18 @@
exportUnrolledArray(context, out, property, array, valuePrefix, suffix);
continue;
+ } else if (type == String[].class) {
+ final String[] array = (String[]) field.get(view);
+ if (property.hasAdjacentMapping() && array != null) {
+ for (int j = 0; j < array.length; j += 2) {
+ if (array[j] != null) {
+ writeEntry(out, categoryPrefix + prefix, array[j], "",
+ array[j + 1] == null ? "null" : array[j + 1]);
+ }
+ }
+ }
+
+ continue;
} else if (!type.isPrimitive()) {
if (property.deepExport()) {
dumpViewProperties(context, field.get(view), out, prefix +
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 92e0245..bb469a3 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2244,7 +2244,6 @@
canvas.drawHardwareLayer(mResizeBuffer, mHardwareXOffset, mHardwareYOffset,
mResizePaint);
}
- drawAccessibilityFocusedDrawableIfNeeded(canvas);
}
/**
@@ -2462,25 +2461,9 @@
if (mHardwareYOffset != yOffset || mHardwareXOffset != xOffset) {
mHardwareYOffset = yOffset;
mHardwareXOffset = xOffset;
- invalidateRoot = true;
- }
- mResizeAlpha = resizeAlpha;
-
- if (!invalidateRoot) {
- // If accessibility focus moved, invalidate the root.
- final Drawable drawable = mAttachInfo.mAccessibilityFocusDrawable;
- if (drawable != null) {
- final Rect bounds = mAttachInfo.mTmpInvalRect;
- if (getAccessibilityFocusedRect(bounds)
- && !bounds.equals(drawable.getBounds())) {
- invalidateRoot = true;
- }
- }
- }
-
- if (invalidateRoot) {
mAttachInfo.mHardwareRenderer.invalidateRoot();
}
+ mResizeAlpha = resizeAlpha;
dirty.setEmpty();
@@ -2600,8 +2583,6 @@
attachInfo.mSetIgnoreDirtyState = false;
mView.draw(canvas);
-
- drawAccessibilityFocusedDrawableIfNeeded(canvas);
} finally {
if (!attachInfo.mSetIgnoreDirtyState) {
// Only clear the flag if it was not set during the mView.draw() call
@@ -2625,54 +2606,7 @@
return true;
}
- /**
- * We want to draw a highlight around the current accessibility focused.
- * Since adding a style for all possible view is not a viable option we
- * have this specialized drawing method.
- *
- * Note: We are doing this here to be able to draw the highlight for
- * virtual views in addition to real ones.
- *
- * @param canvas The canvas on which to draw.
- */
- private void drawAccessibilityFocusedDrawableIfNeeded(Canvas canvas) {
- final Rect bounds = mAttachInfo.mTmpInvalRect;
- if (getAccessibilityFocusedRect(bounds)) {
- final Drawable drawable = getAccessibilityFocusedDrawable();
- if (drawable != null) {
- drawable.setBounds(bounds);
- drawable.draw(canvas);
- }
- }
- }
-
- private boolean getAccessibilityFocusedRect(Rect bounds) {
- final AccessibilityManager manager = AccessibilityManager.getInstance(mView.mContext);
- if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
- return false;
- }
-
- final View host = mAccessibilityFocusedHost;
- if (host == null || host.mAttachInfo == null) {
- return false;
- }
-
- final AccessibilityNodeProvider provider = host.getAccessibilityNodeProvider();
- if (provider == null) {
- host.getBoundsOnScreen(bounds);
- } else if (mAccessibilityFocusedVirtualView != null) {
- mAccessibilityFocusedVirtualView.getBoundsInScreen(bounds);
- } else {
- return false;
- }
-
- final AttachInfo attachInfo = mAttachInfo;
- bounds.offset(-attachInfo.mWindowLeft, -attachInfo.mWindowTop);
- bounds.intersect(0, 0, attachInfo.mViewRootImpl.mWidth, attachInfo.mViewRootImpl.mHeight);
- return true;
- }
-
- private Drawable getAccessibilityFocusedDrawable() {
+ Drawable getAccessibilityFocusedDrawable() {
// Lazily load the accessibility focus drawable.
if (mAttachInfo.mAccessibilityFocusDrawable == null) {
final TypedValue value = new TypedValue();
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 4dd7e07..23f911c 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -1501,7 +1501,7 @@
mRules[ALIGN_PARENT_START] = 0;
}
- if (mRules[ALIGN_PARENT_RIGHT] == 0) {
+ if (mRules[ALIGN_PARENT_END] != 0) {
if (mRules[ALIGN_PARENT_RIGHT] == 0) {
// "right" rule is not defined but "end" rule is: use the "end" rule as the
// "right" rule
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index d801571..6eb0099 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -974,6 +974,16 @@
}
}
+ public boolean isShowImeWithHardKeyboardEnabled() {
+ return Settings.Secure.getIntForUser(mResolver,
+ Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0, mCurrentUserId) == 1;
+ }
+
+ public void setShowImeWithHardKeyboard(boolean show) {
+ Settings.Secure.putIntForUser(mResolver, Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD,
+ show ? 1 : 0, mCurrentUserId);
+ }
+
public int getCurrentUserId() {
return mCurrentUserId;
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 6c9766e..299b0e6 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -105,7 +105,7 @@
// The maximum number of names wakelocks we will keep track of
// per uid; once the limit is reached, we batch the remaining wakelocks
// in to one common name.
- private static final int MAX_WAKELOCKS_PER_UID = 50;
+ private static final int MAX_WAKELOCKS_PER_UID = 100;
private static int sNumSpeedSteps;
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 32cf286..5bd38f3 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -69,9 +69,8 @@
*/
static struct fieldIds {
jmethodID clear;
- jmethodID setInterfaceName;
- jmethodID addLinkAddress;
- jmethodID addGateway;
+ jmethodID setIpAddress;
+ jmethodID setGateway;
jmethodID addDns;
jmethodID setDomains;
jmethodID setServerAddress;
@@ -130,21 +129,16 @@
if (result == 0) {
env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.clear);
- // set mIfaceName
- // dhcpResults->setInterfaceName(ifname)
- env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setInterfaceName, ifname);
-
// set the linkAddress
// dhcpResults->addLinkAddress(inetAddress, prefixLength)
- result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.addLinkAddress,
+ result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.setIpAddress,
env->NewStringUTF(ipaddr), prefixLength);
}
if (result == 0) {
// set the gateway
- // dhcpResults->addGateway(gateway)
result = env->CallBooleanMethod(dhcpResults,
- dhcpResultsFieldIds.addGateway, env->NewStringUTF(gateway));
+ dhcpResultsFieldIds.setGateway, env->NewStringUTF(gateway));
}
if (result == 0) {
@@ -279,12 +273,10 @@
LOG_FATAL_IF(dhcpResultsClass == NULL, "Unable to find class android/net/DhcpResults");
dhcpResultsFieldIds.clear =
env->GetMethodID(dhcpResultsClass, "clear", "()V");
- dhcpResultsFieldIds.setInterfaceName =
- env->GetMethodID(dhcpResultsClass, "setInterfaceName", "(Ljava/lang/String;)V");
- dhcpResultsFieldIds.addLinkAddress =
- env->GetMethodID(dhcpResultsClass, "addLinkAddress", "(Ljava/lang/String;I)Z");
- dhcpResultsFieldIds.addGateway =
- env->GetMethodID(dhcpResultsClass, "addGateway", "(Ljava/lang/String;)Z");
+ dhcpResultsFieldIds.setIpAddress =
+ env->GetMethodID(dhcpResultsClass, "setIpAddress", "(Ljava/lang/String;I)Z");
+ dhcpResultsFieldIds.setGateway =
+ env->GetMethodID(dhcpResultsClass, "setGateway", "(Ljava/lang/String;)Z");
dhcpResultsFieldIds.addDns =
env->GetMethodID(dhcpResultsClass, "addDns", "(Ljava/lang/String;)Z");
dhcpResultsFieldIds.setDomains =
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index aee3090..157147e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1249,13 +1249,13 @@
android:description="@string/permdesc_use_sip"
android:label="@string/permlab_use_sip" />
- <!-- @SystemApi Allows an application to request CallHandlerService implementations.
+ <!-- @SystemApi Allows an application to bind to InCallService implementations.
@hide -->
- <permission android:name="android.permission.BIND_CALL_SERVICE"
+ <permission android:name="android.permission.BIND_INCALL_SERVICE"
android:permissionGroup="android.permission-group.PHONE_CALLS"
android:protectionLevel="system|signature"
- android:description="@string/permdesc_bind_call_service"
- android:label="@string/permlab_bind_call_service" />
+ android:description="@string/permdesc_bind_incall_service"
+ android:label="@string/permlab_bind_incall_service" />
<!-- @SystemApi Allows an application to bind to ConnectionService implementations.
@hide -->
@@ -1265,6 +1265,14 @@
android:description="@string/permdesc_bind_connection_service"
android:label="@string/permlab_bind_connection_service" />
+ <!-- @SystemApi Allows an application to control the in-call experience.
+ @hide -->
+ <permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE"
+ android:permissionGroup="android.permission-group.PHONE_CALLS"
+ android:protectionLevel="system|signature"
+ android:description="@string/permdesc_control_incall_experience"
+ android:label="@string/permlab_control_incall_experience" />
+
<!-- ================================== -->
<!-- Permissions for sdcard interaction -->
<!-- ================================== -->
@@ -2811,11 +2819,11 @@
android:description="@string/permdesc_accessDrmCertificates"
android:protectionLevel="signature|system" />
- <!-- Api Allows an application to create media projection sessions.
+ <!-- Api Allows an application to manage media projection sessions.
@hide This is not a third-party API (intended for system apps). -->
- <permission android:name="android.permission.CREATE_MEDIA_PROJECTION"
- android:label="@string/permlab_createMediaProjection"
- android:description="@string/permdesc_createMediaProjection"
+ <permission android:name="android.permission.MANAGE_MEDIA_PROJECTION"
+ android:label="@string/permlab_manageMediaProjection"
+ android:description="@string/permdesc_manageMediaProjection"
android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to read install sessions
diff --git a/core/res/res/drawable/stat_notify_disabled_data.xml b/core/res/res/drawable/stat_notify_disabled_data.xml
index 2f6ffaf..9089d08 100644
--- a/core/res/res/drawable/stat_notify_disabled_data.xml
+++ b/core/res/res/drawable/stat_notify_disabled_data.xml
@@ -18,17 +18,7 @@
android:height="24dp"
android:viewportWidth="48.0"
android:viewportHeight="48.0">
-
<path
android:fillColor="#FFFFFFFF"
- android:pathData="M40.709,4.5l-6.604,7.337 0.0,16.601 6.604,6.604z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M32.305,13.838l-6.0629997,6.7370005 6.0629997,6.0629997z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M15.498,40.5l0.0,-7.9869995 -7.205,7.9869995z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M10.265,9.72l-2.5460005,2.545 9.971001,9.971 3.7139988,3.7140007 -4.105999,4.5619984 0.0,9.988001 6.6019993,0.0 0.0,-12.054001 1.8029995,1.8030014 0.0,10.250999 6.602001,0.0 0.0,-3.6479988 1.7999992,1.7999992 1.8479996,1.8479996 4.670002,4.669998 2.5459976,-2.5459976z"/>
+ android:pathData="M26.000000,4.100000l0.000000,6.100000c6.800000,1.000000 12.000000,6.800000 12.000000,13.800000c0.000000,1.800000 -0.400000,3.500000 -1.000000,5.100000l5.200000,3.100000c1.100000,-2.500000 1.800000,-5.200000 1.800000,-8.100000C44.000000,13.600000 36.099998,5.100000 26.000000,4.100000zM24.000000,38.000000c-7.700000,0.000000 -14.000000,-6.300000 -14.000000,-14.000000c0.000000,-7.100000 5.200000,-12.900000 12.000000,-13.800000L22.000000,4.100000C11.900000,5.100000 4.000000,13.600000 4.000000,24.000000c0.000000,11.000000 8.900000,20.000000 20.000000,20.000000c6.600000,0.000000 12.500000,-3.200000 16.100000,-8.200000l-5.200000,-3.100000C32.299999,36.000000 28.400000,38.000000 24.000000,38.000000z"/>
</vector>
diff --git a/core/res/res/layout/alert_dialog_material.xml b/core/res/res/layout/alert_dialog_material.xml
index c3f9c76..5f9066a 100644
--- a/core/res/res/layout/alert_dialog_material.xml
+++ b/core/res/res/layout/alert_dialog_material.xml
@@ -31,9 +31,9 @@
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical|start"
- android:paddingStart="16dip"
- android:paddingEnd="16dip"
- android:paddingTop="16dip"
+ android:paddingStart="@dimen/alert_dialog_padding_material"
+ android:paddingEnd="@dimen/alert_dialog_padding_material"
+ android:paddingTop="@dimen/alert_dialog_padding_material"
android:paddingBottom="8dip">
<ImageView android:id="@+id/icon"
android:layout_width="32dip"
@@ -66,10 +66,10 @@
style="?attr/textAppearanceMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingStart="16dip"
- android:paddingEnd="16dip"
- android:paddingTop="16dip"
- android:paddingBottom="16dip" />
+ android:paddingStart="@dimen/alert_dialog_padding_material"
+ android:paddingEnd="@dimen/alert_dialog_padding_material"
+ android:paddingTop="@dimen/alert_dialog_padding_material"
+ android:paddingBottom="@dimen/alert_dialog_padding_material" />
</ScrollView>
</LinearLayout>
@@ -87,35 +87,33 @@
style="?attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical"
- android:gravity="end">
- <LinearLayout
- android:layout_width="match_parent"
+ android:layoutDirection="locale"
+ android:orientation="horizontal"
+ android:paddingStart="6dp"
+ android:paddingEnd="6dp"
+ android:paddingBottom="6dp">
+ <Button android:id="@+id/button3"
+ style="?attr/buttonBarNeutralButtonStyle"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layoutDirection="locale">
- <Button android:id="@+id/button3"
- style="?attr/buttonBarNeutralButtonStyle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:maxLines="2"
- android:minHeight="@dimen/alert_dialog_button_bar_height" />
- <Space
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:layout_weight="1"
- android:visibility="invisible" />
- <Button android:id="@+id/button2"
- style="?attr/buttonBarNegativeButtonStyle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:maxLines="2"
- android:minHeight="@dimen/alert_dialog_button_bar_height" />
- <Button android:id="@+id/button1"
- style="?attr/buttonBarPositiveButtonStyle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:maxLines="2"
- android:minHeight="@dimen/alert_dialog_button_bar_height" />
- </LinearLayout>
- </LinearLayout>
+ android:maxLines="2"
+ android:minHeight="@dimen/alert_dialog_button_bar_height" />
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:visibility="invisible" />
+ <Button android:id="@+id/button2"
+ style="?attr/buttonBarNegativeButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:maxLines="2"
+ android:minHeight="@dimen/alert_dialog_button_bar_height" />
+ <Button android:id="@+id/button1"
+ style="?attr/buttonBarPositiveButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:maxLines="2"
+ android:minHeight="@dimen/alert_dialog_button_bar_height" />
+ </LinearLayout>
</LinearLayout>
diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml
index e5a3c17..972ae5e 100644
--- a/core/res/res/values/dimens_material.xml
+++ b/core/res/res/values/dimens_material.xml
@@ -42,6 +42,8 @@
<dimen name="text_size_headline_material">24sp</dimen>
<dimen name="text_size_title_material">20sp</dimen>
<dimen name="text_size_subhead_material">16sp</dimen>
+ <dimen name="text_size_title_material_toolbar">20dp</dimen>
+ <dimen name="text_size_subtitle_material_toolbar">16dp</dimen>
<dimen name="text_size_menu_material">16sp</dimen>
<dimen name="text_size_body_2_material">14sp</dimen>
<dimen name="text_size_body_1_material">14sp</dimen>
@@ -71,4 +73,6 @@
<!-- Default alpha value for disabled elements. -->
<item name="disabled_alpha_material" format="float" type="dimen">0.26</item>
+
+ <dimen name="alert_dialog_padding_material">12dp</dimen>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 27c8207..7ade51d 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2530,6 +2530,9 @@
<public type="style" name="Widget.Material.Spinner.Form" />
<public type="style" name="Widget.Material.Light.Spinner.Form" />
+ <public type="style" name="TextAppearance.Material.Widget.Toolbar.Title" />
+ <public type="style" name="TextAppearance.Material.Widget.Toolbar.Subtitle" />
+
<public-padding type="string" name="l_resource_pad" end="0x01040030" />
<public type="string" name="config_webSettingsDefaultTextEncoding" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index c68f355..2936e2b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2112,9 +2112,9 @@
<string name="permdesc_use_sip">Allows the app to make and receive SIP calls.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_bind_call_service">interact with in-call screen</string>
+ <string name="permlab_bind_incall_service">interact with in-call screen</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_bind_call_service">Allows the app to control when and how the user sees the in-call screen.</string>
+ <string name="permdesc_bind_incall_service">Allows the app to control when and how the user sees the in-call screen.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_bind_connection_service">interact with telephony services</string>
@@ -2122,6 +2122,11 @@
<string name="permdesc_bind_connection_service">Allows the app to interact with telephony services to make/receive calls.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_control_incall_experience">provide an in-call user experience</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_control_incall_experience">Allows the app to provide an in-call user experience.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_readNetworkUsageHistory">read historical network usage</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_readNetworkUsageHistory">Allows the app to read historical network usage for specific networks and apps.</string>
@@ -3899,10 +3904,10 @@
<!-- Description of an application permission that lets it control keyguard. -->
<string name="permdesc_recovery">Allows an application to interact with the recovery system and system updates.</string>
- <!-- Title of an application permission that lets it create media projection sessions. -->
- <string name="permlab_createMediaProjection">Create media projection sessions</string>
- <!-- Description of an application permission that lets it create media projection sessions. -->
- <string name="permdesc_createMediaProjection">Allows an application to create media projection sessions. These sessions can provide applications the ability to capture display and audio contents. Should never be needed by normal apps.</string>
+ <!-- Title of an application permission that lets it manage media projection sessions. -->
+ <string name="permlab_manageMediaProjection">Manage media projection sessions</string>
+ <!-- Description of an application permission that lets it manage media projection sessions. -->
+ <string name="permdesc_manageMediaProjection">Allows an application to manage media projection sessions. These sessions can provide applications the ability to capture display and audio contents. Should never be needed by normal apps.</string>
<!-- Title of an application permission that lets it read install sessions. -->
<string name="permlab_readInstallSessions">Read install sessions</string>
@@ -4245,15 +4250,15 @@
<string name="data_usage_warning_body">Touch to view usage and settings.</string>
<!-- Notification title when 2G-3G data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
- <string name="data_usage_3g_limit_title">2G-3G data is off</string>
+ <string name="data_usage_3g_limit_title">2G-3G data limit reached</string>
<!-- Notification title when 4G data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
- <string name="data_usage_4g_limit_title">4G data is off</string>
+ <string name="data_usage_4g_limit_title">4G data limit reached</string>
<!-- Notification title when mobile data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
- <string name="data_usage_mobile_limit_title">Cellular data is off</string>
+ <string name="data_usage_mobile_limit_title">Cellular data limit reached</string>
<!-- Notification title when Wi-Fi data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
- <string name="data_usage_wifi_limit_title">Wi-Fi data is off</string>
+ <string name="data_usage_wifi_limit_title">Wi-Fi data limit reached</string>
<!-- Notification body when data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
- <string name="data_usage_limit_body">Limit reached</string>
+ <string name="data_usage_limit_body">Data paused for rest of cycle</string>
<!-- Notification title when 2G-3G data usage has exceeded limit threshold. [CHAR LIMIT=32] -->
<string name="data_usage_3g_limit_snoozed_title">2G-3G data limit exceeded</string>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 298fea3..c8ea699 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -313,15 +313,38 @@
</style>
<style name="TextAppearance.Material.Widget.ActionMode"/>
- <style name="TextAppearance.Material.Widget.ActionMode.Title" parent="TextAppearance.Material.Title" />
- <style name="TextAppearance.Material.Widget.ActionMode.Title.Inverse" parent="TextAppearance.Material.Title.Inverse" />
- <style name="TextAppearance.Material.Widget.ActionMode.Subtitle" parent="TextAppearance.Material.Subhead" />
- <style name="TextAppearance.Material.Widget.ActionMode.Subtitle.Inverse" parent="TextAppearance.Material.Subhead.Inverse" />
-
- <style name="TextAppearance.Material.Widget.ActionBar.Title" parent="TextAppearance.Material.Title" />
- <style name="TextAppearance.Material.Widget.ActionBar.Title.Inverse" parent="TextAppearance.Material.Title.Inverse" />
- <style name="TextAppearance.Material.Widget.ActionBar.Subtitle" parent="TextAppearance.Material.Subhead" />
- <style name="TextAppearance.Material.Widget.ActionBar.Subtitle.Inverse" parent="TextAppearance.Material.Subhead.Inverse" />
+ <style name="TextAppearance.Material.Widget.ActionMode.Title"
+ parent="TextAppearance.Material.Title">
+ <item name="textSize">@dimen/text_size_title_material_toolbar</item>
+ </style>
+ <style name="TextAppearance.Material.Widget.ActionMode.Title.Inverse"
+ parent="TextAppearance.Material.Title.Inverse">
+ <item name="textSize">@dimen/text_size_title_material_toolbar</item>
+ </style>
+ <style name="TextAppearance.Material.Widget.ActionMode.Subtitle"
+ parent="TextAppearance.Material.Subhead">
+ <item name="textSize">@dimen/text_size_subtitle_material_toolbar</item>
+ </style>
+ <style name="TextAppearance.Material.Widget.ActionMode.Subtitle.Inverse"
+ parent="TextAppearance.Material.Subhead.Inverse">
+ <item name="textSize">@dimen/text_size_subtitle_material_toolbar</item>
+ </style>
+ <style name="TextAppearance.Material.Widget.ActionBar.Title"
+ parent="TextAppearance.Material.Title">
+ <item name="textSize">@dimen/text_size_title_material_toolbar</item>
+ </style>
+ <style name="TextAppearance.Material.Widget.ActionBar.Title.Inverse"
+ parent="TextAppearance.Material.Title.Inverse">
+ <item name="textSize">@dimen/text_size_title_material_toolbar</item>
+ </style>
+ <style name="TextAppearance.Material.Widget.ActionBar.Subtitle"
+ parent="TextAppearance.Material.Subhead">
+ <item name="textSize">@dimen/text_size_subtitle_material_toolbar</item>
+ </style>
+ <style name="TextAppearance.Material.Widget.ActionBar.Subtitle.Inverse"
+ parent="TextAppearance.Material.Subhead.Inverse">
+ <item name="textSize">@dimen/text_size_subtitle_material_toolbar</item>
+ </style>
<style name="TextAppearance.Material.Widget.ActionBar.Menu" parent="TextAppearance.Material.Menu">
<item name="textColor">?attr/actionMenuTextColor</item>
@@ -333,6 +356,11 @@
<item name="textAllCaps">@bool/config_actionMenuItemAllCaps</item>
</style>
+ <style name="TextAppearance.Material.Widget.Toolbar.Title"
+ parent="TextAppearance.Material.Widget.ActionBar.Title" />
+ <style name="TextAppearance.Material.Widget.Toolbar.Subtitle"
+ parent="TextAppearance.Material.Widget.ActionBar.Subtitle" />
+
<style name="TextAppearance.Material.WindowTitle" parent="TextAppearance.Material.Title" />
<style name="TextAppearance.Material.DialogWindowTitle" parent="TextAppearance.Material.Title" />
@@ -423,12 +451,15 @@
<style name="Widget.Material" parent="Widget" />
<!-- Bordered ink button -->
- <style name="Widget.Material.Button" parent="Widget.Button">
+ <style name="Widget.Material.Button">
<item name="background">@drawable/btn_default_material</item>
<item name="textAppearance">?attr/textAppearanceButton</item>
<item name="minHeight">48dip</item>
<item name="minWidth">88dip</item>
<item name="stateListAnimator">@anim/button_state_list_anim_material</item>
+ <item name="focusable">true</item>
+ <item name="clickable">true</item>
+ <item name="gravity">center_vertical|center_horizontal</item>
</style>
<!-- Small bordered ink button -->
@@ -471,9 +502,6 @@
<style name="Widget.Material.ButtonBar.AlertDialog">
<item name="background">@null</item>
- <item name="paddingStart">16dp</item>
- <item name="paddingEnd">16dp</item>
- <item name="paddingBottom">16dp</item>
<item name="minHeight">@dimen/alert_dialog_button_bar_height</item>
</style>
@@ -759,6 +787,8 @@
<style name="Widget.Material.Toolbar" parent="Widget.Toolbar">
<item name="navigationButtonStyle">@style/Widget.Material.Toolbar.Button.Navigation</item>
+ <item name="titleTextAppearance">@style/TextAppearance.Material.Widget.Toolbar.Title</item>
+ <item name="subtitleTextAppearance">@style/TextAppearance.Material.Widget.Toolbar.Subtitle</item>
</style>
<style name="Widget.Material.Toolbar.Button.Navigation" parent="Widget.Toolbar.Button.Navigation">
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
index 116a31e..93b16e7 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
@@ -26,8 +26,8 @@
import android.net.IpConfiguration.IpAssignment;
import android.net.IpConfiguration.ProxySettings;
import android.net.LinkAddress;
-import android.net.LinkProperties;
import android.net.RouteInfo;
+import android.net.StaticIpConfiguration;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.AuthAlgorithm;
import android.net.wifi.WifiConfiguration.KeyMgmt;
@@ -116,7 +116,7 @@
boolean usercert = false;
WifiConfiguration config = null;
int securityType = NONE;
- LinkProperties mLinkProperties = null;
+ StaticIpConfiguration mStaticIpConfiguration = null;
InetAddress mInetAddr = null;
@Override
@@ -153,7 +153,7 @@
usercert = true;
}
if (tagName.equalsIgnoreCase("ip")) {
- mLinkProperties = new LinkProperties();
+ mStaticIpConfiguration = new StaticIpConfiguration();
ip = true;
}
if (tagName.equalsIgnoreCase("gateway")) {
@@ -173,15 +173,15 @@
@Override
public void endElement(String uri, String localName, String tagName) throws SAXException {
if (tagName.equalsIgnoreCase("accesspoint")) {
- if (mLinkProperties != null) {
+ if (mStaticIpConfiguration != null) {
config.setIpAssignment(IpAssignment.STATIC);
- config.setLinkProperties(mLinkProperties);
+ config.setStaticIpConfiguration(mStaticIpConfiguration);
} else {
config.setIpAssignment(IpAssignment.DHCP);
}
config.setProxySettings(ProxySettings.NONE);
networks.add(config);
- mLinkProperties = null;
+ mStaticIpConfiguration = null;
}
}
@@ -312,7 +312,7 @@
if (!InetAddress.isNumeric(gwAddr)) {
throw new SAXException();
}
- mLinkProperties.addRoute(new RouteInfo(InetAddress.getByName(gwAddr)));
+ mStaticIpConfiguration.gateway = InetAddress.getByName(gwAddr);
} catch (UnknownHostException e) {
throw new SAXException();
}
@@ -324,7 +324,7 @@
if ((nwPrefixLength < 0) || (nwPrefixLength > 32)) {
throw new SAXException();
}
- mLinkProperties.addLinkAddress(new LinkAddress(mInetAddr, nwPrefixLength));
+ mStaticIpConfiguration.ipAddress = new LinkAddress(mInetAddr, nwPrefixLength);
} catch (NumberFormatException e) {
throw new SAXException();
}
@@ -336,7 +336,7 @@
if (!InetAddress.isNumeric(dnsAddr)) {
throw new SAXException();
}
- mLinkProperties.addDnsServer(InetAddress.getByName(dnsAddr));
+ mStaticIpConfiguration.dnsServers.add(InetAddress.getByName(dnsAddr));
} catch (UnknownHostException e) {
throw new SAXException();
}
@@ -348,7 +348,7 @@
if (!InetAddress.isNumeric(dnsAddr)) {
throw new SAXException();
}
- mLinkProperties.addDnsServer(InetAddress.getByName(dnsAddr));
+ mStaticIpConfiguration.dnsServers.add(InetAddress.getByName(dnsAddr));
} catch (UnknownHostException e) {
throw new SAXException();
}
diff --git a/docs/html/google/play/billing/billing_reference.jd b/docs/html/google/play/billing/billing_reference.jd
index e168d70..4f5e65c 100644
--- a/docs/html/google/play/billing/billing_reference.jd
+++ b/docs/html/google/play/billing/billing_reference.jd
@@ -102,15 +102,28 @@
</tr>
<tr>
<td>{@code type}</td>
- <td>Value must be “inapp” for an in-app product or "subs" for
+ <td>Value must be “inapp” for an in-app product or "subs" for
subscriptions.</td>
</tr>
<tr>
<td>{@code price}</td>
- <td>Formatted price of the item, including its currency sign. The price
+ <td>Formatted price of the item, including its currency sign. The price
does not include tax.</td>
</tr>
<tr>
+ <td>{@code price_amount_micros}</td>
+ <td>Price in micro-units, where 1,000,000 micro-units equal one unit of the
+ currency. For example, if {@code price} is {@code "€7.99"}, {@code
+ price_amount_micros} is {@code "7990000"}.</td>
+ </tr>
+ <tr>
+ <td>{@code price_currency_code}</td>
+ <td><a href="http://en.wikipedia.org/wiki/ISO_4217#Active_codes">ISO 4217
+ currency code</a> for {@code price}. For example, if {@code price} is
+ specified in British pounds sterling, {@code price_currency_code} is {@code
+ "GBP"}.</td>
+ </tr>
+ <tr>
<td>{@code title}</td>
<td>Title of the product.</td>
</tr>
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index 3177023..4bf0b71 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -18,15 +18,15 @@
import android.annotation.NonNull;
import android.graphics.drawable.Drawable;
-import android.view.View;
/**
* Defines a simple shape, used for bounding graphical regions.
* <p>
- * Can be used with a View, or computed by a Drawable, to drive the shape of shadows cast by a
- * View, or to clip the contents of the View.
+ * Can be computed for a View, or computed by a Drawable, to drive the shape of
+ * shadows cast by a View, or to clip the contents of the View.
*
- * @see View#setOutline(Outline)
+ * @see android.view.ViewOutlineProvider
+ * @see android.view.View#setOutlineProvider(android.view.ViewOutlineProvider)
* @see Drawable#getOutline(Outline)
*/
public final class Outline {
@@ -79,21 +79,27 @@
/**
* Returns whether the outline can be used to clip a View.
+ * <p>
+ * Currently, only Outlines that can be represented as a rectangle, circle,
+ * or round rect support clipping.
*
- * Currently, only outlines that can be represented as a rectangle, circle, or round rect
- * support clipping.
- *
- * @see {@link View#setClipToOutline(boolean)}
+ * @see {@link android.view.View#setClipToOutline(boolean)}
*/
public boolean canClip() {
return !isEmpty() && mRect != null;
}
/**
- * Sets the alpha represented by the Outline.
- *
- * Content producing a fully opaque (alpha = 1.0f) outline is assumed by the drawing system
- * to fully cover content beneath it, meaning content beneath may be optimized away.
+ * Sets the alpha represented by the Outline - the degree to which the
+ * producer is guaranteed to be opaque over the Outline's shape.
+ * <p>
+ * An alpha value of <code>0.0f</code> either represents completely
+ * transparent content, or content that isn't guaranteed to fill the shape
+ * it publishes.
+ * <p>
+ * Content producing a fully opaque (alpha = <code>1.0f</code>) outline is
+ * assumed by the drawing system to fully cover content beneath it,
+ * meaning content beneath may be optimized away.
*/
public void setAlpha(float alpha) {
mAlpha = alpha;
@@ -130,7 +136,8 @@
}
/**
- * Sets the Outline to the rounded rect defined by the input rect, and corner radius.
+ * Sets the Outline to the rounded rect defined by the input rect, and
+ * corner radius.
*/
public void setRect(int left, int top, int right, int bottom) {
setRoundRect(left, top, right, bottom, 0.0f);
@@ -145,7 +152,7 @@
/**
* Sets the Outline to the rounded rect defined by the input rect, and corner radius.
- *
+ * <p>
* Passing a zero radius is equivalent to calling {@link #setRect(int, int, int, int)}
*/
public void setRoundRect(int left, int top, int right, int bottom, float radius) {
@@ -196,7 +203,8 @@
}
/**
- * Sets the Constructs an Outline from a {@link android.graphics.Path#isConvex() convex path}.
+ * Sets the Constructs an Outline from a
+ * {@link android.graphics.Path#isConvex() convex path}.
*/
public void setConvexPath(@NonNull Path convexPath) {
if (convexPath.isEmpty()) {
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 1c76d9c..652fe64 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1109,9 +1109,16 @@
* This draws a shadow layer below the main layer, with the specified
* offset and color, and blur radius. If radius is 0, then the shadow
* layer is removed.
+ * <p>
+ * Can be used to create a blurred shadow underneath text. Support for use
+ * with other drawing operations is constrained to the software rendering
+ * pipeline.
+ * <p>
+ * The alpha of the shadow will be the paint's alpha if the shadow color is
+ * opaque, or the alpha from the shadow color if not.
*/
- public void setShadowLayer(float radius, float dx, float dy, int color) {
- native_setShadowLayer(mNativePaint, radius, dx, dy, color);
+ public void setShadowLayer(float radius, float dx, float dy, int shadowColor) {
+ native_setShadowLayer(mNativePaint, radius, dx, dy, shadowColor);
}
/**
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index a383aab..29b9141 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -820,7 +820,7 @@
@Override
public int getOpacity() {
- return (mAlpha == 255 && mGradientState.mOpaque) ?
+ return (mAlpha == 255 && mGradientState.mOpaqueOverBounds) ?
PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT;
}
@@ -1413,7 +1413,8 @@
public void getOutline(Outline outline) {
final GradientState st = mGradientState;
final Rect bounds = getBounds();
- outline.setAlpha(mAlpha / 255.0f);
+ // only report non-zero alpha if shape being drawn is opaque
+ outline.setAlpha(st.mOpaqueOverShape ? (mAlpha / 255.0f) : 0.0f);
switch (st.mShape) {
case RECTANGLE:
@@ -1492,7 +1493,8 @@
private int mGradientRadiusType = RADIUS_TYPE_PIXELS;
private boolean mUseLevel;
private boolean mUseLevelForShape;
- private boolean mOpaque;
+ private boolean mOpaqueOverBounds;
+ private boolean mOpaqueOverShape;
int[] mThemeAttrs;
int[] mAttrSize;
@@ -1544,7 +1546,7 @@
mGradientRadiusType = state.mGradientRadiusType;
mUseLevel = state.mUseLevel;
mUseLevelForShape = state.mUseLevelForShape;
- mOpaque = state.mOpaque;
+ mOpaqueOverBounds = state.mOpaqueOverBounds;
mThemeAttrs = state.mThemeAttrs;
mAttrSize = state.mAttrSize;
mAttrGradient = state.mAttrGradient;
@@ -1606,40 +1608,36 @@
}
private void computeOpacity() {
- if (mShape != RECTANGLE) {
- mOpaque = false;
- return;
- }
+ mOpaqueOverBounds = false;
+ mOpaqueOverShape = false;
- if (mRadius > 0 || mRadiusArray != null) {
- mOpaque = false;
- return;
- }
-
+ // First test opacity of all colors
if (mStrokeWidth > 0) {
if (mStrokeColorStateList != null) {
if (!mStrokeColorStateList.isOpaque()) {
- mOpaque = false;
return;
}
}
}
if (mColorStateList != null && !mColorStateList.isOpaque()) {
- mOpaque = false;
return;
}
if (mColors != null) {
for (int i = 0; i < mColors.length; i++) {
if (!isOpaque(mColors[i])) {
- mOpaque = false;
return;
}
}
}
- mOpaque = true;
+ // Colors are opaque, so opaqueOverShape=true,
+ mOpaqueOverShape = true;
+ // and opaqueOverBounds=true if shape fills bounds
+ mOpaqueOverBounds = mShape == RECTANGLE
+ && mRadius <= 0
+ && mRadiusArray == null;
}
private static boolean isOpaque(int color) {
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index c6d3db7..5f533a7 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -208,6 +208,8 @@
// ensure that local bounds cover mapped bounds
if (!state.mMatrix.isSimple()) return false;
+ if (state.mRoundRectClipState) return false;
+
// check state/paint for transparency
if (mPaint) {
if (mPaint->getShader() && !mPaint->getShader()->isOpaque()) {
@@ -999,6 +1001,8 @@
public:
DrawStrokableOp(float left, float top, float right, float bottom, const SkPaint* paint)
: DrawBoundedOp(left, top, right, bottom, paint) {};
+ DrawStrokableOp(const Rect& localBounds, const SkPaint* paint)
+ : DrawBoundedOp(localBounds, paint) {};
virtual bool getLocalBounds(Rect& localBounds) {
localBounds.set(mLocalBounds);
@@ -1337,11 +1341,11 @@
const float* mPositions;
};
-class DrawTextOp : public DrawBoundedOp {
+class DrawTextOp : public DrawStrokableOp {
public:
DrawTextOp(const char* text, int bytesCount, int count, float x, float y,
const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds)
- : DrawBoundedOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
+ : DrawStrokableOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) {
mPrecacheTransform = SkMatrix::InvalidMatrix();
}
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 94162fc..9a9c544 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -376,7 +376,7 @@
float x, float y, const float* positions, const SkPaint* paint,
float totalAdvance, const Rect& bounds, DrawOpMode drawOpMode) {
- if (!text || count <= 0) return DrawGlInfo::kStatusDone;
+ if (!text || count <= 0 || paintWillNotDrawText(*paint)) return DrawGlInfo::kStatusDone;
text = refText(text, bytesCount);
positions = refBuffer<float>(positions, count * 2);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 721ab3d..bbf0551 100755
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2518,8 +2518,9 @@
status_t OpenGLRenderer::drawRoundRect(float left, float top, float right, float bottom,
float rx, float ry, const SkPaint* p) {
- if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
- (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
+ if (currentSnapshot()->isIgnored()
+ || quickRejectSetupScissor(left, top, right, bottom, p)
+ || paintWillNotDraw(*p)) {
return DrawGlInfo::kStatusDone;
}
@@ -2536,9 +2537,9 @@
}
status_t OpenGLRenderer::drawCircle(float x, float y, float radius, const SkPaint* p) {
- if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(x - radius, y - radius,
- x + radius, y + radius, p) ||
- (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
+ if (currentSnapshot()->isIgnored()
+ || quickRejectSetupScissor(x - radius, y - radius, x + radius, y + radius, p)
+ || paintWillNotDraw(*p)) {
return DrawGlInfo::kStatusDone;
}
if (p->getPathEffect() != 0) {
@@ -2558,8 +2559,9 @@
status_t OpenGLRenderer::drawOval(float left, float top, float right, float bottom,
const SkPaint* p) {
- if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
- (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
+ if (currentSnapshot()->isIgnored()
+ || quickRejectSetupScissor(left, top, right, bottom, p)
+ || paintWillNotDraw(*p)) {
return DrawGlInfo::kStatusDone;
}
@@ -2580,8 +2582,9 @@
status_t OpenGLRenderer::drawArc(float left, float top, float right, float bottom,
float startAngle, float sweepAngle, bool useCenter, const SkPaint* p) {
- if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
- (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
+ if (currentSnapshot()->isIgnored()
+ || quickRejectSetupScissor(left, top, right, bottom, p)
+ || paintWillNotDraw(*p)) {
return DrawGlInfo::kStatusDone;
}
@@ -2614,8 +2617,9 @@
status_t OpenGLRenderer::drawRect(float left, float top, float right, float bottom,
const SkPaint* p) {
- if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
- (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
+ if (currentSnapshot()->isIgnored()
+ || quickRejectSetupScissor(left, top, right, bottom, p)
+ || paintWillNotDraw(*p)) {
return DrawGlInfo::kStatusDone;
}
diff --git a/libs/hwui/Renderer.h b/libs/hwui/Renderer.h
index f5cd266..6d4bb4a 100644
--- a/libs/hwui/Renderer.h
+++ b/libs/hwui/Renderer.h
@@ -67,6 +67,18 @@
return resultMode;
}
+ // TODO: move to a method on android:Paint
+ static inline bool paintWillNotDraw(const SkPaint& paint) {
+ return paint.getAlpha() == 0
+ && getXfermode(paint.getXfermode()) != SkXfermode::kClear_Mode;
+ }
+
+ // TODO: move to a method on android:Paint
+ static inline bool paintWillNotDrawText(const SkPaint& paint) {
+ return paint.getAlpha() == 0
+ && paint.getLooper() == NULL
+ && getXfermode(paint.getXfermode()) == SkXfermode::kSrcOver_Mode;
+ }
// ----------------------------------------------------------------------------
// Frame state operations
// ----------------------------------------------------------------------------
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 6a76a71..e69c456 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2332,18 +2332,21 @@
}
/**
- * Registers a {@link RemoteController} instance for it to receive media metadata updates
- * and playback state information from applications using {@link RemoteControlClient}, and
- * control their playback.
- * <p>Registration requires the {@link OnClientUpdateListener} listener to be one of the
- * enabled notification listeners (see
+ * Registers a {@link RemoteController} instance for it to receive media
+ * metadata updates and playback state information from applications using
+ * {@link RemoteControlClient}, and control their playback.
+ * <p>
+ * Registration requires the {@link OnClientUpdateListener} listener to be
+ * one of the enabled notification listeners (see
* {@link android.service.notification.NotificationListenerService}).
+ *
* @param rctlr the object to register.
- * @return true if the {@link RemoteController} was successfully registered, false if an
- * error occurred, due to an internal system error, or insufficient permissions.
+ * @return true if the {@link RemoteController} was successfully registered,
+ * false if an error occurred, due to an internal system error, or
+ * insufficient permissions.
* @deprecated Use
- * {@link MediaSessionManager#addActiveSessionsListener(android.media.session.MediaSessionManager.SessionListener, ComponentName)}
- * and {@link MediaController} instead.
+ * {@link MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, ComponentName)}
+ * and {@link MediaController} instead.
*/
@Deprecated
public boolean registerRemoteController(RemoteController rctlr) {
@@ -2355,12 +2358,14 @@
}
/**
- * Unregisters a {@link RemoteController}, causing it to no longer receive media metadata and
- * playback state information, and no longer be capable of controlling playback.
+ * Unregisters a {@link RemoteController}, causing it to no longer receive
+ * media metadata and playback state information, and no longer be capable
+ * of controlling playback.
+ *
* @param rctlr the object to unregister.
* @deprecated Use
- * {@link MediaSessionManager#removeActiveSessionsListener(android.media.session.MediaSessionManager.SessionListener)}
- * instead.
+ * {@link MediaSessionManager#removeOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener)}
+ * instead.
*/
@Deprecated
public void unregisterRemoteController(RemoteController rctlr) {
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 2fa0c93..7c3b4fc 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1049,8 +1049,17 @@
private void setDataSource(String path, String[] keys, String[] values)
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
final Uri uri = Uri.parse(path);
- if ("file".equals(uri.getScheme())) {
+ final String scheme = uri.getScheme();
+ if ("file".equals(scheme)) {
path = uri.getPath();
+ } else if (scheme != null) {
+ // handle non-file sources
+ nativeSetDataSource(
+ MediaHTTPService.createHttpServiceBinderIfNecessary(path),
+ path,
+ keys,
+ values);
+ return;
}
final File file = new File(path);
@@ -1060,20 +1069,10 @@
setDataSource(fd);
is.close();
} else {
- _setDataSource(path, keys, values);
+ throw new IOException("setDataSource failed.");
}
}
- private void _setDataSource(
- String path, String[] keys, String[] values)
- throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
- nativeSetDataSource(
- MediaHTTPService.createHttpServiceBinderIfNecessary(path),
- path,
- keys,
- values);
- }
-
private native void nativeSetDataSource(
IBinder httpServiceBinder, String path, String[] keys, String[] values)
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
diff --git a/media/java/android/media/RemoteController.java b/media/java/android/media/RemoteController.java
index adc8391..f378cef 100644
--- a/media/java/android/media/RemoteController.java
+++ b/media/java/android/media/RemoteController.java
@@ -74,7 +74,7 @@
private MetadataEditor mMetadataEditor;
private MediaSessionManager mSessionManager;
- private MediaSessionManager.SessionListener mSessionListener;
+ private MediaSessionManager.OnActiveSessionsChangedListener mSessionListener;
private MediaController.Callback mSessionCb = new MediaControllerCallback();
/**
@@ -140,7 +140,7 @@
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
mSessionManager = (MediaSessionManager) context
.getSystemService(Context.MEDIA_SESSION_SERVICE);
- mSessionListener = new TopTransportSessionListener(context);
+ mSessionListener = new TopTransportSessionListener();
if (ActivityManager.isLowRamDeviceStatic()) {
mMaxBitmapDimension = MAX_BITMAP_DIMENSION;
@@ -710,11 +710,8 @@
* Listens for changes to the active session stack and replaces the
* currently tracked session if it has changed.
*/
- private class TopTransportSessionListener extends MediaSessionManager.SessionListener {
-
- public TopTransportSessionListener(Context context) {
- super(context);
- }
+ private class TopTransportSessionListener implements
+ MediaSessionManager.OnActiveSessionsChangedListener {
@Override
public void onActiveSessionsChanged(List<MediaController> controllers) {
@@ -792,7 +789,7 @@
void startListeningToSessions() {
final ComponentName listenerComponent = new ComponentName(mContext,
mOnClientUpdateListener.getClass());
- mSessionManager.addActiveSessionsListener(mSessionListener, listenerComponent,
+ mSessionManager.addOnActiveSessionsChangedListener(mSessionListener, listenerComponent,
UserHandle.myUserId(), null);
mSessionListener.onActiveSessionsChanged(mSessionManager
.getActiveSessions(listenerComponent));
@@ -806,7 +803,7 @@
* @hide
*/
void stopListeningToSessions() {
- mSessionManager.removeActiveSessionsListener(mSessionListener);
+ mSessionManager.removeOnActiveSessionsChangedListener(mSessionListener);
if (DEBUG) {
Log.d(TAG, "Unregistered session listener for user "
+ UserHandle.myUserId());
diff --git a/media/java/android/media/projection/IMediaProjectionManager.aidl b/media/java/android/media/projection/IMediaProjectionManager.aidl
index 6ed803a..7e10c51 100644
--- a/media/java/android/media/projection/IMediaProjectionManager.aidl
+++ b/media/java/android/media/projection/IMediaProjectionManager.aidl
@@ -17,6 +17,9 @@
package android.media.projection;
import android.media.projection.IMediaProjection;
+import android.media.projection.IMediaProjectionCallback;
+import android.media.projection.IMediaProjectionWatcherCallback;
+import android.media.projection.MediaProjectionInfo;
import android.os.IBinder;
/** {@hide} */
@@ -25,4 +28,8 @@
IMediaProjection createProjection(int uid, String packageName, int type,
boolean permanentGrant);
boolean isValidMediaProjection(IMediaProjection projection);
+ MediaProjectionInfo getActiveProjectionInfo();
+ void stopActiveProjection();
+ void addCallback(IMediaProjectionWatcherCallback callback);
+ void removeCallback(IMediaProjectionWatcherCallback callback);
}
diff --git a/media/java/android/media/projection/IMediaProjectionWatcherCallback.aidl b/media/java/android/media/projection/IMediaProjectionWatcherCallback.aidl
new file mode 100644
index 0000000..2231ce1
--- /dev/null
+++ b/media/java/android/media/projection/IMediaProjectionWatcherCallback.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.projection;
+
+import android.media.projection.MediaProjectionInfo;
+
+/** {@hide} */
+oneway interface IMediaProjectionWatcherCallback {
+ void onStart(in MediaProjectionInfo info);
+ void onStop(in MediaProjectionInfo info);
+}
diff --git a/media/java/android/media/projection/MediaProjectionInfo.aidl b/media/java/android/media/projection/MediaProjectionInfo.aidl
new file mode 100644
index 0000000..3c8f9b6
--- /dev/null
+++ b/media/java/android/media/projection/MediaProjectionInfo.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.projection;
+
+parcelable MediaProjectionInfo;
diff --git a/media/java/android/media/projection/MediaProjectionInfo.java b/media/java/android/media/projection/MediaProjectionInfo.java
new file mode 100644
index 0000000..7ebc31f
--- /dev/null
+++ b/media/java/android/media/projection/MediaProjectionInfo.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.projection;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.UserHandle;
+
+/** @hide */
+public final class MediaProjectionInfo implements Parcelable {
+ private final String mPackageName;
+ private final UserHandle mUserHandle;
+
+ public MediaProjectionInfo(String packageName, UserHandle handle) {
+ mPackageName = packageName;
+ mUserHandle = handle;
+ }
+
+ public MediaProjectionInfo(Parcel in) {
+ mPackageName = in.readString();
+ mUserHandle = UserHandle.readFromParcel(in);
+ }
+
+ public String getPackageName() {
+ return mPackageName;
+ }
+
+ public UserHandle getUserHandle() {
+ return mUserHandle;
+ }
+
+ @Override
+ public String toString() {
+ return "MediaProjectionInfo{mPackageName="
+ + mPackageName + ", mUserHandle="
+ + mUserHandle + "}";
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(mPackageName);
+ UserHandle.writeToParcel(mUserHandle, out);
+ }
+
+ public static final Parcelable.Creator<MediaProjectionInfo> CREATOR =
+ new Parcelable.Creator<MediaProjectionInfo>() {
+ @Override
+ public MediaProjectionInfo createFromParcel(Parcel in) {
+ return new MediaProjectionInfo (in);
+ }
+
+ @Override
+ public MediaProjectionInfo[] newArray(int size) {
+ return new MediaProjectionInfo[size];
+ }
+ };
+}
diff --git a/media/java/android/media/projection/MediaProjectionManager.java b/media/java/android/media/projection/MediaProjectionManager.java
index aac8cf9..50d66c6 100644
--- a/media/java/android/media/projection/MediaProjectionManager.java
+++ b/media/java/android/media/projection/MediaProjectionManager.java
@@ -17,12 +17,20 @@
package android.media.projection;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.media.projection.IMediaProjection;
import android.os.Binder;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import java.util.Map;
/**
* Manages the retrieval of certain types of {@link MediaProjection} tokens.
@@ -35,6 +43,7 @@
* </p>
*/
public final class MediaProjectionManager {
+ private static final String TAG = "MediaProjectionManager";
/** @hide */
public static final String EXTRA_APP_TOKEN = "android.media.projection.extra.EXTRA_APP_TOKEN";
/** @hide */
@@ -49,10 +58,15 @@
public static final int TYPE_PRESENTATION = 2;
private Context mContext;
+ private Map<Callback, CallbackDelegate> mCallbacks;
+ private IMediaProjectionManager mService;
/** @hide */
public MediaProjectionManager(Context context) {
mContext = context;
+ IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE);
+ mService = IMediaProjectionManager.Stub.asInterface(b);
+ mCallbacks = new ArrayMap<>();
}
/**
@@ -88,4 +102,105 @@
}
return new MediaProjection(mContext, IMediaProjection.Stub.asInterface(projection));
}
+
+ /**
+ * Get the {@link MediaProjectionInfo} for the active {@link MediaProjection}.
+ * @hide
+ */
+ public MediaProjectionInfo getActiveProjectionInfo() {
+ try {
+ return mService.getActiveProjectionInfo();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to get the active projection info", e);
+ }
+ return null;
+ }
+
+ /**
+ * Stop the current projection if there is one.
+ * @hide
+ */
+ public void stopActiveProjection() {
+ try {
+ mService.stopActiveProjection();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to stop the currently active media projection", e);
+ }
+ }
+
+ /**
+ * Add a callback to monitor all of the {@link MediaProjection}s activity.
+ * Not for use by regular applications, must have the MANAGE_MEDIA_PROJECTION permission.
+ * @hide
+ */
+ public void addCallback(@NonNull Callback callback, @Nullable Handler handler) {
+ if (callback == null) {
+ throw new IllegalArgumentException("callback must not be null");
+ }
+ CallbackDelegate delegate = new CallbackDelegate(callback, handler);
+ mCallbacks.put(callback, delegate);
+ try {
+ mService.addCallback(delegate);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to add callbacks to MediaProjection service", e);
+ }
+ }
+
+ /**
+ * Remove a MediaProjection monitoring callback.
+ * @hide
+ */
+ public void removeCallback(@NonNull Callback callback) {
+ if (callback == null) {
+ throw new IllegalArgumentException("callback must not be null");
+ }
+ CallbackDelegate delegate = mCallbacks.remove(callback);
+ try {
+ if (delegate != null) {
+ mService.removeCallback(delegate);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to add callbacks to MediaProjection service", e);
+ }
+ }
+
+ /** @hide */
+ public static abstract class Callback {
+ public abstract void onStart(MediaProjectionInfo info);
+ public abstract void onStop(MediaProjectionInfo info);
+ }
+
+ /** @hide */
+ private final static class CallbackDelegate extends IMediaProjectionWatcherCallback.Stub {
+ private Callback mCallback;
+ private Handler mHandler;
+
+ public CallbackDelegate(Callback callback, Handler handler) {
+ mCallback = callback;
+ if (handler == null) {
+ handler = new Handler();
+ }
+ mHandler = handler;
+ }
+
+ @Override
+ public void onStart(final MediaProjectionInfo info) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onStart(info);
+ }
+ });
+ }
+
+ @Override
+ public void onStop(final MediaProjectionInfo info) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onStop(info);
+ }
+ });
+ }
+ }
}
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 63c85f8..074e5ad 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -185,7 +185,7 @@
*
* @return The current play queue or null.
*/
- public @Nullable List<MediaSession.Track> getQueue() {
+ public @Nullable List<MediaSession.Item> getQueue() {
try {
ParceledListSlice queue = mSessionBinder.getQueue();
if (queue != null) {
@@ -259,18 +259,18 @@
}
/**
- * Get the current volume info for this session.
+ * Get the current audio info for this session.
*
- * @return The current volume info or null.
+ * @return The current audio info or null.
*/
- public @Nullable VolumeInfo getVolumeInfo() {
+ public @Nullable AudioInfo getAudioInfo() {
try {
ParcelableVolumeInfo result = mSessionBinder.getVolumeAttributes();
- return new VolumeInfo(result.volumeType, result.audioAttrs, result.controlType,
+ return new AudioInfo(result.volumeType, result.audioAttrs, result.controlType,
result.maxVolume, result.currentVolume);
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling getVolumeInfo.", e);
+ Log.wtf(TAG, "Error calling getAudioInfo.", e);
}
return null;
}
@@ -305,7 +305,7 @@
* {@link VolumeProvider#VOLUME_CONTROL_ABSOLUTE}. The flags in
* {@link AudioManager} may be used to affect the handling.
*
- * @see #getVolumeInfo()
+ * @see #getAudioInfo()
* @param value The value to set it to, between 0 and the reported max.
* @param flags Any flags to pass with the command.
*/
@@ -326,7 +326,7 @@
* {@link VolumeProvider#VOLUME_CONTROL_ABSOLUTE}. The flags in
* {@link AudioManager} may be used to affect the handling.
*
- * @see #getVolumeInfo()
+ * @see #getAudioInfo()
* @param direction The direction to adjust the volume in.
* @param flags Any flags to pass with the command.
*/
@@ -544,13 +544,14 @@
}
/**
- * Override to handle changes to tracks in the queue.
+ * Override to handle changes to items in the queue.
*
- * @param queue A list of tracks in the current play queue. It should include the currently
- * playing track as well as previous and upcoming tracks if applicable.
- * @see MediaSession.Track
+ * @param queue A list of items in the current play queue. It should
+ * include the currently playing item as well as previous and
+ * upcoming items if applicable.
+ * @see MediaSession.Item
*/
- public void onQueueChanged(@Nullable List<MediaSession.Track> queue) {
+ public void onQueueChanged(@Nullable List<MediaSession.Item> queue) {
}
/**
@@ -572,11 +573,11 @@
}
/**
- * Override to handle changes to the volume info.
+ * Override to handle changes to the audio info.
*
- * @param info The current volume info for this session.
+ * @param info The current audio info for this session.
*/
- public void onVolumeInfoChanged(VolumeInfo info) {
+ public void onAudioInfoChanged(AudioInfo info) {
}
}
@@ -638,14 +639,14 @@
}
/**
- * Play a track with a specific id in the play queue.
- * If you specify an id that is not in the play queue, the behavior is undefined.
+ * Play an item with a specific id in the play queue. If you specify an
+ * id that is not in the play queue, the behavior is undefined.
*/
- public void skipToTrack(long id) {
+ public void skipToItem(long id) {
try {
mSessionBinder.skipToTrack(id);
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling skipToTrack(" + id + ").", e);
+ Log.wtf(TAG, "Error calling skipToItem(" + id + ").", e);
}
}
@@ -784,9 +785,9 @@
}
/**
- * Holds information about the way volume is handled for this session.
+ * Holds information about the way audio is handled for this session.
*/
- public static final class VolumeInfo {
+ public static final class AudioInfo {
private final int mVolumeType;
private final int mVolumeControl;
private final int mMaxVolume;
@@ -796,7 +797,7 @@
/**
* @hide
*/
- public VolumeInfo(int type, AudioAttributes attrs, int control, int max, int current) {
+ public AudioInfo(int type, AudioAttributes attrs, int control, int max, int current) {
mVolumeType = type;
mAudioAttrs = attrs;
mVolumeControl = control;
@@ -904,7 +905,7 @@
@Override
public void onQueueChanged(ParceledListSlice parceledQueue) {
- List<MediaSession.Track> queue = parceledQueue.getList();
+ List<MediaSession.Item> queue = parceledQueue.getList();
MediaController controller = mController.get();
if (controller != null) {
controller.postMessage(MSG_UPDATE_QUEUE, queue, null);
@@ -931,7 +932,7 @@
public void onVolumeInfoChanged(ParcelableVolumeInfo pvi) {
MediaController controller = mController.get();
if (controller != null) {
- VolumeInfo info = new VolumeInfo(pvi.volumeType, pvi.audioAttrs, pvi.controlType,
+ AudioInfo info = new AudioInfo(pvi.volumeType, pvi.audioAttrs, pvi.controlType,
pvi.maxVolume, pvi.currentVolume);
controller.postMessage(MSG_UPDATE_VOLUME, info, null);
}
@@ -960,7 +961,7 @@
mCallback.onMetadataChanged((MediaMetadata) msg.obj);
break;
case MSG_UPDATE_QUEUE:
- mCallback.onQueueChanged((List<MediaSession.Track>) msg.obj);
+ mCallback.onQueueChanged((List<MediaSession.Item>) msg.obj);
break;
case MSG_UPDATE_QUEUE_TITLE:
mCallback.onQueueTitleChanged((CharSequence) msg.obj);
@@ -969,7 +970,7 @@
mCallback.onExtrasChanged((Bundle) msg.obj);
break;
case MSG_UPDATE_VOLUME:
- mCallback.onVolumeInfoChanged((VolumeInfo) msg.obj);
+ mCallback.onAudioInfoChanged((AudioInfo) msg.obj);
break;
case MSG_DESTROYED:
mCallback.onSessionDestroyed();
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index cf73c2a..2cd161c 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -435,18 +435,19 @@
}
/**
- * Update the list of tracks in the play queue. It is an ordered list and should contain the
- * current track, and previous or upcoming tracks if they exist.
- * Specify null if there is no current play queue.
+ * Update the list of items in the play queue. It is an ordered list and
+ * should contain the current item, and previous or upcoming items if they
+ * exist. Specify null if there is no current play queue.
* <p>
- * The queue should be of reasonable size. If the play queue is unbounded within your
- * app, it is better to send a reasonable amount in a sliding window instead.
+ * The queue should be of reasonable size. If the play queue is unbounded
+ * within your app, it is better to send a reasonable amount in a sliding
+ * window instead.
*
- * @param queue A list of tracks in the play queue.
+ * @param queue A list of items in the play queue.
*/
- public void setQueue(@Nullable List<Track> queue) {
+ public void setQueue(@Nullable List<Item> queue) {
try {
- mBinder.setQueue(new ParceledListSlice<Track>(queue));
+ mBinder.setQueue(new ParceledListSlice<Item>(queue));
} catch (RemoteException e) {
Log.wtf("Dead object in setQueue.", e);
}
@@ -512,8 +513,8 @@
postToCallback(CallbackMessageHandler.MSG_PLAY_SEARCH, query, extras);
}
- private void dispatchSkipToTrack(long id) {
- postToCallback(CallbackMessageHandler.MSG_SKIP_TO_TRACK, id);
+ private void dispatchSkipToItem(long id) {
+ postToCallback(CallbackMessageHandler.MSG_SKIP_TO_ITEM, id);
}
private void dispatchPause() {
@@ -782,9 +783,10 @@
}
/**
- * Override to handle requests to play a track with a given id from the play queue.
+ * Override to handle requests to play an item with a given id from the
+ * play queue.
*/
- public void onSkipToTrack(long id) {
+ public void onSkipToItem(long id) {
}
/**
@@ -916,7 +918,7 @@
public void onSkipToTrack(long id) {
MediaSession session = mMediaSession.get();
if (session != null) {
- session.dispatchSkipToTrack(id);
+ session.dispatchSkipToItem(id);
}
}
@@ -1015,12 +1017,12 @@
}
/**
- * A single track that is part of the play queue. It contains information necessary to display
- * a single track in the queue.
+ * A single item that is part of the play queue. It contains information
+ * necessary to display a single item in the queue.
*/
- public static final class Track implements Parcelable {
+ public static final class Item implements Parcelable {
/**
- * This id is reserved. No tracks can be explicitly asigned this id.
+ * This id is reserved. No items can be explicitly asigned this id.
*/
public static final int UNKNOWN_ID = -1;
@@ -1030,22 +1032,23 @@
private final Bundle mExtras;
/**
- * Create a new {@link MediaSession.Track}.
+ * Create a new {@link MediaSession.Item}.
*
- * @param metadata The metadata for this track.
- * @param id An identifier for this track. It must be unique within the play queue.
- * @param uri The uri for this track.
- * @param extras A bundle of extras that can be used to add extra information about the
- * track.
+ * @param metadata The metadata for this item.
+ * @param id An identifier for this item. It must be unique within the
+ * play queue.
+ * @param uri The uri for this item.
+ * @param extras A bundle of extras that can be used to add extra
+ * information about this item.
*/
- private Track(MediaMetadata metadata, long id, Uri uri, Bundle extras) {
+ private Item(MediaMetadata metadata, long id, Uri uri, Bundle extras) {
mMetadata = metadata;
mId = id;
mUri = uri;
mExtras = extras;
}
- private Track(Parcel in) {
+ private Item(Parcel in) {
mMetadata = MediaMetadata.CREATOR.createFromParcel(in);
mId = in.readLong();
mUri = Uri.CREATOR.createFromParcel(in);
@@ -1053,35 +1056,35 @@
}
/**
- * Get the metadata for this track.
+ * Get the metadata for this item.
*/
public MediaMetadata getMetadata() {
return mMetadata;
}
/**
- * Get the id for this track.
+ * Get the id for this item.
*/
public long getId() {
return mId;
}
/**
- * Get the Uri for this track.
+ * Get the Uri for this item.
*/
public Uri getUri() {
return mUri;
}
/**
- * Get the extras for this track.
+ * Get the extras for this item.
*/
public Bundle getExtras() {
return mExtras;
}
/**
- * Builder for {@link MediaSession.Track} objects.
+ * Builder for {@link MediaSession.Item} objects.
*/
public static final class Builder {
private final MediaMetadata mMetadata;
@@ -1096,15 +1099,15 @@
public Builder(MediaMetadata metadata, long id, Uri uri) {
if (metadata == null) {
throw new IllegalArgumentException(
- "You must specify a non-null MediaMetadata to build a Track.");
+ "You must specify a non-null MediaMetadata to build an Item.");
}
if (uri == null) {
throw new IllegalArgumentException(
- "You must specify a non-null Uri to build a Track.");
+ "You must specify a non-null Uri to build an Item.");
}
if (id == UNKNOWN_ID) {
throw new IllegalArgumentException(
- "You must specify an id other than UNKNOWN_ID to build a Track.");
+ "You must specify an id other than UNKNOWN_ID to build an Item.");
}
mMetadata = metadata;
mId = id;
@@ -1112,18 +1115,18 @@
}
/**
- * Set optional extras for the track.
+ * Set optional extras for the item.
*/
- public MediaSession.Track.Builder setExtras(Bundle extras) {
+ public MediaSession.Item.Builder setExtras(Bundle extras) {
mExtras = extras;
return this;
}
/**
- * Create the {@link Track}.
+ * Create the {@link Item}.
*/
- public MediaSession.Track build() {
- return new MediaSession.Track(mMetadata, mId, mUri, mExtras);
+ public MediaSession.Item build() {
+ return new MediaSession.Item(mMetadata, mId, mUri, mExtras);
}
}
@@ -1140,23 +1143,23 @@
return 0;
}
- public static final Creator<MediaSession.Track> CREATOR
- = new Creator<MediaSession.Track>() {
+ public static final Creator<MediaSession.Item> CREATOR
+ = new Creator<MediaSession.Item>() {
@Override
- public MediaSession.Track createFromParcel(Parcel p) {
- return new MediaSession.Track(p);
+ public MediaSession.Item createFromParcel(Parcel p) {
+ return new MediaSession.Item(p);
}
@Override
- public MediaSession.Track[] newArray(int size) {
- return new MediaSession.Track[size];
+ public MediaSession.Item[] newArray(int size) {
+ return new MediaSession.Item[size];
}
};
@Override
public String toString() {
- return "MediaSession.Track {" +
+ return "MediaSession.Item {" +
"Metadata=" + mMetadata +
", Id=" + mId +
", Uri=" + mUri +
@@ -1182,7 +1185,7 @@
private static final int MSG_PLAY = 1;
private static final int MSG_PLAY_URI = 2;
private static final int MSG_PLAY_SEARCH = 3;
- private static final int MSG_SKIP_TO_TRACK = 4;
+ private static final int MSG_SKIP_TO_ITEM = 4;
private static final int MSG_PAUSE = 5;
private static final int MSG_STOP = 6;
private static final int MSG_NEXT = 7;
@@ -1232,8 +1235,8 @@
case MSG_PLAY_SEARCH:
mCallback.onPlayFromSearch((String) msg.obj, msg.getData());
break;
- case MSG_SKIP_TO_TRACK:
- mCallback.onSkipToTrack((Long) msg.obj);
+ case MSG_SKIP_TO_ITEM:
+ mCallback.onSkipToItem((Long) msg.obj);
case MSG_PAUSE:
mCallback.onPause();
break;
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index c2fb5a3..8a1e076 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -30,6 +30,7 @@
import android.os.UserHandle;
import android.service.notification.NotificationListenerService;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.Log;
import android.view.KeyEvent;
@@ -50,6 +51,9 @@
public final class MediaSessionManager {
private static final String TAG = "SessionManager";
+ private final ArrayMap<OnActiveSessionsChangedListener, SessionsChangedWrapper> mListeners
+ = new ArrayMap<OnActiveSessionsChangedListener, SessionsChangedWrapper>();
+ private final Object mLock = new Object();
private final ISessionManager mService;
private Context mContext;
@@ -141,10 +145,11 @@
* @param notificationListener The enabled notification listener component.
* May be null.
*/
- public void addActiveSessionsListener(@NonNull SessionListener sessionListener,
+ public void addOnActiveSessionsChangedListener(
+ @NonNull OnActiveSessionsChangedListener sessionListener,
@Nullable ComponentName notificationListener) {
- addActiveSessionsListener(sessionListener, notificationListener, UserHandle.myUserId(),
- null);
+ addOnActiveSessionsChangedListener(sessionListener, notificationListener,
+ UserHandle.myUserId(), null);
}
/**
@@ -163,7 +168,8 @@
* @param handler The handler to post updates on.
* @hide
*/
- public void addActiveSessionsListener(@NonNull SessionListener sessionListener,
+ public void addOnActiveSessionsChangedListener(
+ @NonNull OnActiveSessionsChangedListener sessionListener,
@Nullable ComponentName notificationListener, int userId, @Nullable Handler handler) {
if (sessionListener == null) {
throw new IllegalArgumentException("listener may not be null");
@@ -171,11 +177,18 @@
if (handler == null) {
handler = new Handler();
}
- sessionListener.setHandler(handler);
- try {
- mService.addSessionsListener(sessionListener.mStub, notificationListener, userId);
- } catch (RemoteException e) {
- Log.e(TAG, "Error in addActiveSessionsListener.", e);
+ synchronized (mLock) {
+ if (mListeners.get(sessionListener) != null) {
+ Log.w(TAG, "Attempted to add session listener twice, ignoring.");
+ return;
+ }
+ SessionsChangedWrapper wrapper = new SessionsChangedWrapper(sessionListener, handler);
+ try {
+ mService.addSessionsListener(wrapper.mStub, notificationListener, userId);
+ mListeners.put(sessionListener, wrapper);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error in addOnActiveSessionsChangedListener.", e);
+ }
}
}
@@ -184,14 +197,20 @@
*
* @param listener The listener to remove.
*/
- public void removeActiveSessionsListener(@NonNull SessionListener listener) {
+ public void removeOnActiveSessionsChangedListener(
+ @NonNull OnActiveSessionsChangedListener listener) {
if (listener == null) {
throw new IllegalArgumentException("listener may not be null");
}
- try {
- mService.removeSessionsListener(listener.mStub);
- } catch (RemoteException e) {
- Log.e(TAG, "Error in removeActiveSessionsListener.", e);
+ synchronized (mLock) {
+ SessionsChangedWrapper wrapper = mListeners.remove(listener);
+ if (wrapper != null) {
+ try {
+ mService.removeSessionsListener(wrapper.mStub);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error in removeOnActiveSessionsChangedListener.", e);
+ }
+ }
}
}
@@ -257,28 +276,18 @@
/**
* Listens for changes to the list of active sessions. This can be added
- * using {@link #addActiveSessionsListener}.
+ * using {@link #addOnActiveSessionsChangedListener}.
*/
- public static abstract class SessionListener {
- private final Context mContext;
- private Handler mHandler;
+ public interface OnActiveSessionsChangedListener {
+ public void onActiveSessionsChanged(@Nullable List<MediaController> controllers);
+ }
- public SessionListener(Context context) {
- mContext = context;
- }
- /**
- * Called when the list of active sessions has changed. This can be due
- * to a session being added or removed or the order of sessions
- * changing. The controllers will be provided in priority order with the
- * most important controller at index 0.
- *
- * @param controllers The updated list of controllers for the user that
- * changed.
- */
- public abstract void onActiveSessionsChanged(
- @Nullable List<MediaController> controllers);
+ private final class SessionsChangedWrapper {
+ private final OnActiveSessionsChangedListener mListener;
+ private final Handler mHandler;
- private final void setHandler(Handler handler) {
+ public SessionsChangedWrapper(OnActiveSessionsChangedListener listener, Handler handler) {
+ mListener = listener;
mHandler = handler;
}
@@ -295,7 +304,7 @@
for (int i = 0; i < size; i++) {
controllers.add(new MediaController(mContext, tokens.get(i)));
}
- SessionListener.this.onActiveSessionsChanged(controllers);
+ mListener.onActiveSessionsChanged(controllers);
}
});
}
diff --git a/media/java/android/media/session/ParcelableVolumeInfo.java b/media/java/android/media/session/ParcelableVolumeInfo.java
index e71b539..96a45d9b 100644
--- a/media/java/android/media/session/ParcelableVolumeInfo.java
+++ b/media/java/android/media/session/ParcelableVolumeInfo.java
@@ -21,7 +21,7 @@
/**
* Convenience class for passing information about the audio configuration of a
- * session. The public implementation is {@link MediaController.VolumeInfo}.
+ * session. The public implementation is {@link MediaController.AudioInfo}.
*
* @hide
*/
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index 2ad8eae..566e218 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -120,11 +120,11 @@
public static final long ACTION_PLAY_FROM_SEARCH = 1 << 11;
/**
- * Indicates this performer supports the skip to track command.
+ * Indicates this performer supports the skip to item command.
*
* @see Builder#setActions(long)
*/
- public static final long ACTION_SKIP_TO_TRACK = 1 << 12;
+ public static final long ACTION_SKIP_TO_ITEM = 1 << 12;
/**
* This is the default playback state and indicates that no media has been
@@ -223,11 +223,11 @@
private List<PlaybackState.CustomAction> mCustomActions;
private final CharSequence mErrorMessage;
private final long mUpdateTime;
- private final long mActiveTrackId;
+ private final long mActiveItemId;
private PlaybackState(int state, long position, long updateTime, float speed,
long bufferPosition, long transportControls,
- List<PlaybackState.CustomAction> customActions, long activeTrackId,
+ List<PlaybackState.CustomAction> customActions, long activeItemId,
CharSequence error) {
mState = state;
mPosition = position;
@@ -236,7 +236,7 @@
mBufferPosition = bufferPosition;
mActions = transportControls;
mCustomActions = new ArrayList<>(customActions);
- mActiveTrackId = activeTrackId;
+ mActiveItemId = activeItemId;
mErrorMessage = error;
}
@@ -248,7 +248,7 @@
mBufferPosition = in.readLong();
mActions = in.readLong();
mCustomActions = in.createTypedArrayList(CustomAction.CREATOR);
- mActiveTrackId = in.readLong();
+ mActiveItemId = in.readLong();
mErrorMessage = in.readCharSequence();
}
@@ -263,7 +263,7 @@
bob.append(", updated=").append(mUpdateTime);
bob.append(", actions=").append(mActions);
bob.append(", custom actions=").append(mCustomActions);
- bob.append(", active track id=").append(mActiveTrackId);
+ bob.append(", active item id=").append(mActiveItemId);
bob.append(", error=").append(mErrorMessage);
bob.append("}");
return bob.toString();
@@ -283,7 +283,7 @@
dest.writeLong(mBufferPosition);
dest.writeLong(mActions);
dest.writeTypedList(mCustomActions);
- dest.writeLong(mActiveTrackId);
+ dest.writeLong(mActiveItemId);
dest.writeCharSequence(mErrorMessage);
}
@@ -716,7 +716,7 @@
private long mActions;
private CharSequence mErrorMessage;
private long mUpdateTime;
- private long mActiveTrackId = MediaSession.Track.UNKNOWN_ID;
+ private long mActiveItemId = MediaSession.Item.UNKNOWN_ID;
/**
* Creates an initially empty state builder.
@@ -744,14 +744,14 @@
}
mErrorMessage = from.mErrorMessage;
mUpdateTime = from.mUpdateTime;
- mActiveTrackId = from.mActiveTrackId;
+ mActiveItemId = from.mActiveItemId;
}
/**
* Set the current state of playback.
* <p>
* The position must be in ms and indicates the current playback
- * position within the track. If the position is unknown use
+ * position within the item. If the position is unknown use
* {@link #PLAYBACK_POSITION_UNKNOWN}. When not using an unknown
* position the time at which the position was updated must be provided.
* It is okay to use {@link SystemClock#elapsedRealtime()} if the
@@ -773,7 +773,7 @@
* </ul>
*
* @param state The current state of playback.
- * @param position The position in the current track in ms.
+ * @param position The position in the current item in ms.
* @param playbackSpeed The current speed of playback as a multiple of
* normal playback.
* @param updateTime The time in the {@link SystemClock#elapsedRealtime}
@@ -792,7 +792,7 @@
* Set the current state of playback.
* <p>
* The position must be in ms and indicates the current playback
- * position within the track. If the position is unknown use
+ * position within the item. If the position is unknown use
* {@link #PLAYBACK_POSITION_UNKNOWN}. The update time will be set to
* the current {@link SystemClock#elapsedRealtime()}.
* <p>
@@ -812,7 +812,7 @@
* </ul>
*
* @param state The current state of playback.
- * @param position The position in the current track in ms.
+ * @param position The position in the current item in ms.
* @param playbackSpeed The current speed of playback as a multiple of
* normal playback.
* @return this
@@ -902,14 +902,14 @@
}
/**
- * Set the active track in the play queue by specifying its id.
- * The default value is {@link MediaSession.Track#UNKNOWN_ID}
+ * Set the active item in the play queue by specifying its id. The
+ * default value is {@link MediaSession.Item#UNKNOWN_ID}
*
- * @param id The id of the active track.
+ * @param id The id of the active item.
* @return this
*/
- public Builder setActiveTrack(long id) {
- mActiveTrackId = id;
+ public Builder setActiveItem(long id) {
+ mActiveItemId = id;
return this;
}
@@ -932,7 +932,7 @@
*/
public PlaybackState build() {
return new PlaybackState(mState, mPosition, mUpdateTime, mSpeed, mBufferPosition,
- mActions, mCustomActions, mActiveTrackId, mErrorMessage);
+ mActions, mCustomActions, mActiveItemId, mErrorMessage);
}
}
}
diff --git a/media/java/android/media/tv/ITvInputSession.aidl b/media/java/android/media/tv/ITvInputSession.aidl
index 99fb911..1aad2fa 100644
--- a/media/java/android/media/tv/ITvInputSession.aidl
+++ b/media/java/android/media/tv/ITvInputSession.aidl
@@ -29,7 +29,7 @@
oneway interface ITvInputSession {
void release();
- void setMainSession(boolean isMainSession);
+ void setMain(boolean isMain);
void setSurface(in Surface surface);
void dispatchSurfaceChanged(int format, int width, int height);
// TODO: Remove this once it becomes irrelevant for applications to handle audio focus. The plan
diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java
index 5022cc1..58e46f0 100644
--- a/media/java/android/media/tv/ITvInputSessionWrapper.java
+++ b/media/java/android/media/tv/ITvInputSessionWrapper.java
@@ -42,7 +42,7 @@
private static final String TAG = "TvInputSessionWrapper";
private static final int DO_RELEASE = 1;
- private static final int DO_SET_MAIN_SESSION = 2;
+ private static final int DO_SET_MAIN = 2;
private static final int DO_SET_SURFACE = 3;
private static final int DO_DISPATCH_SURFACE_CHANGED = 4;
private static final int DO_SET_STREAM_VOLUME = 5;
@@ -91,8 +91,8 @@
}
return;
}
- case DO_SET_MAIN_SESSION: {
- mTvInputSessionImpl.setMainSession((Boolean) msg.obj);
+ case DO_SET_MAIN: {
+ mTvInputSessionImpl.setMain((Boolean) msg.obj);
return;
}
case DO_SET_SURFACE: {
@@ -162,8 +162,8 @@
}
@Override
- public void setMainSession(boolean isMain) {
- mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SET_MAIN_SESSION, isMain));
+ public void setMain(boolean isMain) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SET_MAIN, isMain));
}
@Override
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index f76c78b..45aa6d6 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -1023,10 +1023,12 @@
}
/**
- * Sets this as main session. See {@link TvView#setMainTvView} for about meaning of "main".
- * @hide
+ * Sets this as the main session. The main session is a session whose corresponding TV
+ * input determines the HDMI-CEC active source device.
+ *
+ * @see TvView#setMain
*/
- public void setMainSession() {
+ void setMain() {
if (mToken == null) {
Log.w(TAG, "The session has been already released");
return;
@@ -1339,6 +1341,9 @@
Log.w(TAG, "The session has been already released");
return;
}
+ if (unblockedRating == null) {
+ throw new IllegalArgumentException("unblockedRating cannot be null");
+ }
try {
mService.requestUnblockContent(mToken, unblockedRating.flattenToString(), mUserId);
} catch (RemoteException e) {
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index c93b261..e3292b6 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -94,6 +94,8 @@
private final RemoteCallbackList<ITvInputServiceCallback> mCallbacks =
new RemoteCallbackList<ITvInputServiceCallback>();
+ private TvInputManager mTvInputManager;
+
@Override
public final IBinder onBind(Intent intent) {
return new ITvInputService.Stub() {
@@ -225,6 +227,17 @@
return null;
}
+ private boolean isPassthroughInput(String inputId) {
+ if (mTvInputManager == null) {
+ mTvInputManager = (TvInputManager) getSystemService(Context.TV_INPUT_SERVICE);
+ }
+ TvInputInfo info = mTvInputManager.getTvInputInfo(inputId);
+ if (info != null && info.isPassthroughInput()) {
+ return true;
+ }
+ return false;
+ }
+
/**
* Base class for derived classes to implement to provide a TV input session.
*/
@@ -538,29 +551,30 @@
public abstract void onRelease();
/**
- * Set the current session as the "main" session. See {@link TvView#setMainTvView} for the
- * meaning of "main".
+ * Sets the current session as the main session. The main session is a session whose
+ * corresponding TV input determines the HDMI-CEC active source device.
* <p>
- * This is primarily for HDMI-CEC active source management. TV input service that manages
- * HDMI-CEC logical device should make sure not only to select the corresponding HDMI
- * logical device as source device on {@code onSetMainSession(true)}, but also to select
- * internal device on {@code onSetMainSession(false)}. Also, if surface is set to non-main
- * session, it needs to select internal device after temporarily selecting corresponding
- * HDMI logical device for set up.
+ * TV input service that manages HDMI-CEC logical device should implement {@link
+ * #onSetMain} to (1) select the corresponding HDMI logical device as the source device
+ * when {@code isMain} is {@code true}, and to (2) select the internal device (= TV itself)
+ * as the source device when {@code isMain} is {@code false} and the session is still main.
+ * Also, if a surface is passed to a non-main session and active source is changed to
+ * initiate the surface, the active source should be returned to the main session.
* </p><p>
- * It is guaranteed that {@code onSetMainSession(true)} for new session is called first,
- * and {@code onSetMainSession(false)} for old session is called afterwards. This allows
- * {@code onSetMainSession(false)} to be no-op when TV input service knows that the next
- * main session corresponds to another HDMI logical device. Practically, this implies that
- * one TV input service should handle all HDMI port and HDMI-CEC logical devices for smooth
- * active source transition.
+ * {@link TvView} guarantees that, when tuning involves a session transition, {@code
+ * onSetMain(true)} for new session is called first, {@code onSetMain(false)} for old
+ * session is called afterwards. This allows {@code onSetMain(false)} to be no-op when TV
+ * input service knows that the next main session corresponds to another HDMI logical
+ * device. Practically, this implies that one TV input service should handle all HDMI port
+ * and HDMI-CEC logical devices for smooth active source transition.
* </p>
*
- * @param isMainSession If true, session is main.
+ * @param isMain If true, session should become main.
+ * @see TvView#setMain
* @hide
*/
@SystemApi
- public void onSetMainSession(boolean isMainSession) {
+ public void onSetMain(boolean isMain) {
}
/**
@@ -828,10 +842,10 @@
}
/**
- * Calls {@link #onSetMainSession}.
+ * Calls {@link #onSetMain}.
*/
- void setMainSession(boolean isMainSession) {
- onSetMainSession(isMainSession);
+ void setMain(boolean isMain) {
+ onSetMain(isMain);
}
/**
@@ -1229,9 +1243,14 @@
HardwareSession proxySession =
((HardwareSession) sessionImpl);
String harewareInputId = proxySession.getHardwareInputId();
- if (TextUtils.isEmpty(harewareInputId)) {
+ if (TextUtils.isEmpty(harewareInputId) ||
+ !isPassthroughInput(harewareInputId)) {
+ if (TextUtils.isEmpty(harewareInputId)) {
+ Log.w(TAG, "Hardware input id is not setup yet.");
+ } else {
+ Log.w(TAG, "Invalid hardware input id : " + harewareInputId);
+ }
sessionImpl.onRelease();
- Log.w(TAG, "Hardware input id is not setup yet.");
try {
cb.onSessionCreated(null, null);
} catch (RemoteException e) {
@@ -1239,7 +1258,6 @@
}
return;
}
- // TODO: check if the given ID is really hardware TV input.
proxySession.mProxySession = stub;
proxySession.mProxySessionCallback = cb;
proxySession.mServiceHandler = mServiceHandler;
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index 591f543..f348b9b 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -59,19 +59,6 @@
// STOPSHIP: Turn debugging off.
private static final boolean DEBUG = true;
- /**
- * Passed with {@link TvInputListener#onError(String, int)}. Indicates that the connection to
- * the requested TV input was not established thus the view is unable to handle the further
- * operations.
- */
- public static final int ERROR_INPUT_NOT_CONNECTED = 0;
-
- /**
- * Passed with {@link TvInputListener#onError(String, int)}. Indicates that the underlying TV
- * input has been disconnected.
- */
- public static final int ERROR_INPUT_DISCONNECTED = 1;
-
private static final int VIDEO_SIZE_VALUE_UNKNOWN = 0;
private static final int ZORDER_MEDIA = 0;
@@ -116,8 +103,10 @@
private final SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() {
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- Log.d(TAG, "surfaceChanged(holder=" + holder + ", format=" + format + ", width=" + width
- + ", height=" + height + ")");
+ if (DEBUG) {
+ Log.d(TAG, "surfaceChanged(holder=" + holder + ", format=" + format + ", width="
+ + width + ", height=" + height + ")");
+ }
mSurfaceFormat = format;
mSurfaceWidth = width;
mSurfaceHeight = height;
@@ -188,24 +177,27 @@
}
/**
- * Sets this as main TvView.
+ * Sets this as the main {@link TvView}.
* <p>
- * Main TvView is the TvView which user is watching and interacting mainly. It is used for
- * determining internal behavior of hardware TV input devices. For example, this influences
- * how HDMI-CEC active source will be managed.
+ * The main {@link TvView} is a {@link TvView} whose corresponding TV input determines the
+ * HDMI-CEC active source device. For an HDMI port input, one of source devices that is
+ * connected to that HDMI port becomes the active source. For an HDMI-CEC logical device input,
+ * the corresponding HDMI-CEC logical device becomes the active source. For any non-HDMI input
+ * (including the tuner, composite, S-Video, etc.), the internal device (= TV itself) becomes
+ * the active source.
* </p><p>
- * First tuned TvView becomes main automatically, and keeps to be main until setMainTvView() is
- * called for other TvView. Note that main TvView won't be reset even when current main TvView
- * is removed from view hierarchy.
+ * First tuned {@link TvView} becomes main automatically, and keeps to be main until {@link
+ * #setMain} is called for other {@link TvView}. Note that main {@link TvView} won't be reset
+ * even when current main {@link TvView} is removed from view hierarchy.
* </p>
* @hide
*/
@SystemApi
- public void setMainTvView() {
+ public void setMain() {
synchronized (sMainTvViewLock) {
sMainTvView = this;
if (hasWindowFocus() && mSession != null) {
- mSession.setMainSession();
+ mSession.setMain();
}
}
}
@@ -327,6 +319,7 @@
* This method is primarily used to un-tune the current TvView.
*/
public void reset() {
+ if (DEBUG) Log.d(TAG, "reset()");
if (mSession != null) {
release();
resetSurfaceView();
@@ -538,7 +531,7 @@
// Set main again to regain main session.
synchronized (sMainTvViewLock) {
if (hasFocus && this == sMainTvView && mSession != null) {
- mSession.setMainSession();
+ mSession.setMain();
}
}
}
@@ -596,6 +589,7 @@
mSurfaceView.getHolder().removeCallback(mSurfaceHolderCallback);
removeView(mSurfaceView);
}
+ mSurface = null;
mSurfaceView = new SurfaceView(getContext(), mAttrs, mDefStyleAttr) {
@Override
protected void updateWindow(boolean force, boolean redrawNeeded) {
@@ -679,13 +673,20 @@
public abstract static class TvInputListener {
/**
- * This is invoked when an error occurred while handling requested operation.
+ * This is invoked when an error occurred while establishing a connection to the underlying
+ * TV input.
*
* @param inputId The ID of the TV input bound to this view.
- * @param errorCode The error code. For the details of error code, please see
- * {@link TvView}.
*/
- public void onError(String inputId, int errorCode) {
+ public void onConnectionFailed(String inputId) {
+ }
+
+ /**
+ * This is invoked when the existing connection to the underlying TV input is lost.
+ *
+ * @param inputId The ID of the TV input bound to this view.
+ */
+ public void onDisconnected(String inputId) {
}
/**
@@ -821,11 +822,14 @@
}
return;
}
+ if (DEBUG) {
+ Log.d(TAG, "onSessionCreated()");
+ }
mSession = session;
if (session != null) {
synchronized (sMainTvViewLock) {
if (hasWindowFocus() && TvView.this == sMainTvView) {
- mSession.setMainSession();
+ mSession.setMain();
}
}
// mSurface may not be ready yet as soon as starting an application.
@@ -847,7 +851,7 @@
}
} else {
if (mListener != null) {
- mListener.onError(mInputId, ERROR_INPUT_NOT_CONNECTED);
+ mListener.onConnectionFailed(mInputId);
}
}
}
@@ -860,7 +864,7 @@
mSessionCallback = null;
mSession = null;
if (mListener != null) {
- mListener.onError(mInputId, ERROR_INPUT_DISCONNECTED);
+ mListener.onDisconnected(mInputId);
}
}
diff --git a/packages/PrintSpooler/AndroidManifest.xml b/packages/PrintSpooler/AndroidManifest.xml
index 9a62864..055587a 100644
--- a/packages/PrintSpooler/AndroidManifest.xml
+++ b/packages/PrintSpooler/AndroidManifest.xml
@@ -46,7 +46,7 @@
android:label="@string/app_label"
android:allowBackup= "false"
android:supportsRtl="true"
- android:icon="@*android:drawable/ic_print">
+ android:icon="@drawable/ic_print">
<service
android:name=".model.PrintSpoolerService"
diff --git a/packages/PrintSpooler/res/drawable-hdpi/ic_menu_print.png b/packages/PrintSpooler/res/drawable-hdpi/ic_menu_print.png
deleted file mode 100644
index 09ab1a2..0000000
--- a/packages/PrintSpooler/res/drawable-hdpi/ic_menu_print.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-mdpi/ic_menu_print.png b/packages/PrintSpooler/res/drawable-mdpi/ic_menu_print.png
deleted file mode 100644
index 637d94e..0000000
--- a/packages/PrintSpooler/res/drawable-mdpi/ic_menu_print.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xhdpi/ic_menu_print.png b/packages/PrintSpooler/res/drawable-xhdpi/ic_menu_print.png
deleted file mode 100644
index 4d4b3cc..0000000
--- a/packages/PrintSpooler/res/drawable-xhdpi/ic_menu_print.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable/ic_print.xml b/packages/PrintSpooler/res/drawable/ic_print.xml
new file mode 100644
index 0000000..dc6e0fb
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable/ic_print.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@*android:drawable/ic_print"
+ android:tint="@color/promoted_action_background_color" />
diff --git a/packages/PrintSpooler/res/values/themes.xml b/packages/PrintSpooler/res/values/themes.xml
index db319e9..08702291 100644
--- a/packages/PrintSpooler/res/values/themes.xml
+++ b/packages/PrintSpooler/res/values/themes.xml
@@ -16,7 +16,10 @@
<resources>
- <style name="PrintActivity" parent="@android:style/Theme.Material.Settings">
+ <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_A500</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
index 7715579..3905bada 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
@@ -96,7 +96,7 @@
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- getActionBar().setIcon(R.drawable.ic_menu_print);
+ getActionBar().setIcon(R.drawable.ic_print);
setContentView(R.layout.select_printer_activity);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 6f41565..f1d2bee3 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -90,6 +90,7 @@
<uses-permission android:name="android.permission.RETRIEVE_WINDOW_TOKEN" />
<uses-permission android:name="android.permission.FRAME_STATS" />
<uses-permission android:name="android.permission.BIND_APPWIDGET" />
+ <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
<application android:label="@string/app_label">
<provider
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index b8836a0..cbea664 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -111,7 +111,7 @@
<uses-permission android:name="android.permission.CAMERA" />
<!-- Screen Capturing -->
- <uses-permission android:name="android.permission.CREATE_MEDIA_PROJECTION" />
+ <uses-permission android:name="android.permission.MANAGE_MEDIA_PROJECTION" />
<application
android:name=".SystemUIApplication"
diff --git a/packages/SystemUI/res/drawable/ic_qs_bugreport.xml b/packages/SystemUI/res/drawable/ic_qs_bugreport.xml
deleted file mode 100644
index 0df1a96..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_bugreport.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="64dp"
- android:height="64dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
-
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M20.0,8.0l-2.8,0.0c-0.5,-0.8 -1.1,-1.5 -1.8,-2.0L17.0,4.4L15.6,3.0l-2.2,2.2C13.0,5.1 12.5,5.0 12.0,5.0s-1.0,0.1 -1.4,0.2L8.4,3.0L7.0,4.4L8.6,6.0C7.9,6.5 7.3,7.2 6.8,8.0L4.0,8.0l0.0,2.0l2.1,0.0C6.0,10.3 6.0,10.7 6.0,11.0l0.0,1.0L4.0,12.0l0.0,2.0l2.0,0.0l0.0,1.0c0.0,0.3 0.0,0.7 0.1,1.0L4.0,16.0l0.0,2.0l2.8,0.0c1.0,1.8 3.0,3.0 5.2,3.0s4.2,-1.2 5.2,-3.0L20.0,18.0l0.0,-2.0l-2.1,0.0c0.1,-0.3 0.1,-0.7 0.1,-1.0l0.0,-1.0l2.0,0.0l0.0,-2.0l-2.0,0.0l0.0,-1.0c0.0,-0.3 0.0,-0.7 -0.1,-1.0L20.0,10.0L20.0,8.0zM14.0,16.0l-4.0,0.0l0.0,-2.0l4.0,0.0L14.0,16.0zM14.0,12.0l-4.0,0.0l0.0,-2.0l4.0,0.0L14.0,12.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/layout/keyguard_status_bar.xml b/packages/SystemUI/res/layout/keyguard_status_bar.xml
index fcc0f4a..faa2820 100644
--- a/packages/SystemUI/res/layout/keyguard_status_bar.xml
+++ b/packages/SystemUI/res/layout/keyguard_status_bar.xml
@@ -60,7 +60,8 @@
android:paddingEnd="@dimen/battery_level_padding_end"
android:textColor="#ffffff"
android:visibility="gone"
- android:textSize="@dimen/battery_level_text_size"/>
+ android:textSize="@dimen/battery_level_text_size"
+ android:importantForAccessibility="noHideDescendants"/>
</LinearLayout>
<com.android.keyguard.CarrierText
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index 828065b..5253ee0 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -69,6 +69,7 @@
android:layout_gravity="bottom|right"
android:layout_marginRight="15dp"
android:layout_marginBottom="15dp"
+ android:translationZ="3dp"
android:contentDescription="@string/recents_lock_to_app_button_label"
android:background="@drawable/recents_lock_to_task_button_bg">
<ImageView
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 079b97b..aa276bc 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -72,7 +72,8 @@
android:layout_marginStart="@dimen/header_battery_margin_expanded"
android:paddingEnd="@dimen/battery_level_padding_end"
android:textColor="#ffffff"
- android:textSize="@dimen/battery_level_text_size"/>
+ android:textSize="@dimen/battery_level_text_size"
+ android:importantForAccessibility="noHideDescendants"/>
</LinearLayout>
<TextView
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 5415d19..1b8eeb2 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -205,10 +205,10 @@
<dimen name="recents_task_view_rounded_corners_radius">2dp</dimen>
<!-- The min translation in the Z index for the last task. -->
- <dimen name="recents_task_view_z_min">5dp</dimen>
+ <dimen name="recents_task_view_z_min">25dp</dimen>
<!-- The max translation in the Z index for the last task. -->
- <dimen name="recents_task_view_z_max">65dp</dimen>
+ <dimen name="recents_task_view_z_max">100dp</dimen>
<!-- The amount to translate when animating the removal of a task. -->
<dimen name="recents_task_view_remove_anim_translation_x">100dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d145172..d49312d 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -273,6 +273,13 @@
<!-- Content description of the WIFI signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_wifi_signal_full">Wifi signal full.</string>
+ <!-- Content description of the wifi label showing what we are connected to. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_wifi_name">Connected to <xliff:g id="wifi" example="Home Network">%s</xliff:g>.</string>
+
+ <!-- Content description of the bluetooth label showing what we are connected to. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_bluetooth_name">Connected to <xliff:g id="bluetooth" example="Car Audio">%s</xliff:g>.</string>
+
+
<!-- Content description of the WiMAX signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_no_wimax">No WiMAX.</string>
<!-- Content description of the WiMAX signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
@@ -390,6 +397,8 @@
<string name="accessibility_desc_notification_shade">Notification shade.</string>
<!-- Content description for the quick settings panel (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_desc_quick_settings">Quick settings.</string>
+ <!-- Content description for the lock screen (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_desc_lock_screen">Lock screen.</string>
<!-- Content description for the settings button in the status bar header. [CHAR LIMIT=NONE] -->
<string name="accessibility_desc_settings">Settings</string>
<!-- Content description for the recent apps panel (not shown on the screen). [CHAR LIMIT=NONE] -->
@@ -398,7 +407,7 @@
<!-- 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>
<!-- Content description of the wifi tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_wifi"><xliff:g id="signal" example="Three bars">%1$s</xliff:g>. <xliff:g id="network" example="MyWifiNetwork">%2$s</xliff:g></string>
+ <string name="accessibility_quick_settings_wifi"><xliff:g id="signal" example="Three bars">%1$s</xliff:g>.</string>
<!-- Content description of the mobile data tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_mobile">Mobile <xliff:g id="signal" example="Three bars">%1$s</xliff:g>. <xliff:g id="type" example="4G">%2$s</xliff:g>. <xliff:g id="network" example="T-Mobile">%3$s</xliff:g>.</string>
<!-- Content description of the battery tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
@@ -577,7 +586,7 @@
<!-- QuickSettings: Cellular detail panel, remaining data title [CHAR LIMIT=NONE] -->
<string name="quick_settings_cellular_detail_remaining_data">Remaining data</string>
<!-- QuickSettings: Cellular detail panel, over limit title [CHAR LIMIT=NONE] -->
- <string name="quick_settings_cellular_detail_over_limit">Over limit</string>
+ <string name="quick_settings_cellular_detail_over_limit">Limit reached – data usage paused</string>
<!-- QuickSettings: Cellular detail panel, data used format string [CHAR LIMIT=NONE] -->
<string name="quick_settings_cellular_detail_data_used"><xliff:g id="data_used" example="2.0 GB">%s</xliff:g> used</string>
<!-- QuickSettings: Cellular detail panel, data limit format string [CHAR LIMIT=NONE] -->
@@ -659,8 +668,6 @@
<!-- Shows when people have clicked at the right edge of the screen to explain how to open the phone. In right-to-left languages, this is the opposite direction. [CHAR LIMIT=60] -->
<string name="camera_hint">Swipe left for camera</string>
- <string name="bugreport_tile_extended" translatable="false">%s\n%s (%s)</string>
-
<!-- Zen mode condition: no exit criteria. [CHAR LIMIT=NONE] -->
<string name="zen_mode_forever">Indefinitely</string>
@@ -700,10 +707,13 @@
<string name="guest_exit_guest">Remove guest</string>
<!-- Title of the confirmation dialog when exiting guest session [CHAR LIMIT=NONE] -->
- <string name="guest_exit_guest_dialog_title">Exiting guest session?</string>
+ <string name="guest_exit_guest_dialog_title">Remove guest?</string>
<!-- Message of the confirmation dialog when exiting guest session [CHAR LIMIT=NONE] -->
- <string name="guest_exit_guest_dialog_message">Exiting the guest session will remove local data.</string>
+ <string name="guest_exit_guest_dialog_message">All apps and data in this session will be deleted.</string>
+
+ <!-- Label for button in confirmation dialog when exiting guest session [CHAR LIMIT=35] -->
+ <string name="guest_exit_guest_dialog_remove">Remove</string>
<!-- Title of the notification when resuming an existing guest session [CHAR LIMIT=NONE] -->
<string name="guest_wipe_session_title">Welcome back, guest!</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 27e58a4..48a031a 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -21,11 +21,23 @@
</style>
<!-- Alternate Recents theme -->
- <style name="RecentsTheme" parent="@android:style/Theme.DeviceDefault.Wallpaper.NoTitleBar">
+ <style name="RecentsTheme" parent="@android:style/Theme">
+ <!-- NoTitle -->
+ <item name="android:windowNoTitle">true</item>
+ <!-- Wallpaper -->
+ <item name="android:windowBackground">@color/transparent</item>
+ <item name="android:colorBackgroundCacheHint">@null</item>
+ <item name="android:windowShowWallpaper">true</item>
+ <!-- Misc -->
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:windowAnimationStyle">@style/Animation.RecentsActivity</item>
+ <item name="*android:lightingStyle">@style/RecentsLighting</item>
+ </style>
+
+ <style name="RecentsLighting" parent="@*android:style/Lighting">
+ <item name="*android:ambientShadowAlpha">0.30</item>
</style>
<!-- Animations for a non-full-screen window or activity. -->
diff --git a/packages/SystemUI/src/com/android/systemui/net/NetworkOverLimitActivity.java b/packages/SystemUI/src/com/android/systemui/net/NetworkOverLimitActivity.java
index fe7aa75..b3c0783 100644
--- a/packages/SystemUI/src/com/android/systemui/net/NetworkOverLimitActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/net/NetworkOverLimitActivity.java
@@ -33,6 +33,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
+import android.view.WindowManager;
import com.android.systemui.R;
@@ -62,6 +63,7 @@
});
final Dialog dialog = builder.create();
+ dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
public void onDismiss(DialogInterface dialog) {
finish();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 1fa97bd..bf01b7b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -347,8 +347,8 @@
}
for (TileRecord record : mRecords) {
- if (record.tileView.getVisibility() == GONE) continue;
record.tileView.setDual(record.tile.supportsDualTargets());
+ if (record.tileView.getVisibility() == GONE) continue;
final int cw = record.row == 0 ? mLargeCellWidth : mCellWidth;
final int ch = record.row == 0 ? mLargeCellHeight : mCellHeight;
record.tileView.measure(exactly(cw), exactly(ch));
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 6975541..409cc46 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -286,6 +286,7 @@
public Drawable icon;
public String label;
public String contentDescription;
+ public String dualLabelContentDescription;
public boolean copyTo(State other) {
if (other == null) throw new IllegalArgumentException();
@@ -294,12 +295,15 @@
|| other.iconId != iconId
|| !Objects.equals(other.icon, icon)
|| !Objects.equals(other.label, label)
- || !Objects.equals(other.contentDescription, contentDescription);
+ || !Objects.equals(other.contentDescription, contentDescription)
+ || !Objects.equals(other.dualLabelContentDescription,
+ dualLabelContentDescription);
other.visible = visible;
other.iconId = iconId;
other.icon = icon;
other.label = label;
other.contentDescription = contentDescription;
+ other.dualLabelContentDescription = dualLabelContentDescription;
return changed;
}
@@ -315,6 +319,7 @@
sb.append(",icon=").append(icon);
sb.append(",label=").append(label);
sb.append(",contentDescription=").append(contentDescription);
+ sb.append(",dualLabelContentDescription=").append(dualLabelContentDescription);
return sb.append(']');
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
index 597bb93..2cc1f07 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
@@ -87,6 +87,7 @@
private void recreateLabel() {
CharSequence labelText = null;
+ CharSequence labelDescription = null;
if (mLabel != null) {
labelText = mLabel.getText();
removeView(mLabel);
@@ -94,6 +95,7 @@
}
if (mDualLabel != null) {
labelText = mDualLabel.getText();
+ labelDescription = mLabel.getContentDescription();
removeView(mDualLabel);
mDualLabel = null;
}
@@ -113,6 +115,9 @@
if (labelText != null) {
mDualLabel.setText(labelText);
}
+ if (labelDescription != null) {
+ mDualLabel.setContentDescription(labelDescription);
+ }
addView(mDualLabel);
} else {
mLabel = new TextView(mContext);
@@ -228,6 +233,7 @@
}
if (mDual) {
mDualLabel.setText(state.label);
+ mDualLabel.setContentDescription(state.dualLabelContentDescription);
} else {
mLabel.setText(state.label);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 1b2c0b0..19b9ec1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -114,6 +114,12 @@
}
state.contentDescription = mContext.getString(
R.string.accessibility_quick_settings_bluetooth, stateContentDescription);
+ String bluetoothName = state.label;
+ if (connected) {
+ bluetoothName = state.dualLabelContentDescription = mContext.getString(
+ R.string.accessibility_bluetooth_name, state.label);
+ }
+ state.dualLabelContentDescription = bluetoothName;
}
private final BluetoothController.Callback mCallback = new BluetoothController.Callback() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BugreportTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BugreportTile.java
deleted file mode 100644
index a308e84..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BugreportTile.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles;
-
-import android.app.ActivityManagerNative;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
-import android.os.Build;
-import android.os.RemoteException;
-import android.provider.Settings.Global;
-import android.view.WindowManager;
-import android.view.WindowManagerGlobal;
-
-import com.android.systemui.R;
-import com.android.systemui.qs.GlobalSetting;
-import com.android.systemui.qs.QSTile;
-
-/** Quick settings tile: Bug report **/
-public class BugreportTile extends QSTile<QSTile.State> {
-
- private final GlobalSetting mSetting;
-
- public BugreportTile(Host host) {
- super(host);
- mSetting = new GlobalSetting(mContext, mHandler, Global.BUGREPORT_IN_POWER_MENU) {
- @Override
- protected void handleValueChanged(int value) {
- handleRefreshState(null);
- }
- };
- }
-
- @Override
- protected State newTileState() {
- return new State();
- }
-
- @Override
- public void setListening(boolean listening) {
- mSetting.setListening(listening);
- }
-
- @Override
- protected void handleClick() {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mHost.collapsePanels();
- mUiHandler.post(mShowDialog);
- }
- });
- }
-
- @Override
- protected void handleUpdateState(State state, Object pushArg) {
- state.visible = mSetting.getValue() != 0;
- state.iconId = R.drawable.ic_qs_bugreport;
- state.label = mContext.getString(
- R.string.bugreport_tile_extended,
- mContext.getString(com.android.internal.R.string.bugreport_title),
- Build.VERSION.RELEASE,
- Build.ID);
- }
-
- private final Runnable mShowDialog = new Runnable() {
- @Override
- public void run() {
- final AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
- builder.setPositiveButton(com.android.internal.R.string.report, new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- if (which == DialogInterface.BUTTON_POSITIVE) {
- // Add a little delay before executing, to give the
- // dialog a chance to go away before it takes a
- // screenshot.
- mHandler.postDelayed(new Runnable() {
- @Override public void run() {
- try {
- ActivityManagerNative.getDefault().requestBugReport();
- } catch (RemoteException e) {
- }
- }
- }, 500);
- }
- }
- });
- builder.setMessage(com.android.internal.R.string.bugreport_message);
- builder.setTitle(com.android.internal.R.string.bugreport_title);
- builder.setCancelable(true);
- final Dialog dialog = builder.create();
- dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
- try {
- WindowManagerGlobal.getWindowManagerService().dismissKeyguard();
- } catch (RemoteException e) {
- }
- dialog.show();
- }
- };
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index 21254d4..edb5932 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -29,6 +29,8 @@
private final SecureSetting mSetting;
private final UsageTracker mUsageTracker;
+ private boolean mListening;
+
public ColorInversionTile(Host host) {
super(host);
@@ -36,18 +38,25 @@
Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED) {
@Override
protected void handleValueChanged(int value) {
- handleRefreshState(value);
mUsageTracker.trackUsage();
+ if (mListening) {
+ handleRefreshState(value);
+ }
}
};
mUsageTracker = new UsageTracker(host.getContext(), ColorInversionTile.class);
+ if (mSetting.getValue() != 0 && !mUsageTracker.isRecentlyUsed()) {
+ mUsageTracker.trackUsage();
+ }
mUsageTracker.setListening(true);
+ mSetting.setListening(true);
}
@Override
protected void handleDestroy() {
super.handleDestroy();
mUsageTracker.setListening(false);
+ mSetting.setListening(false);
}
@Override
@@ -57,7 +66,7 @@
@Override
public void setListening(boolean listening) {
- mSetting.setListening(listening);
+ mListening = listening;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 5651d49..a8bf026 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -132,8 +132,12 @@
}
state.contentDescription = mContext.getString(
R.string.accessibility_quick_settings_wifi,
- signalContentDescription,
- state.connected ? state.label : "");
+ signalContentDescription);
+ String wifiName = state.label;
+ if (state.connected) {
+ wifiName = r.getString(R.string.accessibility_wifi_name, state.label);
+ }
+ state.dualLabelContentDescription = wifiName;
}
private static String removeDoubleQuotes(String string) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
index 667faa7..f0bdfa2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
@@ -53,7 +53,7 @@
// Log function
static final float XScale = 1.75f; // The large the XScale, the longer the flat area of the curve
- static final float LogBase = 300;
+ static final float LogBase = 3000;
static final int PrecisionSteps = 250;
static float[] xp;
static float[] px;
@@ -84,7 +84,7 @@
left + size, mStackRect.top + size);
// Update the affiliation offsets
- float visibleTaskPct = 0.55f;
+ float visibleTaskPct = 0.5f;
mWithinAffiliationOffset = mConfig.taskBarHeight;
mBetweenAffiliationOffset = (int) (visibleTaskPct * mTaskRect.height());
}
@@ -312,4 +312,4 @@
}
return px[xFloorIndex] + pFraction;
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 5914b39..e514c90 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -21,12 +21,14 @@
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Color;
+import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
+import android.view.ViewOutlineProvider;
import android.view.animation.AccelerateInterpolator;
import android.widget.FrameLayout;
import com.android.systemui.R;
@@ -57,7 +59,7 @@
ObjectAnimator mDimAnimator;
float mMaxDimScale;
int mDim;
- AccelerateInterpolator mDimInterpolator = new AccelerateInterpolator(1.25f);
+ AccelerateInterpolator mDimInterpolator = new AccelerateInterpolator(1f);
PorterDuffColorFilter mDimColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.MULTIPLY);
Task mTask;
@@ -129,6 +131,14 @@
mHeaderView = (TaskViewHeader) findViewById(R.id.task_view_bar);
mThumbnailView = (TaskViewThumbnail) findViewById(R.id.task_view_thumbnail);
mActionButtonView = findViewById(R.id.lock_to_app_fab);
+ mActionButtonView.setOutlineProvider(new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ // Set the outline to match the FAB background
+ outline.setOval(0, 0, mActionButtonView.getWidth(),
+ mActionButtonView.getHeight());
+ }
+ });
if (mFooterView != null) {
mFooterView.setCallbacks(this);
}
@@ -469,7 +479,8 @@
boolean occludesLaunchTarget) {
if (isLaunchingTask) {
// Disable the thumbnail clip and animate the bar out for the window animation out
- mHeaderView.startLaunchTaskAnimation(mThumbnailView.disableTaskBarClipAsRunnable(), r);
+ mHeaderView.startLaunchTaskAnimation(mThumbnailView.disableTaskBarClipAsRunnable(), r,
+ mIsFocused);
// Animate the thumbnail alpha back into full opacity for the window animation out
mThumbnailView.startLaunchTaskAnimation();
@@ -624,7 +635,7 @@
public void setDim(int dim) {
mDim = dim;
// Defer setting hardware layers if we have not yet measured, or there is no dim to draw
- if (getMeasuredWidth() > 0 && getMeasuredHeight() > 0 && dim > 0) {
+ if (getMeasuredWidth() > 0 && getMeasuredHeight() > 0) {
if (mDimAnimator != null) {
mDimAnimator.removeAllListeners();
mDimAnimator.cancel();
@@ -828,6 +839,10 @@
} else if (v == mHeaderView.mDismissButton) {
dismissTask();
} else {
+ if (v == mActionButtonView) {
+ // Reset the translation of the action button before we animate it out
+ mActionButtonView.setTranslationZ(0f);
+ }
mCb.onTaskViewClicked(tv, tv.getTask(),
(v == mFooterView || v == mActionButtonView));
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index 4b09549..c7198fe 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -18,7 +18,9 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
import android.animation.ArgbEvaluator;
+import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.ColorStateList;
@@ -59,7 +61,8 @@
ColorDrawable mBackgroundColor;
Drawable mLightDismissDrawable;
Drawable mDarkDismissDrawable;
- ValueAnimator mBackgroundColorAnimator;
+ AnimatorSet mFocusAnimator;
+ ValueAnimator backgroundColorAnimator;
boolean mIsFullscreen;
boolean mCurrentPrimaryColorIsDark;
@@ -117,6 +120,14 @@
@Override
protected void onFinishInflate() {
+ // Set the outline provider
+ setOutlineProvider(new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ outline.setRect(0, 0, getMeasuredWidth(), getMeasuredHeight());
+ }
+ });
+
// Initialize the icon and description views
mApplicationIcon = (ImageView) findViewById(R.id.application_icon);
mActivityDescription = (TextView) findViewById(R.id.activity_description);
@@ -211,23 +222,29 @@
void startEnterRecentsAnimation(int delay, Runnable postAnimRunnable) {
// Animate the task bar of the first task view
setVisibility(View.VISIBLE);
- setTranslationY(-getMeasuredHeight());
+ setAlpha(0f);
animate()
- .translationY(0)
+ .alpha(1f)
.setStartDelay(delay)
- .setInterpolator(mConfig.fastOutSlowInInterpolator)
+ .setInterpolator(mConfig.linearOutSlowInInterpolator)
.setDuration(mConfig.taskBarEnterAnimDuration)
.withEndAction(postAnimRunnable)
+ .withLayer()
.start();
}
/** Animates this task bar as it exits recents */
- void startLaunchTaskAnimation(Runnable preAnimRunnable, final Runnable postAnimRunnable) {
+ void startLaunchTaskAnimation(Runnable preAnimRunnable, final Runnable postAnimRunnable,
+ boolean isFocused) {
+ if (isFocused) {
+ onTaskViewFocusChanged(false);
+ }
+
// Animate the task bar out of the first task view
animate()
- .translationY(-getMeasuredHeight())
+ .alpha(0f)
.setStartDelay(0)
- .setInterpolator(mConfig.fastOutLinearInInterpolator)
+ .setInterpolator(mConfig.linearOutSlowInInterpolator)
.setDuration(mConfig.taskBarExitAnimDuration)
.withStartAction(preAnimRunnable)
.withEndAction(new Runnable() {
@@ -236,6 +253,7 @@
post(postAnimRunnable);
}
})
+ .withLayer()
.start();
}
@@ -278,10 +296,10 @@
/** Notifies the associated TaskView has been focused. */
void onTaskViewFocusChanged(boolean focused) {
boolean isRunning = false;
- if (mBackgroundColorAnimator != null) {
- isRunning = mBackgroundColorAnimator.isRunning();
- mBackgroundColorAnimator.removeAllUpdateListeners();
- mBackgroundColorAnimator.cancel();
+ if (mFocusAnimator != null) {
+ isRunning = mFocusAnimator.isRunning();
+ mFocusAnimator.removeAllListeners();
+ mFocusAnimator.cancel();
}
if (focused) {
int secondaryColor = getSecondaryColor(mCurrentPrimaryColor, mCurrentPrimaryColorIsDark);
@@ -302,42 +320,54 @@
// Pulse the background color
int currentColor = mBackgroundColor.getColor();
int lightPrimaryColor = getSecondaryColor(mCurrentPrimaryColor, mCurrentPrimaryColorIsDark);
- mBackgroundColorAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), lightPrimaryColor,
- currentColor);
- mBackgroundColorAnimator.addListener(new AnimatorListenerAdapter() {
+ ValueAnimator backgroundColor = ValueAnimator.ofObject(new ArgbEvaluator(),
+ lightPrimaryColor, currentColor);
+ backgroundColor.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
- mBackground.setState(new int[] {});
+ mBackground.setState(new int[]{});
}
});
- mBackgroundColorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ backgroundColor.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mBackgroundColor.setColor((Integer) animation.getAnimatedValue());
}
});
- mBackgroundColorAnimator.setRepeatCount(ValueAnimator.INFINITE);
- mBackgroundColorAnimator.setRepeatMode(ValueAnimator.REVERSE);
- mBackgroundColorAnimator.setStartDelay(750);
- mBackgroundColorAnimator.setDuration(750);
- mBackgroundColorAnimator.start();
+ backgroundColor.setRepeatCount(ValueAnimator.INFINITE);
+ backgroundColor.setRepeatMode(ValueAnimator.REVERSE);
+ // Pulse the translation
+ ObjectAnimator translation = ObjectAnimator.ofFloat(this, "translationZ", 15f);
+ translation.setRepeatCount(ValueAnimator.INFINITE);
+ translation.setRepeatMode(ValueAnimator.REVERSE);
+
+ mFocusAnimator = new AnimatorSet();
+ mFocusAnimator.playTogether(backgroundColor, translation);
+ mFocusAnimator.setStartDelay(750);
+ mFocusAnimator.setDuration(750);
+ mFocusAnimator.start();
} else {
if (isRunning) {
// Restore the background color
int currentColor = mBackgroundColor.getColor();
- mBackgroundColorAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), currentColor,
- mCurrentPrimaryColor);
- mBackgroundColorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ ValueAnimator backgroundColor = ValueAnimator.ofObject(new ArgbEvaluator(),
+ currentColor, mCurrentPrimaryColor);
+ backgroundColor.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mBackgroundColor.setColor((Integer) animation.getAnimatedValue());
}
});
- mBackgroundColorAnimator.setRepeatCount(0);
- mBackgroundColorAnimator.setDuration(150);
- mBackgroundColorAnimator.start();
+ // Restore the translation
+ ObjectAnimator translation = ObjectAnimator.ofFloat(this, "translationZ", 0f);
+
+ mFocusAnimator = new AnimatorSet();
+ mFocusAnimator.playTogether(backgroundColor, translation);
+ mFocusAnimator.setDuration(150);
+ mFocusAnimator.start();
} else {
mBackground.setState(new int[] {});
+ setTranslationZ(0f);
}
}
}
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 42ae0c9..d398bc1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -36,7 +36,6 @@
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
-
import com.android.systemui.R;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.statusbar.ExpandableView;
@@ -160,6 +159,7 @@
private boolean mShadeEmpty;
private boolean mQsScrimEnabled = true;
+ private boolean mLastAnnouncementWasQuickSettings;
public NotificationPanelView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -425,8 +425,8 @@
@Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
- event.getText()
- .add(getContext().getString(R.string.accessibility_desc_notification_shade));
+ event.getText().add(getKeyguardOrLockScreenString());
+ mLastAnnouncementWasQuickSettings = false;
return true;
}
@@ -987,6 +987,10 @@
setQsExpanded(true);
} else if (height <= mQsMinExpansionHeight && mQsExpanded) {
setQsExpanded(false);
+ if (mLastAnnouncementWasQuickSettings && !mTracking) {
+ announceForAccessibility(getKeyguardOrLockScreenString());
+ mLastAnnouncementWasQuickSettings = false;
+ }
}
mQsExpansionHeight = height;
mHeader.setExpansion(getHeaderExpansionFraction());
@@ -1000,6 +1004,22 @@
&& !mStackScrollerOverscrolling && mQsScrimEnabled) {
mQsNavbarScrim.setAlpha(getQsExpansionFraction());
}
+
+ // Upon initialisation when we are not layouted yet we don't want to announce that we are
+ // fully expanded, hence the != 0.0f check.
+ if (height != 0.0f && mQsFullyExpanded && !mLastAnnouncementWasQuickSettings) {
+ announceForAccessibility(getContext().getString(
+ R.string.accessibility_desc_quick_settings));
+ mLastAnnouncementWasQuickSettings = true;
+ }
+ }
+
+ private String getKeyguardOrLockScreenString() {
+ if (mStatusBarState == StatusBarState.KEYGUARD) {
+ return getContext().getString(R.string.accessibility_desc_lock_screen);
+ } else {
+ return getContext().getString(R.string.accessibility_desc_notification_shade);
+ }
}
private void updateNotificationScrim(float height) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 4e9f37d..15a7047 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -602,6 +602,8 @@
mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
mQSPhoneSignalIconId = R.drawable.ic_qs_signal_no_signal;
mDataSignalIconId = R.drawable.stat_sys_signal_null;
+ mContentDescriptionPhoneSignal = mContext.getString(
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0]);
} else {
if (mSignalStrength == null) {
if (CHATTY) Log.d(TAG, "updateTelephonySignalStrength: mSignalStrength == null");
@@ -665,8 +667,7 @@
mDataIconList = TelephonyIcons.DATA_G[mInetCondition];
mDataTypeIconId = 0;
mQSDataTypeIconId = 0;
- mContentDescriptionDataType = mContext.getString(
- R.string.accessibility_data_connection_gprs);
+ mContentDescriptionDataType = "";
break;
} else {
// fall through
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 47e3e73..d53aa47 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -508,9 +508,9 @@
setTitle(R.string.guest_exit_guest_dialog_title);
setMessage(context.getString(R.string.guest_exit_guest_dialog_message));
setButton(DialogInterface.BUTTON_NEGATIVE,
- context.getString(android.R.string.no), this);
+ context.getString(android.R.string.cancel), this);
setButton(DialogInterface.BUTTON_POSITIVE,
- context.getString(android.R.string.yes), this);
+ context.getString(R.string.guest_exit_guest_dialog_remove), this);
setCanceledOnTouchOutside(false);
mGuestId = guestId;
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index b05c242..51876b8 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -37,7 +37,7 @@
import android.media.ToneGenerator;
import android.media.VolumeProvider;
import android.media.session.MediaController;
-import android.media.session.MediaController.VolumeInfo;
+import android.media.session.MediaController.AudioInfo;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
@@ -537,8 +537,8 @@
if (mStreamControls != null) {
StreamControl sc = mStreamControls.get(streamType);
if (sc != null && sc.controller != null) {
- VolumeInfo vi = sc.controller.getVolumeInfo();
- return vi.getMaxVolume();
+ AudioInfo ai = sc.controller.getAudioInfo();
+ return ai.getMaxVolume();
}
}
return -1;
@@ -554,8 +554,8 @@
if (mStreamControls != null) {
StreamControl sc = mStreamControls.get(streamType);
if (sc != null && sc.controller != null) {
- VolumeInfo vi = sc.controller.getVolumeInfo();
- return vi.getCurrentVolume();
+ AudioInfo ai = sc.controller.getAudioInfo();
+ return ai.getCurrentVolume();
}
}
return -1;
@@ -990,7 +990,7 @@
// We still don't have one, ignore the command.
Log.w(mTag, "sent remote volume change without a controller!");
} else {
- VolumeInfo vi = controller.getVolumeInfo();
+ AudioInfo vi = controller.getAudioInfo();
index = vi.getCurrentVolume();
max = vi.getMaxVolume();
if ((vi.getVolumeControl() & VolumeProvider.VOLUME_CONTROL_FIXED) != 0) {
@@ -1362,7 +1362,7 @@
};
private final MediaController.Callback mMediaControllerCb = new MediaController.Callback() {
- public void onVolumeInfoChanged(VolumeInfo info) {
+ public void onAudioInfoChanged(AudioInfo info) {
onRemoteVolumeUpdateIfShown();
}
};
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 964acbd..73358c8 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -3559,6 +3559,10 @@
if (transitionId != -1 && transitionId != R.transition.no_transition) {
TransitionInflater inflater = TransitionInflater.from(getContext());
transition = inflater.inflateTransition(transitionId);
+ if (transition instanceof TransitionSet &&
+ ((TransitionSet)transition).getTransitionCount() == 0) {
+ transition = null;
+ }
}
return transition;
}
diff --git a/rs/java/android/renderscript/Allocation.java b/rs/java/android/renderscript/Allocation.java
index 7db85f2..3cda6de 100644
--- a/rs/java/android/renderscript/Allocation.java
+++ b/rs/java/android/renderscript/Allocation.java
@@ -1868,7 +1868,7 @@
}
}
- static void sendBufferNotification(int id) {
+ static void sendBufferNotification(long id) {
synchronized(mAllocationMap) {
Allocation a = mAllocationMap.get(new Long(id));
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 340efef..6c5c508 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -1156,7 +1156,12 @@
}
if (msg == RS_MESSAGE_TO_CLIENT_NEW_BUFFER) {
- Allocation.sendBufferNotification(subID);
+ if (mRS.nContextGetUserMessage(mRS.mContext, rbuf) !=
+ RS_MESSAGE_TO_CLIENT_NEW_BUFFER) {
+ throw new RSDriverException("Error processing message from RenderScript.");
+ }
+ long bufferID = ((long)rbuf[1] << 32L) + ((long)rbuf[0] & 0xffffffffL);
+ Allocation.sendBufferNotification(bufferID);
continue;
}
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 16df377..13a649a 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -222,7 +222,7 @@
nDeviceCreate(JNIEnv *_env, jobject _this)
{
LOG_API("nDeviceCreate");
- return (jlong)rsDeviceCreate();
+ return (jlong)(uintptr_t)rsDeviceCreate();
}
static void
@@ -243,7 +243,7 @@
nContextCreate(JNIEnv *_env, jobject _this, jlong dev, jint ver, jint sdkVer, jint ct)
{
LOG_API("nContextCreate");
- return (jlong)rsContextCreate((RsDevice)dev, ver, sdkVer, (RsContextType)ct, 0);
+ return (jlong)(uintptr_t)rsContextCreate((RsDevice)dev, ver, sdkVer, (RsContextType)ct, 0);
}
static jlong
@@ -267,7 +267,7 @@
sc.samplesQ = samplesQ;
LOG_API("nContextCreateGL");
- return (jlong)rsContextCreateGL((RsDevice)dev, ver, sdkVer, sc, dpi);
+ return (jlong)(uintptr_t)rsContextCreateGL((RsDevice)dev, ver, sdkVer, sc, dpi);
}
static void
@@ -409,7 +409,7 @@
nElementCreate(JNIEnv *_env, jobject _this, jlong con, jlong type, jint kind, jboolean norm, jint size)
{
LOG_API("nElementCreate, con(%p), type(%i), kind(%i), norm(%i), size(%i)", (RsContext)con, type, kind, norm, size);
- return (jlong)rsElementCreate((RsContext)con, (RsDataType)type, (RsDataKind)kind, norm, size);
+ return (jlong)(uintptr_t)rsElementCreate((RsContext)con, (RsDataType)type, (RsDataKind)kind, norm, size);
}
static jlong
@@ -435,7 +435,7 @@
const char **nameArray = names.c_str();
size_t *sizeArray = names.c_str_len();
- jlong id = (jlong)rsElementCreate2((RsContext)con,
+ jlong id = (jlong)(uintptr_t)rsElementCreate2((RsContext)con,
(const RsElement *)ids, fieldCount,
nameArray, fieldCount * sizeof(size_t), sizeArray,
(const uint32_t *)arraySizes, fieldCount);
@@ -445,7 +445,7 @@
_env->ReleaseLongArrayElements(_ids, jIds, JNI_ABORT);
_env->ReleaseIntArrayElements(_arraySizes, jArraySizes, JNI_ABORT);
- return (jlong)id;
+ return (jlong)(uintptr_t)id;
}
static void
@@ -483,7 +483,7 @@
rsaElementGetSubElements((RsContext)con, (RsElement)id, ids, names, arraySizes, (uint32_t)dataSize);
for(uint32_t i = 0; i < dataSize; i++) {
- const jlong id = (jlong)ids[i];
+ const jlong id = (jlong)(uintptr_t)ids[i];
const jint arraySize = (jint)arraySizes[i];
_env->SetObjectArrayElement(_names, i, _env->NewStringUTF(names[i]));
_env->SetLongArrayRegion(_IDs, i, 1, &id);
@@ -504,7 +504,7 @@
LOG_API("nTypeCreate, con(%p) eid(%p), x(%i), y(%i), z(%i), mips(%i), faces(%i), yuv(%i)",
(RsContext)con, eid, dimx, dimy, dimz, mips, faces, yuv);
- return (jlong)rsTypeCreate((RsContext)con, (RsElement)eid, dimx, dimy, dimz, mips, faces, yuv);
+ return (jlong)(uintptr_t)rsTypeCreate((RsContext)con, (RsElement)eid, dimx, dimy, dimz, mips, faces, yuv);
}
static void
@@ -521,7 +521,7 @@
rsaTypeGetNativeData((RsContext)con, (RsType)id, typeData, 6);
for(jint i = 0; i < elementCount; i ++) {
- const jlong data = (jlong)typeData[i];
+ const jlong data = (jlong)(uintptr_t)typeData[i];
_env->SetLongArrayRegion(_typeData, i, 1, &data);
}
}
@@ -532,7 +532,7 @@
nAllocationCreateTyped(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mips, jint usage, jlong pointer)
{
LOG_API("nAllocationCreateTyped, con(%p), type(%p), mip(%i), usage(%i), ptr(%p)", (RsContext)con, (RsElement)type, mips, usage, (void *)pointer);
- return (jlong) rsAllocationCreateTyped((RsContext)con, (RsType)type, (RsAllocationMipmapControl)mips, (uint32_t)usage, (uintptr_t)pointer);
+ return (jlong)(uintptr_t) rsAllocationCreateTyped((RsContext)con, (RsType)type, (RsAllocationMipmapControl)mips, (uint32_t)usage, (uintptr_t)pointer);
}
static void
@@ -600,7 +600,7 @@
bitmap.lockPixels();
const void* ptr = bitmap.getPixels();
- jlong id = (jlong)rsAllocationCreateFromBitmap((RsContext)con,
+ jlong id = (jlong)(uintptr_t)rsAllocationCreateFromBitmap((RsContext)con,
(RsType)type, (RsAllocationMipmapControl)mip,
ptr, bitmap.getSize(), usage);
bitmap.unlockPixels();
@@ -616,7 +616,7 @@
bitmap.lockPixels();
const void* ptr = bitmap.getPixels();
- jlong id = (jlong)rsAllocationCreateTyped((RsContext)con,
+ jlong id = (jlong)(uintptr_t)rsAllocationCreateTyped((RsContext)con,
(RsType)type, (RsAllocationMipmapControl)mip,
(uint32_t)usage, (uintptr_t)ptr);
bitmap.unlockPixels();
@@ -632,7 +632,7 @@
bitmap.lockPixels();
const void* ptr = bitmap.getPixels();
- jlong id = (jlong)rsAllocationCubeCreateFromBitmap((RsContext)con,
+ jlong id = (jlong)(uintptr_t)rsAllocationCubeCreateFromBitmap((RsContext)con,
(RsType)type, (RsAllocationMipmapControl)mip,
ptr, bitmap.getSize(), usage);
bitmap.unlockPixels();
@@ -810,7 +810,7 @@
nAllocationGetType(JNIEnv *_env, jobject _this, jlong con, jlong a)
{
LOG_API("nAllocationGetType, con(%p), a(%p)", (RsContext)con, (RsAllocation)a);
- return (jlong) rsaAllocationGetType((RsContext)con, (RsAllocation)a);
+ return (jlong)(uintptr_t) rsaAllocationGetType((RsContext)con, (RsAllocation)a);
}
static void
@@ -828,7 +828,7 @@
Asset* asset = reinterpret_cast<Asset*>(native_asset);
ALOGV("______nFileA3D %p", asset);
- jlong id = (jlong)rsaFileA3DCreateFromMemory((RsContext)con, asset->getBuffer(false), asset->getLength());
+ jlong id = (jlong)(uintptr_t)rsaFileA3DCreateFromMemory((RsContext)con, asset->getBuffer(false), asset->getLength());
return id;
}
@@ -846,7 +846,7 @@
return 0;
}
- jlong id = (jlong)rsaFileA3DCreateFromAsset((RsContext)con, asset);
+ jlong id = (jlong)(uintptr_t)rsaFileA3DCreateFromAsset((RsContext)con, asset);
return id;
}
@@ -854,7 +854,7 @@
nFileA3DCreateFromFile(JNIEnv *_env, jobject _this, jlong con, jstring fileName)
{
AutoJavaStringToUTF8 fileNameUTF(_env, fileName);
- jlong id = (jlong)rsaFileA3DCreateFromFile((RsContext)con, fileNameUTF.c_str());
+ jlong id = (jlong)(uintptr_t)rsaFileA3DCreateFromFile((RsContext)con, fileNameUTF.c_str());
return id;
}
@@ -887,7 +887,7 @@
nFileA3DGetEntryByIndex(JNIEnv *_env, jobject _this, jlong con, jlong fileA3D, jint index)
{
ALOGV("______nFileA3D %p", (RsFile) fileA3D);
- jlong id = (jlong)rsaFileA3DGetEntryByIndex((RsContext)con, (uint32_t)index, (RsFile)fileA3D);
+ jlong id = (jlong)(uintptr_t)rsaFileA3DGetEntryByIndex((RsContext)con, (uint32_t)index, (RsFile)fileA3D);
return id;
}
@@ -898,7 +898,7 @@
jstring fileName, jfloat fontSize, jint dpi)
{
AutoJavaStringToUTF8 fileNameUTF(_env, fileName);
- jlong id = (jlong)rsFontCreateFromFile((RsContext)con,
+ jlong id = (jlong)(uintptr_t)rsFontCreateFromFile((RsContext)con,
fileNameUTF.c_str(), fileNameUTF.length(),
fontSize, dpi);
@@ -912,7 +912,7 @@
Asset* asset = reinterpret_cast<Asset*>(native_asset);
AutoJavaStringToUTF8 nameUTF(_env, name);
- jlong id = (jlong)rsFontCreateFromMemory((RsContext)con,
+ jlong id = (jlong)(uintptr_t)rsFontCreateFromMemory((RsContext)con,
nameUTF.c_str(), nameUTF.length(),
fontSize, dpi,
asset->getBuffer(false), asset->getLength());
@@ -934,7 +934,7 @@
return 0;
}
- jlong id = (jlong)rsFontCreateFromMemory((RsContext)con,
+ jlong id = (jlong)(uintptr_t)rsFontCreateFromMemory((RsContext)con,
str.c_str(), str.length(),
fontSize, dpi,
asset->getBuffer(false), asset->getLength());
@@ -1283,7 +1283,7 @@
//rsScriptCSetText((RsContext)con, (const char *)script_ptr, length);
- ret = (jlong)rsScriptCCreate((RsContext)con,
+ ret = (jlong)(uintptr_t)rsScriptCCreate((RsContext)con,
resNameUTF.c_str(), resNameUTF.length(),
cacheDirUTF.c_str(), cacheDirUTF.length(),
(const char *)script_ptr, length);
@@ -1294,28 +1294,28 @@
_exception ? JNI_ABORT: 0);
}
- return (jlong)ret;
+ return (jlong)(uintptr_t)ret;
}
static jlong
nScriptIntrinsicCreate(JNIEnv *_env, jobject _this, jlong con, jint id, jlong eid)
{
LOG_API("nScriptIntrinsicCreate, con(%p) id(%i) element(%p)", (RsContext)con, id, (void *)eid);
- return (jlong)rsScriptIntrinsicCreate((RsContext)con, id, (RsElement)eid);
+ return (jlong)(uintptr_t)rsScriptIntrinsicCreate((RsContext)con, id, (RsElement)eid);
}
static jlong
nScriptKernelIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot, jint sig)
{
LOG_API("nScriptKernelIDCreate, con(%p) script(%p), slot(%i), sig(%i)", (RsContext)con, (void *)sid, slot, sig);
- return (jlong)rsScriptKernelIDCreate((RsContext)con, (RsScript)sid, slot, sig);
+ return (jlong)(uintptr_t)rsScriptKernelIDCreate((RsContext)con, (RsScript)sid, slot, sig);
}
static jlong
nScriptFieldIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot)
{
LOG_API("nScriptFieldIDCreate, con(%p) script(%p), slot(%i)", (RsContext)con, (void *)sid, slot);
- return (jlong)rsScriptFieldIDCreate((RsContext)con, (RsScript)sid, slot);
+ return (jlong)(uintptr_t)rsScriptFieldIDCreate((RsContext)con, (RsScript)sid, slot);
}
static jlong
@@ -1359,7 +1359,7 @@
typesPtr[i] = (RsType)jTypesPtr[i];
}
- jlong id = (jlong)rsScriptGroupCreate((RsContext)con,
+ jlong id = (jlong)(uintptr_t)rsScriptGroupCreate((RsContext)con,
(RsScriptKernelID *)kernelsPtr, kernelsLen * sizeof(RsScriptKernelID),
(RsScriptKernelID *)srcPtr, srcLen * sizeof(RsScriptKernelID),
(RsScriptKernelID *)dstkPtr, dstkLen * sizeof(RsScriptKernelID),
@@ -1412,7 +1412,7 @@
jint depthFunc)
{
LOG_API("nProgramStoreCreate, con(%p)", (RsContext)con);
- return (jlong)rsProgramStoreCreate((RsContext)con, colorMaskR, colorMaskG, colorMaskB, colorMaskA,
+ return (jlong)(uintptr_t)rsProgramStoreCreate((RsContext)con, colorMaskR, colorMaskG, colorMaskB, colorMaskA,
depthMask, ditherEnable, (RsBlendSrcFunc)srcFunc,
(RsBlendDstFunc)destFunc, (RsDepthFunc)depthFunc);
}
@@ -1461,7 +1461,7 @@
for(int i = 0; i < paramLen; ++i) {
paramPtr[i] = (uintptr_t)jParamPtr[i];
}
- jlong ret = (jlong)rsProgramFragmentCreate((RsContext)con, shaderUTF.c_str(), shaderUTF.length(),
+ jlong ret = (jlong)(uintptr_t)rsProgramFragmentCreate((RsContext)con, shaderUTF.c_str(), shaderUTF.length(),
nameArray, texCount, sizeArray,
paramPtr, paramLen);
@@ -1493,7 +1493,7 @@
paramPtr[i] = (uintptr_t)jParamPtr[i];
}
- jlong ret = (jlong)rsProgramVertexCreate((RsContext)con, shaderUTF.c_str(), shaderUTF.length(),
+ jlong ret = (jlong)(uintptr_t)rsProgramVertexCreate((RsContext)con, shaderUTF.c_str(), shaderUTF.length(),
nameArray, texCount, sizeArray,
paramPtr, paramLen);
@@ -1508,7 +1508,7 @@
nProgramRasterCreate(JNIEnv *_env, jobject _this, jlong con, jboolean pointSprite, jint cull)
{
LOG_API("nProgramRasterCreate, con(%p), pointSprite(%i), cull(%i)", (RsContext)con, pointSprite, cull);
- return (jlong)rsProgramRasterCreate((RsContext)con, pointSprite, (RsCullMode)cull);
+ return (jlong)(uintptr_t)rsProgramRasterCreate((RsContext)con, pointSprite, (RsCullMode)cull);
}
@@ -1557,7 +1557,7 @@
jint wrapS, jint wrapT, jint wrapR, jfloat aniso)
{
LOG_API("nSamplerCreate, con(%p)", (RsContext)con);
- return (jlong)rsSamplerCreate((RsContext)con,
+ return (jlong)(uintptr_t)rsSamplerCreate((RsContext)con,
(RsSamplerValue)magFilter,
(RsSamplerValue)minFilter,
(RsSamplerValue)wrapS,
@@ -1572,7 +1572,7 @@
nPathCreate(JNIEnv *_env, jobject _this, jlong con, jint prim, jboolean isStatic, jlong _vtx, jlong _loop, jfloat q) {
LOG_API("nPathCreate, con(%p)", (RsContext)con);
- jlong id = (jlong)rsPathCreate((RsContext)con, (RsPathPrimitive)prim, isStatic,
+ jlong id = (jlong)(uintptr_t)rsPathCreate((RsContext)con, (RsPathPrimitive)prim, isStatic,
(RsAllocation)_vtx,
(RsAllocation)_loop, q);
return id;
@@ -1600,7 +1600,7 @@
jint primLen = _env->GetArrayLength(_prim);
jint *primPtr = _env->GetIntArrayElements(_prim, NULL);
- jlong id = (jlong)rsMeshCreate((RsContext)con,
+ jlong id = (jlong)(uintptr_t)rsMeshCreate((RsContext)con,
(RsAllocation *)vtxPtr, vtxLen,
(RsAllocation *)idxPtr, idxLen,
(uint32_t *)primPtr, primLen);
@@ -1640,7 +1640,7 @@
rsaMeshGetVertices((RsContext)con, (RsMesh)mesh, allocs, (uint32_t)numVtxIDs);
for(jint i = 0; i < numVtxIDs; i ++) {
- const jlong alloc = (jlong)allocs[i];
+ const jlong alloc = (jlong)(uintptr_t)allocs[i];
_env->SetLongArrayRegion(_ids, i, 1, &alloc);
}
@@ -1658,7 +1658,7 @@
rsaMeshGetIndices((RsContext)con, (RsMesh)mesh, allocs, prims, (uint32_t)numIndices);
for(jint i = 0; i < numIndices; i ++) {
- const jlong alloc = (jlong)allocs[i];
+ const jlong alloc = (jlong)(uintptr_t)allocs[i];
const jint prim = (jint)prims[i];
_env->SetLongArrayRegion(_idxIds, i, 1, &alloc);
_env->SetIntArrayRegion(_primitives, i, 1, &prim);
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index e0f9b9c..2e7b745 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -66,6 +66,7 @@
import android.content.res.TypedArray;
import android.database.ContentObserver;
import android.inputmethodservice.InputMethodService;
+import android.net.Uri;
import android.os.Binder;
import android.os.Environment;
import android.os.Handler;
@@ -392,6 +393,7 @@
private InputMethodInfo[] mIms;
private int[] mSubtypeIds;
private Locale mLastSystemLocale;
+ private boolean mShowImeWithHardKeyboard;
private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor();
private final IPackageManager mIPackageManager;
@@ -407,17 +409,25 @@
Settings.Secure.ENABLED_INPUT_METHODS), false, this);
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE), false, this);
+ resolver.registerContentObserver(Settings.Secure.getUriFor(
+ Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD), false, this);
}
- @Override public void onChange(boolean selfChange) {
+ @Override public void onChange(boolean selfChange, Uri uri) {
+ final Uri showImeUri =
+ Settings.Secure.getUriFor(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);
synchronized (mMethodMap) {
- boolean enabledChanged = false;
- String newEnabled = mSettings.getEnabledInputMethodsStr();
- if (!mLastEnabled.equals(newEnabled)) {
- mLastEnabled = newEnabled;
- enabledChanged = true;
+ if (showImeUri.equals(uri)) {
+ updateKeyboardFromSettingsLocked();
+ } else {
+ boolean enabledChanged = false;
+ String newEnabled = mSettings.getEnabledInputMethodsStr();
+ if (!mLastEnabled.equals(newEnabled)) {
+ mLastEnabled = newEnabled;
+ enabledChanged = true;
+ }
+ updateInputMethodsFromSettingsLocked(enabledChanged);
}
- updateFromSettingsLocked(enabledChanged);
}
}
}
@@ -598,16 +608,14 @@
private class HardKeyboardListener
implements WindowManagerService.OnHardKeyboardStatusChangeListener {
@Override
- public void onHardKeyboardStatusChange(boolean available, boolean enabled) {
- mHandler.sendMessage(mHandler.obtainMessage(
- MSG_HARD_KEYBOARD_SWITCH_CHANGED, available ? 1 : 0, enabled ? 1 : 0));
+ public void onHardKeyboardStatusChange(boolean available) {
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_HARD_KEYBOARD_SWITCH_CHANGED,
+ available ? 1 : 0));
}
- public void handleHardKeyboardStatusChange(boolean available,
- boolean showImeWithHardKeyboard) {
+ public void handleHardKeyboardStatusChange(boolean available) {
if (DEBUG) {
- Slog.w(TAG, "HardKeyboardStatusChanged: available = " + available
- + ", showImeWithHardKeyboard= " + showImeWithHardKeyboard);
+ Slog.w(TAG, "HardKeyboardStatusChanged: available=" + available);
}
synchronized(mMethodMap) {
if (mSwitchingDialog != null && mSwitchingDialogTitleView != null
@@ -1657,6 +1665,11 @@
}
void updateFromSettingsLocked(boolean enabledMayChange) {
+ updateInputMethodsFromSettingsLocked(enabledMayChange);
+ updateKeyboardFromSettingsLocked();
+ }
+
+ void updateInputMethodsFromSettingsLocked(boolean enabledMayChange) {
if (enabledMayChange) {
List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
for (int i=0; i<enabled.size(); i++) {
@@ -1710,6 +1723,18 @@
// TODO: Make sure that mSwitchingController and mSettings are sharing the
// the same enabled IMEs list.
mSwitchingController.resetCircularListLocked(mContext);
+
+ }
+
+ public void updateKeyboardFromSettingsLocked() {
+ mShowImeWithHardKeyboard = mSettings.isShowImeWithHardKeyboardEnabled();
+ if (mSwitchingDialog != null
+ && mSwitchingDialogTitleView != null
+ && mSwitchingDialog.isShowing()) {
+ final Switch hardKeySwitch = (Switch)mSwitchingDialogTitleView.findViewById(
+ com.android.internal.R.id.hard_keyboard_switch);
+ hardKeySwitch.setChecked(mShowImeWithHardKeyboard);
+ }
}
/* package */ void setInputMethodLocked(String id, int subtypeId) {
@@ -2594,8 +2619,7 @@
// --------------------------------------------------------------
case MSG_HARD_KEYBOARD_SWITCH_CHANGED:
- mHardKeyboardListener.handleHardKeyboardStatusChange(
- msg.arg1 == 1, msg.arg2 == 1);
+ mHardKeyboardListener.handleHardKeyboardStatusChange(msg.arg1 == 1);
return true;
}
return false;
@@ -2684,7 +2708,7 @@
if (!map.containsKey(defaultImiId)) {
Slog.w(TAG, "Default IME is uninstalled. Choose new default IME.");
if (chooseNewDefaultIMELocked()) {
- updateFromSettingsLocked(true);
+ updateInputMethodsFromSettingsLocked(true);
}
} else {
// Double check that the default IME is certainly enabled.
@@ -2811,11 +2835,11 @@
? View.VISIBLE : View.GONE);
final Switch hardKeySwitch = (Switch)mSwitchingDialogTitleView.findViewById(
com.android.internal.R.id.hard_keyboard_switch);
- hardKeySwitch.setChecked(mWindowManagerService.isShowImeWithHardKeyboardEnabled());
+ hardKeySwitch.setChecked(mShowImeWithHardKeyboard);
hardKeySwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- mWindowManagerService.setShowImeWithHardKeyboard(isChecked);
+ mSettings.setShowImeWithHardKeyboard(isChecked);
// Ensure that the input method dialog is dismissed when changing
// the hardware keyboard state.
hideInputMethodMenu();
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index e528d57..abacb2d 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -575,6 +575,10 @@
void makeFinishing() {
if (!finishing) {
+ if (this == task.stack.getVisibleBehindActivity()) {
+ // A finishing activity should not remain as visible in the background
+ mStackSupervisor.requestVisibleBehindLocked(this, false);
+ }
finishing = true;
if (stopped) {
clearOptionsLocked();
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 1107139..931f448 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2659,13 +2659,20 @@
}
// A non-top activity is reporting a visibility change.
- if (top.fullscreen || top.state != ActivityState.RESUMED || top.app == null ||
- top.app.thread == null) {
+ if ((visible && (top.fullscreen || top.state != ActivityState.RESUMED)) ||
+ top.app == null || top.app.thread == null) {
// Can't carry out this request.
if (DEBUG_VISIBLE_BEHIND) Slog.d(TAG, "requestVisibleBehind: returning top.fullscreen="
- + top.fullscreen+ " top.state=" + top.state + " top.app=" + top.app +
+ + top.fullscreen + " top.state=" + top.state + " top.app=" + top.app +
" top.app.thread=" + top.app.thread);
return false;
+ } else if (!visible && stack.getVisibleBehindActivity() != r) {
+ // Only the activity set as currently visible behind should actively reset its
+ // visible behind state.
+ if (DEBUG_VISIBLE_BEHIND) Slog.d(TAG, "requestVisibleBehind: returning visible="
+ + visible + " stack.getVisibleBehindActivity()=" +
+ stack.getVisibleBehindActivity() + " r=" + r);
+ return false;
}
stack.setVisibleBehindActivity(visible ? r : null);
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 4c887dd..0dc163b 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -41,12 +41,17 @@
String, Class<?>>();
private static final Map<String, Class<?>> sSystemSettingToTypeMap = new HashMap<
String, Class<?>>();
+ private static final Map<String, Class<?>> sGlobalSettingToTypeMap = new HashMap<
+ String, Class<?>>();
static {
sSecureSettingToTypeMap.put(Settings.Secure.LONG_PRESS_TIMEOUT, int.class);
// add other secure settings here...
sSystemSettingToTypeMap.put(Settings.System.TIME_12_24, String.class);
// add other system settings here...
+
+ sGlobalSettingToTypeMap.put(Settings.Global.DEBUG_VIEW_ATTRIBUTES, int.class);
+ // add other global settings here...
}
private final Bundle mCoreSettings = new Bundle();
@@ -74,6 +79,7 @@
private void sendCoreSettings() {
populateSettings(mCoreSettings, sSecureSettingToTypeMap);
populateSettings(mCoreSettings, sSystemSettingToTypeMap);
+ populateSettings(mCoreSettings, sGlobalSettingToTypeMap);
mActivityManagerService.onCoreSettingsChange(mCoreSettings);
}
@@ -89,6 +95,12 @@
mActivityManagerService.mContext.getContentResolver().registerContentObserver(
uri, false, this);
}
+
+ for (String setting : sGlobalSettingToTypeMap.keySet()) {
+ Uri uri = Settings.Global.getUriFor(setting);
+ mActivityManagerService.mContext.getContentResolver().registerContentObserver(
+ uri, false, this);
+ }
}
private void populateSettings(Bundle snapshot, Map<String, Class<?>> map) {
@@ -101,32 +113,40 @@
final String value;
if (map == sSecureSettingToTypeMap) {
value = Settings.Secure.getString(context.getContentResolver(), setting);
- } else {
+ } else if (map == sSystemSettingToTypeMap) {
value = Settings.System.getString(context.getContentResolver(), setting);
+ } else {
+ value = Settings.Global.getString(context.getContentResolver(), setting);
}
snapshot.putString(setting, value);
} else if (type == int.class) {
final int value;
if (map == sSecureSettingToTypeMap) {
value = Settings.Secure.getInt(context.getContentResolver(), setting);
- } else {
+ } else if (map == sSystemSettingToTypeMap) {
value = Settings.System.getInt(context.getContentResolver(), setting);
+ } else {
+ value = Settings.Global.getInt(context.getContentResolver(), setting);
}
snapshot.putInt(setting, value);
} else if (type == float.class) {
final float value;
if (map == sSecureSettingToTypeMap) {
value = Settings.Secure.getFloat(context.getContentResolver(), setting);
- } else {
+ } else if (map == sSystemSettingToTypeMap) {
value = Settings.System.getFloat(context.getContentResolver(), setting);
+ } else {
+ value = Settings.Global.getFloat(context.getContentResolver(), setting);
}
snapshot.putFloat(setting, value);
} else if (type == long.class) {
final long value;
if (map == sSecureSettingToTypeMap) {
value = Settings.Secure.getLong(context.getContentResolver(), setting);
- } else {
+ } else if (map == sSystemSettingToTypeMap) {
value = Settings.System.getLong(context.getContentResolver(), setting);
+ } else {
+ value = Settings.Global.getLong(context.getContentResolver(), setting);
}
snapshot.putLong(setting, value);
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java b/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java
index 46b2b3e..aed5dcc 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java
@@ -155,7 +155,7 @@
}
/**
- * A mapping between andorid and cec keycode.
+ * A mapping between Android and CEC keycode.
*
* <p>Normal implementation of this looks like
* <pre>
@@ -174,43 +174,28 @@
private static class KeycodeEntry {
private final int mAndroidKeycode;
private final int mCecKeycode;
- private final int mParam;
private final boolean mIsRepeatable;
- private KeycodeEntry(int androidKeycode, int cecKeycode, int param, boolean isRepeatable) {
+ private KeycodeEntry(int androidKeycode, int cecKeycode, boolean isRepeatable) {
mAndroidKeycode = androidKeycode;
mCecKeycode = cecKeycode;
- mParam = param;
mIsRepeatable = isRepeatable;
}
private KeycodeEntry(int androidKeycode, int cecKeycode) {
- this(androidKeycode, cecKeycode, NO_PARAM, true);
+ this(androidKeycode, cecKeycode, true);
}
- private KeycodeEntry(int androidKeycode, int cecKeycode, boolean isRepeatable) {
- this(androidKeycode, cecKeycode, NO_PARAM, isRepeatable);
- }
-
- private byte[] toCecKeycodeIfMatched(int androidKeycode) {
+ private int toCecKeycodeIfMatched(int androidKeycode) {
if (mAndroidKeycode == androidKeycode) {
- if (mParam == NO_PARAM) {
- return new byte[] {
- (byte) (mCecKeycode & 0xFF)
- };
- } else {
- return new byte[] {
- (byte) (mCecKeycode & 0xFF),
- (byte) (mParam & 0xFF)
- };
- }
+ return mCecKeycode;
} else {
- return null;
+ return UNSUPPORTED_KEYCODE;
}
}
- private int toAndroidKeycodeIfMatched(int cecKeycode, int param) {
- if (cecKeycode == mCecKeycode && mParam == param) {
+ private int toAndroidKeycodeIfMatched(int cecKeycode) {
+ if (cecKeycode == mCecKeycode) {
return mAndroidKeycode;
} else {
return UNSUPPORTED_KEYCODE;
@@ -365,29 +350,28 @@
* Translate Android keycode to Hdmi Cec keycode.
*
* @param keycode Android keycode. For details, refer {@link KeyEvent}
- * @return array of byte which contains cec keycode and param if it has;
- * return null if failed to find matched cec keycode
+ * @return single byte CEC keycode if matched.
*/
- static byte[] androidKeyToCecKey(int keycode) {
+ static int androidKeyToCecKey(int keycode) {
for (int i = 0; i < KEYCODE_ENTRIES.length; ++i) {
- byte[] cecKeycode = KEYCODE_ENTRIES[i].toCecKeycodeIfMatched(keycode);
- if (cecKeycode != null) {
+ int cecKeycode = KEYCODE_ENTRIES[i].toCecKeycodeIfMatched(keycode);
+ if (cecKeycode != UNSUPPORTED_KEYCODE) {
return cecKeycode;
}
}
- return null;
+ return UNSUPPORTED_KEYCODE;
}
/**
* Translate Hdmi CEC keycode to Android keycode.
*
- * @param keycode Cec keycode. If has no param, put {@link #NO_PARAM}
+ * @param keycode CEC keycode
* @return cec keycode corresponding to the given android keycode.
* If finds no matched keycode, return {@link #UNSUPPORTED_KEYCODE}
*/
- static int cecKeyToAndroidKey(int keycode, int param) {
+ static int cecKeyToAndroidKey(int keycode) {
for (int i = 0; i < KEYCODE_ENTRIES.length; ++i) {
- int androidKey = KEYCODE_ENTRIES[i].toAndroidKeycodeIfMatched(keycode, param);
+ int androidKey = KEYCODE_ENTRIES[i].toAndroidKeycodeIfMatched(keycode);
if (androidKey != UNSUPPORTED_KEYCODE) {
return androidKey;
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index 4862f93..b43ad1b 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -405,8 +405,9 @@
final long downTime = SystemClock.uptimeMillis();
final byte[] params = message.getParams();
- final int keycode = HdmiCecKeycode.cecKeyToAndroidKey(params[0],
- params.length > 1 ? params[1] : HdmiCecKeycode.NO_PARAM);
+ // Note that we don't support parameterized keycode now.
+ // TODO: translate parameterized keycode as well.
+ final int keycode = HdmiCecKeycode.cecKeyToAndroidKey(params[0]);
int keyRepeatCount = 0;
if (mLastKeycode != HdmiCecKeycode.UNSUPPORTED_KEYCODE) {
if (keycode == mLastKeycode) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 809fef4..126a56d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -1007,10 +1007,8 @@
/**
* Return external input devices.
*/
- List<HdmiDeviceInfo> getSafeExternalInputs() {
- synchronized (mLock) {
- return mSafeExternalInputs;
- }
+ List<HdmiDeviceInfo> getSafeExternalInputsLocked() {
+ return mSafeExternalInputs;
}
@ServiceThreadOnly
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 14c066e..32d97ba 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -16,6 +16,8 @@
package com.android.server.hdmi;
+import static android.hardware.hdmi.HdmiControlManager.DEVICE_EVENT_ADD_DEVICE;
+import static android.hardware.hdmi.HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE;
import static com.android.server.hdmi.Constants.DISABLED;
import static com.android.server.hdmi.Constants.ENABLED;
import static com.android.server.hdmi.Constants.OPTION_CEC_AUTO_WAKEUP;
@@ -202,6 +204,9 @@
@GuardedBy("mLock")
private boolean mMhlInputChangeEnabled;
+ @GuardedBy("mLock")
+ private List<HdmiDeviceInfo> mMhlDevices;
+
// List of listeners registered by callers that want to get notified of
// system audio mode changes.
private final ArrayList<IHdmiSystemAudioModeChangeListener>
@@ -293,6 +298,7 @@
Slog.i(TAG, "Device does not support MHL-control.");
}
initPortInfo();
+ mMhlDevices = Collections.emptyList();
mMessageValidator = new HdmiCecMessageValidator(this);
publishBinderService(Context.HDMI_CONTROL_SERVICE, new BinderService());
@@ -320,7 +326,6 @@
}
}
-
private void registerContentObserver() {
ContentResolver resolver = getContext().getContentResolver();
String[] settings = new String[] {
@@ -330,7 +335,7 @@
Global.MHL_INPUT_SWITCHING_ENABLED,
Global.MHL_POWER_CHARGE_ENABLED
};
- for (String s: settings) {
+ for (String s : settings) {
resolver.registerContentObserver(Global.getUriFor(s), false, mSettingsObserver,
UserHandle.USER_ALL);
}
@@ -684,16 +689,16 @@
/**
* Called when a new hotplug event is issued.
*
- * @param portNo hdmi port number where hot plug event issued.
+ * @param portId hdmi port number where hot plug event issued.
* @param connected whether to be plugged in or not
*/
@ServiceThreadOnly
- void onHotplug(int portNo, boolean connected) {
+ void onHotplug(int portId, boolean connected) {
assertRunOnServiceThread();
for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {
- device.onHotplug(portNo, connected);
+ device.onHotplug(portId, connected);
}
- announceHotplugEvent(portNo, connected);
+ announceHotplugEvent(portId, connected);
}
/**
@@ -794,10 +799,15 @@
HdmiMhlLocalDevice device = mMhlController.removeLocalDevice(portId);
if (device != null) {
device.onDeviceRemoved();
+ // There is no explicit event for device removal unlike capability register event
+ // used for device addition . Hence we remove the device on hotplug event.
+ invokeDeviceEventListeners(device.getInfo(), DEVICE_EVENT_REMOVE_DEVICE);
+ updateSafeMhlInput();
} else {
Slog.w(TAG, "No device to remove:[portId=" + portId);
}
}
+ announceHotplugEvent(portId, connected);
}
@ServiceThreadOnly
@@ -824,18 +834,45 @@
}
@ServiceThreadOnly
- void handleCapabilityRegisterChanged(int portId, int adopterId, int deviceId) {
+ void handleMhlCapabilityRegisterChanged(int portId, int adopterId, int deviceId) {
assertRunOnServiceThread();
HdmiMhlLocalDevice device = mMhlController.getLocalDevice(portId);
- // Hot plug event should be called before capability register change event.
+
+ // Hotplug event should already have been called before capability register change event.
if (device != null) {
device.setCapabilityRegister(adopterId, deviceId);
+ invokeDeviceEventListeners(device.getInfo(), DEVICE_EVENT_ADD_DEVICE);
+ updateSafeMhlInput();
} else {
Slog.w(TAG, "No mhl device exists for capability register change event[portId:"
+ portId + ", adopterId:" + adopterId + ", deviceId:" + deviceId + "]");
}
}
+ @ServiceThreadOnly
+ private void updateSafeMhlInput() {
+ assertRunOnServiceThread();
+ List<HdmiDeviceInfo> inputs = Collections.emptyList();
+ SparseArray<HdmiMhlLocalDevice> devices = mMhlController.getAllLocalDevices();
+ for (int i = 0; i < devices.size(); ++i) {
+ HdmiMhlLocalDevice device = devices.valueAt(i);
+ HdmiDeviceInfo info = device.getInfo();
+ if (info != null) {
+ if (inputs.isEmpty()) {
+ inputs = new ArrayList<>();
+ }
+ inputs.add(device.getInfo());
+ }
+ }
+ synchronized (mLock) {
+ mMhlDevices = inputs;
+ }
+ }
+
+ private List<HdmiDeviceInfo> getMhlDevicesLocked() {
+ return mMhlDevices;
+ }
+
// Record class that monitors the event of the caller of being killed. Used to clean up
// the listener list and record list accordingly.
private final class HotplugEventListenerRecord implements IBinder.DeathRecipient {
@@ -1139,10 +1176,12 @@
// No need to hold the lock for obtaining TV device as the local device instance
// is preserved while the HDMI control is enabled.
HdmiCecLocalDeviceTv tv = tv();
- if (tv == null) {
- return Collections.emptyList();
+ synchronized (mLock) {
+ List<HdmiDeviceInfo> cecDevices = (tv == null)
+ ? Collections.<HdmiDeviceInfo>emptyList()
+ : tv.getSafeExternalInputsLocked();
+ return HdmiUtils.mergeToUnmodifiableList(cecDevices, getMhlDevicesLocked());
}
- return tv.getSafeExternalInputs();
}
@Override
diff --git a/services/core/java/com/android/server/hdmi/HdmiUtils.java b/services/core/java/com/android/server/hdmi/HdmiUtils.java
index 23f19ff..22a519b 100644
--- a/services/core/java/com/android/server/hdmi/HdmiUtils.java
+++ b/services/core/java/com/android/server/hdmi/HdmiUtils.java
@@ -206,6 +206,22 @@
return list;
}
+ static <T> List<T> mergeToUnmodifiableList(List<T> a, List<T> b) {
+ if (a.isEmpty() && b.isEmpty()) {
+ return Collections.emptyList();
+ }
+ if (a.isEmpty()) {
+ return Collections.unmodifiableList(b);
+ }
+ if (b.isEmpty()) {
+ return Collections.unmodifiableList(a);
+ }
+ List<T> newList = new ArrayList<>();
+ newList.addAll(a);
+ newList.addAll(b);
+ return Collections.unmodifiableList(newList);
+ }
+
/**
* See if the new path is affecting the active path.
*
diff --git a/services/core/java/com/android/server/hdmi/SendKeyAction.java b/services/core/java/com/android/server/hdmi/SendKeyAction.java
index 9f09eb4..ed978e0 100644
--- a/services/core/java/com/android/server/hdmi/SendKeyAction.java
+++ b/services/core/java/com/android/server/hdmi/SendKeyAction.java
@@ -109,12 +109,12 @@
}
private void sendKeyDown(int keycode) {
- byte[] keycodeAndParam = getCecKeycodeAndParam(keycode);
- if (keycodeAndParam == null) {
+ int cecKeycode = HdmiCecKeycode.androidKeyToCecKey(keycode);
+ if (cecKeycode == HdmiCecKeycode.UNSUPPORTED_KEYCODE) {
return;
}
sendCommand(HdmiCecMessageBuilder.buildUserControlPressed(getSourceAddress(),
- mTargetAddress, keycodeAndParam));
+ mTargetAddress, new byte[] { (byte) (cecKeycode & 0xFF) }));
}
private void sendKeyUp() {
@@ -141,13 +141,4 @@
sendKeyDown(mLastKeycode);
addTimer(mState, IRT_MS);
}
-
- // Converts the Android key code to corresponding CEC key code definition. Those CEC keys
- // with additional parameters should be mapped from individual Android key code. 'Select
- // Broadcast' with the parameter 'cable', for instance, shall have its counterpart such as
- // KeyEvent.KEYCODE_TV_BROADCAST_CABLE.
- // The return byte array contains both UI command (keycode) and optional parameter.
- private byte[] getCecKeycodeAndParam(int keycode) {
- return HdmiCecKeycode.androidKeyToCecKey(keycode);
- }
}
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index 289b5aa..69d1dc9 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -26,6 +26,8 @@
import android.media.projection.IMediaProjectionManager;
import android.media.projection.IMediaProjection;
import android.media.projection.IMediaProjectionCallback;
+import android.media.projection.IMediaProjectionWatcherCallback;
+import android.media.projection.MediaProjectionInfo;
import android.media.projection.MediaProjectionManager;
import android.os.Binder;
import android.os.Handler;
@@ -34,6 +36,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Slog;
@@ -59,15 +62,20 @@
private static final String TAG = "MediaProjectionManagerService";
private final Object mLock = new Object(); // Protects the list of media projections
- private final Map<IBinder, MediaProjection> mProjectionGrants;
+ private final Map<IBinder, IBinder.DeathRecipient> mDeathEaters;
+ private final CallbackDelegate mCallbackDelegate;
private final Context mContext;
private final AppOpsManager mAppOps;
+ private IBinder mProjectionToken;
+ private MediaProjection mProjectionGrant;
+
public MediaProjectionManagerService(Context context) {
super(context);
mContext = context;
- mProjectionGrants = new ArrayMap<IBinder, MediaProjection>();
+ mDeathEaters = new ArrayMap<IBinder, IBinder.DeathRecipient>();
+ mCallbackDelegate = new CallbackDelegate();
mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
Watchdog.getInstance().addMonitor(this);
}
@@ -83,13 +91,97 @@
synchronized (mLock) { /* check for deadlock */ }
}
+ private void startProjectionLocked(final MediaProjection projection) {
+ if (mProjectionGrant != null) {
+ mProjectionGrant.stop();
+ }
+ mProjectionToken = projection.asBinder();
+ mProjectionGrant = projection;
+ dispatchStart(projection);
+ }
+
+ private void stopProjectionLocked(final MediaProjection projection) {
+ mProjectionToken = null;
+ mProjectionGrant = null;
+ dispatchStop(projection);
+ }
+
+ private void addCallback(final IMediaProjectionWatcherCallback callback) {
+ IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {
+ @Override
+ public void binderDied() {
+ synchronized (mLock) {
+ unlinkDeathRecipientLocked(callback);
+ removeCallback(callback);
+ }
+ }
+ };
+ synchronized (mLock) {
+ mCallbackDelegate.add(callback);
+ linkDeathRecipientLocked(callback, deathRecipient);
+ }
+ }
+
+ private void removeCallback(IMediaProjectionWatcherCallback callback) {
+ synchronized (mLock) {
+ unlinkDeathRecipientLocked(callback);
+ removeCallback(callback);
+ }
+ }
+
+ private void linkDeathRecipientLocked(IMediaProjectionWatcherCallback callback,
+ IBinder.DeathRecipient deathRecipient) {
+ try {
+ final IBinder token = callback.asBinder();
+ token.linkToDeath(deathRecipient, 0);
+ mDeathEaters.put(token, deathRecipient);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to link to death for media projection monitoring callback", e);
+ }
+ }
+
+ private void unlinkDeathRecipientLocked(IMediaProjectionWatcherCallback callback) {
+ final IBinder token = callback.asBinder();
+ IBinder.DeathRecipient deathRecipient = mDeathEaters.remove(token);
+ if (deathRecipient != null) {
+ token.unlinkToDeath(deathRecipient, 0);
+ }
+ }
+
+ private void dispatchStart(MediaProjection projection) {
+ mCallbackDelegate.dispatchStart(projection);
+ }
+
+ private void dispatchStop(MediaProjection projection) {
+ mCallbackDelegate.dispatchStop(projection);
+ }
+
+ private boolean isValidMediaProjection(IBinder token) {
+ synchronized (mLock) {
+ if (mProjectionToken != null) {
+ return mProjectionToken.equals(token);
+ }
+ return false;
+ }
+ }
+
+ private MediaProjectionInfo getActiveProjectionInfo() {
+ synchronized (mLock) {
+ if (mProjectionGrant == null) {
+ return null;
+ }
+ return mProjectionGrant.getProjectionInfo();
+ }
+ }
+
private void dump(final PrintWriter pw) {
pw.println("MEDIA PROJECTION MANAGER (dumpsys media_projection)");
synchronized (mLock) {
- Collection<MediaProjection> projections = mProjectionGrants.values();
- pw.println("Media Projections: size=" + projections.size());
- for (MediaProjection mp : projections) {
- mp.dump(pw, " ");
+ pw.println("Media Projection: ");
+ if (mProjectionGrant != null ) {
+ mProjectionGrant.dump(pw);
+ } else {
+ pw.println("null");
}
}
}
@@ -115,11 +207,14 @@
@Override // Binder call
public IMediaProjection createProjection(int uid, String packageName, int type,
boolean isPermanentGrant) {
- if (mContext.checkCallingPermission(Manifest.permission.CREATE_MEDIA_PROJECTION)
+ if (mContext.checkCallingPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION)
!= PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires CREATE_MEDIA_PROJECTION in order to grant "
+ throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to grant "
+ "projection permission");
}
+ if (packageName == null || packageName.isEmpty()) {
+ throw new IllegalArgumentException("package name must not be empty");
+ }
long callingToken = Binder.clearCallingIdentity();
MediaProjection projection;
try {
@@ -136,7 +231,71 @@
@Override // Binder call
public boolean isValidMediaProjection(IMediaProjection projection) {
- return mProjectionGrants.containsKey(projection.asBinder());
+ return MediaProjectionManagerService.this.isValidMediaProjection(
+ projection.asBinder());
+ }
+
+ @Override // Binder call
+ public MediaProjectionInfo getActiveProjectionInfo() {
+ if (mContext.checkCallingPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to add "
+ + "projection callbacks");
+ }
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return MediaProjectionManagerService.this.getActiveProjectionInfo();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override // Binder call
+ public void stopActiveProjection() {
+ if (mContext.checkCallingPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to add "
+ + "projection callbacks");
+ }
+ final long token = Binder.clearCallingIdentity();
+ try {
+ if (mProjectionGrant != null) {
+ mProjectionGrant.stop();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+
+ }
+
+ @Override //Binder call
+ public void addCallback(final IMediaProjectionWatcherCallback callback) {
+ if (mContext.checkCallingPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to add "
+ + "projection callbacks");
+ }
+ final long token = Binder.clearCallingIdentity();
+ try {
+ MediaProjectionManagerService.this.addCallback(callback);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void removeCallback(IMediaProjectionWatcherCallback callback) {
+ if (mContext.checkCallingPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to remove "
+ + "projection callbacks");
+ }
+ final long token = Binder.clearCallingIdentity();
+ try {
+ MediaProjectionManagerService.this.removeCallback(callback);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override // Binder call
@@ -157,25 +316,27 @@
}
}
+
private boolean checkPermission(String packageName, String permission) {
return mContext.getPackageManager().checkPermission(permission, packageName)
== PackageManager.PERMISSION_GRANTED;
}
}
- private final class MediaProjection extends IMediaProjection.Stub implements DeathRecipient {
- public int uid;
- public String packageName;
+ private final class MediaProjection extends IMediaProjection.Stub {
+ public final int uid;
+ public final String packageName;
+ public final UserHandle userHandle;
private IBinder mToken;
+ private IBinder.DeathRecipient mDeathEater;
private int mType;
- private CallbackDelegate mCallbackDelegate;
public MediaProjection(int type, int uid, String packageName) {
mType = type;
this.uid = uid;
this.packageName = packageName;
- mCallbackDelegate = new CallbackDelegate();
+ userHandle = new UserHandle(UserHandle.getUserId(uid));
}
@Override // Binder call
@@ -220,49 +381,50 @@
}
@Override // Binder call
- public void start(IMediaProjectionCallback callback) {
+ public void start(final IMediaProjectionCallback callback) {
if (callback == null) {
throw new IllegalArgumentException("callback must not be null");
}
synchronized (mLock) {
- if (mProjectionGrants.containsKey(asBinder())) {
+ if (isValidMediaProjection(asBinder())) {
throw new IllegalStateException(
"Cannot start already started MediaProjection");
}
addCallback(callback);
try {
mToken = callback.asBinder();
- mToken.linkToDeath(this, 0);
+ mDeathEater = new IBinder.DeathRecipient() {
+ @Override
+ public void binderDied() {
+ mCallbackDelegate.remove(callback);
+ stop();
+ }
+ };
+ mToken.linkToDeath(mDeathEater, 0);
} catch (RemoteException e) {
Slog.w(TAG,
"MediaProjectionCallbacks must be valid, aborting MediaProjection", e);
return;
}
- mProjectionGrants.put(asBinder(), this);
+ startProjectionLocked(this);
}
}
@Override // Binder call
public void stop() {
synchronized (mLock) {
- if (!mProjectionGrants.containsKey(asBinder())) {
+ if (!isValidMediaProjection(asBinder())) {
Slog.w(TAG, "Attempted to stop inactive MediaProjection "
+ "(uid=" + Binder.getCallingUid() + ", "
+ "pid=" + Binder.getCallingPid() + ")");
return;
}
- mToken.unlinkToDeath(this, 0);
- mCallbackDelegate.dispatchStop();
- mProjectionGrants.remove(asBinder());
+ mToken.unlinkToDeath(mDeathEater, 0);
+ stopProjectionLocked(this);
}
}
@Override
- public void binderDied() {
- stop();
- }
-
- @Override
public void addCallback(IMediaProjectionCallback callback) {
if (callback == null) {
throw new IllegalArgumentException("callback must not be null");
@@ -278,52 +440,143 @@
mCallbackDelegate.remove(callback);
}
- public void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + "(" + packageName + ", uid=" + uid + "): " + typeToString(mType));
+ public MediaProjectionInfo getProjectionInfo() {
+ return new MediaProjectionInfo(packageName, userHandle);
+ }
+
+ public void dump(PrintWriter pw) {
+ pw.println("(" + packageName + ", uid=" + uid + "): " + typeToString(mType));
}
}
+
private static class CallbackDelegate {
- private static final int MSG_ON_STOP = 0;
- private List<IMediaProjectionCallback> mCallbacks;
+ private Map<IBinder, IMediaProjectionCallback> mClientCallbacks;
+ private Map<IBinder, IMediaProjectionWatcherCallback> mWatcherCallbacks;
private Handler mHandler;
private Object mLock = new Object();
public CallbackDelegate() {
mHandler = new Handler(Looper.getMainLooper(), null, true /*async*/);
- mCallbacks = new ArrayList<IMediaProjectionCallback>();
+ mClientCallbacks = new ArrayMap<IBinder, IMediaProjectionCallback>();
+ mWatcherCallbacks = new ArrayMap<IBinder, IMediaProjectionWatcherCallback>();
}
public void add(IMediaProjectionCallback callback) {
synchronized (mLock) {
- mCallbacks.add(callback);
+ mClientCallbacks.put(callback.asBinder(), callback);
+ }
+ }
+
+ public void add(IMediaProjectionWatcherCallback callback) {
+ synchronized (mLock) {
+ mWatcherCallbacks.put(callback.asBinder(), callback);
}
}
public void remove(IMediaProjectionCallback callback) {
synchronized (mLock) {
- mCallbacks.remove(callback);
+ mClientCallbacks.remove(callback.asBinder());
}
}
- public void dispatchStop() {
+ public void remove(IMediaProjectionWatcherCallback callback) {
synchronized (mLock) {
- for (final IMediaProjectionCallback callback : mCallbacks) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- try {
- callback.onStop();
- } catch (RemoteException e) {
- Slog.w(TAG, "Failed to notify media projection has stopped", e);
- }
- }
- });
+ mWatcherCallbacks.remove(callback.asBinder());
+ }
+ }
+
+ public void dispatchStart(MediaProjection projection) {
+ if (projection == null) {
+ Slog.e(TAG, "Tried to dispatch start notification for a null media projection."
+ + " Ignoring!");
+ return;
+ }
+ synchronized (mLock) {
+ for (IMediaProjectionWatcherCallback callback : mWatcherCallbacks.values()) {
+ MediaProjectionInfo info = projection.getProjectionInfo();
+ mHandler.post(new WatcherStartCallback(info, callback));
+ }
+ }
+ }
+
+ public void dispatchStop(MediaProjection projection) {
+ if (projection == null) {
+ Slog.e(TAG, "Tried to dispatch stop notification for a null media projection."
+ + " Ignoring!");
+ return;
+ }
+ synchronized (mLock) {
+ for (IMediaProjectionCallback callback : mClientCallbacks.values()) {
+ mHandler.post(new ClientStopCallback(callback));
+ }
+
+ for (IMediaProjectionWatcherCallback callback : mWatcherCallbacks.values()) {
+ MediaProjectionInfo info = projection.getProjectionInfo();
+ mHandler.post(new WatcherStopCallback(info, callback));
}
}
}
}
+ private static final class WatcherStartCallback implements Runnable {
+ private IMediaProjectionWatcherCallback mCallback;
+ private MediaProjectionInfo mInfo;
+
+ public WatcherStartCallback(MediaProjectionInfo info,
+ IMediaProjectionWatcherCallback callback) {
+ mInfo = info;
+ mCallback = callback;
+ }
+
+ @Override
+ public void run() {
+ try {
+ mCallback.onStart(mInfo);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to notify media projection has stopped", e);
+ }
+ }
+ }
+
+ private static final class WatcherStopCallback implements Runnable {
+ private IMediaProjectionWatcherCallback mCallback;
+ private MediaProjectionInfo mInfo;
+
+ public WatcherStopCallback(MediaProjectionInfo info,
+ IMediaProjectionWatcherCallback callback) {
+ mInfo = info;
+ mCallback = callback;
+ }
+
+ @Override
+ public void run() {
+ try {
+ mCallback.onStop(mInfo);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to notify media projection has stopped", e);
+ }
+ }
+ }
+
+ private static final class ClientStopCallback implements Runnable {
+ private IMediaProjectionCallback mCallback;
+
+ public ClientStopCallback(IMediaProjectionCallback callback) {
+ mCallback = callback;
+ }
+
+ @Override
+ public void run() {
+ try {
+ mCallback.onStop();
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to notify media projection has stopped", e);
+ }
+ }
+ }
+
+
private static String typeToString(int type) {
switch (type) {
case MediaProjectionManager.TYPE_SCREEN_CAPTURE:
diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java
index 907eeb2..857b9e9 100644
--- a/services/core/java/com/android/server/net/IpConfigStore.java
+++ b/services/core/java/com/android/server/net/IpConfigStore.java
@@ -20,10 +20,10 @@
import android.net.IpConfiguration.IpAssignment;
import android.net.IpConfiguration.ProxySettings;
import android.net.LinkAddress;
-import android.net.LinkProperties;
import android.net.NetworkUtils;
import android.net.ProxyInfo;
import android.net.RouteInfo;
+import android.net.StaticIpConfiguration;
import android.os.Handler;
import android.os.HandlerThread;
import android.text.TextUtils;
@@ -41,6 +41,7 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
+import java.net.Inet4Address;
import java.util.Map;
public class IpConfigStore {
@@ -69,40 +70,32 @@
}
private boolean writeConfig(DataOutputStream out, int configKey,
- IpConfiguration config) throws IOException {
+ IpConfiguration config) throws IOException {
boolean written = false;
try {
- LinkProperties linkProperties = config.linkProperties;
switch (config.ipAssignment) {
case STATIC:
out.writeUTF(IP_ASSIGNMENT_KEY);
out.writeUTF(config.ipAssignment.toString());
- for (LinkAddress linkAddr : linkProperties.getLinkAddresses()) {
- out.writeUTF(LINK_ADDRESS_KEY);
- out.writeUTF(linkAddr.getAddress().getHostAddress());
- out.writeInt(linkAddr.getPrefixLength());
- }
- for (RouteInfo route : linkProperties.getRoutes()) {
- out.writeUTF(GATEWAY_KEY);
- LinkAddress dest = route.getDestinationLinkAddress();
- if (dest != null) {
- out.writeInt(1);
- out.writeUTF(dest.getAddress().getHostAddress());
- out.writeInt(dest.getPrefixLength());
- } else {
- out.writeInt(0);
+ StaticIpConfiguration staticIpConfiguration = config.staticIpConfiguration;
+ if (staticIpConfiguration != null) {
+ if (staticIpConfiguration.ipAddress != null) {
+ LinkAddress ipAddress = staticIpConfiguration.ipAddress;
+ out.writeUTF(LINK_ADDRESS_KEY);
+ out.writeUTF(ipAddress.getAddress().getHostAddress());
+ out.writeInt(ipAddress.getPrefixLength());
}
- if (route.getGateway() != null) {
- out.writeInt(1);
- out.writeUTF(route.getGateway().getHostAddress());
- } else {
- out.writeInt(0);
+ if (staticIpConfiguration.gateway != null) {
+ out.writeUTF(GATEWAY_KEY);
+ out.writeInt(0); // Default route.
+ out.writeInt(1); // Have a gateway.
+ out.writeUTF(staticIpConfiguration.gateway.getHostAddress());
}
- }
- for (InetAddress inetAddr : linkProperties.getDnsServers()) {
- out.writeUTF(DNS_KEY);
- out.writeUTF(inetAddr.getHostAddress());
+ for (InetAddress inetAddr : staticIpConfiguration.dnsServers) {
+ out.writeUTF(DNS_KEY);
+ out.writeUTF(inetAddr.getHostAddress());
+ }
}
written = true;
break;
@@ -121,7 +114,7 @@
switch (config.proxySettings) {
case STATIC:
- ProxyInfo proxyProperties = linkProperties.getHttpProxy();
+ ProxyInfo proxyProperties = config.httpProxy;
String exclusionList = proxyProperties.getExclusionListAsString();
out.writeUTF(PROXY_SETTINGS_KEY);
out.writeUTF(config.proxySettings.toString());
@@ -134,7 +127,7 @@
written = true;
break;
case PAC:
- ProxyInfo proxyPacProperties = linkProperties.getHttpProxy();
+ ProxyInfo proxyPacProperties = config.httpProxy;
out.writeUTF(PROXY_SETTINGS_KEY);
out.writeUTF(config.proxySettings.toString());
out.writeUTF(PROXY_PAC_FILE);
@@ -159,7 +152,7 @@
out.writeInt(configKey);
}
} catch (NullPointerException e) {
- loge("Failure in writing " + config.linkProperties + e);
+ loge("Failure in writing " + config + e);
}
out.writeUTF(EOS);
@@ -196,7 +189,7 @@
// Default is DHCP with no proxy
IpAssignment ipAssignment = IpAssignment.DHCP;
ProxySettings proxySettings = ProxySettings.NONE;
- LinkProperties linkProperties = new LinkProperties();
+ StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration();
String proxyHost = null;
String pacFileUrl = null;
int proxyPort = -1;
@@ -213,13 +206,23 @@
} else if (key.equals(LINK_ADDRESS_KEY)) {
LinkAddress linkAddr = new LinkAddress(
NetworkUtils.numericToInetAddress(in.readUTF()), in.readInt());
- linkProperties.addLinkAddress(linkAddr);
+ if (linkAddr.getAddress() instanceof Inet4Address &&
+ staticIpConfiguration.ipAddress == null) {
+ staticIpConfiguration.ipAddress = linkAddr;
+ } else {
+ loge("Non-IPv4 or duplicate address: " + linkAddr);
+ }
} else if (key.equals(GATEWAY_KEY)) {
LinkAddress dest = null;
InetAddress gateway = null;
if (version == 1) {
// only supported default gateways - leave the dest/prefix empty
gateway = NetworkUtils.numericToInetAddress(in.readUTF());
+ if (staticIpConfiguration.gateway == null) {
+ staticIpConfiguration.gateway = gateway;
+ } else {
+ loge("Duplicate gateway: " + gateway.getHostAddress());
+ }
} else {
if (in.readInt() == 1) {
dest = new LinkAddress(
@@ -229,10 +232,16 @@
if (in.readInt() == 1) {
gateway = NetworkUtils.numericToInetAddress(in.readUTF());
}
+ RouteInfo route = new RouteInfo(dest, gateway);
+ if (route.isIPv4Default() &&
+ staticIpConfiguration.gateway == null) {
+ staticIpConfiguration.gateway = gateway;
+ } else {
+ loge("Non-IPv4 default or duplicate route: " + route);
+ }
}
- linkProperties.addRoute(new RouteInfo(dest, gateway));
} else if (key.equals(DNS_KEY)) {
- linkProperties.addDnsServer(
+ staticIpConfiguration.dnsServers.add(
NetworkUtils.numericToInetAddress(in.readUTF()));
} else if (key.equals(PROXY_SETTINGS_KEY)) {
proxySettings = ProxySettings.valueOf(in.readUTF());
@@ -258,9 +267,11 @@
IpConfiguration config = new IpConfiguration();
networks.put(id, config);
- config.linkProperties = linkProperties;
switch (ipAssignment) {
case STATIC:
+ config.staticIpConfiguration = staticIpConfiguration;
+ config.ipAssignment = ipAssignment;
+ break;
case DHCP:
config.ipAssignment = ipAssignment;
break;
@@ -276,16 +287,15 @@
switch (proxySettings) {
case STATIC:
- config.proxySettings = proxySettings;
- ProxyInfo ProxyInfo =
+ ProxyInfo proxyInfo =
new ProxyInfo(proxyHost, proxyPort, exclusionList);
- linkProperties.setHttpProxy(ProxyInfo);
+ config.proxySettings = proxySettings;
+ config.httpProxy = proxyInfo;
break;
case PAC:
+ ProxyInfo proxyPacProperties = new ProxyInfo(pacFileUrl);
config.proxySettings = proxySettings;
- ProxyInfo proxyPacProperties =
- new ProxyInfo(pacFileUrl);
- linkProperties.setHttpProxy(proxyPacProperties);
+ config.httpProxy = proxyPacProperties;
break;
case NONE:
config.proxySettings = proxySettings;
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index 1b59f52..97f0a1e 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -16,8 +16,6 @@
package com.android.server.notification;
-import android.os.IBinder;
-
public interface NotificationDelegate {
void onSetDisabled(int status);
void onClearAll(int callingUid, int callingPid, int userId);
@@ -29,7 +27,6 @@
int uid, int initialPid, String message, int userId);
void onPanelRevealed();
void onPanelHidden();
- boolean allowDisable(int what, IBinder token, String pkg);
void onNotificationVisibilityChanged(
String[] newlyVisibleKeys, String[] noLongerVisibleKeys);
void onNotificationExpansionChanged(String key, boolean userAction, boolean expanded);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index f2ac963..7117933 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -29,7 +29,6 @@
import android.app.INotificationManager;
import android.app.ITransientNotification;
import android.app.Notification;
-import android.app.Notification.Builder;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
@@ -50,7 +49,6 @@
import android.media.IRingtonePlayer;
import android.net.Uri;
import android.os.Binder;
-import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
@@ -585,11 +583,6 @@
}
@Override
- public boolean allowDisable(int what, IBinder token, String pkg) {
- return mZenModeHelper.allowDisable(what, token, pkg);
- }
-
- @Override
public void onNotificationVisibilityChanged(
String[] newlyVisibleKeys, String[] noLongerVisibleKeys) {
// Using ';' as separator since eventlogs uses ',' to separate
diff --git a/services/core/java/com/android/server/notification/ZenLog.java b/services/core/java/com/android/server/notification/ZenLog.java
index 525f5f8..f84409e 100644
--- a/services/core/java/com/android/server/notification/ZenLog.java
+++ b/services/core/java/com/android/server/notification/ZenLog.java
@@ -30,10 +30,7 @@
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
-import java.util.Arrays;
import java.util.Date;
-import java.util.HashSet;
-import java.util.Set;
public class ZenLog {
private static final String TAG = "ZenLog";
@@ -45,10 +42,6 @@
private static final String[] MSGS = new String[SIZE];
private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
- private static final Set<String> SYSTEM_PACKAGES = new HashSet<String>(Arrays.asList(
- "android",
- "com.android.systemui"
- ));
private static final int TYPE_INTERCEPTED = 1;
private static final int TYPE_ALLOW_DISABLE = 2;
@@ -76,11 +69,6 @@
append(TYPE_NOT_INTERCEPTED, record.getKey() + "," + reason);
}
- public static void traceAllowDisable(String pkg, boolean allowDisable, String reason) {
- if (SYSTEM_PACKAGES.contains(pkg)) return;
- append(TYPE_ALLOW_DISABLE, allowDisable + "," + pkg + "," + reason);
- }
-
public static void traceSetRingerMode(int ringerMode) {
append(TYPE_SET_RINGER_MODE, ringerModeToString(ringerMode));
}
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 758f334..0b93690 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -35,7 +35,6 @@
import android.media.AudioManager;
import android.net.Uri;
import android.os.Handler;
-import android.os.IBinder;
import android.os.UserHandle;
import android.provider.Settings.Global;
import android.provider.Settings.Secure;
@@ -265,18 +264,6 @@
dispatchOnZenModeChanged();
}
- public boolean allowDisable(int what, IBinder token, String pkg) {
- // TODO(cwren): delete this API before the next release. Bug:15344099
- boolean allowDisable = true;
- String reason = null;
- if (isDefaultPhoneApp(pkg)) {
- allowDisable = mZenMode == Global.ZEN_MODE_OFF || mConfig.allowCalls;
- reason = mZenMode == Global.ZEN_MODE_OFF ? "zenOff" : "allowCalls";
- }
- ZenLog.traceAllowDisable(pkg, allowDisable, reason);
- return allowDisable;
- }
-
public void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("mZenMode=");
pw.println(Global.zenModeToString(mZenMode));
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 51559aa..f47e64f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3292,6 +3292,7 @@
intent, resolvedType, flags, userId);
if (resolveInfo != null) {
result.add(resolveInfo);
+ Collections.sort(result, mResolvePrioritySorter);
}
return result;
}
@@ -11575,18 +11576,20 @@
}
}
- if (DEBUG_PREFERRED) {
- Slog.i(TAG, existing.size() + " existing preferred matches for:");
- filter.dump(new LogPrinter(Log.INFO, TAG), " ");
- }
- for (int i = 0; i < existing.size(); i++) {
- PreferredActivity pa = existing.get(i);
+ if (existing != null) {
if (DEBUG_PREFERRED) {
- Slog.i(TAG, "Removing existing preferred activity "
- + pa.mPref.mComponent + ":");
- pa.dump(new LogPrinter(Log.INFO, TAG), " ");
+ Slog.i(TAG, existing.size() + " existing preferred matches for:");
+ filter.dump(new LogPrinter(Log.INFO, TAG), " ");
}
- pir.removeFilter(pa);
+ for (int i = 0; i < existing.size(); i++) {
+ PreferredActivity pa = existing.get(i);
+ if (DEBUG_PREFERRED) {
+ Slog.i(TAG, "Removing existing preferred activity "
+ + pa.mPref.mComponent + ":");
+ pa.dump(new LogPrinter(Log.INFO, TAG), " ");
+ }
+ pir.removeFilter(pa);
+ }
}
}
addPreferredActivityInternal(filter, match, set, activity, true, userId,
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 297dacf..f85e2d9 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -22,7 +22,6 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.service.notification.StatusBarNotification;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
@@ -39,9 +38,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
/**
@@ -187,10 +184,6 @@
@Override
public void disable(int what, IBinder token, String pkg) {
- if (!mNotificationDelegate.allowDisable(what, token, pkg)) {
- if (SPEW) Slog.d(TAG, "Blocking disable request from " + pkg);
- return;
- }
disableInternal(mCurrentUserId, what, token, pkg);
}
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 88ce860..a084cab 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -691,6 +691,10 @@
private void releaseSessionLocked(IBinder sessionToken, int callingUid, int userId) {
SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userId);
if (sessionState.mSession != null) {
+ UserState userState = getUserStateLocked(userId);
+ if (sessionToken == userState.mainSessionToken) {
+ setMainLocked(sessionToken, false, callingUid, userId);
+ }
try {
sessionState.mSession.release();
} catch (RemoteException e) {
@@ -704,6 +708,9 @@
private void removeSessionStateLocked(IBinder sessionToken, int userId) {
UserState userState = getUserStateLocked(userId);
if (sessionToken == userState.mainSessionToken) {
+ if (DEBUG) {
+ Slog.d(TAG, "mainSessionToken=null");
+ }
userState.mainSessionToken = null;
}
@@ -740,6 +747,25 @@
mWatchLogHandler.obtainMessage(WatchLogHandler.MSG_LOG_WATCH_END, args).sendToTarget();
}
+ private void setMainLocked(IBinder sessionToken, boolean isMain, int callingUid, int userId) {
+ SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userId);
+ if (sessionState.mHardwareSessionToken != null) {
+ sessionState = getSessionStateLocked(sessionState.mHardwareSessionToken,
+ Process.SYSTEM_UID, userId);
+ }
+ ServiceState serviceState = getServiceStateLocked(sessionState.mInfo.getComponent(),
+ userId);
+ if (!serviceState.mIsHardware) {
+ return;
+ }
+ ITvInputSession session = getSessionLocked(sessionState);
+ try {
+ session.setMain(isMain);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "error in setMain", e);
+ }
+ }
+
private void notifyInputAddedLocked(UserState userState, String inputId) {
if (DEBUG) {
Slog.d(TAG, "notifyInputAdded: inputId = " + inputId);
@@ -1050,6 +1076,9 @@
@Override
public void releaseSession(IBinder sessionToken, int userId) {
+ if (DEBUG) {
+ Slog.d(TAG, "releaseSession(): " + sessionToken);
+ }
final int callingUid = Binder.getCallingUid();
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
userId, "releaseSession");
@@ -1065,6 +1094,9 @@
@Override
public void setMainSession(IBinder sessionToken, int userId) {
+ if (DEBUG) {
+ Slog.d(TAG, "setMainSession(): " + sessionToken);
+ }
final int callingUid = Binder.getCallingUid();
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
userId, "setMainSession");
@@ -1075,50 +1107,19 @@
if (userState.mainSessionToken == sessionToken) {
return;
}
-
- SessionState newMainSessionState = getSessionStateLocked(
- sessionToken, callingUid, resolvedUserId);
- if (newMainSessionState.mHardwareSessionToken != null) {
- newMainSessionState = getSessionStateLocked(
- newMainSessionState.mHardwareSessionToken,
- Process.SYSTEM_UID, resolvedUserId);
+ if (DEBUG) {
+ Slog.d(TAG, "mainSessionToken=" + sessionToken);
}
- ServiceState newMainServiceState = getServiceStateLocked(
- newMainSessionState.mInfo.getComponent(), resolvedUserId);
- ITvInputSession newMainSession = getSessionLocked(newMainSessionState);
-
- ServiceState oldMainServiceState = null;
- ITvInputSession oldMainSession = null;
- if (userState.mainSessionToken != null) {
- SessionState oldMainSessionState = getSessionStateLocked(
- userState.mainSessionToken, Process.SYSTEM_UID, resolvedUserId);
- if (oldMainSessionState.mHardwareSessionToken != null) {
- oldMainSessionState = getSessionStateLocked(
- oldMainSessionState.mHardwareSessionToken,
- Process.SYSTEM_UID, resolvedUserId);
- }
- oldMainServiceState = getServiceStateLocked(
- oldMainSessionState.mInfo.getComponent(), resolvedUserId);
- oldMainSession = getSessionLocked(oldMainSessionState);
- }
-
+ IBinder oldMainSessionToken = userState.mainSessionToken;
userState.mainSessionToken = sessionToken;
// Inform the new main session first.
- // See {@link TvInputService#onSetMainSession}.
- if (newMainServiceState.mIsHardware) {
- try {
- newMainSession.setMainSession(true);
- } catch (RemoteException e) {
- Slog.e(TAG, "error in setMainSession", e);
- }
+ // See {@link TvInputService.Session#onSetMain}.
+ if (sessionToken != null) {
+ setMainLocked(sessionToken, true, callingUid, userId);
}
- if (oldMainSession != null && oldMainServiceState.mIsHardware) {
- try {
- oldMainSession.setMainSession(false);
- } catch (RemoteException e) {
- Slog.e(TAG, "error in setMainSession", e);
- }
+ if (oldMainSessionToken != null) {
+ setMainLocked(oldMainSessionToken, false, Process.SYSTEM_UID, userId);
}
}
} finally {
@@ -1800,11 +1801,8 @@
UserState userState = getUserStateLocked(mUserId);
for (SessionState sessionState : userState.sessionStateMap.values()) {
if (mSessionToken == sessionState.mHardwareSessionToken) {
- try {
- sessionState.mSession.release();
- } catch (RemoteException e) {
- Slog.e(TAG, "error in release", e);
- }
+ releaseSessionLocked(sessionState.mSessionToken, Process.SYSTEM_UID,
+ mUserId);
try {
sessionState.mClient.onSessionReleased(sessionState.mSeq);
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index aa20892..b57a090 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -51,6 +51,7 @@
import android.app.admin.DevicePolicyManager;
import android.animation.ValueAnimator;
import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -58,6 +59,7 @@
import android.content.pm.PackageManager;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
+import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
@@ -539,6 +541,21 @@
boolean mHardKeyboardAvailable;
boolean mShowImeWithHardKeyboard;
OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
+ SettingsObserver mSettingsObserver;
+
+ private final class SettingsObserver extends ContentObserver {
+ public SettingsObserver() {
+ super(new Handler());
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.registerContentObserver(Settings.Secure.getUriFor(
+ Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD), false, this);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ updateShowImeWithHardKeyboard();
+ }
+ }
final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
@@ -838,6 +855,9 @@
filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
mContext.registerReceiver(mBroadcastReceiver, filter);
+ mSettingsObserver = new SettingsObserver();
+ updateShowImeWithHardKeyboard();
+
mHoldingScreenWakeLock = mPowerManager.newWakeLock(
PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG);
mHoldingScreenWakeLock.setReferenceCounted(false);
@@ -7018,7 +7038,6 @@
boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
if (hardKeyboardAvailable != mHardKeyboardAvailable) {
mHardKeyboardAvailable = hardKeyboardAvailable;
- mShowImeWithHardKeyboard = !hardKeyboardAvailable;
mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
}
@@ -7042,18 +7061,12 @@
}
}
- public boolean isShowImeWithHardKeyboardEnabled() {
+ public void updateShowImeWithHardKeyboard() {
+ boolean showImeWithHardKeyboard = Settings.Secure.getIntForUser(
+ mContext.getContentResolver(), Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0,
+ mCurrentUserId) == 1;
synchronized (mWindowMap) {
- return mShowImeWithHardKeyboard;
- }
- }
-
- public void setShowImeWithHardKeyboard(boolean enabled) {
- synchronized (mWindowMap) {
- if (mShowImeWithHardKeyboard != enabled) {
- mShowImeWithHardKeyboard = enabled;
- mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
- }
+ mShowImeWithHardKeyboard = showImeWithHardKeyboard;
}
}
@@ -7065,15 +7078,14 @@
}
void notifyHardKeyboardStatusChange() {
- final boolean available, showImeWithHardKeyboard;
+ final boolean available;
final OnHardKeyboardStatusChangeListener listener;
synchronized (mWindowMap) {
listener = mHardKeyboardStatusChangeListener;
available = mHardKeyboardAvailable;
- showImeWithHardKeyboard = mShowImeWithHardKeyboard;
}
if (listener != null) {
- listener.onHardKeyboardStatusChange(available, showImeWithHardKeyboard);
+ listener.onHardKeyboardStatusChange(available);
}
}
@@ -11056,7 +11068,7 @@
}
public interface OnHardKeyboardStatusChangeListener {
- public void onHardKeyboardStatusChange(boolean available, boolean showIme);
+ public void onHardKeyboardStatusChange(boolean available);
}
void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java
index 27debde..c1d5715 100644
--- a/telecomm/java/android/telecomm/Connection.java
+++ b/telecomm/java/android/telecomm/Connection.java
@@ -36,6 +36,15 @@
/**
* Represents a connection to a remote endpoint that carries voice traffic.
+ * <p>
+ * Implementations create a custom subclass of {@code Connection} and return it to the framework
+ * as the return value of
+ * {@link ConnectionService#onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)}
+ * or
+ * {@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
+ * Implementations are then responsible for updating the state of the {@code Connection}, and
+ * must call {@link #destroy()} to signal to the framework that the {@code Connection} is no
+ * longer used and associated resources may be recovered.
*/
public abstract class Connection {
@@ -53,10 +62,6 @@
public static final int STATE_DISCONNECTED = 6;
- public static final int STATE_FAILED = 7;
-
- public static final int STATE_CANCELED = 8;
-
// Flag controlling whether PII is emitted into the logs
private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
@@ -644,10 +649,6 @@
return "STATE_HOLDING";
case STATE_DISCONNECTED:
return "DISCONNECTED";
- case STATE_FAILED:
- return "STATE_FAILED";
- case STATE_CANCELED:
- return "STATE_CANCELED";
default:
Log.wtf(Connection.class, "Unknown state %d", state);
return "UNKNOWN";
@@ -694,33 +695,6 @@
}
/**
- * Cancel the {@link Connection}. Once this is called, the {@link Connection} will not be used,
- * and no subsequent {@link Connection}s will be attempted.
- */
- public final void setCanceled() {
- Log.d(this, "setCanceled");
- setState(STATE_CANCELED);
- }
-
- /**
- * Move the {@link Connection} to the {@link #STATE_FAILED} state, with the given code
- * ({@see DisconnectCause}) and message. This message is not shown to the user, but is useful
- * for logging and debugging purposes.
- * <p>
- * After calling this, the {@link Connection} will not be used.
- *
- * @param code The {@link DisconnectCause} indicating why the connection
- * failed.
- * @param message A message explaining why the {@link Connection} failed.
- */
- public final void setFailed(int code, String message) {
- Log.d(this, "setFailed (%d: %s)", code, message);
- mFailureCode = code;
- mFailureMessage = message;
- setState(STATE_FAILED);
- }
-
- /**
* Set the video state for the connection.
* Valid values: {@link VideoProfile.VideoState#AUDIO_ONLY},
* {@link VideoProfile.VideoState#BIDIRECTIONAL},
@@ -1094,9 +1068,8 @@
}
private void setState(int state) {
- if (mState == STATE_FAILED || mState == STATE_CANCELED) {
- Log.d(this, "Connection already %s; cannot transition out of this state.",
- stateToString(mState));
+ if (mState == STATE_DISCONNECTED && mState != state) {
+ Log.d(this, "Connection already DISCONNECTED; cannot transition out of this state.");
return;
}
if (mState != state) {
@@ -1109,33 +1082,41 @@
}
}
+ static class FailureSignalingConnection extends Connection {
+ public FailureSignalingConnection(int code, String message) {
+ setDisconnected(code, message);
+ }
+ }
+
/**
- * Return a {@link Connection} which represents a failed connection attempt. The returned
- * {@link Connection} will have {@link #getFailureCode()}, {@link #getFailureMessage()}, and
- * {@link #getState()} set appropriately, but the {@link Connection} itself should not be used
- * for anything.
+ * Return a {@code Connection} which represents a failed connection attempt. The returned
+ * {@code Connection} will have a {@link #getFailureCode()} and {@link #getFailureMessage()}
+ * as specified, a {@link #getState()} of {@link #STATE_DISCONNECTED}.
+ * <p>
+ * The returned {@code Connection} can be assumed to {@link #destroy()} itself when appropriate,
+ * so users of this method need not maintain a reference to its return value to destroy it.
*
* @param code The failure code ({@see DisconnectCause}).
* @param message A reason for why the connection failed (not intended to be shown to the user).
- * @return A {@link Connection} which indicates failure.
+ * @return A {@code Connection} which indicates failure.
*/
public static Connection createFailedConnection(final int code, final String message) {
- return new Connection() {{
- setFailed(code, message);
- }};
+ return new FailureSignalingConnection(code, message);
}
- private static final Connection CANCELED_CONNECTION = new Connection() {{
- setCanceled();
- }};
+ private static final Connection CANCELED_CONNECTION =
+ new FailureSignalingConnection(DisconnectCause.OUTGOING_CANCELED, null);
/**
- * Return a {@link Connection} which represents a canceled a connection attempt. The returned
- * {@link Connection} will have state {@link #STATE_CANCELED}, and cannot be moved out of that
- * state. This connection should not be used for anything, and no other {@link Connection}s
- * should be attempted.
+ * Return a {@code Connection} which represents a canceled connection attempt. The returned
+ * {@code Connection} will have state {@link #STATE_DISCONNECTED}, and cannot be moved out of
+ * that state. This connection should not be used for anything, and no other
+ * {@code Connection}s should be attempted.
+ * <p>
+ * The returned {@code Connection} can be assumed to {@link #destroy()} itself when appropriate,
+ * so users of this method need not maintain a reference to its return value to destroy it.
*
- * @return A {@link Connection} which indicates that the underlying call should be canceled.
+ * @return A {@code Connection} which indicates that the underlying call should be canceled.
*/
public static Connection createCanceledConnection() {
return CANCELED_CONNECTION;
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index 97a3102..03b6c7b 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -500,81 +500,26 @@
boolean isIncoming) {
Log.d(this, "call %s", request);
- final Connection createdConnection;
- if (isIncoming) {
- createdConnection = onCreateIncomingConnection(callManagerAccount, request);
- } else {
- createdConnection = onCreateOutgoingConnection(callManagerAccount, request);
- }
+ Connection createdConnection = isIncoming
+ ? onCreateIncomingConnection(callManagerAccount, request)
+ : onCreateOutgoingConnection(callManagerAccount, request);
- if (createdConnection != null) {
- Log.d(this, "adapter handleCreateConnectionSuccessful %s", callId);
- if (createdConnection.getState() == Connection.STATE_INITIALIZING) {
- // Wait for the connection to become initialized.
- createdConnection.addConnectionListener(new Connection.Listener() {
- @Override
- public void onStateChanged(Connection c, int state) {
- switch (state) {
- case Connection.STATE_FAILED:
- Log.d(this, "Connection (%s) failed (%d: %s)", request,
- c.getFailureCode(), c.getFailureMessage());
- Log.d(this, "adapter handleCreateConnectionFailed %s",
- callId);
- mAdapter.handleCreateConnectionFailed(
- callId,
- request,
- c.getFailureCode(),
- c.getFailureMessage());
- break;
- case Connection.STATE_CANCELED:
- Log.d(this, "adapter handleCreateConnectionCanceled %s",
- callId);
- mAdapter.handleCreateConnectionCancelled(callId, request);
- break;
- case Connection.STATE_INITIALIZING:
- Log.d(this, "State changed to STATE_INITIALIZING; ignoring");
- return; // Don't want to stop listening on this state transition.
- }
- c.removeConnectionListener(this);
- }
-
- @Override
- public void onDestroyed(Connection c) {
- // Listen to onDestroy in case the connection is destroyed before
- // transitioning to another state.
- c.removeConnectionListener(this);
- }
- });
- Log.d(this, "Connection created in state INITIALIZING");
- connectionCreated(callId, request, createdConnection);
- } else if (createdConnection.getState() == Connection.STATE_CANCELED) {
- // Tell telecomm not to attempt any more services.
- mAdapter.handleCreateConnectionCancelled(callId, request);
- } else if (createdConnection.getState() == Connection.STATE_FAILED) {
- mAdapter.handleCreateConnectionFailed(
- callId,
- request,
- createdConnection.getFailureCode(),
- createdConnection.getFailureMessage());
- } else {
- connectionCreated(callId, request, createdConnection);
- }
- } else {
+ if (createdConnection == null) {
+ Log.d(this, "adapter handleCreateConnectionComplete CANCELED %s", callId);
// Tell telecomm to try a different service.
- Log.d(this, "adapter handleCreateConnectionFailed %s", callId);
- mAdapter.handleCreateConnectionFailed(
- callId,
- request,
- DisconnectCause.ERROR_UNSPECIFIED,
- null);
+ createdConnection = Connection.createCanceledConnection();
}
+ connectionCreated(callId, request, createdConnection);
}
private void connectionCreated(
String callId,
ConnectionRequest request,
Connection connection) {
- addConnection(callId, connection);
+ if (!(connection instanceof Connection.FailureSignalingConnection)) {
+ addConnection(callId, connection);
+ }
+
Uri handle = connection.getHandle();
String number = handle == null ? "null" : handle.getSchemeSpecificPart();
Log.v(this, "connectionCreated, parcelableconnection: %s, %d, %s",
@@ -583,7 +528,7 @@
PhoneCapabilities.toString(connection.getCallCapabilities()));
Log.d(this, "adapter handleCreateConnectionSuccessful %s", callId);
- mAdapter.handleCreateConnectionSuccessful(
+ mAdapter.handleCreateConnectionComplete(
callId,
request,
new ParcelableConnection(
@@ -599,7 +544,9 @@
connection.getVideoState(),
connection.isRequestingRingback(),
connection.getAudioModeIsVoip(),
- connection.getStatusHints()));
+ connection.getStatusHints(),
+ connection.getFailureCode(),
+ connection.getFailureMessage()));
}
private void abort(String callId) {
@@ -699,7 +646,8 @@
final List<ComponentName> componentNames,
final List<IBinder> services) {
mHandler.post(new Runnable() {
- @Override public void run() {
+ @Override
+ public void run() {
for (int i = 0; i < componentNames.size() && i < services.size(); i++) {
mRemoteConnectionManager.addConnectionService(
componentNames.get(i),
@@ -714,7 +662,8 @@
@Override
public void onError() {
mHandler.post(new Runnable() {
- @Override public void run() {
+ @Override
+ public void run() {
mAreAccountsInitialized = true;
}
});
diff --git a/telecomm/java/android/telecomm/ConnectionServiceAdapter.java b/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
index 0188e62..41c6360 100644
--- a/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
@@ -76,37 +76,13 @@
}
}
- void handleCreateConnectionSuccessful(
+ void handleCreateConnectionComplete(
String id,
ConnectionRequest request,
ParcelableConnection connection) {
for (IConnectionServiceAdapter adapter : mAdapters) {
try {
- adapter.handleCreateConnectionSuccessful(id, request, connection);
- } catch (RemoteException e) {
- }
- }
- }
-
- void handleCreateConnectionFailed(
- String id,
- ConnectionRequest request,
- int errorCode,
- String errorMsg) {
- for (IConnectionServiceAdapter adapter : mAdapters) {
- try {
- adapter.handleCreateConnectionFailed(id, request, errorCode, errorMsg);
- } catch (RemoteException e) {
- }
- }
- }
-
- void handleCreateConnectionCancelled(
- String id,
- ConnectionRequest request) {
- for (IConnectionServiceAdapter adapter : mAdapters) {
- try {
- adapter.handleCreateConnectionCancelled(id, request);
+ adapter.handleCreateConnectionComplete(id, request, connection);
} catch (RemoteException e) {
}
}
diff --git a/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java
index 2654ace..0e1c516 100644
--- a/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java
@@ -38,29 +38,27 @@
* @hide
*/
final class ConnectionServiceAdapterServant {
- private static final int MSG_HANDLE_CREATE_CONNECTION_SUCCESSFUL = 1;
- private static final int MSG_HANDLE_CREATE_CONNECTION_FAILED = 2;
- private static final int MSG_HANDLE_CREATE_CONNECTION_CANCELLED = 3;
- private static final int MSG_SET_ACTIVE = 4;
- private static final int MSG_SET_RINGING = 5;
- private static final int MSG_SET_DIALING = 6;
- private static final int MSG_SET_DISCONNECTED = 7;
- private static final int MSG_SET_ON_HOLD = 8;
- private static final int MSG_SET_REQUESTING_RINGBACK = 9;
- private static final int MSG_SET_CALL_CAPABILITIES = 10;
- private static final int MSG_SET_IS_CONFERENCED = 11;
- private static final int MSG_ADD_CONFERENCE_CALL = 12;
- private static final int MSG_REMOVE_CALL = 13;
- private static final int MSG_ON_POST_DIAL_WAIT = 14;
- private static final int MSG_QUERY_REMOTE_CALL_SERVICES = 15;
- private static final int MSG_SET_VIDEO_STATE = 16;
- private static final int MSG_SET_VIDEO_CALL_PROVIDER = 17;
- private static final int MSG_SET_AUDIO_MODE_IS_VOIP = 18;
- private static final int MSG_SET_STATUS_HINTS = 19;
- private static final int MSG_SET_HANDLE = 20;
- private static final int MSG_SET_CALLER_DISPLAY_NAME = 21;
- private static final int MSG_START_ACTIVITY_FROM_IN_CALL = 22;
- private static final int MSG_SET_CONFERENCEABLE_CONNECTIONS = 23;
+ private static final int MSG_HANDLE_CREATE_CONNECTION_COMPLETE = 1;
+ private static final int MSG_SET_ACTIVE = 2;
+ private static final int MSG_SET_RINGING = 3;
+ private static final int MSG_SET_DIALING = 4;
+ private static final int MSG_SET_DISCONNECTED = 5;
+ private static final int MSG_SET_ON_HOLD = 6;
+ private static final int MSG_SET_REQUESTING_RINGBACK = 7;
+ private static final int MSG_SET_CALL_CAPABILITIES = 8;
+ private static final int MSG_SET_IS_CONFERENCED = 9;
+ private static final int MSG_ADD_CONFERENCE_CALL = 10;
+ private static final int MSG_REMOVE_CALL = 11;
+ private static final int MSG_ON_POST_DIAL_WAIT = 12;
+ private static final int MSG_QUERY_REMOTE_CALL_SERVICES = 13;
+ private static final int MSG_SET_VIDEO_STATE = 14;
+ private static final int MSG_SET_VIDEO_CALL_PROVIDER = 15;
+ private static final int MSG_SET_AUDIO_MODE_IS_VOIP = 16;
+ private static final int MSG_SET_STATUS_HINTS = 17;
+ private static final int MSG_SET_HANDLE = 18;
+ private static final int MSG_SET_CALLER_DISPLAY_NAME = 19;
+ private static final int MSG_START_ACTIVITY_FROM_IN_CALL = 20;
+ private static final int MSG_SET_CONFERENCEABLE_CONNECTIONS = 21;
private final IConnectionServiceAdapter mDelegate;
@@ -76,10 +74,10 @@
// Internal method defined to centralize handling of RemoteException
private void internalHandleMessage(Message msg) throws RemoteException {
switch (msg.what) {
- case MSG_HANDLE_CREATE_CONNECTION_SUCCESSFUL: {
+ case MSG_HANDLE_CREATE_CONNECTION_COMPLETE: {
SomeArgs args = (SomeArgs) msg.obj;
try {
- mDelegate.handleCreateConnectionSuccessful(
+ mDelegate.handleCreateConnectionComplete(
(String) args.arg1,
(ConnectionRequest) args.arg2,
(ParcelableConnection) args.arg3);
@@ -88,30 +86,6 @@
}
break;
}
- case MSG_HANDLE_CREATE_CONNECTION_FAILED: {
- SomeArgs args = (SomeArgs) msg.obj;
- try {
- mDelegate.handleCreateConnectionFailed(
- (String) args.arg1,
- (ConnectionRequest) args.arg2,
- args.argi1,
- (String) args.arg3);
- } finally {
- args.recycle();
- }
- break;
- }
- case MSG_HANDLE_CREATE_CONNECTION_CANCELLED: {
- SomeArgs args = (SomeArgs) msg.obj;
- try {
- mDelegate.handleCreateConnectionCancelled(
- (String) args.arg1,
- (ConnectionRequest) args.arg2);
- } finally {
- args.recycle();
- }
- break;
- }
case MSG_SET_ACTIVE:
mDelegate.setActive((String) msg.obj);
break;
@@ -244,7 +218,7 @@
private final IConnectionServiceAdapter mStub = new IConnectionServiceAdapter.Stub() {
@Override
- public void handleCreateConnectionSuccessful(
+ public void handleCreateConnectionComplete(
String id,
ConnectionRequest request,
ParcelableConnection connection) {
@@ -252,31 +226,7 @@
args.arg1 = id;
args.arg2 = request;
args.arg3 = connection;
- mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_SUCCESSFUL, args).sendToTarget();
- }
-
- @Override
- public void handleCreateConnectionFailed(
- String id,
- ConnectionRequest request,
- int errorCode,
- String errorMessage) {
- SomeArgs args = SomeArgs.obtain();
- args.arg1 = id;
- args.arg2 = request;
- args.argi1 = errorCode;
- args.arg3 = errorMessage;
- mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_FAILED, args).sendToTarget();
- }
-
- @Override
- public void handleCreateConnectionCancelled(
- String id,
- ConnectionRequest request) {
- SomeArgs args = SomeArgs.obtain();
- args.arg1 = id;
- args.arg2 = request;
- mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_CANCELLED, args).sendToTarget();
+ mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_COMPLETE, args).sendToTarget();
}
@Override
diff --git a/telecomm/java/android/telecomm/InCallService.java b/telecomm/java/android/telecomm/InCallService.java
index de05d1c..5795e0e 100644
--- a/telecomm/java/android/telecomm/InCallService.java
+++ b/telecomm/java/android/telecomm/InCallService.java
@@ -16,6 +16,7 @@
package android.telecomm;
+import android.annotation.SdkConstant;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
@@ -39,6 +40,13 @@
* {@hide}
*/
public abstract class InCallService extends Service {
+
+ /**
+ * The {@link Intent} that must be declared as handled by the service.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+ public static final String SERVICE_INTERFACE = "android.telecomm.InCallService";
+
private static final int MSG_SET_IN_CALL_ADAPTER = 1;
private static final int MSG_ADD_CALL = 2;
private static final int MSG_UPDATE_CALL = 3;
diff --git a/telecomm/java/android/telecomm/ParcelableConnection.java b/telecomm/java/android/telecomm/ParcelableConnection.java
index 7a87b87..30ff5be 100644
--- a/telecomm/java/android/telecomm/ParcelableConnection.java
+++ b/telecomm/java/android/telecomm/ParcelableConnection.java
@@ -41,6 +41,8 @@
private boolean mRequestingRingback;
private boolean mAudioModeIsVoip;
private StatusHints mStatusHints;
+ private int mFailureCode;
+ private String mFailureMessage;
/** @hide */
public ParcelableConnection(
@@ -55,7 +57,9 @@
int videoState,
boolean requestingRingback,
boolean audioModeIsVoip,
- StatusHints statusHints) {
+ StatusHints statusHints,
+ int failureCode,
+ String failureMessage) {
mPhoneAccount = phoneAccount;
mState = state;
mCapabilities = capabilities;
@@ -68,6 +72,8 @@
mRequestingRingback = requestingRingback;
mAudioModeIsVoip = audioModeIsVoip;
mStatusHints = statusHints;
+ mFailureCode = failureCode;
+ mFailureMessage = failureMessage;
}
public PhoneAccountHandle getPhoneAccount() {
@@ -119,6 +125,14 @@
return mStatusHints;
}
+ public final int getFailureCode() {
+ return mFailureCode;
+ }
+
+ public final String getFailureMessage() {
+ return mFailureMessage;
+ }
+
@Override
public String toString() {
return new StringBuilder()
@@ -150,6 +164,8 @@
boolean requestingRingback = source.readByte() == 1;
boolean audioModeIsVoip = source.readByte() == 1;
StatusHints statusHints = source.readParcelable(classLoader);
+ int disconnectCauseCode = source.readInt();
+ String disconnectCauseMessage = source.readString();
return new ParcelableConnection(
phoneAccount,
@@ -163,7 +179,9 @@
videoState,
requestingRingback,
audioModeIsVoip,
- statusHints);
+ statusHints,
+ disconnectCauseCode,
+ disconnectCauseMessage);
}
@Override
@@ -194,5 +212,7 @@
destination.writeByte((byte) (mRequestingRingback ? 1 : 0));
destination.writeByte((byte) (mAudioModeIsVoip ? 1 : 0));
destination.writeParcelable(mStatusHints, 0);
+ destination.writeInt(mFailureCode);
+ destination.writeString(mFailureMessage);
}
}
diff --git a/telecomm/java/android/telecomm/RemoteConnection.java b/telecomm/java/android/telecomm/RemoteConnection.java
index f1cee10..30cfdde 100644
--- a/telecomm/java/android/telecomm/RemoteConnection.java
+++ b/telecomm/java/android/telecomm/RemoteConnection.java
@@ -233,9 +233,9 @@
RemoteConnection(int failureCode, String failureMessage) {
this("NULL", null, null);
mConnected = false;
- mState = Connection.STATE_FAILED;
- mFailureCode = failureCode;
- mFailureMessage = failureMessage;
+ mState = Connection.STATE_DISCONNECTED;
+ mFailureCode = DisconnectCause.OUTGOING_FAILURE;
+ mFailureMessage = failureMessage + " original code = " + failureCode;
}
/**
@@ -675,8 +675,9 @@
}
/**
- * Create a RemoteConnection which is in the {@link Connection#STATE_FAILED} state. Attempting
- * to use it for anything will almost certainly result in bad things happening. Do not do this.
+ * Create a RemoteConnection represents a failure, and which will be in
+ * {@link Connection#STATE_DISCONNECTED}. Attempting to use it for anything will almost
+ * certainly result in bad things happening. Do not do this.
*
* @return a failed {@link RemoteConnection}
*
diff --git a/telecomm/java/android/telecomm/RemoteConnectionService.java b/telecomm/java/android/telecomm/RemoteConnectionService.java
index dedb10e..541df4e 100644
--- a/telecomm/java/android/telecomm/RemoteConnectionService.java
+++ b/telecomm/java/android/telecomm/RemoteConnectionService.java
@@ -48,7 +48,7 @@
private final IConnectionServiceAdapter mServantDelegate = new IConnectionServiceAdapter() {
@Override
- public void handleCreateConnectionSuccessful(
+ public void handleCreateConnectionComplete(
String id,
ConnectionRequest request,
ParcelableConnection parcel) {
@@ -56,6 +56,7 @@
findConnectionForAction(id, "handleCreateConnectionSuccessful");
if (connection != NULL_CONNECTION && mPendingConnections.contains(connection)) {
mPendingConnections.remove(connection);
+ // Unconditionally initialize the connection ...
connection.setState(parcel.getState());
connection.setCallCapabilities(parcel.getCapabilities());
connection.setHandle(
@@ -64,29 +65,15 @@
parcel.getCallerDisplayName(),
parcel.getCallerDisplayNamePresentation());
// TODO: Do we need to support video providers for remote connections?
+ if (connection.getState() == Connection.STATE_DISCONNECTED) {
+ // ... then, if it was created in a disconnected state, that indicates
+ // failure on the providing end, so immediately mark it destroyed
+ connection.setDestroyed();
+ }
}
}
@Override
- public void handleCreateConnectionFailed(
- String id,
- ConnectionRequest request,
- int errorCode,
- String errorMessage) {
- // TODO: How do we propagate the failure codes?
- findConnectionForAction(id, "handleCreateConnectionFailed")
- .setDestroyed();
- }
-
- @Override
- public void handleCreateConnectionCancelled(
- String id,
- ConnectionRequest request) {
- findConnectionForAction(id, "handleCreateConnectionCancelled")
- .setDestroyed();
- }
-
- @Override
public void setActive(String callId) {
findConnectionForAction(callId, "setActive")
.setState(Connection.STATE_ACTIVE);
diff --git a/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
index e6ebae5..ef1769f 100644
--- a/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
@@ -34,20 +34,11 @@
* {@hide}
*/
oneway interface IConnectionServiceAdapter {
- void handleCreateConnectionSuccessful(
+ void handleCreateConnectionComplete(
String callId,
in ConnectionRequest request,
in ParcelableConnection connection);
- void handleCreateConnectionFailed(
- String callId,
- in ConnectionRequest request,
- int errorCode, String errorMessage);
-
- void handleCreateConnectionCancelled(
- String callId,
- in ConnectionRequest request);
-
void setActive(String callId);
void setRinging(String callId);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index c50110a..d4f8362 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2459,7 +2459,7 @@
* @param filePath
* @return The APDU response.
*/
- byte[] iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
+ public byte[] iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
String filePath) {
try {
return getITelephony().iccExchangeSimIO(fileID, command, p1, p2,
diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk
index 700afa1..4ce5045 100644
--- a/tools/aapt/Android.mk
+++ b/tools/aapt/Android.mk
@@ -66,6 +66,8 @@
libexpat \
libziparchive-host
+aaptCFlags := -DAAPT_VERSION=\"$(BUILD_NUMBER)\"
+
ifeq ($(HOST_OS),linux)
aaptHostLdLibs += -lrt -ldl -lpthread
endif
@@ -91,6 +93,7 @@
LOCAL_CFLAGS += -Wno-format-y2k
LOCAL_CFLAGS += -DSTATIC_ANDROIDFW_FOR_TOOLS
+LOCAL_CFLAGS += $(aaptCFlags)
ifeq (darwin,$(HOST_OS))
LOCAL_CFLAGS += -D_DARWIN_UNLIMITED_STREAMS
endif
@@ -110,7 +113,9 @@
LOCAL_STATIC_LIBRARIES += \
libaapt \
$(aaptHostStaticLibs)
+
LOCAL_LDLIBS += $(aaptHostLdLibs)
+LOCAL_CFLAGS += $(aaptCFlags)
include $(BUILD_HOST_EXECUTABLE)
@@ -128,7 +133,9 @@
LOCAL_STATIC_LIBRARIES += \
libaapt \
$(aaptHostStaticLibs)
+
LOCAL_LDLIBS += $(aaptHostLdLibs)
+LOCAL_CFLAGS += $(aaptCFlags)
include $(BUILD_HOST_NATIVE_TEST)
@@ -159,6 +166,7 @@
libstlport_static \
libexpat_static
+LOCAL_CFLAGS += $(aaptCFlags)
LOCAL_CPPFLAGS += -Wno-non-virtual-dtor
include $(BUILD_EXECUTABLE)
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 5d146d6..bdbf47b 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -24,6 +24,10 @@
using namespace android;
+#ifndef AAPT_VERSION
+ #define AAPT_VERSION ""
+#endif
+
/*
* Show version info. All the cool kids do it.
*/
@@ -32,7 +36,7 @@
if (bundle->getFileSpecCount() != 0) {
printf("(ignoring extra arguments)\n");
}
- printf("Android Asset Packaging Tool, v0.2\n");
+ printf("Android Asset Packaging Tool, v0.2-" AAPT_VERSION "\n");
return 0;
}
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index cf1d4fd..c98808f 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -484,15 +484,6 @@
attr.hasErrors = true;
}
- // Make sure an id is defined for this enum/flag identifier...
- if (!attr.hasErrors && !outTable->hasBagOrEntry(itemIdent, &id16, &myPackage)) {
- err = outTable->startBag(SourcePos(in->getPrintableSource(), block.getLineNumber()),
- myPackage, id16, itemIdent, String16(), NULL);
- if (err != NO_ERROR) {
- attr.hasErrors = true;
- }
- }
-
if (!attr.hasErrors) {
if (enumOrFlagsComment.size() == 0) {
enumOrFlagsComment.append(mayOrMust(attr.type,
@@ -2508,11 +2499,13 @@
sp<Type> attr = p->getType(String16("attr"), unknown);
// Assign indices...
- for (ti=0; ti<N; ti++) {
+ const size_t typeCount = p->getOrderedTypes().size();
+ for (size_t ti = 0; ti < typeCount; ti++) {
sp<Type> t = p->getOrderedTypes().itemAt(ti);
if (t == NULL) {
continue;
}
+
err = t->applyPublicEntryOrder();
if (err != NO_ERROR && firstError == NO_ERROR) {
firstError = err;
@@ -2534,7 +2527,7 @@
}
// Assign resource IDs to keys in bags...
- for (ti=0; ti<N; ti++) {
+ for (size_t ti = 0; ti < typeCount; ti++) {
sp<Type> t = p->getOrderedTypes().itemAt(ti);
if (t == NULL) {
continue;
@@ -3296,11 +3289,16 @@
Item item(sourcePos, false, value, style);
if (mType == TYPE_BAG) {
- const Item& item(mBag.valueAt(0));
- sourcePos.error("Resource entry %s is already defined as a bag.\n"
- "%s:%d: Originally defined here.\n",
- String8(mName).string(),
- item.sourcePos.file.string(), item.sourcePos.line);
+ if (mBag.size() == 0) {
+ sourcePos.error("Resource entry %s is already defined as a bag.",
+ String8(mName).string());
+ } else {
+ const Item& item(mBag.valueAt(0));
+ sourcePos.error("Resource entry %s is already defined as a bag.\n"
+ "%s:%d: Originally defined here.\n",
+ String8(mName).string(),
+ item.sourcePos.file.string(), item.sourcePos.line);
+ }
return UNKNOWN_ERROR;
}
if ( (mType != TYPE_UNKNOWN) && (overwrite == false) ) {
@@ -3374,6 +3372,9 @@
if (it.isId) {
if (!table->hasBagOrEntry(key, &id16, &package)) {
String16 value("false");
+ NOISY(fprintf(stderr, "Generating %s:id/%s\n",
+ String8(package).string(),
+ String8(key).string()));
status_t err = table->addEntry(SourcePos(String8("<generated>"), 0), package,
id16, key, value);
if (err != NO_ERROR) {
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 3c37b94..ac2a176 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -21,7 +21,7 @@
import android.net.IpConfiguration.ProxySettings;
import android.net.IpConfiguration.IpAssignment;
import android.net.ProxyInfo;
-import android.net.LinkProperties;
+import android.net.StaticIpConfiguration;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -1096,13 +1096,13 @@
}
/** @hide */
- public LinkProperties getLinkProperties() {
- return mIpConfiguration.linkProperties;
+ public StaticIpConfiguration getStaticIpConfiguration() {
+ return mIpConfiguration.getStaticIpConfiguration();
}
/** @hide */
- public void setLinkProperties(LinkProperties linkProperties) {
- mIpConfiguration.linkProperties = linkProperties;
+ public void setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration) {
+ mIpConfiguration.setStaticIpConfiguration(staticIpConfiguration);
}
/** @hide */
@@ -1126,9 +1126,19 @@
}
/** @hide */
+ public ProxyInfo getHttpProxy() {
+ return mIpConfiguration.httpProxy;
+ }
+
+ /** @hide */
+ public void setHttpProxy(ProxyInfo httpProxy) {
+ mIpConfiguration.httpProxy = httpProxy;
+ }
+
+ /** @hide */
public void setProxy(ProxySettings settings, ProxyInfo proxy) {
mIpConfiguration.proxySettings = settings;
- mIpConfiguration.linkProperties.setHttpProxy(proxy);
+ mIpConfiguration.httpProxy = proxy;
}
/** Implement the Parcelable interface {@hide} */