summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CleanSpec.mk3
-rw-r--r--api/current.txt57
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java50
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java1
-rw-r--r--core/java/android/content/pm/PackageParser.java73
-rw-r--r--core/java/android/os/FileUtils.java27
-rw-r--r--core/java/android/os/SELinux.java19
-rw-r--r--core/java/android/widget/NumberPicker.java2
-rw-r--r--core/java/com/android/internal/app/IMediaContainerService.aidl26
-rw-r--r--core/java/com/android/internal/util/ArrayUtils.java7
-rw-r--r--core/res/res/drawable-hdpi/notification_bg_low_normal.9.pngbin176 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/notification_bg_low_pressed.9.pngbin165 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/notification_bg_normal.9.pngbin176 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/notification_bg_normal_pressed.9.pngbin165 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/progress_mtrl_alpha.9.pngbin106 -> 184 bytes
-rw-r--r--core/res/res/drawable-hdpi/progress_primary_mtrl_alpha.9.pngbin545 -> 0 bytes
-rw-r--r--core/res/res/drawable-ldpi/progress_mtrl_alpha.9.pngbin102 -> 173 bytes
-rw-r--r--core/res/res/drawable-ldpi/progress_primary_mtrl_alpha.9.pngbin300 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/notification_bg_low_normal.9.pngbin165 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/notification_bg_low_pressed.9.pngbin157 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/notification_bg_normal.9.pngbin165 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/notification_bg_normal_pressed.9.pngbin157 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/progress_mtrl_alpha.9.pngbin104 -> 178 bytes
-rw-r--r--core/res/res/drawable-mdpi/progress_primary_mtrl_alpha.9.pngbin363 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/notification_bg_low_normal.9.pngbin200 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/notification_bg_low_pressed.9.pngbin171 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/notification_bg_normal.9.pngbin200 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/notification_bg_normal_pressed.9.pngbin171 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/progress_mtrl_alpha.9.pngbin111 -> 185 bytes
-rw-r--r--core/res/res/drawable-xhdpi/progress_primary_mtrl_alpha.9.pngbin697 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/notification_bg_low_pressed.9.pngbin1061 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/notification_bg_normal_pressed.9.pngbin1061 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/progress_mtrl_alpha.9.pngbin156 -> 177 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/progress_primary_mtrl_alpha.9.pngbin672 -> 0 bytes
-rw-r--r--core/res/res/drawable/notification_bg.xml22
-rw-r--r--core/res/res/drawable/notification_bg_low.xml22
-rw-r--r--core/res/res/drawable/notification_material_bg.xml31
-rw-r--r--core/res/res/drawable/progress_horizontal_material.xml5
-rw-r--r--core/res/res/values/arrays.xml1
-rw-r--r--core/res/res/values/attrs.xml2
-rw-r--r--core/res/res/values/dimens.xml3
-rw-r--r--core/res/res/values/symbols.xml6
-rw-r--r--media/java/android/media/AudioDevice.java115
-rw-r--r--media/java/android/media/AudioDevicePortConfig.java5
-rw-r--r--packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java80
-rw-r--r--packages/SystemUI/res/drawable/notification_material_bg.xml (renamed from core/res/res/drawable/notification_material_bg_dim.xml)12
-rw-r--r--packages/SystemUI/res/drawable/notification_material_bg_dim.xml (renamed from core/res/res/drawable/notification_bg_dim.xml)9
-rw-r--r--packages/SystemUI/res/drawable/notification_scrim.xml4
-rw-r--r--packages/SystemUI/res/drawable/qs_panel_background.xml4
-rw-r--r--packages/SystemUI/res/layout/qs_detail.xml47
-rw-r--r--packages/SystemUI/res/layout/qs_detail_header.xml35
-rw-r--r--packages/SystemUI/res/layout/qs_detail_item.xml51
-rw-r--r--packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml2
-rw-r--r--packages/SystemUI/res/layout/status_bar_expanded.xml23
-rw-r--r--packages/SystemUI/res/layout/status_bar_expanded_header.xml23
-rw-r--r--packages/SystemUI/res/layout/zen_mode_condition.xml4
-rw-r--r--packages/SystemUI/res/layout/zen_mode_panel.xml2
-rw-r--r--packages/SystemUI/res/values/colors.xml18
-rw-r--r--packages/SystemUI/res/values/dimens.xml12
-rw-r--r--packages/SystemUI/res/values/internal.xml1
-rw-r--r--packages/SystemUI/res/values/strings.xml4
-rw-r--r--packages/SystemUI/res/values/styles.xml6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/CircularClipper.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java81
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTile.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/BugreportTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/NotificationsTile.java97
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java118
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Console.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Constants.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java46
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsService.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java71
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java74
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java51
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java81
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java82
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java180
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java62
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java84
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiAccessPointController.java200
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java89
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java7
-rw-r--r--services/core/java/com/android/server/hdmi/FeatureAction.java2
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecController.java21
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiControlService.java7
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java20
-rw-r--r--services/core/java/com/android/server/notification/NotificationRecord.java11
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java6
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java4
-rw-r--r--services/core/java/com/android/server/pm/PackageKeySetData.java15
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java435
-rw-r--r--services/core/java/com/android/server/pm/PackageSettingBase.java6
-rw-r--r--telecomm/java/android/telecomm/CallCapabilities.java8
-rw-r--r--telecomm/java/android/telecomm/CallService.java178
-rw-r--r--telecomm/java/android/telecomm/CallServiceAdapter.java17
-rw-r--r--telecomm/java/android/telecomm/Connection.java6
-rw-r--r--telecomm/java/android/telecomm/ConnectionService.java60
-rw-r--r--telecomm/java/android/telecomm/InCallAdapter.java8
-rw-r--r--telecomm/java/android/telecomm/InCallCall.java20
-rw-r--r--telecomm/java/android/telecomm/RemoteConnectionService.java6
-rw-r--r--telecomm/java/android/telecomm/TelecommConstants.java16
-rw-r--r--telecomm/java/com/android/internal/telecomm/ICallService.aidl2
-rw-r--r--telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl2
-rw-r--r--telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl2
-rw-r--r--telephony/java/com/android/internal/telephony/IMms.aidl21
125 files changed, 2042 insertions, 1284 deletions
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 909fdb6..20e48f9 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -206,6 +206,9 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/servic
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/app)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/ims-common_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework2_intermediates)
# ******************************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
diff --git a/api/current.txt b/api/current.txt
index c7a62ac..fb598fd 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5324,7 +5324,6 @@ package android.app.admin {
method public void wipeData(int);
field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
field public static final java.lang.String ACTION_PROVISION_MANAGED_PROFILE = "android.app.action.ACTION_PROVISION_MANAGED_PROFILE";
- field public static final java.lang.String ACTION_SEND_PROVISIONING_VALUES = "android.app.action.ACTION_SEND_PROVISIONING_VALUES";
field public static final java.lang.String ACTION_SET_NEW_PASSWORD = "android.app.action.SET_NEW_PASSWORD";
field public static final java.lang.String ACTION_START_ENCRYPTION = "android.app.action.START_ENCRYPTION";
field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2
@@ -5341,7 +5340,6 @@ package android.app.admin {
field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.locale";
field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.localTime";
field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.timeZone";
- field public static final java.lang.String EXTRA_PROVISIONING_TOKEN = "android.app.extra.token";
field public static final java.lang.String EXTRA_PROVISIONING_WIFI_HIDDEN = "android.app.extra.wifiHidden";
field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PAC_URL = "android.app.extra.wifiPacUrl";
field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PASSWORD = "android.app.extra.wifiPassword";
@@ -27472,8 +27470,7 @@ package android.telecomm {
public final class CallCapabilities {
method public static java.lang.String toString(int);
field public static final int ADD_CALL = 16; // 0x10
- field public static final int ALL = 511; // 0x1ff
- field public static final int CONNECTION_HANDOFF = 256; // 0x100
+ field public static final int ALL = 255; // 0xff
field public static final int GENERIC_CONFERENCE = 128; // 0x80
field public static final int HOLD = 1; // 0x1
field public static final int MERGE_CALLS = 4; // 0x4
@@ -27515,43 +27512,8 @@ package android.telecomm {
public abstract class CallService extends android.app.Service {
ctor public CallService();
- method public abstract void abort(java.lang.String);
- method public abstract void answer(java.lang.String);
- method public abstract void call(android.telecomm.CallInfo);
- method public abstract void disconnect(java.lang.String);
- method protected final android.telecomm.CallServiceAdapter getAdapter();
method public final android.os.IBinder getBinder();
- method public abstract void hold(java.lang.String);
- method protected void onAdapterAttached(android.telecomm.CallServiceAdapter);
- method public abstract void onAudioStateChanged(java.lang.String, android.telecomm.CallAudioState);
method public final android.os.IBinder onBind(android.content.Intent);
- method public abstract void onFeaturesChanged(java.lang.String, int);
- method public void onPostDialContinue(java.lang.String, boolean);
- method public void onPostDialWait(android.telecomm.Connection, java.lang.String);
- method public abstract void playDtmfTone(java.lang.String, char);
- method public abstract void reject(java.lang.String);
- method public abstract void setIncomingCallId(java.lang.String, android.os.Bundle);
- method public abstract void stopDtmfTone(java.lang.String);
- method public abstract void unhold(java.lang.String);
- }
-
- public final class CallServiceAdapter implements android.os.IBinder.DeathRecipient {
- method public void addConferenceCall(java.lang.String);
- method public void binderDied();
- method public void cancelOutgoingCall(java.lang.String);
- method public void handleFailedOutgoingCall(android.telecomm.ConnectionRequest, int, java.lang.String);
- method public void handleSuccessfulOutgoingCall(java.lang.String);
- method public void handoffCall(java.lang.String);
- method public void notifyIncomingCall(android.telecomm.CallInfo);
- method public void onPostDialWait(java.lang.String, java.lang.String);
- method public void setActive(java.lang.String);
- method public void setCallVideoProvider(java.lang.String, android.telecomm.CallVideoProvider);
- method public void setDialing(java.lang.String);
- method public void setDisconnected(java.lang.String, int, java.lang.String);
- method public void setFeatures(java.lang.String, int);
- method public void setOnHold(java.lang.String);
- method public void setRequestingRingback(java.lang.String, boolean);
- method public void setRinging(java.lang.String);
}
public final class CallServiceDescriptor implements android.os.Parcelable {
@@ -27645,6 +27607,7 @@ package android.telecomm {
method protected void onConference();
method protected void onDisconnect();
method protected void onHold();
+ method protected void onPhoneAccountClicked();
method protected void onPlayDtmfTone(char);
method protected void onPostDialContinue(boolean);
method protected void onReject();
@@ -27694,27 +27657,15 @@ package android.telecomm {
public abstract class ConnectionService extends android.telecomm.CallService {
ctor public ConnectionService();
- method public final void abort(java.lang.String);
- method public final void answer(java.lang.String);
- method public final void call(android.telecomm.CallInfo);
method public final void createRemoteOutgoingConnection(android.telecomm.ConnectionRequest, android.telecomm.ConnectionService.OutgoingCallResponse<android.telecomm.RemoteConnection>);
- method public final void disconnect(java.lang.String);
method public final java.util.Collection<android.telecomm.Connection> getAllConnections();
- method public final void hold(java.lang.String);
method public final void lookupRemoteAccounts(android.net.Uri, android.telecomm.SimpleResponse<android.net.Uri, java.util.List<android.telecomm.PhoneAccount>>);
method public final void maybeRespondToAccountLookup();
- method public final void onAudioStateChanged(java.lang.String, android.telecomm.CallAudioState);
method protected void onConnectionAdded(android.telecomm.Connection);
method protected void onConnectionRemoved(android.telecomm.Connection);
method protected void onCreateConferenceConnection(java.lang.String, android.telecomm.Connection, android.telecomm.Response<java.lang.String, android.telecomm.Connection>);
method protected void onCreateConnections(android.telecomm.ConnectionRequest, android.telecomm.ConnectionService.OutgoingCallResponse<android.telecomm.Connection>);
method protected void onCreateIncomingConnection(android.telecomm.ConnectionRequest, android.telecomm.Response<android.telecomm.ConnectionRequest, android.telecomm.Connection>);
- method public final void onFeaturesChanged(java.lang.String, int);
- method public final void playDtmfTone(java.lang.String, char);
- method public final void reject(java.lang.String);
- method public final void setIncomingCallId(java.lang.String, android.os.Bundle);
- method public final void stopDtmfTone(java.lang.String);
- method public final void unhold(java.lang.String);
}
public static abstract interface ConnectionService.OutgoingCallResponse {
@@ -27736,9 +27687,9 @@ package android.telecomm {
public final class InCallAdapter {
method public void answerCall(java.lang.String);
method public void disconnectCall(java.lang.String);
- method public void handoffCall(java.lang.String);
method public void holdCall(java.lang.String);
method public void mute(boolean);
+ method public void phoneAccountClicked(java.lang.String);
method public void playDtmfTone(java.lang.String, char);
method public void postDialContinue(java.lang.String, boolean);
method public void rejectCall(java.lang.String, boolean, java.lang.String);
@@ -27760,7 +27711,6 @@ package android.telecomm {
method public int getFeatures();
method public android.telecomm.GatewayInfo getGatewayInfo();
method public android.net.Uri getHandle();
- method public android.telecomm.CallServiceDescriptor getHandoffCallServiceDescriptor();
method public java.lang.String getId();
method public android.telecomm.CallState getState();
method public void writeToParcel(android.os.Parcel, int);
@@ -27869,6 +27819,7 @@ package android.telecomm {
field public static final java.lang.String EXTRA_CALL_SERVICE_DESCRIPTOR = "android.intent.extra.CALL_SERVICE_DESCRIPTOR";
field public static final java.lang.String EXTRA_INCOMING_CALL_EXTRAS = "android.intent.extra.INCOMING_CALL_EXTRAS";
field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.intent.extra.START_CALL_WITH_SPEAKERPHONE";
+ field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO = "android.intent.extra.START_CALL_WITH_VIDEO";
}
public class VideoCallProfile implements android.os.Parcelable {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index df51ff5..fe51d82 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -86,20 +86,6 @@ public class DevicePolicyManager {
}
/**
- * Activity action: Used to indicate that the receiving activity is being started as part of the
- * managed profile provisioning flow. This intent is typically sent to a mobile device
- * management application (mdm) after the first part of the provisioning process is complete in
- * the expectation that this app will (after optionally showing it's own UI) ultimately call
- * {@link #ACTION_PROVISION_MANAGED_PROFILE} to complete the creation of the managed profile.
- *
- * <p> The intent may contain the extras {@link #EXTRA_PROVISIONING_TOKEN} and
- * {@link #EXTRA_PROVISIONING_EMAIL_ADDRESS}.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_SEND_PROVISIONING_VALUES
- = "android.app.action.ACTION_SEND_PROVISIONING_VALUES";
-
- /**
* Activity action: Starts the provisioning flow which sets up a managed profile.
*
* <p>A managed profile allows data separation for example for the usage of a
@@ -128,17 +114,6 @@ public class DevicePolicyManager {
= "android.app.action.ACTION_PROVISION_MANAGED_PROFILE";
/**
- * A broadcast intent with this action can be sent to ManagedProvisionning to specify that the
- * user has already consented to the creation of the managed profile.
- * The intent must contain the extras
- * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME} and
- * {@link #EXTRA_PROVISIONING_TOKEN}
- * @hide
- */
- public static final String ACTION_PROVISIONING_USER_HAS_CONSENTED
- = "android.app.action.ACTION_PROVISIONING_USER_HAS_CONSENTED";
-
- /**
* A String extra holding the package name of the mobile device management application that
* will be set as the profile owner or device owner.
*
@@ -153,18 +128,6 @@ public class DevicePolicyManager {
= "android.app.extra.deviceAdminPackageName";
/**
- * An int extra used to identify that during the current setup process the user has already
- * consented to setting up a managed profile. This is typically received by
- * a mobile device management application when it is started with
- * {@link #ACTION_SEND_PROVISIONING_VALUES} and passed on in an intent
- * {@link #ACTION_PROVISION_MANAGED_PROFILE} which starts the setup of the managed profile. The
- * token indicates that steps asking for user consent can be skipped as the user has previously
- * consented.
- */
- public static final String EXTRA_PROVISIONING_TOKEN
- = "android.app.extra.token";
-
- /**
* A String extra holding the default name of the profile that is created during managed profile
* provisioning.
*
@@ -174,12 +137,15 @@ public class DevicePolicyManager {
= "android.app.extra.defaultManagedProfileName";
/**
- * A String extra holding the email address of the profile that is created during managed
- * profile provisioning. This is typically received by a mobile management application when it
- * is started with {@link #ACTION_SEND_PROVISIONING_VALUES} and passed on in an intent
- * {@link #ACTION_PROVISION_MANAGED_PROFILE} which starts the setup of the managed profile. It
- * is eventually passed on in an intent
+ * A String extra that, holds the email address of the account which a managed profile is
+ * created for. Used with {@link #ACTION_PROVISION_MANAGED_PROFILE} and
* {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE}.
+ *
+ * <p> If the {@link #ACTION_PROVISION_MANAGED_PROFILE} intent that starts managed provisioning
+ * contains this extra, it is forwarded in the
+ * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} intent to the mobile
+ * device management application that was set as the profile owner during provisioning.
+ * It is usually used to avoid that the user has to enter their email address twice.
*/
public static final String EXTRA_PROVISIONING_EMAIL_ADDRESS
= "android.app.extra.ManagedProfileEmailAddress";
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index be4e864..bb90fd7 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -413,6 +413,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
/**
* Full path to the base APK for this application.
*/
+ // TODO: verify that nobody is doing codePath comparisons against this
public String sourceDir;
/**
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index f176dfb..319559a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -279,11 +279,11 @@ public class PackageParser {
mMetrics = metrics;
}
- private static final boolean isPackageFilename(File file) {
+ public static final boolean isPackageFilename(File file) {
return isPackageFilename(file.getName());
}
- private static final boolean isPackageFilename(String name) {
+ public static final boolean isPackageFilename(String name) {
return name.endsWith(".apk");
}
@@ -552,7 +552,7 @@ public class PackageParser {
* Note that this <em>does not</em> perform signature verification; that
* must be done separately in {@link #collectCertificates(Package, int)}.
*/
- public Package parseSplitPackage(File apkDir, int flags) throws PackageParserException {
+ public Package parseClusterPackage(File apkDir, int flags) throws PackageParserException {
final File[] files = apkDir.listFiles();
if (ArrayUtils.isEmpty(files)) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
@@ -600,27 +600,23 @@ public class PackageParser {
"Missing base APK in " + apkDir);
}
- // Always apply deterministic ordering based on splitName
- final int size = apks.size();
-
- final String[] splitNames = apks.keySet().toArray(new String[size]);
- Arrays.sort(splitNames, sSplitNameComparator);
-
- final File[] splitFiles = new File[size];
- for (int i = 0; i < size; i++) {
- splitFiles[i] = apks.get(splitNames[i]);
- }
-
final Package pkg = parseBaseApk(baseFile, flags);
if (pkg == null) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
"Failed to parse base APK: " + baseFile);
}
- for (File splitFile : splitFiles) {
- parseSplitApk(pkg, splitFile, flags);
+ // Always apply deterministic ordering based on splitName
+ final int size = apks.size();
+ final String[] splitNames = apks.keySet().toArray(new String[size]);
+ Arrays.sort(splitNames, sSplitNameComparator);
+
+ for (String splitName : splitNames) {
+ final File splitFile = apks.get(splitName);
+ parseSplitApk(pkg, splitFile, splitName, flags);
}
+ pkg.codePath = apkDir.getAbsolutePath();
return pkg;
}
@@ -632,11 +628,12 @@ public class PackageParser {
*/
public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
final Package pkg = parseBaseApk(apkFile, flags);
- if (pkg != null) {
- return pkg;
- } else {
+ if (pkg == null) {
throw new PackageParserException(mParseError, "Failed to parse " + apkFile);
}
+
+ pkg.codePath = apkFile.getAbsolutePath();
+ return pkg;
}
private Package parseBaseApk(File apkFile, int flags) {
@@ -723,19 +720,28 @@ public class PackageParser {
parser.close();
assmgr.close();
- pkg.codePath = apkPath;
+ pkg.baseCodePath = apkPath;
pkg.mSignatures = null;
+ // TODO: Remove this when the WebView can load resources dynamically. b/11505352
+ if (pkg.usesOptionalLibraries == null) {
+ pkg.usesOptionalLibraries = new ArrayList<String>();
+ }
+ pkg.usesOptionalLibraries.add("com.android.webview");
+
return pkg;
}
- private void parseSplitApk(Package pkg, File apkFile, int flags) throws PackageParserException {
- final String apkPath = apkFile.getAbsolutePath();
+ private void parseSplitApk(Package pkg, File apkFile, String splitName, int flags)
+ throws PackageParserException {
+ final String splitCodePath = apkFile.getAbsolutePath();
mArchiveSourcePath = apkFile.getAbsolutePath();
// TODO: expand split APK parsing
+ // TODO: extract splitName during parse
+ pkg.splitNames = ArrayUtils.appendElement(String.class, pkg.splitNames, splitName);
pkg.splitCodePaths = ArrayUtils.appendElement(String.class, pkg.splitCodePaths,
- apkFile.getAbsolutePath());
+ splitCodePath);
}
/**
@@ -748,7 +754,7 @@ public class PackageParser {
// TODO: extend to gather digest for split APKs
try {
- final StrictJarFile jarFile = new StrictJarFile(pkg.codePath);
+ final StrictJarFile jarFile = new StrictJarFile(pkg.baseCodePath);
try {
final ZipEntry je = jarFile.findEntry(ANDROID_MANIFEST_FILENAME);
if (je != null) {
@@ -773,7 +779,7 @@ public class PackageParser {
pkg.mSignatures = null;
pkg.mSigningKeys = null;
- collectCertificates(pkg, new File(pkg.codePath), flags);
+ collectCertificates(pkg, new File(pkg.baseCodePath), flags);
if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
for (String splitCodePath : pkg.splitCodePaths) {
@@ -3692,12 +3698,21 @@ public class PackageParser {
public final static class Package {
public String packageName;
+ /** Names of any split APKs, ordered by parsed splitName */
+ public String[] splitNames;
// TODO: work towards making these paths invariant
- /** Base APK */
+ /**
+ * Path where this package was found on disk. For monolithic packages
+ * this is path to single base APK file; for cluster packages this is
+ * path to the cluster directory.
+ */
public String codePath;
- /** Split APKs, ordered by parsed splitName */
+
+ /** Path of base APK */
+ public String baseCodePath;
+ /** Paths of any split APKs, ordered by parsed splitName */
public String[] splitCodePaths;
// For now we only support one application per package.
@@ -3816,9 +3831,9 @@ public class PackageParser {
applicationInfo.uid = -1;
}
- public Collection<String> getAllCodePaths() {
+ public List<String> getAllCodePaths() {
ArrayList<String> paths = new ArrayList<>();
- paths.add(codePath);
+ paths.add(baseCodePath);
if (!ArrayUtils.isEmpty(splitCodePaths)) {
Collections.addAll(paths, splitCodePaths);
}
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 1dba77d..d5d5eb8 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -384,16 +384,18 @@ public class FileUtils {
return filePath.startsWith(dirPath);
}
- public static void deleteContents(File dir) {
+ public static boolean deleteContents(File dir) {
File[] files = dir.listFiles();
+ boolean success = true;
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
- deleteContents(file);
+ success &= deleteContents(file);
}
- file.delete();
+ success &= file.delete();
}
}
+ return success;
}
/**
@@ -411,4 +413,23 @@ public class FileUtils {
}
return true;
}
+
+ public static String rewriteAfterRename(File beforeDir, File afterDir, String path) {
+ final File result = rewriteAfterRename(beforeDir, afterDir, new File(path));
+ return (result != null) ? result.getAbsolutePath() : null;
+ }
+
+ /**
+ * Given a path under the "before" directory, rewrite it to live under the
+ * "after" directory. For example, {@code /before/foo/bar.txt} would become
+ * {@code /after/foo/bar.txt}.
+ */
+ public static File rewriteAfterRename(File beforeDir, File afterDir, File file) {
+ if (contains(beforeDir, file)) {
+ final String splice = file.getAbsolutePath().substring(
+ beforeDir.getAbsolutePath().length());
+ return new File(afterDir, splice);
+ }
+ return null;
+ }
}
diff --git a/core/java/android/os/SELinux.java b/core/java/android/os/SELinux.java
index c9dd5d7..71d12c6 100644
--- a/core/java/android/os/SELinux.java
+++ b/core/java/android/os/SELinux.java
@@ -171,4 +171,23 @@ public class SELinux {
return false;
}
}
+
+ /**
+ * Recursively restores all files under the given path to their default
+ * SELinux security context. If the system is not compiled with SELinux,
+ * then {@code true} is automatically returned. If SELinux is compiled in,
+ * but disabled, then {@code true} is returned.
+ *
+ * @return a boolean indicating whether the relabeling succeeded.
+ */
+ public static boolean restoreconTree(File dir) {
+ final File[] files = dir.listFiles();
+ boolean success = true;
+ if (files != null) {
+ for (File file : files) {
+ success &= restorecon(file);
+ }
+ }
+ return success;
+ }
}
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index d6fa05a..755bb48 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -62,7 +62,7 @@ import java.util.List;
import java.util.Locale;
/**
- * A widget that enables the user to select a number form a predefined range.
+ * A widget that enables the user to select a number from a predefined range.
* There are two flavors of this widget and which one is presented to the user
* depends on the current theme.
* <ul>
diff --git a/core/java/com/android/internal/app/IMediaContainerService.aidl b/core/java/com/android/internal/app/IMediaContainerService.aidl
index 77f0dec..3cd0417 100644
--- a/core/java/com/android/internal/app/IMediaContainerService.aidl
+++ b/core/java/com/android/internal/app/IMediaContainerService.aidl
@@ -16,27 +16,25 @@
package com.android.internal.app;
-import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.content.pm.ContainerEncryptionParams;
import android.content.pm.PackageInfoLite;
import android.content.res.ObbInfo;
interface IMediaContainerService {
- String copyResourceToContainer(in Uri packageURI, String containerId, String key,
+ String copyResourceToContainer(String packagePath, String containerId, String key,
String resFileName, String publicResFileName, boolean isExternal,
- boolean isForwardLocked, in String abiOverride);
- int copyResource(in Uri packageURI, in ContainerEncryptionParams encryptionParams,
+ boolean isForwardLocked, String abiOverride);
+ int copyResource(String packagePath, in ContainerEncryptionParams encryptionParams,
in ParcelFileDescriptor outStream);
- PackageInfoLite getMinimalPackageInfo(in String packagePath, in int flags, in long threshold,
- in String abiOverride);
- boolean checkInternalFreeStorage(in Uri fileUri, boolean isForwardLocked, in long threshold);
- boolean checkExternalFreeStorage(in Uri fileUri, boolean isForwardLocked, in String abiOverride);
- ObbInfo getObbInfo(in String filename);
- long calculateDirectorySize(in String directory);
+ PackageInfoLite getMinimalPackageInfo(String packagePath, int flags, long threshold,
+ String abiOverride);
+ boolean checkInternalFreeStorage(String packagePath, boolean isForwardLocked, long threshold);
+ boolean checkExternalFreeStorage(String packagePath, boolean isForwardLocked, String abiOverride);
+ ObbInfo getObbInfo(String filename);
+ long calculateDirectorySize(String directory);
/** Return file system stats: [0] is total bytes, [1] is available bytes */
- long[] getFileSystemStats(in String path);
- void clearDirectory(in String directory);
- long calculateInstalledSize(in String packagePath, boolean isForwardLocked,
- in String abiOverride);
+ long[] getFileSystemStats(String path);
+ void clearDirectory(String directory);
+ long calculateInstalledSize(String packagePath, boolean isForwardLocked, String abiOverride);
}
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index d66ef83..7f6159d 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -138,6 +138,7 @@ public class ArrayUtils
* not found.
*/
public static <T> int indexOf(T[] array, T value) {
+ if (array == null) return -1;
for (int i = 0; i < array.length; i++) {
if (array[i] == null) {
if (value == null) return i;
@@ -161,6 +162,7 @@ public class ArrayUtils
}
public static boolean contains(int[] array, int value) {
+ if (array == null) return false;
for (int element : array) {
if (element == value) {
return true;
@@ -170,6 +172,7 @@ public class ArrayUtils
}
public static boolean contains(long[] array, long value) {
+ if (array == null) return false;
for (long element : array) {
if (element == value) {
return true;
@@ -325,4 +328,8 @@ public class ArrayUtils
}
return cur;
}
+
+ public static long[] cloneOrNull(long[] array) {
+ return (array != null) ? array.clone() : null;
+ }
}
diff --git a/core/res/res/drawable-hdpi/notification_bg_low_normal.9.png b/core/res/res/drawable-hdpi/notification_bg_low_normal.9.png
deleted file mode 100644
index af91f5e..0000000
--- a/core/res/res/drawable-hdpi/notification_bg_low_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/notification_bg_low_pressed.9.png b/core/res/res/drawable-hdpi/notification_bg_low_pressed.9.png
deleted file mode 100644
index 9832ace..0000000
--- a/core/res/res/drawable-hdpi/notification_bg_low_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/notification_bg_normal.9.png b/core/res/res/drawable-hdpi/notification_bg_normal.9.png
deleted file mode 100644
index 6ebed8b..0000000
--- a/core/res/res/drawable-hdpi/notification_bg_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/notification_bg_normal_pressed.9.png b/core/res/res/drawable-hdpi/notification_bg_normal_pressed.9.png
deleted file mode 100644
index c271b11..0000000
--- a/core/res/res/drawable-hdpi/notification_bg_normal_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progress_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/progress_mtrl_alpha.9.png
index b11de9e..fbb2e0c 100644
--- a/core/res/res/drawable-hdpi/progress_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/progress_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progress_primary_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/progress_primary_mtrl_alpha.9.png
deleted file mode 100644
index a278ed7..0000000
--- a/core/res/res/drawable-hdpi/progress_primary_mtrl_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-ldpi/progress_mtrl_alpha.9.png b/core/res/res/drawable-ldpi/progress_mtrl_alpha.9.png
index a58128f..cd39bb4 100644
--- a/core/res/res/drawable-ldpi/progress_mtrl_alpha.9.png
+++ b/core/res/res/drawable-ldpi/progress_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/progress_primary_mtrl_alpha.9.png b/core/res/res/drawable-ldpi/progress_primary_mtrl_alpha.9.png
deleted file mode 100644
index eb0933b..0000000
--- a/core/res/res/drawable-ldpi/progress_primary_mtrl_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/notification_bg_low_normal.9.png b/core/res/res/drawable-mdpi/notification_bg_low_normal.9.png
deleted file mode 100644
index 62de9d7..0000000
--- a/core/res/res/drawable-mdpi/notification_bg_low_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/notification_bg_low_pressed.9.png b/core/res/res/drawable-mdpi/notification_bg_low_pressed.9.png
deleted file mode 100644
index 8a6011e..0000000
--- a/core/res/res/drawable-mdpi/notification_bg_low_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/notification_bg_normal.9.png b/core/res/res/drawable-mdpi/notification_bg_normal.9.png
deleted file mode 100644
index aa239b3..0000000
--- a/core/res/res/drawable-mdpi/notification_bg_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/notification_bg_normal_pressed.9.png b/core/res/res/drawable-mdpi/notification_bg_normal_pressed.9.png
deleted file mode 100644
index 525120d..0000000
--- a/core/res/res/drawable-mdpi/notification_bg_normal_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progress_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/progress_mtrl_alpha.9.png
index 8991421..92d4b05 100644
--- a/core/res/res/drawable-mdpi/progress_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/progress_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progress_primary_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/progress_primary_mtrl_alpha.9.png
deleted file mode 100644
index 07cbed8..0000000
--- a/core/res/res/drawable-mdpi/progress_primary_mtrl_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/notification_bg_low_normal.9.png b/core/res/res/drawable-xhdpi/notification_bg_low_normal.9.png
deleted file mode 100644
index 8c884de..0000000
--- a/core/res/res/drawable-xhdpi/notification_bg_low_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/notification_bg_low_pressed.9.png b/core/res/res/drawable-xhdpi/notification_bg_low_pressed.9.png
deleted file mode 100644
index 2159cf5..0000000
--- a/core/res/res/drawable-xhdpi/notification_bg_low_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/notification_bg_normal.9.png b/core/res/res/drawable-xhdpi/notification_bg_normal.9.png
deleted file mode 100644
index bdf477b..0000000
--- a/core/res/res/drawable-xhdpi/notification_bg_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/notification_bg_normal_pressed.9.png b/core/res/res/drawable-xhdpi/notification_bg_normal_pressed.9.png
deleted file mode 100644
index 3f054fb..0000000
--- a/core/res/res/drawable-xhdpi/notification_bg_normal_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progress_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/progress_mtrl_alpha.9.png
index 4970f56..e3c4eeb 100644
--- a/core/res/res/drawable-xhdpi/progress_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/progress_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progress_primary_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/progress_primary_mtrl_alpha.9.png
deleted file mode 100644
index 5c7e5cd..0000000
--- a/core/res/res/drawable-xhdpi/progress_primary_mtrl_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/notification_bg_low_pressed.9.png b/core/res/res/drawable-xxhdpi/notification_bg_low_pressed.9.png
deleted file mode 100644
index b4e7559..0000000
--- a/core/res/res/drawable-xxhdpi/notification_bg_low_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/notification_bg_normal_pressed.9.png b/core/res/res/drawable-xxhdpi/notification_bg_normal_pressed.9.png
deleted file mode 100644
index 936fbe5..0000000
--- a/core/res/res/drawable-xxhdpi/notification_bg_normal_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progress_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/progress_mtrl_alpha.9.png
index 74a259b..452f45c 100644
--- a/core/res/res/drawable-xxhdpi/progress_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/progress_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progress_primary_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/progress_primary_mtrl_alpha.9.png
deleted file mode 100644
index 2d4eb3f..0000000
--- a/core/res/res/drawable-xxhdpi/progress_primary_mtrl_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/notification_bg.xml b/core/res/res/drawable/notification_bg.xml
deleted file mode 100644
index 362a524..0000000
--- a/core/res/res/drawable/notification_bg.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
- android:exitFadeDuration="@android:integer/config_mediumAnimTime">
-
- <item android:state_pressed="true" android:drawable="@drawable/notification_bg_normal_pressed" />
- <item android:state_pressed="false" android:drawable="@drawable/notification_bg_normal" />
-</selector>
diff --git a/core/res/res/drawable/notification_bg_low.xml b/core/res/res/drawable/notification_bg_low.xml
deleted file mode 100644
index 466a885..0000000
--- a/core/res/res/drawable/notification_bg_low.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
- android:exitFadeDuration="@android:integer/config_mediumAnimTime">
-
- <item android:state_pressed="true" android:drawable="@drawable/notification_bg_low_pressed" />
- <item android:state_pressed="false" android:drawable="@drawable/notification_bg_low_normal" />
-</selector>
diff --git a/core/res/res/drawable/notification_material_bg.xml b/core/res/res/drawable/notification_material_bg.xml
deleted file mode 100644
index 44c67be..0000000
--- a/core/res/res/drawable/notification_material_bg.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?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
- -->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_pressed="true">
- <shape>
- <solid android:color="#ffd0d0d0" />
- <corners android:radius="@dimen/notification_material_rounded_rect_radius" />
- </shape>
- </item>
- <item>
- <shape>
- <solid android:color="#fffafafa" />
- <corners android:radius="@dimen/notification_material_rounded_rect_radius" />
- </shape>
- </item>
-</selector> \ No newline at end of file
diff --git a/core/res/res/drawable/progress_horizontal_material.xml b/core/res/res/drawable/progress_horizontal_material.xml
index eca1a24..d7440a9 100644
--- a/core/res/res/drawable/progress_horizontal_material.xml
+++ b/core/res/res/drawable/progress_horizontal_material.xml
@@ -22,12 +22,13 @@
<item android:id="@id/secondaryProgress">
<scale android:scaleWidth="100%">
<nine-patch android:src="@drawable/progress_mtrl_alpha"
- android:tint="?attr/colorControlActivated" />
+ android:tint="?attr/colorControlActivated"
+ android:alpha="0.5" />
</scale>
</item>
<item android:id="@id/progress">
<scale android:scaleWidth="100%">
- <nine-patch android:src="@drawable/progress_primary_mtrl_alpha"
+ <nine-patch android:src="@drawable/progress_mtrl_alpha"
android:tint="?attr/colorControlActivated" />
</scale>
</item>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 11d6dca..590abd4 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -432,7 +432,6 @@
<item>@drawable/list_divider_mtrl_alpha</item>
<item>@drawable/list_section_divider_mtrl_alpha</item>
<item>@drawable/popup_background_mtrl_mult</item>
- <item>@drawable/progress_primary_mtrl_alpha</item>
<item>@drawable/progress_mtrl_alpha</item>
<item>@drawable/scrollbar_handle_mtrl_alpha</item>
<item>@drawable/scrubber_control_from_pressed_mtrl_000</item>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a252a8b..3d1f5ee 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2394,7 +2394,7 @@
accessibility purposes. For example, a TextView before an EditText in
the UI usually specifies what infomation is contained in the EditText.
Hence, the TextView is a label for the EditText. -->
- <attr name="labelFor" format="integer" />
+ <attr name="labelFor" format="reference" />
<!-- Specifies a theme override for a view. When a theme override is set, the
view will be inflated using a {@link android.content.Context} themed with
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index e94b9dd..d2e023d 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -365,7 +365,4 @@
<!-- width of ImmersiveModeConfirmation (-1 for match_parent) -->
<dimen name="immersive_mode_cling_width">-1px</dimen>
- <!-- radius of the corners of the material rounded rect background -->
- <dimen name="notification_material_rounded_rect_radius">2dp</dimen>
-
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c68e6e6..5fea729 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -347,7 +347,6 @@
<java-symbol type="dimen" name="notification_title_text_size" />
<java-symbol type="dimen" name="notification_subtext_size" />
<java-symbol type="dimen" name="immersive_mode_cling_width" />
- <java-symbol type="dimen" name="notification_material_rounded_rect_radius" />
<java-symbol type="string" name="add_account_button_label" />
<java-symbol type="string" name="addToDictionary" />
@@ -1116,9 +1115,6 @@
<java-symbol type="drawable" name="unlock_halo" />
<java-symbol type="drawable" name="unlock_ring" />
<java-symbol type="drawable" name="unlock_wave" />
- <java-symbol type="drawable" name="notification_bg" />
- <java-symbol type="drawable" name="notification_bg_dim" />
- <java-symbol type="drawable" name="notification_bg_low" />
<java-symbol type="drawable" name="notification_template_icon_bg" />
<java-symbol type="drawable" name="notification_template_icon_low_bg" />
<java-symbol type="drawable" name="ic_media_route_on_holo_dark" />
@@ -1695,8 +1691,6 @@
<java-symbol type="color" name="notification_icon_bg_color" />
<java-symbol type="drawable" name="notification_icon_legacy_bg" />
<java-symbol type="drawable" name="notification_icon_legacy_bg_inset" />
- <java-symbol type="drawable" name="notification_material_bg_dim" />
- <java-symbol type="drawable" name="notification_material_bg" />
<java-symbol type="drawable" name="notification_material_media_progress" />
<java-symbol type="color" name="notification_media_action_bg" />
<java-symbol type="color" name="notification_media_progress" />
diff --git a/media/java/android/media/AudioDevice.java b/media/java/android/media/AudioDevice.java
new file mode 100644
index 0000000..1fd27fe
--- /dev/null
+++ b/media/java/android/media/AudioDevice.java
@@ -0,0 +1,115 @@
+/*
+ * 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;
+
+import android.util.SparseIntArray;
+
+/**
+ * @hide
+ * CANDIDATE FOR PUBLIC API
+ */
+public class AudioDevice {
+
+ public static final int DEVICE_TYPE_UNKNOWN = 0;
+ public static final int DEVICE_TYPE_BUILTIN_EARPIECE = 1;
+ public static final int DEVICE_TYPE_BUILTIN_SPEAKER = 2;
+ public static final int DEVICE_TYPE_WIRED_HEADSET = 3;
+ public static final int DEVICE_TYPE_WIRED_HEADPHONES = 4;
+ public static final int DEVICE_TYPE_LINE_ANALOG = 5;
+ public static final int DEVICE_TYPE_LINE_DIGITAL = 6;
+ public static final int DEVICE_TYPE_BLUETOOTH_SCO = 7;
+ public static final int DEVICE_TYPE_BLUETOOTH_A2DP = 8;
+ public static final int DEVICE_TYPE_HDMI = 9;
+ public static final int DEVICE_TYPE_HDMI_ARC = 10;
+ public static final int DEVICE_TYPE_USB_DEVICE = 11;
+ public static final int DEVICE_TYPE_USB_ACCESSORY = 12;
+ public static final int DEVICE_TYPE_DOCK = 13;
+ public static final int DEVICE_TYPE_FM = 14;
+ public static final int DEVICE_TYPE_BUILTIN_MIC = 15;
+ public static final int DEVICE_TYPE_FM_TUNER = 16;
+ public static final int DEVICE_TYPE_TV_TUNER = 17;
+ public static final int DEVICE_TYPE_TELEPHONY = 18;
+
+ AudioDevicePortConfig mConfig;
+
+ AudioDevice(AudioDevicePortConfig config) {
+ mConfig = new AudioDevicePortConfig(config);
+ }
+
+ public boolean isInputDevice() {
+ return (mConfig.port().role() == AudioPort.ROLE_SOURCE);
+ }
+
+ public boolean isOutputDevice() {
+ return (mConfig.port().role() == AudioPort.ROLE_SINK);
+ }
+
+ public int getDeviceType() {
+ return INT_TO_EXT_DEVICE_MAPPING.get(mConfig.port().type(), DEVICE_TYPE_UNKNOWN);
+ }
+
+ public String getAddress() {
+ return mConfig.port().address();
+ }
+
+ private static final SparseIntArray INT_TO_EXT_DEVICE_MAPPING;
+
+ static {
+ INT_TO_EXT_DEVICE_MAPPING = new SparseIntArray();
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_EARPIECE, DEVICE_TYPE_BUILTIN_EARPIECE);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_SPEAKER, DEVICE_TYPE_BUILTIN_SPEAKER);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_WIRED_HEADSET, DEVICE_TYPE_WIRED_HEADSET);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE, DEVICE_TYPE_WIRED_HEADPHONES);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, DEVICE_TYPE_BLUETOOTH_SCO);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET, DEVICE_TYPE_BLUETOOTH_SCO);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT, DEVICE_TYPE_BLUETOOTH_SCO);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, DEVICE_TYPE_BLUETOOTH_A2DP);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, DEVICE_TYPE_BLUETOOTH_A2DP);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, DEVICE_TYPE_BLUETOOTH_A2DP);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_HDMI, DEVICE_TYPE_HDMI);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET, DEVICE_TYPE_DOCK);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET, DEVICE_TYPE_DOCK);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_USB_ACCESSORY, DEVICE_TYPE_USB_ACCESSORY);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_USB_DEVICE, DEVICE_TYPE_USB_DEVICE);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_TELEPHONY_TX, DEVICE_TYPE_TELEPHONY);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_LINE, DEVICE_TYPE_LINE_ANALOG);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_HDMI_ARC, DEVICE_TYPE_HDMI_ARC);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_SPDIF, DEVICE_TYPE_LINE_DIGITAL);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_FM, DEVICE_TYPE_FM);
+
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUILTIN_MIC, DEVICE_TYPE_BUILTIN_MIC);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET, DEVICE_TYPE_BLUETOOTH_SCO);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_WIRED_HEADSET, DEVICE_TYPE_WIRED_HEADSET);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_HDMI, DEVICE_TYPE_HDMI);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_TELEPHONY_RX, DEVICE_TYPE_TELEPHONY);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BACK_MIC, DEVICE_TYPE_BUILTIN_MIC);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_ANLG_DOCK_HEADSET, DEVICE_TYPE_DOCK);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_DGTL_DOCK_HEADSET, DEVICE_TYPE_DOCK);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_USB_ACCESSORY, DEVICE_TYPE_USB_ACCESSORY);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_USB_DEVICE, DEVICE_TYPE_USB_DEVICE);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_FM_TUNER, DEVICE_TYPE_FM_TUNER);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_TV_TUNER, DEVICE_TYPE_TV_TUNER);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_LINE, DEVICE_TYPE_LINE_ANALOG);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_SPDIF, DEVICE_TYPE_LINE_DIGITAL);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, DEVICE_TYPE_BLUETOOTH_A2DP);
+
+ // not covered here, legacy
+ //AudioSystem.DEVICE_OUT_REMOTE_SUBMIX
+ //AudioSystem.DEVICE_IN_REMOTE_SUBMIX
+ }
+}
+
diff --git a/media/java/android/media/AudioDevicePortConfig.java b/media/java/android/media/AudioDevicePortConfig.java
index a381e10..e468a53 100644
--- a/media/java/android/media/AudioDevicePortConfig.java
+++ b/media/java/android/media/AudioDevicePortConfig.java
@@ -31,6 +31,11 @@ public class AudioDevicePortConfig extends AudioPortConfig {
super((AudioPort)devicePort, samplingRate, channelMask, format, gain);
}
+ AudioDevicePortConfig(AudioDevicePortConfig config) {
+ this(config.port(), config.samplingRate(), config.channelMask(), config.format(),
+ config.gain());
+ }
+
/**
* Returns the audio device port this AudioDevicePortConfig is issued from.
*/
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 168fb41..74ff3b1 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -30,7 +30,6 @@ import android.content.pm.PackageParser;
import android.content.pm.PackageParser.PackageParserException;
import android.content.res.ObbInfo;
import android.content.res.ObbScanner;
-import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Environment.UserEnvironment;
@@ -45,7 +44,6 @@ import android.provider.Settings;
import android.system.ErrnoException;
import android.system.Os;
import android.system.StructStatVfs;
-import android.util.DisplayMetrics;
import android.util.Slog;
import com.android.internal.app.IMediaContainerService;
@@ -53,6 +51,9 @@ import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.NativeLibraryHelper.ApkHandle;
import com.android.internal.content.PackageHelper;
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
@@ -71,9 +72,6 @@ import javax.crypto.CipherInputStream;
import javax.crypto.Mac;
import javax.crypto.NoSuchPaddingException;
-import libcore.io.IoUtils;
-import libcore.io.Streams;
-
/*
* This service copies a downloaded apk to a file passed in as
* a ParcelFileDescriptor or to a newly created container specified
@@ -101,14 +99,14 @@ public class DefaultContainerService extends IntentService {
* @return Returns the new cache path where the resource has been copied into
*
*/
- public String copyResourceToContainer(final Uri packageURI, final String cid,
+ @Override
+ public String copyResourceToContainer(final String packagePath, final String cid,
final String key, final String resFileName, final String publicResFileName,
boolean isExternal, boolean isForwardLocked, String abiOverride) {
- if (packageURI == null || cid == null) {
+ if (packagePath == null || cid == null) {
return null;
}
-
if (isExternal) {
// Make sure the sdcard is mounted.
String status = Environment.getExternalStorageState();
@@ -120,11 +118,11 @@ public class DefaultContainerService extends IntentService {
ApkHandle handle = null;
try {
- handle = ApkHandle.create(packageURI.getPath());
- return copyResourceInner(packageURI, cid, key, resFileName, publicResFileName,
+ handle = ApkHandle.create(packagePath);
+ return copyResourceInner(packagePath, cid, key, resFileName, publicResFileName,
isExternal, isForwardLocked, handle, abiOverride);
} catch (IOException ioe) {
- Slog.w(TAG, "Problem opening APK: " + packageURI.getPath());
+ Slog.w(TAG, "Problem opening APK: " + packagePath);
return null;
} finally {
IoUtils.closeQuietly(handle);
@@ -142,9 +140,10 @@ public class DefaultContainerService extends IntentService {
* @return returns status code according to those in
* {@link PackageManager}
*/
- public int copyResource(final Uri packageURI, ContainerEncryptionParams encryptionParams,
- ParcelFileDescriptor outStream) {
- if (packageURI == null || outStream == null) {
+ @Override
+ public int copyResource(final String packagePath,
+ ContainerEncryptionParams encryptionParams, ParcelFileDescriptor outStream) {
+ if (packagePath == null || outStream == null) {
return PackageManager.INSTALL_FAILED_INVALID_URI;
}
@@ -152,18 +151,18 @@ public class DefaultContainerService extends IntentService {
= new ParcelFileDescriptor.AutoCloseOutputStream(outStream);
try {
- copyFile(packageURI, autoOut, encryptionParams);
+ copyFile(packagePath, autoOut, encryptionParams);
return PackageManager.INSTALL_SUCCEEDED;
} catch (FileNotFoundException e) {
- Slog.e(TAG, "Could not copy URI " + packageURI.toString() + " FNF: "
+ Slog.e(TAG, "Could not copy URI " + packagePath.toString() + " FNF: "
+ e.getMessage());
return PackageManager.INSTALL_FAILED_INVALID_URI;
} catch (IOException e) {
- Slog.e(TAG, "Could not copy URI " + packageURI.toString() + " IO: "
+ Slog.e(TAG, "Could not copy URI " + packagePath.toString() + " IO: "
+ e.getMessage());
return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
} catch (DigestException e) {
- Slog.e(TAG, "Could not copy URI " + packageURI.toString() + " Security: "
+ Slog.e(TAG, "Could not copy URI " + packagePath.toString() + " Security: "
+ e.getMessage());
return PackageManager.INSTALL_FAILED_INVALID_APK;
} finally {
@@ -217,9 +216,9 @@ public class DefaultContainerService extends IntentService {
}
@Override
- public boolean checkInternalFreeStorage(Uri packageUri, boolean isForwardLocked,
+ public boolean checkInternalFreeStorage(String packagePath, boolean isForwardLocked,
long threshold) throws RemoteException {
- final File apkFile = new File(packageUri.getPath());
+ final File apkFile = new File(packagePath);
try {
return isUnderInternalThreshold(apkFile, isForwardLocked, threshold);
} catch (IOException e) {
@@ -228,9 +227,9 @@ public class DefaultContainerService extends IntentService {
}
@Override
- public boolean checkExternalFreeStorage(Uri packageUri, boolean isForwardLocked,
+ public boolean checkExternalFreeStorage(String packagePath, boolean isForwardLocked,
String abiOverride) throws RemoteException {
- final File apkFile = new File(packageUri.getPath());
+ final File apkFile = new File(packagePath);
try {
return isUnderExternalThreshold(apkFile, isForwardLocked, abiOverride);
} catch (IOException e) {
@@ -238,6 +237,7 @@ public class DefaultContainerService extends IntentService {
}
}
+ @Override
public ObbInfo getObbInfo(String filename) {
try {
return ObbScanner.getObbInfo(filename);
@@ -347,11 +347,11 @@ public class DefaultContainerService extends IntentService {
return mBinder;
}
- private String copyResourceInner(Uri packageURI, String newCid, String key, String resFileName,
+ private String copyResourceInner(String packagePath, String newCid, String key, String resFileName,
String publicResFileName, boolean isExternal, boolean isForwardLocked,
ApkHandle handle, String abiOverride) {
// The .apk file
- String codePath = packageURI.getPath();
+ String codePath = packagePath;
File codeFile = new File(codePath);
String[] abiList = Build.SUPPORTED_ABIS;
@@ -492,39 +492,13 @@ public class DefaultContainerService extends IntentService {
}
}
- private void copyFile(Uri pPackageURI, OutputStream outStream,
+ private void copyFile(String packagePath, OutputStream outStream,
ContainerEncryptionParams encryptionParams) throws FileNotFoundException, IOException,
DigestException {
- String scheme = pPackageURI.getScheme();
InputStream inStream = null;
try {
- if (scheme == null || scheme.equals("file")) {
- final InputStream is = new FileInputStream(new File(pPackageURI.getPath()));
- inStream = new BufferedInputStream(is);
- } else if (scheme.equals("content")) {
- final ParcelFileDescriptor fd;
- try {
- fd = getContentResolver().openFileDescriptor(pPackageURI, "r");
- } catch (FileNotFoundException e) {
- Slog.e(TAG, "Couldn't open file descriptor from download service. "
- + "Failed with exception " + e);
- throw e;
- }
-
- if (fd == null) {
- Slog.e(TAG, "Provider returned no file descriptor for " +
- pPackageURI.toString());
- throw new FileNotFoundException("provider returned no file descriptor");
- } else {
- if (localLOGV) {
- Slog.i(TAG, "Opened file descriptor from download service.");
- }
- inStream = new ParcelFileDescriptor.AutoCloseInputStream(fd);
- }
- } else {
- Slog.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
- throw new FileNotFoundException("Package URI is not 'file:' or 'content:'");
- }
+ final InputStream is = new FileInputStream(new File(packagePath));
+ inStream = new BufferedInputStream(is);
/*
* If this resource is encrypted, get the decrypted stream version
diff --git a/core/res/res/drawable/notification_material_bg_dim.xml b/packages/SystemUI/res/drawable/notification_material_bg.xml
index 9b691e6..6a0277f 100644
--- a/core/res/res/drawable/notification_material_bg_dim.xml
+++ b/packages/SystemUI/res/drawable/notification_material_bg.xml
@@ -16,17 +16,11 @@
-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="@color/white">
+ android:color="@color/notification_ripple_untinted_color">
<item>
<shape>
- <solid android:color="#d4ffffff" />
+ <solid android:color="@color/notification_material_background_color" />
<corners android:radius="@dimen/notification_material_rounded_rect_radius" />
</shape>
</item>
- <item android:id="@id/mask">
- <shape>
- <solid android:color="@color/white" />
- <corners android:radius="@dimen/notification_material_rounded_rect_radius" />
- </shape>
- </item>
-</ripple>
+</ripple> \ No newline at end of file
diff --git a/core/res/res/drawable/notification_bg_dim.xml b/packages/SystemUI/res/drawable/notification_material_bg_dim.xml
index 5c245f8..b04394d 100644
--- a/core/res/res/drawable/notification_bg_dim.xml
+++ b/packages/SystemUI/res/drawable/notification_material_bg_dim.xml
@@ -14,8 +14,7 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="#ff444444">
- <item android:drawable="@drawable/notification_bg_normal" />
-</ripple> \ No newline at end of file
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@color/notification_material_background_dimmed_color" />
+ <corners android:radius="@dimen/notification_material_rounded_rect_radius" />
+</shape>
diff --git a/packages/SystemUI/res/drawable/notification_scrim.xml b/packages/SystemUI/res/drawable/notification_scrim.xml
index ff7e31f..53ba213 100644
--- a/packages/SystemUI/res/drawable/notification_scrim.xml
+++ b/packages/SystemUI/res/drawable/notification_scrim.xml
@@ -17,6 +17,6 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="#34000000" />
- <corners android:radius="@*android:dimen/notification_material_rounded_rect_radius" />
+ <solid android:color="#08000000" />
+ <corners android:radius="@dimen/notification_material_rounded_rect_radius" />
</shape> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/qs_panel_background.xml b/packages/SystemUI/res/drawable/qs_panel_background.xml
index e579d87..b4e311f 100644
--- a/packages/SystemUI/res/drawable/qs_panel_background.xml
+++ b/packages/SystemUI/res/drawable/qs_panel_background.xml
@@ -18,6 +18,6 @@
<corners
android:topLeftRadius="0dp"
android:topRightRadius="0dp"
- android:bottomLeftRadius="@*android:dimen/notification_material_rounded_rect_radius"
- android:bottomRightRadius="@*android:dimen/notification_material_rounded_rect_radius"/>
+ android:bottomLeftRadius="@dimen/notification_material_rounded_rect_radius"
+ android:bottomRightRadius="@dimen/notification_material_rounded_rect_radius"/>
</shape>
diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml
index e1c460c..ca46437 100644
--- a/packages/SystemUI/res/layout/qs_detail.xml
+++ b/packages/SystemUI/res/layout/qs_detail.xml
@@ -17,41 +17,36 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@color/system_primary_color" >
+ android:background="@color/system_primary_color"
+ android:padding="16dp" >
- <ImageView
+ <TextView
android:id="@android:id/button1"
- android:layout_width="64dp"
- android:layout_height="64dp"
- android:layout_alignParentStart="true"
- android:contentDescription="@string/accessibility_quick_settings_close"
- android:padding="@dimen/qs_panel_padding"
- android:src="@drawable/ic_qs_back" />
+ style="@style/QSBorderlessButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minWidth="88dp"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentEnd="true"
+ android:text="@string/quick_settings_done"
+ android:textAppearance="@style/TextAppearance.QS.DetailButton" />
<TextView
- android:id="@android:id/title"
- android:layout_width="match_parent"
- android:layout_height="64dp"
- android:layout_alignParentTop="true"
- android:layout_toEndOf="@android:id/button1"
- android:layout_toStartOf="@android:id/checkbox"
- android:gravity="center_vertical"
- android:textAppearance="@style/TextAppearance.QS.DetailHeader" />
-
- <ImageView
- android:id="@android:id/custom"
- android:layout_width="match_parent"
+ android:id="@android:id/button2"
+ style="@style/QSBorderlessButton"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_below="@android:id/title"
- android:layout_marginLeft="16dip"
- android:layout_marginRight="16dip"
- android:scaleType="fitXY"
- android:src="?android:attr/dividerHorizontal" />
+ android:layout_alignParentBottom="true"
+ android:layout_marginEnd="8dp"
+ android:minWidth="132dp"
+ android:layout_toStartOf="@android:id/button1"
+ android:text="@string/quick_settings_more_settings"
+ android:textAppearance="@style/TextAppearance.QS.DetailButton" />
<FrameLayout
android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_below="@android:id/custom" />
+ android:layout_above="@android:id/button1" />
</RelativeLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_detail_header.xml b/packages/SystemUI/res/layout/qs_detail_header.xml
new file mode 100644
index 0000000..fcbb32c
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_detail_header.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/BrightnessDialogContainer"
+ android:background="@drawable/btn_borderless_rect" >
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:textAppearance="@style/TextAppearance.QS.DetailHeader" />
+
+ <Switch
+ android:id="@android:id/toggle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="false"
+ android:textAppearance="@style/TextAppearance.QS.DetailHeader" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_detail_item.xml b/packages/SystemUI/res/layout/qs_detail_item.xml
new file mode 100644
index 0000000..c5eaed9
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_detail_item.xml
@@ -0,0 +1,51 @@
+<?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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/qs_detail_item_height"
+ android:gravity="center_vertical"
+ android:background="@drawable/btn_borderless_rect"
+ android:clickable="true"
+ android:orientation="horizontal" >
+
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_marginEnd="12dp" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="20dp"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="@style/TextAppearance.QS.DetailItemPrimary" />
+
+ <TextView
+ android:id="@android:id/summary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="2dp"
+ android:textAppearance="@style/TextAppearance.QS.DetailItemSecondary" />
+ </LinearLayout>
+
+</LinearLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
index 97ed9a0..58547b9 100644
--- a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
+++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
@@ -30,7 +30,7 @@
<com.android.systemui.settings.ToggleSlider
android:id="@+id/brightness_slider"
android:layout_width="0dp"
- android:layout_height="44dp"
+ android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
systemui:text="@string/status_bar_settings_auto_brightness_label" />
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 2188a8e..1f68cd8 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -56,12 +56,6 @@
android:clipToPadding="false"
android:clipChildren="false">
- <com.android.systemui.statusbar.stack.NotificationStackScrollLayout
- android:id="@+id/notification_stack_scroller"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_marginBottom="@dimen/close_handle_underlap"/>
-
<ViewStub
android:id="@+id/keyguard_user_switcher"
android:layout_height="wrap_content"
@@ -90,12 +84,25 @@
android:layout_marginRight="@dimen/notification_side_padding"/>
<!-- A view to reserve space for the collapsed stack -->
+ <!-- Layout height: notification_min_height + bottom_stack_peek_amount -->
<View
- android:layout_height="@dimen/collapsed_stack_height"
- android:layout_width="match_parent"/>
+ android:id="@+id/reserve_notification_space"
+ android:layout_height="@dimen/min_stack_height"
+ android:layout_width="match_parent"
+ android:layout_marginTop="@dimen/notifications_top_padding" />
+
+ <View
+ android:layout_height="@dimen/notification_side_padding"
+ android:layout_width="match_parent" />
</LinearLayout>
</com.android.systemui.statusbar.phone.ObservableScrollView>
+ <com.android.systemui.statusbar.stack.NotificationStackScrollLayout
+ android:id="@+id/notification_stack_scroller"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginBottom="@dimen/close_handle_underlap"/>
+
</com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer>
<include layout="@layout/status_bar_expanded_header" />
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index d239208..70589b7 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -135,13 +135,22 @@
android:textColor="#ffffff"
android:singleLine="true" />
- <include
- layout="@layout/quick_settings_brightness_dialog"
- android:id="@+id/brightness_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- />
+
+ <include
+ android:id="@+id/qs_detail_header"
+ layout="@layout/qs_detail_header"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ />
+ <include
+ android:id="@+id/brightness_container"
+ layout="@layout/quick_settings_brightness_dialog"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ />
+
<TextView
android:id="@+id/header_debug_info"
diff --git a/packages/SystemUI/res/layout/zen_mode_condition.xml b/packages/SystemUI/res/layout/zen_mode_condition.xml
index 6d63bb0..6ab8cf3 100644
--- a/packages/SystemUI/res/layout/zen_mode_condition.xml
+++ b/packages/SystemUI/res/layout/zen_mode_condition.xml
@@ -41,7 +41,7 @@
<ImageView
android:id="@android:id/button1"
- style="@style/BorderlessButton"
+ style="@style/QSBorderlessButton"
android:layout_width="@dimen/zen_mode_condition_height"
android:layout_height="@dimen/zen_mode_condition_height"
android:layout_alignParentEnd="true"
@@ -53,7 +53,7 @@
<ImageView
android:id="@android:id/button2"
- style="@style/BorderlessButton"
+ style="@style/QSBorderlessButton"
android:layout_width="@dimen/zen_mode_condition_height"
android:layout_height="@dimen/zen_mode_condition_height"
android:layout_alignParentEnd="true"
diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml
index 0a8f852..0420cbc 100644
--- a/packages/SystemUI/res/layout/zen_mode_panel.xml
+++ b/packages/SystemUI/res/layout/zen_mode_panel.xml
@@ -42,7 +42,7 @@
<TextView
android:id="@android:id/button2"
- style="@style/BorderlessButton"
+ style="@style/QSBorderlessButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 19d72c4..a93768b 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -60,6 +60,24 @@
<color name="keyguard_affordance">#ffffffff</color>
+ <!-- The color of the legacy notification background -->
+ <color name="notification_legacy_background_color">#ff1a1a1a</color>
+
+ <!-- The color of the material notification background -->
+ <color name="notification_material_background_color">#fffafafa</color>
+
+ <!-- The color of the material notification background when dimmed -->
+ <color name="notification_material_background_dimmed_color">#d4ffffff</color>
+
+ <!-- The color of the material notification background when low priority -->
+ <color name="notification_material_background_low_priority_color">#ffdcdcdc</color>
+
+ <!-- The color of the ripples on the untinted notifications -->
+ <color name="notification_ripple_untinted_color">#20000000</color>
+
+ <!-- The color of the ripples on the tinted notifications -->
+ <color name="notification_ripple_tinted_color">#30ffffff</color>
+
<!-- The color of the circle around the primary user in the user switcher -->
<color name="current_user_border_color">@color/primary_color</color>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 8ee9155..adec883 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -168,6 +168,9 @@
<dimen name="qs_tile_padding_bottom">16dp</dimen>
<dimen name="qs_tile_spacing">4dp</dimen>
<dimen name="qs_panel_padding_bottom">8dp</dimen>
+ <dimen name="qs_detail_item_height">48dp</dimen>
+ <dimen name="qs_detail_item_height_connected">72dp</dimen>
+
<!-- How far the expanded QS panel peeks from the header in collapsed state. -->
<dimen name="qs_peek_height">8dp</dimen>
@@ -227,6 +230,9 @@
<!-- Space reserved for the cards behind the top card in the bottom stack -->
<dimen name="bottom_stack_peek_amount">12dp</dimen>
+ <!-- bottom_stack_peek_amount + notification_min_height -->
+ <dimen name="min_stack_height">76dp</dimen>
+
<!-- The height of the area before the bottom stack in which the notifications slow down -->
<dimen name="bottom_stack_slow_down_length">12dp</dimen>
@@ -248,9 +254,6 @@
<!-- The height of the speed bump view. -->
<dimen name="speed_bump_height">16dp</dimen>
- <!-- The total height of the stack in its collapsed size (i.e. when quick settings is open) -->
- <dimen name="collapsed_stack_height">94dp</dimen>
-
<!-- Width of the zen mode interstitial dialog. -->
<dimen name="zen_mode_dialog_width">320dp</dimen>
@@ -306,6 +309,9 @@
phone hints. -->
<dimen name="edge_tap_area_width">48dp</dimen>
+ <!-- radius of the corners of the material rounded rect background -->
+ <dimen name="notification_material_rounded_rect_radius">2dp</dimen>
+
<!-- end margin for multi user switch in expanded quick settings -->
<dimen name="multi_user_switch_expanded_margin">8dp</dimen>
diff --git a/packages/SystemUI/res/values/internal.xml b/packages/SystemUI/res/values/internal.xml
index 7b93d31..3b593d2 100644
--- a/packages/SystemUI/res/values/internal.xml
+++ b/packages/SystemUI/res/values/internal.xml
@@ -17,6 +17,5 @@
<resources>
<dimen name="status_bar_height">@*android:dimen/status_bar_height</dimen>
<dimen name="navigation_bar_height">@*android:dimen/navigation_bar_height</dimen>
- <drawable name="notification_material_bg">@*android:drawable/notification_material_bg</drawable>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index a8799f7..a5cfdbc 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -534,6 +534,10 @@
<string name="quick_settings_color_space_label">Color correction mode</string>
<!-- QuickSettings: Control panel: Label for button that navigates to settings. [CHAR LIMIT=NONE] -->
<string name="quick_settings_more_settings">More settings</string>
+ <!-- QuickSettings: Control panel: Label for button that dismisses control panel. [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_done">Done</string>
+ <!-- QuickSettings: Control panel: Label for connected device. [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_connected">Connected</string>
<!-- QuickSettings: Tethering. [CHAR LIMIT=NONE] -->
<string name="quick_settings_tethering_label">Tethering</string>
<!-- QuickSettings: Hotspot. [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index e5d5b03..dd1b749 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -176,6 +176,7 @@
<item name="android:textSize">14sp</item>
<item name="android:textAllCaps">true</item>
<item name="android:fontFamily">sans-serif-medium</item>
+ <item name="android:gravity">center</item>
</style>
<style name="BaseBrightnessDialogContainer">
@@ -233,6 +234,11 @@
<item name="android:colorControlActivated">#ffffffff</item>
</style>
+ <style name="QSBorderlessButton">
+ <item name="android:padding">12dp</item>
+ <item name="android:background">@drawable/btn_borderless_rect</item>
+ <item name="android:gravity">center</item>
+ </style>
<style name="BorderlessButton" parent="@android:style/Widget.Material.Button.Borderless" />
<style name="BorderlessButton.Tiny">
diff --git a/packages/SystemUI/src/com/android/systemui/qs/CircularClipper.java b/packages/SystemUI/src/com/android/systemui/qs/CircularClipper.java
index ff904b3..327ed6a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/CircularClipper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/CircularClipper.java
@@ -21,23 +21,19 @@ import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.view.View;
+import android.view.ViewAnimationUtils;
/** Helper for view-level circular clip animations. **/
public class CircularClipper {
private final View mTarget;
- private Utils mUtils;
private ValueAnimator mAnimator;
public CircularClipper(View target) {
mTarget = target;
}
- public void setUtils(Utils utils) {
- mUtils = utils;
- }
-
public void animateCircularClip(int x, int y, boolean in, AnimatorListener listener) {
if (mAnimator != null) {
mAnimator.cancel();
@@ -49,14 +45,7 @@ public class CircularClipper {
r = (int) Math.max(r, Math.ceil(Math.sqrt(w * w + h * h)));
r = (int) Math.max(r, Math.ceil(Math.sqrt(x * x + h * h)));
- if (mUtils == null) {
- mTarget.setVisibility(in ? View.VISIBLE : View.GONE);
- if (listener != null) {
- listener.onAnimationEnd(null);
- }
- return;
- }
- mAnimator = mUtils.createRevealAnimator(mTarget, x, y, 0, r);
+ mAnimator = ViewAnimationUtils.createCircularReveal(mTarget, x, y, 0, r);
mAnimator.removeAllListeners();
if (listener != null) {
mAnimator.addListener(listener);
@@ -83,9 +72,4 @@ public class CircularClipper {
mTarget.setVisibility(View.GONE);
};
};
-
- public interface Utils {
- ValueAnimator createRevealAnimator(View v, int centerX, int centerY,
- float startRadius, float endRadius);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index d152887..51befd6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -20,15 +20,17 @@ import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
+import android.content.Intent;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.FrameLayout;
import com.android.systemui.R;
+import com.android.systemui.qs.QSTile.DetailAdapter;
import java.util.ArrayList;
@@ -38,7 +40,10 @@ public class QSPanel extends ViewGroup {
private final Context mContext;
private final ArrayList<TileRecord> mRecords = new ArrayList<TileRecord>();
- private final FrameLayout mDetail;
+ private final View mDetail;
+ private final ViewGroup mDetailContent;
+ private final View mDetailSettingsButton;
+ private final View mDetailDoneButton;
private final CircularClipper mClipper;
private final H mHandler = new H();
@@ -63,8 +68,10 @@ public class QSPanel extends ViewGroup {
super(context, attrs);
mContext = context;
- mDetail = new FrameLayout(mContext);
- mDetail.setBackgroundColor(mContext.getResources().getColor(R.color.system_primary_color));
+ mDetail = LayoutInflater.from(context).inflate(R.layout.qs_detail, this, false);
+ mDetailContent = (ViewGroup) mDetail.findViewById(android.R.id.content);
+ mDetailSettingsButton = mDetail.findViewById(android.R.id.button2);
+ mDetailDoneButton = mDetail.findViewById(android.R.id.button1);
mDetail.setVisibility(GONE);
mDetail.setClickable(true);
addView(mDetail);
@@ -91,10 +98,6 @@ public class QSPanel extends ViewGroup {
}
}
- public void setUtils(CircularClipper.Utils utils) {
- mClipper.setUtils(utils);
- }
-
public void setExpanded(boolean expanded) {
if (mExpanded == expanded) return;
mExpanded = expanded;
@@ -141,6 +144,12 @@ public class QSPanel extends ViewGroup {
public void onShowDetail(boolean show) {
QSPanel.this.showDetail(show, r);
}
+ @Override
+ public void onToggleStateChanged(boolean state) {
+ if (mDetailRecord == r) {
+ fireToggleStateChanged(state);
+ }
+ }
});
final View.OnClickListener click = new View.OnClickListener() {
@Override
@@ -165,20 +174,34 @@ public class QSPanel extends ViewGroup {
if (r == null) return;
AnimatorListener listener = null;
if (show) {
- if (mDetailRecord != null) return;
- if (r.detailView == null) {
- r.detailView = r.tile.createDetailView(mContext, mDetail);
- }
- if (r.detailView == null) return;
+ if (mDetailRecord != null) return; // already showing something in detail
+ r.detailAdapter = r.tile.getDetailAdapter();
+ if (r.detailAdapter == null) return;
+ r.detailView = r.detailAdapter.createDetailView(mContext, r.detailView, mDetailContent);
+ if (r.detailView == null) throw new IllegalStateException("Must return detail view");
+ mDetailDoneButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showDetail(false, mDetailRecord);
+ }
+ });
+ final Intent settingsIntent = r.detailAdapter.getSettingsIntent();
+ mDetailSettingsButton.setVisibility(settingsIntent != null ? VISIBLE : GONE);
+ mDetailSettingsButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mDetailRecord.tile.mHost.startSettingsActivity(settingsIntent);
+ }
+ });
mDetailRecord = r;
- mDetail.removeAllViews();
+ mDetailContent.removeAllViews();
mDetail.bringToFront();
- mDetail.addView(r.detailView);
+ mDetailContent.addView(r.detailView);
} else {
if (mDetailRecord == null) return;
listener = mTeardownDetailWhenDone;
}
- fireShowingDetail(show);
+ fireShowingDetail(show ? r.detailAdapter : null);
int x = r.tileView.getLeft() + r.tileView.getWidth() / 2;
int y = r.tileView.getTop() + r.tileView.getHeight() / 2;
mClipper.animateCircularClip(x, y, show, listener);
@@ -215,11 +238,7 @@ public class QSPanel extends ViewGroup {
record.tileView.measure(exactly(cw), exactly(ch));
}
int h = rows == 0 ? 0 : (getRowTop(rows) + mPanelPaddingBottom);
- mDetail.measure(exactly(width), unspecified());
- if (mDetail.getVisibility() == VISIBLE && mDetail.getChildCount() > 0) {
- final int dmh = mDetail.getMeasuredHeight();
- if (dmh > 0) h = Math.max(h, dmh);
- }
+ mDetail.measure(exactly(width), exactly(h));
setMeasuredDimension(width, h);
}
@@ -227,10 +246,6 @@ public class QSPanel extends ViewGroup {
return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
}
- private static int unspecified() {
- return MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
- }
-
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int w = getWidth();
@@ -263,9 +278,15 @@ public class QSPanel extends ViewGroup {
return cols;
}
- private void fireShowingDetail(boolean showingDetail) {
+ private void fireShowingDetail(QSTile.DetailAdapter detail) {
+ if (mCallback != null) {
+ mCallback.onShowingDetail(detail);
+ }
+ }
+
+ private void fireToggleStateChanged(boolean state) {
if (mCallback != null) {
- mCallback.onShowingDetail(showingDetail);
+ mCallback.onToggleStateChanged(state);
}
}
@@ -286,18 +307,20 @@ public class QSPanel extends ViewGroup {
QSTile<?> tile;
QSTileView tileView;
View detailView;
+ DetailAdapter detailAdapter;
int row;
int col;
}
private final AnimatorListenerAdapter mTeardownDetailWhenDone = new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
- mDetail.removeAllViews();
+ mDetailContent.removeAllViews();
mDetailRecord = null;
};
};
public interface Callback {
- void onShowingDetail(boolean showingDetail);
+ void onShowingDetail(QSTile.DetailAdapter detail);
+ void onToggleStateChanged(boolean state);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index ba350e5..62c9d9f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -26,7 +26,6 @@ import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
-import com.android.systemui.R;
import com.android.systemui.qs.QSTile.State;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.CastController;
@@ -57,7 +56,6 @@ public abstract class QSTile<TState extends State> implements Listenable {
protected final Context mContext;
protected final H mHandler;
protected final Handler mUiHandler = new Handler(Looper.getMainLooper());
- private final int mFeedbackStartDelay;
private Callback mCallback;
protected final TState mState = newTileState();
@@ -71,7 +69,6 @@ public abstract class QSTile<TState extends State> implements Listenable {
mHost = host;
mContext = host.getContext();
mHandler = new H(host.getLooper());
- mFeedbackStartDelay = mContext.getResources().getInteger(R.integer.feedback_start_delay);
}
public boolean supportsDualTargets() {
@@ -86,10 +83,18 @@ public abstract class QSTile<TState extends State> implements Listenable {
return new QSTileView(context);
}
- public View createDetailView(Context context, ViewGroup root) {
+ public DetailAdapter getDetailAdapter() {
return null; // optional
}
+ public interface DetailAdapter {
+ int getTitle();
+ Boolean getToggleState();
+ View createDetailView(Context context, View convertView, ViewGroup parent);
+ Intent getSettingsIntent();
+ void setToggleState(boolean state);
+ }
+
// safe to call from any thread
public void setCallback(Callback callback) {
@@ -120,8 +125,8 @@ public abstract class QSTile<TState extends State> implements Listenable {
mHandler.obtainMessage(H.USER_SWITCH, newUserId).sendToTarget();
}
- protected void postAfterFeedback(Runnable runnable) {
- mHandler.postDelayed(runnable, mFeedbackStartDelay);
+ public void fireToggleStateChanged(boolean state) {
+ mHandler.obtainMessage(H.TOGGLE_STATE_CHANGED, state ? 1 : 0, 0).sendToTarget();
}
// call only on tile worker looper
@@ -155,6 +160,12 @@ public abstract class QSTile<TState extends State> implements Listenable {
}
}
+ private void handleToggleStateChanged(boolean state) {
+ if (mCallback != null) {
+ mCallback.onToggleStateChanged(state);
+ }
+ }
+
protected void handleUserSwitch(int newUserId) {
handleRefreshState(null);
}
@@ -166,6 +177,7 @@ public abstract class QSTile<TState extends State> implements Listenable {
private static final int REFRESH_STATE = 4;
private static final int SHOW_DETAIL = 5;
private static final int USER_SWITCH = 6;
+ private static final int TOGGLE_STATE_CHANGED = 7;
private H(Looper looper) {
super(looper);
@@ -193,6 +205,9 @@ public abstract class QSTile<TState extends State> implements Listenable {
} else if (msg.what == USER_SWITCH) {
name = "handleUserSwitch";
handleUserSwitch(msg.arg1);
+ } else if (msg.what == TOGGLE_STATE_CHANGED) {
+ name = "handleToggleStateChanged";
+ handleToggleStateChanged(msg.arg1 != 0);
}
} catch (Throwable t) {
final String error = "Error in " + name;
@@ -205,6 +220,7 @@ public abstract class QSTile<TState extends State> implements Listenable {
public interface Callback {
void onStateChanged(State state);
void onShowDetail(boolean show);
+ void onToggleStateChanged(boolean state);
}
public interface Host {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BugreportTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BugreportTile.java
index 07ea825..a308e84 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BugreportTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BugreportTile.java
@@ -58,7 +58,7 @@ public class BugreportTile extends QSTile<QSTile.State> {
@Override
protected void handleClick() {
- postAfterFeedback(new Runnable() {
+ mHandler.post(new Runnable() {
@Override
public void run() {
mHost.collapsePanels();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 6793051..502713f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -65,7 +65,7 @@ public class CastTile extends QSTile<QSTile.BooleanState> {
@Override
protected void handleClick() {
- postAfterFeedback(new Runnable() {
+ mHandler.post(new Runnable() {
public void run() {
mHost.collapsePanels();
mUiHandler.post(mShowDialog);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NotificationsTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NotificationsTile.java
index c4bdb19..3bdea79 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NotificationsTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NotificationsTile.java
@@ -22,11 +22,9 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.util.Log;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.ViewGroup;
-import android.widget.TextView;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
@@ -47,45 +45,8 @@ public class NotificationsTile extends QSTile<NotificationsTile.NotificationsSta
}
@Override
- public View createDetailView(Context context, ViewGroup root) {
- final View v = LayoutInflater.from(context).inflate(R.layout.qs_detail, root, false);
- final TextView title = (TextView) v.findViewById(android.R.id.title);
- title.setText(R.string.quick_settings_notifications_label);
- final View close = v.findViewById(android.R.id.button1);
- close.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- showDetail(false);
- }
- });
- final ViewGroup content = (ViewGroup) v.findViewById(android.R.id.content);
- final VolumeComponent volumeComponent = mHost.getVolumeComponent();
- final VolumePanel vp = new VolumePanel(mContext, content, mZenController);
- v.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
- @Override
- public void onViewDetachedFromWindow(View v) {
- volumeComponent.setVolumePanel(null);
- }
-
- @Override
- public void onViewAttachedToWindow(View v) {
- vp.updateStates();
- volumeComponent.setVolumePanel(vp);
- }
- });
- vp.setZenModePanelCallback(new ZenModePanel.Callback() {
- @Override
- public void onMoreSettings() {
- mHost.startSettingsActivity(ZenModePanel.ZEN_SETTINGS);
- }
-
- @Override
- public void onInteraction() {
- // noop
- }
- });
- vp.postVolumeChanged(AudioManager.STREAM_RING, AudioManager.FLAG_SHOW_UI);
- return v;
+ public DetailAdapter getDetailAdapter() {
+ return mDetailAdapter;
}
@Override
@@ -164,4 +125,58 @@ public class NotificationsTile extends QSTile<NotificationsTile.NotificationsSta
}
}
};
+
+ private final DetailAdapter mDetailAdapter = new DetailAdapter() {
+
+ @Override
+ public int getTitle() {
+ return R.string.quick_settings_notifications_label;
+ }
+
+ @Override
+ public Boolean getToggleState() {
+ return null;
+ }
+
+ public void setToggleState(boolean state) {
+ // noop
+ }
+
+ public Intent getSettingsIntent() {
+ return ZenModePanel.ZEN_SETTINGS;
+ }
+
+ @Override
+ public View createDetailView(Context context, View convertView, ViewGroup parent) {
+ if (convertView != null) return convertView;
+ final VolumeComponent volumeComponent = mHost.getVolumeComponent();
+ final VolumePanel vp = new VolumePanel(mContext, parent, mZenController);
+ final View v = vp.getContentView();
+ v.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ volumeComponent.setVolumePanel(null);
+ }
+
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ vp.updateStates();
+ volumeComponent.setVolumePanel(vp);
+ }
+ });
+ vp.setZenModePanelCallback(new ZenModePanel.Callback() {
+ @Override
+ public void onMoreSettings() {
+ mHost.startSettingsActivity(ZenModePanel.ZEN_SETTINGS);
+ }
+
+ @Override
+ public void onInteraction() {
+ // noop
+ }
+ });
+ vp.postVolumeChanged(AudioManager.STREAM_RING, AudioManager.FLAG_SHOW_UI);
+ return v;
+ }
+ };
}
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 a236497..84eee24 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -21,23 +21,34 @@ import android.content.Intent;
import android.content.res.Resources;
import android.provider.Settings;
import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.QSTileView;
import com.android.systemui.qs.SignalTileView;
import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.NetworkController.AccessPoint;
import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
/** Quick settings tile: Wifi **/
public class WifiTile extends QSTile<QSTile.SignalState> {
private static final Intent WIFI_SETTINGS = new Intent(Settings.ACTION_WIFI_SETTINGS);
+ private static final int MAX_ITEMS = 4; // TODO temporary visual restriction
private final NetworkController mController;
+ private final WifiDetailAdapter mDetailAdapter;
public WifiTile(Host host) {
super(host);
mController = host.getNetworkController();
+ mDetailAdapter = new WifiDetailAdapter();
}
@Override
@@ -54,12 +65,20 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
public void setListening(boolean listening) {
if (listening) {
mController.addNetworkSignalChangedCallback(mCallback);
+ mController.addAccessPointCallback(mDetailAdapter);
+ mController.scanForAccessPoints();
} else {
mController.removeNetworkSignalChangedCallback(mCallback);
+ mController.removeAccessPointCallback(mDetailAdapter);
}
}
@Override
+ public DetailAdapter getDetailAdapter() {
+ return mDetailAdapter;
+ }
+
+ @Override
public QSTileView createTileView(Context context) {
return new SignalTileView(context);
}
@@ -71,7 +90,7 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
@Override
protected void handleSecondaryClick() {
- mHost.startSettingsActivity(WIFI_SETTINGS);
+ showDetail(true);
}
@Override
@@ -83,6 +102,11 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
boolean wifiConnected = cb.enabled && (cb.wifiSignalIconId > 0) && (cb.enabledDesc != null);
boolean wifiNotConnected = (cb.wifiSignalIconId > 0) && (cb.enabledDesc == null);
+ boolean enabledChanging = state.enabled != cb.enabled;
+ if (enabledChanging) {
+ mDetailAdapter.postUpdateItems();
+ fireToggleStateChanged(cb.enabled);
+ }
state.enabled = cb.enabled;
state.connected = wifiConnected;
state.activityIn = cb.enabled && cb.activityIn;
@@ -169,4 +193,96 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
// noop
}
};
+
+ private final class WifiDetailAdapter implements DetailAdapter,
+ NetworkController.AccessPointCallback {
+
+ private LinearLayout mItems;
+ private AccessPoint[] mAccessPoints;
+
+ @Override
+ public int getTitle() {
+ return R.string.quick_settings_wifi_label;
+ }
+
+ public Intent getSettingsIntent() {
+ return WIFI_SETTINGS;
+ }
+
+ @Override
+ public Boolean getToggleState() {
+ return mState.enabled;
+ }
+
+ @Override
+ public void setToggleState(boolean state) {
+ if (DEBUG) Log.d(TAG, "setToggleState " + state);
+ mController.setWifiEnabled(state);
+ showDetail(false);
+ }
+
+ @Override
+ public View createDetailView(Context context, View convertView, ViewGroup parent) {
+ if (convertView != null) return convertView;
+ mItems = new LinearLayout(context);
+ mItems.setOrientation(LinearLayout.VERTICAL);
+ updateItems();
+ return mItems;
+ }
+
+ @Override
+ public void onAccessPointsChanged(final AccessPoint[] accessPoints) {
+ mUiHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mAccessPoints = accessPoints;
+ updateItems();
+ }
+ });
+ }
+
+ public void postUpdateItems() {
+ mUiHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ updateItems();
+ }
+ });
+ }
+
+ private void updateItems() {
+ if (mItems == null) return;
+ mItems.removeAllViews();
+ if (mAccessPoints == null || mAccessPoints.length == 0 || !mState.enabled) return;
+ for (int i = 0; i < mAccessPoints.length; i++) {
+ final AccessPoint ap = mAccessPoints[i];
+ if (ap == null) continue;
+ final View item = LayoutInflater.from(mContext).inflate(R.layout.qs_detail_item,
+ mItems, false);
+ final ImageView iv = (ImageView) item.findViewById(android.R.id.icon);
+ iv.setImageResource(ap.iconId);
+ final TextView title = (TextView) item.findViewById(android.R.id.title);
+ title.setText(ap.ssid);
+ final TextView summary = (TextView) item.findViewById(android.R.id.summary);
+ if (ap.isConnected) {
+ item.setMinimumHeight(mContext.getResources()
+ .getDimensionPixelSize(R.dimen.qs_detail_item_height_connected));
+ summary.setText(R.string.quick_settings_connected);
+ } else {
+ summary.setVisibility(View.GONE);
+ }
+ item.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (!ap.isConnected) {
+ mController.connect(ap);
+ }
+ showDetail(false);
+ }
+ });
+ mItems.addView(item);
+ if (mItems.getChildCount() == MAX_ITEMS) break;
+ }
+ }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Console.java b/packages/SystemUI/src/com/android/systemui/recents/Console.java
index 33e05dd..0cb74b9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Console.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Console.java
@@ -43,7 +43,7 @@ public class Console {
public static final String AnsiWhite = "\u001B[37m";
// Console enabled state
- public static final boolean Enabled = false;
+ public static boolean Enabled = false;
/** Logs a key */
public static void log(String key) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 4fb1918..7a49a04 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -55,9 +55,9 @@ public class Constants {
public static final String TimeRecentsStartupKey = "startup";
public static final String TimeRecentsLaunchKey = "launchTask";
public static final String TimeRecentsScreenshotTransitionKey = "screenshot";
- public static final boolean TimeRecentsStartup = true;
- public static final boolean TimeRecentsLaunchTask = true;
- public static final boolean TimeRecentsScreenshotTransition = true;
+ public static final boolean TimeRecentsStartup = false;
+ public static final boolean TimeRecentsLaunchTask = false;
+ public static final boolean TimeRecentsScreenshotTransition = false;
public static final boolean RecentsComponent = false;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 4c52b24..19a38c7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -65,7 +65,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
AppWidgetHostView mSearchAppWidgetHostView;
boolean mVisible;
- boolean mTaskLaunched;
// Runnables to finish the Recents activity
FinishRecentsRunnable mFinishRunnable = new FinishRecentsRunnable(true);
@@ -198,18 +197,24 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
AlternateRecentsComponent.EXTRA_TRIGGERED_FROM_ALT_TAB, false);
mConfig.launchedWithNoRecentTasks = !root.hasTasks();
- // Show the scrim if we animate into Recents without window transitions
- mScrimViews.prepareEnterRecentsAnimation();
-
// Add the default no-recents layout
if (mEmptyView == null) {
mEmptyView = mEmptyViewStub.inflate();
}
if (mConfig.launchedWithNoRecentTasks) {
mEmptyView.setVisibility(View.VISIBLE);
+ mRecentsView.setSearchBarVisibility(View.GONE);
} else {
mEmptyView.setVisibility(View.GONE);
+ if (mRecentsView.hasSearchBar()) {
+ mRecentsView.setSearchBarVisibility(View.VISIBLE);
+ } else {
+ addSearchBarAppWidgetView();
+ }
}
+
+ // Show the scrim if we animate into Recents without window transitions
+ mScrimViews.prepareEnterRecentsAnimation();
}
/** Attempts to allocate and bind the search bar app widget */
@@ -352,20 +357,10 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
mFullscreenOverlayStub = (ViewStub) findViewById(R.id.fullscreen_overlay_stub);
mScrimViews = new SystemBarScrimViews(this, mConfig);
- // Update the recent tasks
- updateRecentsTasks(getIntent());
-
- // Prepare the screenshot transition if necessary
- if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
- mFullScreenOverlayView = (FullscreenTransitionOverlayView) mFullscreenOverlayStub.inflate();
- mFullScreenOverlayView.setCallbacks(this);
- mFullScreenOverlayView.prepareAnimateOnEnterRecents(AlternateRecentsComponent.getLastScreenshot());
- }
-
// Bind the search app widget when we first start up
bindSearchBarAppWidget();
- // Add the search bar layout
- addSearchBarAppWidgetView();
+ // Update the recent tasks
+ updateRecentsTasks(getIntent());
// Update if we are getting a configuration change
if (savedInstanceState != null) {
@@ -390,6 +385,13 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
} catch (InvocationTargetException e) {
e.printStackTrace();
}
+
+ // Prepare the screenshot transition if necessary
+ if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
+ mFullScreenOverlayView = (FullscreenTransitionOverlayView) mFullscreenOverlayStub.inflate();
+ mFullScreenOverlayView.setCallbacks(this);
+ mFullScreenOverlayView.prepareAnimateOnEnterRecents(AlternateRecentsComponent.getLastScreenshot());
+ }
}
void onConfigurationChange() {
@@ -404,8 +406,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
- // Reset the task launched flag if we encounter an onNewIntent() before onStop()
- mTaskLaunched = false;
if (Console.Enabled) {
Console.logDivider(Constants.Log.App.SystemUIHandshake);
@@ -426,9 +426,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
mFullScreenOverlayView.prepareAnimateOnEnterRecents(AlternateRecentsComponent.getLastScreenshot());
}
-
- // Don't attempt to rebind the search bar widget, but just add the search bar layout
- addSearchBarAppWidgetView();
}
@Override
@@ -509,7 +506,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
mVisible = false;
- mTaskLaunched = false;
}
@Override
@@ -632,15 +628,13 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
@Override
- public void onTaskLaunching() {
- mTaskLaunched = true;
-
+ public void onTaskViewClicked() {
// Mark recents as no longer visible
AlternateRecentsComponent.notifyVisibilityChanged(false);
}
@Override
- public void onLastTaskRemoved() {
+ public void onAllTaskViewsDismissed() {
mFinishLaunchHomeRunnable.run();
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index d57f779..3041a3c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -149,6 +149,9 @@ public class RecentsConfiguration {
// Debug mode
debugModeEnabled = settings.getBoolean(Constants.Values.App.Key_DebugModeEnabled, false);
+ if (debugModeEnabled) {
+ Console.Enabled = true;
+ }
// Animations
animationPxMovementPerSecond =
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
index b6895d1..49149a6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
@@ -69,7 +69,7 @@ class SystemUIMessageHandler extends Handler {
// since that is done when we compute the animation itself in the Recents component
// Create a dummy task stack & compute the rect for the thumbnail to animate to
- TaskStack stack = new TaskStack(context);
+ TaskStack stack = new TaskStack();
TaskStackView tsv = new TaskStackView(context, stack);
TaskStackViewLayoutAlgorithm algo = tsv.getStackAlgorithm();
Bundle replyData = new Bundle();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index 15f4a76..9d8d746 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -239,13 +239,14 @@ class TaskResourceLoader implements Runnable {
}
thumbnail.setHasAlpha(false);
loadThumbnail = thumbnail;
- mThumbnailCache.put(t.key, thumbnail);
} else {
loadThumbnail = mDefaultThumbnail;
Console.logError(mContext,
"Failed to load task top thumbnail for: " +
t.key.baseIntent.getComponent().getPackageName());
}
+ // We put the default thumbnail in the cache anyways
+ mThumbnailCache.put(t.key, loadThumbnail);
}
}
if (!mCancelled) {
@@ -321,6 +322,17 @@ public class RecentsTaskLoader {
" iconCache: " + iconCacheSize);
}
+ // Create the default assets
+ Bitmap icon = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
+ icon.eraseColor(0x00000000);
+ mDefaultThumbnail = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
+ mDefaultThumbnail.setHasAlpha(false);
+ mDefaultThumbnail.eraseColor(0xFFffffff);
+ mLoadingThumbnail = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
+ mLoadingThumbnail.setHasAlpha(false);
+ mLoadingThumbnail.eraseColor(0xFFffffff);
+ mDefaultApplicationIcon = new BitmapDrawable(context.getResources(), icon);
+
// Initialize the proxy, cache and loaders
mSystemServicesProxy = new SystemServicesProxy(context);
mPackageMonitor = new RecentsPackageMonitor();
@@ -330,14 +342,6 @@ public class RecentsTaskLoader {
mLoader = new TaskResourceLoader(mLoadQueue, mApplicationIconCache, mThumbnailCache,
mDefaultThumbnail);
- // Create the default assets
- Bitmap icon = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
- icon.eraseColor(0x00000000);
- mDefaultThumbnail = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
- mDefaultThumbnail.eraseColor(0xFFffffff);
- mLoadingThumbnail = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
- mLoadingThumbnail.eraseColor(0x00000000);
- mDefaultApplicationIcon = new BitmapDrawable(context.getResources(), icon);
if (Console.Enabled) {
Console.log(Constants.Log.App.TaskDataLoader,
"[RecentsTaskLoader|defaultBitmaps]",
@@ -392,7 +396,7 @@ public class RecentsTaskLoader {
RecentsConfiguration config = RecentsConfiguration.getInstance();
Resources res = context.getResources();
ArrayList<Task> tasksToForceLoad = new ArrayList<Task>();
- TaskStack stack = new TaskStack(context);
+ TaskStack stack = new TaskStack();
SpaceNode root = new SpaceNode(context);
root.setStack(stack);
@@ -416,7 +420,9 @@ public class RecentsTaskLoader {
activityLabel = (av.getLabel() != null ? av.getLabel() : ssp.getActivityLabel(info));
activityIcon = (av.getIcon() != null) ?
ssp.getBadgedIcon(new BitmapDrawable(res, av.getIcon()), t.userId) : null;
- activityColor = av.getPrimaryColor();
+ if (av.getPrimaryColor() != 0) {
+ activityColor = av.getPrimaryColor();
+ }
} else {
activityLabel = ssp.getActivityLabel(info);
}
@@ -464,10 +470,10 @@ public class RecentsTaskLoader {
task.thumbnail = ssp.getTaskThumbnail(task.key.id);
if (task.thumbnail != null) {
task.thumbnail.setHasAlpha(false);
- mThumbnailCache.put(task.key, task.thumbnail);
} else {
task.thumbnail = mDefaultThumbnail;
}
+ mThumbnailCache.put(task.key, task.thumbnail);
} else {
// Either the task has updated, or we haven't cached any information for the
// task, so reload it
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index d2de185..24e01bd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -139,13 +139,10 @@ public class TaskStack {
public void onStackUnfiltered(TaskStack newStack, ArrayList<Task> curTasks);
}
- Context mContext;
-
FilteredTaskList mTaskList = new FilteredTaskList();
TaskStackCallbacks mCb;
- public TaskStack(Context context) {
- mContext = context;
+ public TaskStack() {
}
/** Sets the callbacks for this task stack */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index b5b9cb5..f203d3e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -55,8 +55,8 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
/** The RecentsView callbacks */
public interface RecentsViewCallbacks {
- public void onTaskLaunching();
- public void onLastTaskRemoved();
+ public void onTaskViewClicked();
+ public void onAllTaskViewsDismissed();
public void onExitToHomeAnimationTriggered();
}
@@ -66,8 +66,6 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
// The space partitioning root of this container
SpaceNode mBSP;
- // Whether there are any tasks
- boolean mHasTasks;
// Search bar view
View mSearchBar;
// Recents view callbacks
@@ -100,15 +98,21 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
public void setBSP(SpaceNode n) {
mBSP = n;
+ // Remove all TaskStackViews (but leave the search bar)
+ int childCount = getChildCount();
+ for (int i = childCount - 1; i >= 0; i--) {
+ View v = getChildAt(i);
+ if (v != mSearchBar) {
+ removeViewAt(i);
+ }
+ }
+
// Create and add all the stacks for this partition of space.
- mHasTasks = false;
- removeAllViews();
ArrayList<TaskStack> stacks = mBSP.getStacks();
for (TaskStack stack : stacks) {
TaskStackView stackView = new TaskStackView(getContext(), stack);
stackView.setCallbacks(this);
addView(stackView);
- mHasTasks |= (stack.getTaskCount() > 0);
}
// Enable debug mode drawing
@@ -127,7 +131,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
- if (child instanceof TaskStackView) {
+ if (child != mSearchBar) {
TaskStackView stackView = (TaskStackView) child;
TaskStack stack = stackView.mStack;
// Iterate the stack views and try and find the focused task
@@ -140,7 +144,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
Console.log(Constants.Log.UI.Focus, "[RecentsView|launchFocusedTask]",
"Found focused Task");
}
- onTaskLaunched(stackView, tv, stack, task);
+ onTaskViewClicked(stackView, tv, stack, task);
return true;
}
}
@@ -159,7 +163,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
- if (child instanceof TaskStackView) {
+ if (child != mSearchBar) {
TaskStackView stackView = (TaskStackView) child;
TaskStack stack = stackView.mStack;
ArrayList<Task> tasks = stack.getTasks();
@@ -176,7 +180,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
tv = stv;
}
}
- onTaskLaunched(stackView, tv, stack, task);
+ onTaskViewClicked(stackView, tv, stack, task);
return true;
}
}
@@ -193,7 +197,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
- if (child instanceof TaskStackView) {
+ if (child != mSearchBar) {
TaskStackView stackView = (TaskStackView) child;
stackView.startEnterRecentsAnimation(ctx);
}
@@ -213,7 +217,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
- if (child instanceof TaskStackView) {
+ if (child != mSearchBar) {
TaskStackView stackView = (TaskStackView) child;
stackView.startExitToHomeAnimation(ctx);
}
@@ -238,7 +242,6 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
// Add the new search bar
if (searchBar != null) {
mSearchBar = searchBar;
- mSearchBar.setVisibility(mHasTasks ? View.VISIBLE : View.GONE);
addView(mSearchBar);
if (Console.Enabled) {
@@ -250,6 +253,18 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
}
}
+ /** Returns whether there is currently a search bar */
+ public boolean hasSearchBar() {
+ return mSearchBar != null;
+ }
+
+ /** Sets the visibility of the search bar */
+ public void setSearchBarVisibility(int visibility) {
+ if (mSearchBar != null) {
+ mSearchBar.setVisibility(visibility);
+ }
+ }
+
/**
* This is called with the full size of the window since we are handling our own insets.
*/
@@ -289,7 +304,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
- if (child instanceof TaskStackView && child.getVisibility() != GONE) {
+ if (child != mSearchBar && child.getVisibility() != GONE) {
child.measure(MeasureSpec.makeMeasureSpec(childWidth, widthMode),
MeasureSpec.makeMeasureSpec(childHeight, heightMode));
}
@@ -333,7 +348,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
- if (child instanceof TaskStackView && child.getVisibility() != GONE) {
+ if (child != mSearchBar && child.getVisibility() != GONE) {
TaskStackView tsv = (TaskStackView) child;
child.layout(left, top, left + tsv.getMeasuredWidth(), top + tsv.getMeasuredHeight());
}
@@ -370,7 +385,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
- if (child instanceof TaskStackView) {
+ if (child != mSearchBar) {
stackView = (TaskStackView) child;
stackView.onUserInteraction();
}
@@ -384,7 +399,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
- if (child instanceof TaskStackView) {
+ if (child != mSearchBar) {
stackView = (TaskStackView) child;
break;
}
@@ -415,11 +430,11 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
/**** TaskStackView.TaskStackCallbacks Implementation ****/
@Override
- public void onTaskLaunched(final TaskStackView stackView, final TaskView tv,
- final TaskStack stack, final Task task) {
+ public void onTaskViewClicked(final TaskStackView stackView, final TaskView tv,
+ final TaskStack stack, final Task task) {
// Notify any callbacks of the launching of a new task
if (mCb != null) {
- mCb.onTaskLaunching();
+ mCb.onTaskViewClicked();
}
// Upfront the processing of the thumbnail
@@ -491,7 +506,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
}
// And clean up the old task
- onTaskRemoved(task);
+ onTaskViewDismissed(task);
}
if (Console.Enabled) {
@@ -515,7 +530,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
}
@Override
- public void onTaskAppInfoLaunched(Task t) {
+ public void onTaskViewAppInfoClicked(Task t) {
// Create a new task stack with the application info details activity
Intent baseIntent = t.key.baseIntent;
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
@@ -526,9 +541,9 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
}
@Override
- public void onTaskRemoved(Task t) {
+ public void onTaskViewDismissed(Task t) {
// Remove any stored data from the loader. We currently don't bother notifying the views
- // that the data has been unloaded because at the point we call onTaskRemoved(), the views
+ // that the data has been unloaded because at the point we call onTaskViewDismissed(), the views
// either don't need to be updated, or have already been removed.
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
loader.deleteTaskData(t, false);
@@ -542,8 +557,8 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
}
@Override
- public void onLastTaskRemoved() {
- mCb.onLastTaskRemoved();
+ public void onAllTaskViewsDismissed() {
+ mCb.onAllTaskViewsDismissed();
}
@Override
@@ -582,7 +597,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
- if (child instanceof TaskStackView) {
+ if (child != mSearchBar) {
TaskStackView stackView = (TaskStackView) child;
stackView.onComponentRemoved(cns);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
index 2c0dea3..9c60603 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
@@ -92,7 +92,6 @@ class TaskBarView extends FrameLayout {
public boolean onTouchEvent(MotionEvent event) {
// We ignore taps on the task bar except on the filter and dismiss buttons
if (!Constants.DebugFlags.App.EnableTaskBarTouchEvents) return true;
- if (mConfig.debugModeEnabled) return true;
return super.onTouchEvent(event);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 2c05daa..dd47fdd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -53,10 +53,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
/** The TaskView callbacks */
interface TaskStackViewCallbacks {
- public void onTaskLaunched(TaskStackView stackView, TaskView tv, TaskStack stack, Task t);
- public void onTaskAppInfoLaunched(Task t);
- public void onTaskRemoved(Task t);
- public void onLastTaskRemoved();
+ public void onTaskViewClicked(TaskStackView stackView, TaskView tv, TaskStack stack, Task t);
+ public void onTaskViewAppInfoClicked(Task t);
+ public void onTaskViewDismissed(Task t);
+ public void onAllTaskViewsDismissed();
public void onTaskStackFilterTriggered();
public void onTaskStackUnfilterTriggered();
}
@@ -69,7 +69,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
TaskStackViewTouchHandler mTouchHandler;
TaskStackViewCallbacks mCb;
ViewPool<TaskView, Task> mViewPool;
- ArrayList<TaskViewTransform> mTaskTransforms = new ArrayList<TaskViewTransform>();
+ ArrayList<TaskViewTransform> mCurrentTaskTransforms = new ArrayList<TaskViewTransform>();
DozeTrigger mUIDozeTrigger;
// The virtual stack scroll that we use for the card layout
@@ -205,12 +205,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
int stackScroll,
int[] visibleRangeOut,
boolean boundTranslationsToRect) {
- // XXX: Optimization: Use binary search to find the visible range
+ // XXX: We should be intelligent about where to look for the visible stack range using the
+ // current stack scroll.
int taskTransformCount = taskTransforms.size();
int taskCount = tasks.size();
- int firstVisibleIndex = -1;
- int lastVisibleIndex = -1;
+ int frontMostVisibleIndex = -1;
+ int backMostVisibleIndex = -1;
// We can reuse the task transforms where possible to reduce object allocation
if (taskTransformCount < taskCount) {
@@ -224,14 +225,24 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
// Update the stack transforms
- for (int i = 0; i < taskCount; i++) {
+ for (int i = taskCount - 1; i >= 0; i--) {
TaskViewTransform transform = mStackAlgorithm.getStackTransform(i, stackScroll,
taskTransforms.get(i));
if (transform.visible) {
- if (firstVisibleIndex < 0) {
- firstVisibleIndex = i;
+ if (frontMostVisibleIndex < 0) {
+ frontMostVisibleIndex = i;
+ }
+ backMostVisibleIndex = i;
+ } else {
+ if (backMostVisibleIndex != -1) {
+ // We've reached the end of the visible range, so going down the rest of the
+ // stack, we can just reset the transforms accordingly
+ while (i >= 0) {
+ taskTransforms.get(i).reset();
+ i--;
+ }
+ break;
}
- lastVisibleIndex = i;
}
if (boundTranslationsToRect) {
@@ -240,8 +251,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
}
if (visibleRangeOut != null) {
- visibleRangeOut[0] = firstVisibleIndex;
- visibleRangeOut[1] = lastVisibleIndex;
+ visibleRangeOut[0] = frontMostVisibleIndex;
+ visibleRangeOut[1] = backMostVisibleIndex;
}
}
@@ -275,13 +286,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
int[] visibleRange = mTmpVisibleRange;
int stackScroll = getStackScroll();
ArrayList<Task> tasks = mStack.getTasks();
- updateStackTransforms(mTaskTransforms, tasks, stackScroll, visibleRange, false);
+ updateStackTransforms(mCurrentTaskTransforms, tasks, stackScroll, visibleRange, false);
// Update the visible state of all the tasks
int taskCount = tasks.size();
for (int i = 0; i < taskCount; i++) {
Task task = tasks.get(i);
- TaskViewTransform transform = mTaskTransforms.get(i);
+ TaskViewTransform transform = mCurrentTaskTransforms.get(i);
TaskView tv = getChildViewForTask(task);
if (transform.visible) {
@@ -290,8 +301,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// When we are picking up a new view from the view pool, prepare it for any
// following animation by putting it in a reasonable place
if (mStackViewsAnimationDuration > 0 && i != 0) {
- int fromIndex = (transform.t < 0) ? (visibleRange[0] - 1) :
- (visibleRange[1] + 1);
+ int fromIndex = (transform.t < 0) ?
+ Math.max(0, (visibleRange[1] - 1)) :
+ Math.min(taskCount - 1, (visibleRange[0] + 1));
tv.updateViewPropertiesToTaskTransform(
mStackAlgorithm.getStackTransform(fromIndex, stackScroll), 0);
}
@@ -310,10 +322,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
TaskView tv = (TaskView) getChildAt(i);
Task task = tv.getTask();
int taskIndex = mStack.indexOfTask(task);
- if (taskIndex < 0 || !mTaskTransforms.get(taskIndex).visible) {
+ if (taskIndex < 0 || !mCurrentTaskTransforms.get(taskIndex).visible) {
mViewPool.returnViewToPool(tv);
} else {
- tv.updateViewPropertiesToTaskTransform(mTaskTransforms.get(taskIndex),
+ tv.updateViewPropertiesToTaskTransform(mCurrentTaskTransforms.get(taskIndex),
mStackViewsAnimationDuration);
}
}
@@ -769,9 +781,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
if (mConfig.launchedWithAltTab) {
// When alt-tabbing, we focus the next previous task
focusTask(Math.max(0, mStack.getTaskCount() - 2), false);
- } else {
- // Normally we just focus the front task
- focusTask(Math.max(0, mStack.getTaskCount() - 1), false);
}
}
}
@@ -864,7 +873,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
// Notify the callback that we've removed the task and it can clean up after it
- mCb.onTaskRemoved(t);
+ mCb.onTaskViewDismissed(t);
// Update the min/max scroll and animate other task views into their new positions
updateMinMaxScroll(true);
@@ -880,7 +889,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
shouldFinishActivity = (mStack.getTaskCount() == 0);
}
if (shouldFinishActivity) {
- mCb.onLastTaskRemoved();
+ mCb.onAllTaskViewsDismissed();
}
}
}
@@ -1033,7 +1042,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
/**** TaskViewCallbacks Implementation ****/
@Override
- public void onTaskIconClicked(TaskView tv) {
+ public void onTaskViewAppIconClicked(TaskView tv) {
if (Console.Enabled) {
Console.log(Constants.Log.UI.ClickEvents, "[TaskStack|Clicked|Icon]",
tv.getTask() + " is currently filtered: " + mStack.hasFilteredTasks(),
@@ -1049,19 +1058,14 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
@Override
- public void onTaskAppInfoClicked(TaskView tv) {
+ public void onTaskViewAppInfoClicked(TaskView tv) {
if (mCb != null) {
- mCb.onTaskAppInfoLaunched(tv.getTask());
+ mCb.onTaskViewAppInfoClicked(tv.getTask());
}
}
@Override
- public void onTaskFocused(TaskView tv) {
- // Do nothing
- }
-
- @Override
- public void onTaskDismissed(TaskView tv) {
+ public void onTaskViewDismissed(TaskView tv) {
Task task = tv.getTask();
// Remove the task from the view
mStack.removeTask(task);
@@ -1082,7 +1086,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
mUIDozeTrigger.stopDozing();
if (mCb != null) {
- mCb.onTaskLaunched(this, tv, mStack, task);
+ mCb.onTaskViewClicked(this, tv, mStack, task);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index 51f994e..304d45c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -400,16 +400,11 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
// Re-enable clipping with the stack (we will reuse this view)
tv.setClipViewInStack(true);
// Remove the task view from the stack
- mSv.onTaskDismissed(tv);
+ mSv.onTaskViewDismissed(tv);
}
@Override
public void onSnapBackCompleted(View v) {
- onDragCancelled(v);
- }
-
- @Override
- public void onDragCancelled(View v) {
TaskView tv = (TaskView) v;
// Disable HW layers on that task
if (mSv.mHwLayersTrigger.getCount() == 0) {
@@ -420,4 +415,9 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
// Re-enable touch events from this task view
mSv.setTouchOnTaskView(tv, true);
}
+
+ @Override
+ public void onDragCancelled(View v) {
+ // Do nothing
+ }
}
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 c6bacbd..6b06945 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -47,10 +47,9 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
View.OnLongClickListener {
/** The TaskView callbacks */
interface TaskViewCallbacks {
- public void onTaskIconClicked(TaskView tv);
- public void onTaskAppInfoClicked(TaskView tv);
- public void onTaskFocused(TaskView tv);
- public void onTaskDismissed(TaskView tv);
+ public void onTaskViewAppIconClicked(TaskView tv);
+ public void onTaskViewAppInfoClicked(TaskView tv);
+ public void onTaskViewDismissed(TaskView tv);
}
RecentsConfiguration mConfig;
@@ -63,8 +62,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
boolean mTaskDataLoaded;
boolean mIsFocused;
boolean mClipViewInStack;
- Point mLastTouchDown = new Point();
- Path mRoundedRectClipPath = new Path();
Rect mTmpRect = new Rect();
Paint mLayerPaint = new Paint();
@@ -110,6 +107,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
super(context, attrs, defStyleAttr, defStyleRes);
mConfig = RecentsConfiguration.getInstance();
setWillNotDraw(false);
+ setClipToOutline(true);
setDim(getDim());
}
@@ -133,30 +131,13 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- // Update the rounded rect clip path
- float radius = mConfig.taskViewRoundedCornerRadiusPx;
- mRoundedRectClipPath.reset();
- mRoundedRectClipPath.addRoundRect(new RectF(0, 0, getMeasuredWidth(), getMeasuredHeight()),
- radius, radius, Path.Direction.CW);
-
// Update the outline
Outline o = new Outline();
o.setRoundRect(0, 0, getMeasuredWidth(), getMeasuredHeight() -
- mConfig.taskViewShadowOutlineBottomInsetPx, radius);
+ mConfig.taskViewShadowOutlineBottomInsetPx, mConfig.taskViewRoundedCornerRadiusPx);
setOutline(o);
}
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- switch (ev.getAction()) {
- case MotionEvent.ACTION_DOWN:
- case MotionEvent.ACTION_MOVE:
- mLastTouchDown.set((int) ev.getX(), (int) ev.getY());
- break;
- }
- return super.onInterceptTouchEvent(ev);
- }
-
/** Set callback */
void setCallbacks(TaskViewCallbacks cb) {
mCb = cb;
@@ -291,7 +272,9 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
} else if (mConfig.launchedFromHome) {
// Move the task view off screen (below) so we can animate it in
setTranslationY(offscreenY);
- setTranslationZ(0);
+ if (Constants.DebugFlags.App.EnableShadows) {
+ setTranslationZ(0);
+ }
setScaleX(1f);
setScaleY(1f);
}
@@ -365,11 +348,13 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
int frontIndex = (ctx.stackViewCount - ctx.stackViewIndex - 1);
int delay = mConfig.taskBarEnterAnimDelay +
frontIndex * mConfig.taskViewEnterFromHomeDelay;
+ if (Constants.DebugFlags.App.EnableShadows) {
+ animate().translationZ(transform.translationZ);
+ }
animate()
.scaleX(transform.scale)
.scaleY(transform.scale)
.translationY(transform.translationY)
- .translationZ(transform.translationZ)
.setStartDelay(delay)
.setUpdateListener(null)
.setInterpolator(mConfig.quintOutInterpolator)
@@ -385,6 +370,9 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
})
.start();
ctx.postAnimationTrigger.increment();
+ } else {
+ // Otherwise, just enable the thumbnail clip
+ mEnableThumbnailClip.run();
}
}
@@ -527,11 +515,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
@Override
public void draw(Canvas canvas) {
- int restoreCount = canvas.save(Canvas.CLIP_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
- // Apply the rounded rect clip path on the whole view
- canvas.clipPath(mRoundedRectClipPath);
super.draw(canvas);
- canvas.restoreToCount(restoreCount);
// Apply the dim if necessary
if (mDim > 0) {
@@ -553,7 +537,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
requestFocus();
setFocusableInTouchMode(false);
invalidate();
- mCb.onTaskFocused(this);
}
/**
@@ -626,13 +609,13 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
@Override
public void run() {
if (v == mBarView.mApplicationIcon) {
- mCb.onTaskIconClicked(tv);
+ mCb.onTaskViewAppIconClicked(tv);
} else if (v == mBarView.mDismissButton) {
// Animate out the view and call the callback
startDeleteTaskAnimation(new Runnable() {
@Override
public void run() {
- mCb.onTaskDismissed(tv);
+ mCb.onTaskViewDismissed(tv);
}
});
}
@@ -643,7 +626,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
@Override
public boolean onLongClick(View v) {
if (v == mBarView.mApplicationIcon) {
- mCb.onTaskAppInfoClicked(this);
+ mCb.onTaskViewAppInfoClicked(this);
return true;
}
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 1550217..c02a598 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -94,11 +94,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private boolean mDark;
private final Paint mDarkPaint = createDarkPaint();
- private int mBgResId = com.android.internal.R.drawable.notification_material_bg;
- private int mDimmedBgResId = com.android.internal.R.drawable.notification_material_bg_dim;
-
private int mBgTint = 0;
- private int mDimmedBgTint = 0;
private final int mRoundedRectCornerRadius;
/**
@@ -133,6 +129,11 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private ValueAnimator mAppearAnimator;
private float mAppearAnimationFraction = -1.0f;
private float mAppearAnimationTranslation;
+ private boolean mShowingLegacyBackground;
+ private final int mLegacyColor;
+ private final int mNormalColor;
+ private final int mLowPriorityColor;
+ private boolean mIsBelowSpeedBump;
public ActivatableNotificationView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -148,7 +149,11 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
setClipToPadding(false);
mAppearAnimationFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_ATOP);
mRoundedRectCornerRadius = getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.notification_material_rounded_rect_radius);
+ R.dimen.notification_material_rounded_rect_radius);
+ mLegacyColor = getResources().getColor(R.color.notification_legacy_background_color);
+ mNormalColor = getResources().getColor(R.color.notification_material_background_color);
+ mLowPriorityColor = getResources().getColor(
+ R.color.notification_material_background_low_priority_color);
}
@Override
@@ -156,9 +161,12 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
super.onFinishInflate();
mBackgroundNormal = (NotificationBackgroundView) findViewById(R.id.backgroundNormal);
mBackgroundDimmed = (NotificationBackgroundView) findViewById(R.id.backgroundDimmed);
+ mBackgroundNormal.setCustomBackground(R.drawable.notification_material_bg);
+ mBackgroundDimmed.setCustomBackground(R.drawable.notification_material_bg_dim);
updateBackground();
- updateBackgroundResources();
+ updateBackgroundTint();
mScrimView = (NotificationScrimView) findViewById(R.id.scrim_view);
+ setScrimAmount(0);
}
private final Runnable mTapTimeoutRunnable = new Runnable() {
@@ -177,6 +185,13 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
}
}
+ @Override
+ public void drawableHotspotChanged(float x, float y) {
+ if (!mDimmed){
+ mBackgroundNormal.drawableHotspotChanged(x, y);
+ }
+ }
+
private boolean handleTouchEventDimmed(MotionEvent event) {
int action = event.getActionMasked();
switch (action) {
@@ -327,22 +342,36 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
return p;
}
+ public void setShowingLegacyBackground(boolean showing) {
+ mShowingLegacyBackground = showing;
+ updateBackgroundTint();
+ }
+
+ @Override
+ public void setBelowSpeedBump(boolean below) {
+ super.setBelowSpeedBump(below);
+ if (below != mIsBelowSpeedBump) {
+ mIsBelowSpeedBump = below;
+ updateBackgroundTint();
+ }
+ }
+
/**
- * Sets the resource id for the background of this notification.
- *
- * @param bgResId The background resource to use in normal state.
- * @param dimmedBgResId The background resource to use in dimmed state.
+ * Sets the tint color of the background
*/
- public void setBackgroundResourceIds(int bgResId, int bgTint, int dimmedBgResId, int dimmedTint) {
- mBgResId = bgResId;
- mBgTint = bgTint;
- mDimmedBgResId = dimmedBgResId;
- mDimmedBgTint = dimmedTint;
- updateBackgroundResources();
+ public void setTintColor(int color) {
+ mBgTint = color;
+ updateBackgroundTint();
}
- public void setBackgroundResourceIds(int bgResId, int dimmedBgResId) {
- setBackgroundResourceIds(bgResId, 0, dimmedBgResId, 0);
+ private void updateBackgroundTint() {
+ int color = getBackgroundColor();
+ if (color == mNormalColor) {
+ // We don't need to tint a normal notification
+ color = 0;
+ }
+ mBackgroundDimmed.setTint(color);
+ mBackgroundNormal.setTint(color);
}
private void fadeBackground() {
@@ -396,11 +425,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
}
}
- private void updateBackgroundResources() {
- mBackgroundDimmed.setCustomBackground(mDimmedBgResId, mDimmedBgTint);
- mBackgroundNormal.setCustomBackground(mBgResId, mBgTint);
- }
-
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
@@ -575,8 +599,15 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
}
private int getBackgroundColor() {
- // TODO: get real color
- return 0xfffafafa;
+ if (mBgTint != 0) {
+ return mBgTint;
+ } else if (mShowingLegacyBackground) {
+ return mLegacyColor;
+ } else if (mIsBelowSpeedBump) {
+ return mLowPriorityColor;
+ } else {
+ return mNormalColor;
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 3690701..df3e25d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -562,20 +562,14 @@ public abstract class BaseStatusBar extends SystemUI implements
if (entry.expanded.getId() != com.android.internal.R.id.status_bar_latest_event_content) {
// Using custom RemoteViews
if (version >= Build.VERSION_CODES.GINGERBREAD && version < Build.VERSION_CODES.L) {
- entry.row.setBackgroundResourceIds(
- com.android.internal.R.drawable.notification_bg,
- com.android.internal.R.drawable.notification_bg_dim);
+ entry.row.setShowingLegacyBackground(true);
entry.legacy = true;
}
} else {
// Using platform templates
final int color = sbn.getNotification().color;
if (isMediaNotification(entry)) {
- entry.row.setBackgroundResourceIds(
- com.android.internal.R.drawable.notification_material_bg,
- color,
- com.android.internal.R.drawable.notification_material_bg_dim,
- color);
+ entry.row.setTintColor(color);
}
}
}
@@ -903,15 +897,15 @@ public abstract class BaseStatusBar extends SystemUI implements
protected void onShowSearchPanel() {
}
- public boolean inflateViews(NotificationData.Entry entry, ViewGroup parent) {
+ private boolean inflateViews(NotificationData.Entry entry, ViewGroup parent) {
return inflateViews(entry, parent, false);
}
- public boolean inflateViewsForHeadsUp(NotificationData.Entry entry, ViewGroup parent) {
+ protected boolean inflateViewsForHeadsUp(NotificationData.Entry entry, ViewGroup parent) {
return inflateViews(entry, parent, true);
}
- public boolean inflateViews(NotificationData.Entry entry, ViewGroup parent, boolean isHeadsUp) {
+ private boolean inflateViews(NotificationData.Entry entry, ViewGroup parent, boolean isHeadsUp) {
int maxHeight = mRowMaxHeight;
StatusBarNotification sbn = entry.notification;
RemoteViews contentView = sbn.getNotification().contentView;
@@ -933,11 +927,30 @@ public abstract class BaseStatusBar extends SystemUI implements
Notification publicNotification = sbn.getNotification().publicVersion;
- // create the row view
- LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- ExpandableNotificationRow row = (ExpandableNotificationRow) inflater.inflate(
- R.layout.status_bar_notification_row, parent, false);
+ ExpandableNotificationRow row;
+
+ // Stash away previous user expansion state so we can restore it at
+ // the end.
+ boolean hasUserChangedExpansion = false;
+ boolean userExpanded = false;
+ boolean userLocked = false;
+
+ if (entry.row != null) {
+ row = entry.row;
+ hasUserChangedExpansion = row.hasUserChangedExpansion();
+ userExpanded = row.isUserExpanded();
+ userLocked = row.isUserLocked();
+ row.reset();
+ if (hasUserChangedExpansion) {
+ row.setUserExpanded(userExpanded);
+ }
+ } else {
+ // create the row view
+ LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ row = (ExpandableNotificationRow) inflater.inflate(R.layout.status_bar_notification_row,
+ parent, false);
+ }
// for blaming (see SwipeHelper.setLongPressListener)
row.setTag(sbn.getPackageName());
@@ -1077,13 +1090,20 @@ public abstract class BaseStatusBar extends SystemUI implements
entry.row = row;
entry.row.setHeightRange(mRowMinHeight, maxHeight);
entry.row.setOnActivatedListener(this);
- entry.row.setIsBelowSpeedBump(isBelowSpeedBump(entry.notification));
entry.expanded = contentViewLocal;
entry.expandedPublic = publicViewLocal;
entry.setBigContentView(bigContentViewLocal);
applyLegacyRowBackground(sbn, entry);
+ // Restore previous flags.
+ if (hasUserChangedExpansion) {
+ // Note: setUserExpanded() conveniently ignores calls with
+ // userExpanded=true if !isExpandable().
+ row.setUserExpanded(userExpanded);
+ }
+ row.setUserLocked(userLocked);
+
return true;
}
@@ -1324,12 +1344,13 @@ public abstract class BaseStatusBar extends SystemUI implements
RankingMap ranking);
protected abstract void updateNotificationRanking(RankingMap ranking);
public abstract void removeNotification(String key, RankingMap ranking);
+
public void updateNotification(StatusBarNotification notification, RankingMap ranking) {
if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");
final String key = notification.getKey();
boolean wasHeadsUp = isHeadsUp(key);
- NotificationData.Entry oldEntry;
+ Entry oldEntry;
if (wasHeadsUp) {
oldEntry = mHeadsUpNotificationView.getEntry();
} else {
@@ -1370,8 +1391,7 @@ public abstract class BaseStatusBar extends SystemUI implements
+ " publicView=" + publicContentView);
}
- // Can we just reapply the RemoteViews in place? If when didn't change, the order
- // didn't change.
+ // Can we just reapply the RemoteViews in place?
// 1U is never null
boolean contentsUnchanged = oldEntry.expanded != null
@@ -1484,15 +1504,9 @@ public abstract class BaseStatusBar extends SystemUI implements
addNotification(notification, ranking); //this will pop the headsup
} else {
if (DEBUG) Log.d(TAG, "rebuilding update in place for key: " + key);
- removeNotificationViews(key, ranking);
- addNotificationViews(notification, ranking);
- final NotificationData.Entry newEntry = mNotificationData.findByKey(key);
- final boolean userChangedExpansion = oldEntry.row.hasUserChangedExpansion();
- if (userChangedExpansion) {
- boolean userExpanded = oldEntry.row.isUserExpanded();
- newEntry.row.setUserExpanded(userExpanded);
- newEntry.row.notifyHeightChanged();
- }
+ oldEntry.notification = notification;
+ inflateViews(oldEntry, mStackScroller, wasHeadsUp);
+ updateNotifications();
}
}
}
@@ -1554,19 +1568,9 @@ public abstract class BaseStatusBar extends SystemUI implements
} else {
entry.row.setOnClickListener(null);
}
- boolean wasBelow = entry.row.isBelowSpeedBump();
- boolean nowBelow = isBelowSpeedBump(notification);
- if (wasBelow != nowBelow) {
- entry.row.setIsBelowSpeedBump(nowBelow);
- }
entry.row.notifyContentUpdated();
}
- private boolean isBelowSpeedBump(StatusBarNotification notification) {
- return notification.getNotification().priority ==
- Notification.PRIORITY_MIN;
- }
-
protected void notifyHeadsUpScreenOn(boolean screenOn) {
if (!screenOn) {
scheduleHeadsUpEscalation();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 5981898..280bade 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -52,13 +52,29 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
private NotificationContentView mPublicLayout;
private NotificationContentView mPrivateLayout;
private int mMaxExpandHeight;
- private boolean mIsBelowSpeedBump;
private View mVetoButton;
public ExpandableNotificationRow(Context context, AttributeSet attrs) {
super(context, attrs);
}
+ /**
+ * Resets this view so it can be re-used for an updated notification.
+ */
+ public void reset() {
+ mRowMinHeight = 0;
+ mRowMaxHeight = 0;
+ mExpandable = false;
+ mHasUserChangedExpansion = false;
+ mUserLocked = false;
+ mShowingPublic = false;
+ mIsSystemExpanded = false;
+ mExpansionDisabled = false;
+ mPublicLayout.reset();
+ mPrivateLayout.reset();
+ mMaxExpandHeight = 0;
+ }
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();
@@ -111,6 +127,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
* @param userExpanded whether the user wants this notification to be expanded
*/
public void setUserExpanded(boolean userExpanded) {
+ if (userExpanded && !mExpandable) return;
mHasUserChangedExpansion = true;
mUserExpanded = userExpanded;
}
@@ -245,14 +262,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
mPublicLayout.setClipTopAmount(clipTopAmount);
}
- public boolean isBelowSpeedBump() {
- return mIsBelowSpeedBump;
- }
-
- public void setIsBelowSpeedBump(boolean isBelow) {
- this.mIsBelowSpeedBump = isBelow;
- }
-
public void notifyContentUpdated() {
mPublicLayout.notifyContentUpdated();
mPrivateLayout.notifyContentUpdated();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 0a5d138..b71cd77 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -234,10 +234,18 @@ public abstract class ExpandableView extends FrameLayout {
public abstract void setScrimAmount(float scrimAmount);
+ public void setBelowSpeedBump(boolean below) {
+ }
+
/**
* A listener notifying when {@link #getActualHeight} changes.
*/
public interface OnHeightChangedListener {
+
+ /**
+ * @param view the view for which the height changed, or {@code null} if just the top
+ * padding or the padding between the elements changed
+ */
void onHeightChanged(ExpandableView view);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
index 1c2ca91..ad274b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
@@ -17,11 +17,15 @@
package com.android.systemui.statusbar;
import android.content.Context;
+import android.content.res.ColorStateList;
import android.graphics.Canvas;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.RippleDrawable;
import android.util.AttributeSet;
+import android.view.MotionEvent;
import android.view.View;
+import com.android.systemui.R;
/**
* A view that can be used for both the dimmed and normal background of an notification.
@@ -31,9 +35,15 @@ public class NotificationBackgroundView extends View {
private Drawable mBackground;
private int mClipTopAmount;
private int mActualHeight;
+ private final int mTintedRippleColor;
+ private final int mNormalRippleColor;
public NotificationBackgroundView(Context context, AttributeSet attrs) {
super(context, attrs);
+ mTintedRippleColor = context.getResources().getColor(
+ R.color.notification_ripple_tinted_color);
+ mNormalRippleColor = context.getResources().getColor(
+ R.color.notification_ripple_untinted_color);
}
@Override
@@ -64,6 +74,13 @@ public class NotificationBackgroundView extends View {
}
}
+ @Override
+ public void drawableHotspotChanged(float x, float y) {
+ if (mBackground != null) {
+ mBackground.setHotspot(x, y);
+ }
+ }
+
/**
* Sets a background drawable. As we need to change our bounds independently of layout, we need
* the notion of a background independently of the regular View background..
@@ -80,12 +97,25 @@ public class NotificationBackgroundView extends View {
invalidate();
}
- public void setCustomBackground(int drawableResId, int tintColor) {
- final Drawable d = getResources().getDrawable(drawableResId);
+ public void setCustomBackground(int drawableResId) {
+ final Drawable d = mContext.getDrawable(drawableResId);
+ setCustomBackground(d);
+ }
+
+ public void setTint(int tintColor) {
+ int rippleColor;
if (tintColor != 0) {
- d.setColorFilter(tintColor, PorterDuff.Mode.SRC_ATOP);
+ mBackground.setColorFilter(tintColor, PorterDuff.Mode.SRC_ATOP);
+ rippleColor = mTintedRippleColor;
+ } else {
+ mBackground.clearColorFilter();
+ rippleColor = mNormalRippleColor;
}
- setCustomBackground(d);
+ if (mBackground instanceof RippleDrawable) {
+ RippleDrawable ripple = (RippleDrawable) mBackground;
+ ripple.setColor(ColorStateList.valueOf(rippleColor));
+ }
+ invalidate();
}
public void setActualHeight(int actualHeight) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index f919501..f3aba0e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -51,13 +51,12 @@ public class NotificationContentView extends FrameLayout {
private boolean mContractedVisible = true;
- private Paint mFadePaint = new Paint();
+ private final Paint mFadePaint = new Paint();
public NotificationContentView(Context context, AttributeSet attrs) {
super(context, attrs);
- mSmallHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height);
- mActualHeight = mSmallHeight;
mFadePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
+ reset();
}
@Override
@@ -66,6 +65,15 @@ public class NotificationContentView extends FrameLayout {
updateClipping();
}
+ public void reset() {
+ removeAllViews();
+ mContractedChild = null;
+ mExpandedChild = null;
+ mSmallHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height);
+ mActualHeight = mSmallHeight;
+ mContractedVisible = true;
+ }
+
public void setContractedChild(View child) {
if (mContractedChild != null) {
removeView(mContractedChild);
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 b2e79c9..be2c515 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -66,7 +66,7 @@ public class NotificationPanelView extends PanelView implements
private View mKeyguardStatusView;
private ObservableScrollView mScrollView;
private TextView mClockView;
-
+ private View mReserveNotificationSpace;
private MirrorView mSystemIconsCopy;
private NotificationStackScrollLayout mNotificationStackScroller;
@@ -89,8 +89,10 @@ public class NotificationPanelView extends PanelView implements
*/
private boolean mIntercepting;
private boolean mQsExpanded;
+ private boolean mQsExpandedWhenExpandingStarted;
private boolean mQsFullyExpanded;
private boolean mKeyguardShowing;
+ private int mStatusBarState;
private float mInitialHeightOnTouch;
private float mInitialTouchX;
private float mInitialTouchY;
@@ -112,7 +114,6 @@ public class NotificationPanelView extends PanelView implements
private Interpolator mFastOutSlowInInterpolator;
private Interpolator mFastOutLinearInterpolator;
- private Interpolator mLinearOutSlowInInterpolator;
private ObjectAnimator mClockAnimator;
private int mClockAnimationTarget = -1;
private int mTopPaddingAdjustment;
@@ -125,7 +126,13 @@ public class NotificationPanelView extends PanelView implements
private boolean mBlockTouches;
private ArrayList<View> mSwipeTranslationViews = new ArrayList<>();
private int mNotificationScrimWaitDistance;
- private boolean mOnNotificationsOnDown;
+
+ /**
+ * If we are in a panel collapsing motion, we reset scrollY of our scroll view but still
+ * need to take this into account in our panel height calculation.
+ */
+ private int mScrollYOverride = -1;
+ private boolean mQsAnimatorExpand;
public NotificationPanelView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -148,14 +155,14 @@ public class NotificationPanelView extends PanelView implements
mClockView = (TextView) findViewById(R.id.clock_view);
mScrollView = (ObservableScrollView) findViewById(R.id.scroll_view);
mScrollView.setListener(this);
+ mReserveNotificationSpace = findViewById(R.id.reserve_notification_space);
mNotificationStackScroller = (NotificationStackScrollLayout)
findViewById(R.id.notification_stack_scroller);
mNotificationStackScroller.setOnHeightChangedListener(this);
mNotificationStackScroller.setOverscrollTopChangedListener(this);
+ mNotificationStackScroller.setScrollView(mScrollView);
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(),
android.R.interpolator.fast_out_slow_in);
- mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(),
- android.R.interpolator.linear_out_slow_in);
mFastOutLinearInterpolator = AnimationUtils.loadInterpolator(getContext(),
android.R.interpolator.fast_out_linear_in);
mKeyguardBottomArea = (KeyguardBottomAreaView) findViewById(R.id.keyguard_bottom_area);
@@ -283,13 +290,6 @@ public class NotificationPanelView extends PanelView implements
requestLayout();
}
- /**
- * @return Whether Quick Settings are currently expanded.
- */
- public boolean isQsExpanded() {
- return mQsExpanded;
- }
-
public void setQsExpansionEnabled(boolean qsExpansionEnabled) {
mQsExpansionEnabled = qsExpansionEnabled;
}
@@ -309,6 +309,18 @@ public class NotificationPanelView extends PanelView implements
setQsExpansion(mQsMinExpansionHeight);
}
+ public void animateCloseQs() {
+ if (mQsExpansionAnimator != null) {
+ if (!mQsAnimatorExpand) {
+ return;
+ }
+ float height = mQsExpansionHeight;
+ mQsExpansionAnimator.cancel();
+ setQsExpansion(height);
+ }
+ flingSettings(0 /* vel */, false);
+ }
+
public void openQs() {
cancelAnimation();
if (mQsExpansionEnabled) {
@@ -356,10 +368,16 @@ public class NotificationPanelView extends PanelView implements
mInitialTouchX = x;
initVelocityTracker();
trackMovement(event);
- mOnNotificationsOnDown = isOnNotifications(x, y);
if (shouldQuickSettingsIntercept(mInitialTouchX, mInitialTouchY, 0)) {
getParent().requestDisallowInterceptTouchEvent(true);
}
+ if (mQsExpansionAnimator != null) {
+ onQsExpansionStarted();
+ mInitialHeightOnTouch = mQsExpansionHeight;
+ mQsTracking = true;
+ mIntercepting = false;
+ mNotificationStackScroller.removeLongPressCallback();
+ }
break;
case MotionEvent.ACTION_POINTER_UP:
final int upPointer = event.getPointerId(event.getActionIndex());
@@ -404,8 +422,6 @@ public class NotificationPanelView extends PanelView implements
if (mQsTracking) {
flingQsWithCurrentVelocity();
mQsTracking = false;
- } else if (mQsFullyExpanded && mOnNotificationsOnDown) {
- flingSettings(0 /* vel */, false /* expand */);
}
mIntercepting = false;
break;
@@ -413,10 +429,6 @@ public class NotificationPanelView extends PanelView implements
return !mQsExpanded && super.onInterceptTouchEvent(event);
}
- private boolean isOnNotifications(float x, float y) {
- return mNotificationStackScroller.getChildAtPosition(x, y) != null;
- }
-
@Override
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
@@ -443,8 +455,9 @@ public class NotificationPanelView extends PanelView implements
private float getQsExpansionFraction() {
return (mQsExpansionHeight - mQsMinExpansionHeight)
- / (mQsMaxExpansionHeight - mQsMinExpansionHeight);
+ / (getTempQsMaxExpansion() - mQsMinExpansionHeight);
}
+
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mBlockTouches) {
@@ -550,6 +563,8 @@ public class NotificationPanelView extends PanelView implements
if ((fraction != 0f || y >= mInitialTouchY)
&& (fraction != 1f || y <= mInitialTouchY)) {
flingQsWithCurrentVelocity();
+ } else {
+ mScrollYOverride = -1;
}
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
@@ -570,7 +585,6 @@ public class NotificationPanelView extends PanelView implements
}
}
-
@Override
public void onOverscrollTopChanged(float amount, boolean isRubberbanded) {
cancelAnimation();
@@ -589,6 +603,7 @@ public class NotificationPanelView extends PanelView implements
public void run() {
mStackScrollerOverscrolling = false;
mQsExpansionFromOverscroll = false;
+ updateQsState();
}
});
}
@@ -602,6 +617,9 @@ public class NotificationPanelView extends PanelView implements
// Reset scroll position and apply that position to the expanded height.
float height = mQsExpansionHeight - mScrollView.getScrollY() - overscrollAmount;
+ if (mScrollView.getScrollY() != 0) {
+ mScrollYOverride = mScrollView.getScrollY();
+ }
mScrollView.scrollTo(0, 0);
setQsExpansion(height);
}
@@ -611,14 +629,19 @@ public class NotificationPanelView extends PanelView implements
if (changed) {
mQsExpanded = expanded;
updateQsState();
+ requestPanelHeightUpdate();
+ mNotificationStackScroller.setInterceptDelegateEnabled(expanded);
}
}
- public void setKeyguardShowing(boolean keyguardShowing) {
+ public void setBarState(int statusBarState) {
+ boolean keyguardShowing = statusBarState == StatusBarState.KEYGUARD
+ || statusBarState == StatusBarState.SHADE_LOCKED;
if (!mKeyguardShowing && keyguardShowing) {
setQsTranslation(mQsExpansionHeight);
mHeader.setTranslationY(0f);
}
+ mStatusBarState = statusBarState;
mKeyguardShowing = keyguardShowing;
updateQsState();
}
@@ -626,12 +649,12 @@ public class NotificationPanelView extends PanelView implements
private void updateQsState() {
boolean expandVisually = mQsExpanded || mStackScrollerOverscrolling;
mHeader.setExpanded(expandVisually, mStackScrollerOverscrolling);
- mNotificationStackScroller.setEnabled(!mQsExpanded || mQsExpansionFromOverscroll);
+ mNotificationStackScroller.setScrollingEnabled(mStatusBarState != StatusBarState.KEYGUARD
+ && (!mQsExpanded || mQsExpansionFromOverscroll));
mQsPanel.setVisibility(expandVisually ? View.VISIBLE : View.INVISIBLE);
mQsContainer.setVisibility(
mKeyguardShowing && !expandVisually ? View.INVISIBLE : View.VISIBLE);
mScrollView.setTouchEnabled(mQsExpanded);
- mNotificationStackScroller.setTouchEnabled(!mQsExpanded || mQsExpansionFromOverscroll);
}
private void setQsExpansion(float height) {
@@ -643,7 +666,7 @@ public class NotificationPanelView extends PanelView implements
setQsExpanded(false);
}
mQsExpansionHeight = height;
- mHeader.setExpansion(height - mQsPeekHeight);
+ mHeader.setExpansion(getQsExpansionFraction());
setQsTranslation(height);
requestScrollerTopPaddingUpdate(false /* animate */);
updateNotificationScrim(height);
@@ -702,6 +725,7 @@ public class NotificationPanelView extends PanelView implements
private void flingSettings(float vel, boolean expand, final Runnable onFinishRunnable) {
float target = expand ? mQsMaxExpansionHeight : mQsMinExpansionHeight;
if (target == mQsExpansionHeight) {
+ mScrollYOverride = -1;
if (onFinishRunnable != null) {
onFinishRunnable.run();
}
@@ -718,6 +742,7 @@ public class NotificationPanelView extends PanelView implements
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
+ mScrollYOverride = -1;
mQsExpansionAnimator = null;
if (onFinishRunnable != null) {
onFinishRunnable.run();
@@ -726,6 +751,7 @@ public class NotificationPanelView extends PanelView implements
});
animator.start();
mQsExpansionAnimator = animator;
+ mQsAnimatorExpand = expand;
}
/**
@@ -794,16 +820,23 @@ public class NotificationPanelView extends PanelView implements
@Override
protected int getMaxPanelHeight() {
+ int min = mStatusBarMinHeight;
if (mStatusBar.getBarState() != StatusBarState.KEYGUARD
&& mNotificationStackScroller.getNotGoneChildCount() == 0) {
- return (int) ((mQsMinExpansionHeight + getOverExpansionAmount())
+ int minHeight = (int) ((mQsMinExpansionHeight + getOverExpansionAmount())
* HEADER_RUBBERBAND_FACTOR);
+ min = Math.max(min, minHeight);
}
- // TODO: Figure out transition for collapsing when QS is open, adjust height here.
- int emptyBottomMargin = mNotificationStackScroller.getEmptyBottomMargin();
- int maxHeight = mNotificationStackScroller.getHeight() - emptyBottomMargin
- - mTopPaddingAdjustment;
- maxHeight = Math.max(maxHeight, mStatusBarMinHeight);
+ int maxHeight;
+ if (mQsExpanded || mIsExpanding && mQsExpandedWhenExpandingStarted) {
+ maxHeight = (int) calculatePanelHeightQsExpanded();
+ } else {
+ int emptyBottomMargin = mNotificationStackScroller.getEmptyBottomMargin();
+ maxHeight = mNotificationStackScroller.getHeight() - emptyBottomMargin
+ - mTopPaddingAdjustment;
+ maxHeight += mNotificationStackScroller.getTopPaddingOverflow();
+ }
+ maxHeight = Math.max(maxHeight, min);
return maxHeight;
}
@@ -816,12 +849,59 @@ public class NotificationPanelView extends PanelView implements
if (!mQsExpanded) {
positionClockAndNotifications();
}
+ if (mQsExpanded && !mQsTracking && mQsExpansionAnimator == null
+ && !mQsExpansionFromOverscroll) {
+ float panelHeightQsCollapsed = mNotificationStackScroller.getIntrinsicPadding()
+ + mNotificationStackScroller.getMinStackHeight()
+ + mNotificationStackScroller.getNotificationTopPadding();
+ float panelHeightQsExpanded = calculatePanelHeightQsExpanded();
+ float t = (expandedHeight - panelHeightQsCollapsed)
+ / (panelHeightQsExpanded - panelHeightQsCollapsed);
+
+ setQsExpansion(mQsMinExpansionHeight
+ + t * (getTempQsMaxExpansion() - mQsMinExpansionHeight));
+ }
mNotificationStackScroller.setStackHeight(expandedHeight);
updateHeader();
updateUnlockIcon();
updateNotificationTranslucency();
}
+ /**
+ * @return a temporary override of {@link #mQsMaxExpansionHeight}, which is needed when
+ * collapsing QS / the panel when QS was scrolled
+ */
+ private int getTempQsMaxExpansion() {
+ int qsTempMaxExpansion = mQsMaxExpansionHeight;
+ if (mScrollYOverride != -1) {
+ qsTempMaxExpansion -= mScrollYOverride;
+ }
+ return qsTempMaxExpansion;
+ }
+
+ private float calculatePanelHeightQsExpanded() {
+ float notificationHeight = mNotificationStackScroller.getHeight()
+ - mNotificationStackScroller.getEmptyBottomMargin()
+ - mNotificationStackScroller.getTopPadding();
+ float totalHeight = mQsMaxExpansionHeight + notificationHeight
+ + mNotificationStackScroller.getNotificationTopPadding();
+ if (totalHeight > mNotificationStackScroller.getHeight()) {
+ float fullyCollapsedHeight = mQsMaxExpansionHeight
+ + mNotificationStackScroller.getMinStackHeight()
+ + mNotificationStackScroller.getNotificationTopPadding()
+ - getScrollViewScrollY();
+ totalHeight = Math.max(fullyCollapsedHeight, mNotificationStackScroller.getHeight());
+ }
+ return totalHeight;
+ }
+
+ private int getScrollViewScrollY() {
+ if (mScrollYOverride != -1) {
+ return mScrollYOverride;
+ } else {
+ return mScrollView.getScrollY();
+ }
+ }
private void updateNotificationTranslucency() {
float alpha = (mNotificationStackScroller.getNotificationsTopY()
+ mNotificationStackScroller.getItemHeight())
@@ -931,6 +1011,10 @@ public class NotificationPanelView extends PanelView implements
super.onExpandingStarted();
mNotificationStackScroller.onExpansionStarted();
mIsExpanding = true;
+ mQsExpandedWhenExpandingStarted = mQsExpanded;
+ if (mQsExpanded) {
+ onQsExpansionStarted();
+ }
}
@Override
@@ -938,6 +1022,7 @@ public class NotificationPanelView extends PanelView implements
super.onExpandingFinished();
mNotificationStackScroller.onExpansionStopped();
mIsExpanding = false;
+ mScrollYOverride = -1;
if (mExpandedHeight == 0f) {
mHeader.setListening(false);
mQsPanel.setListening(false);
@@ -1005,6 +1090,12 @@ public class NotificationPanelView extends PanelView implements
@Override
public void onHeightChanged(ExpandableView view) {
+
+ // Block update if we are in quick settings and just the top padding changed
+ // (i.e. view == null).
+ if (view == null && mQsExpanded) {
+ return;
+ }
requestPanelHeightUpdate();
}
@@ -1012,6 +1103,7 @@ public class NotificationPanelView extends PanelView implements
public void onScrollChanged() {
if (mQsExpanded) {
requestScrollerTopPaddingUpdate(false /* animate */);
+ requestPanelHeightUpdate();
}
}
@@ -1128,4 +1220,30 @@ public class NotificationPanelView extends PanelView implements
return mQsMinExpansionHeight * HEADER_RUBBERBAND_FACTOR;
}
}
+
+ @Override
+ protected float getCannedFlingDurationFactor() {
+ if (mQsExpanded) {
+ return 0.7f;
+ } else {
+ return 0.6f;
+ }
+ }
+
+ @Override
+ protected boolean isTrackingBlocked() {
+ return mConflictingQsExpansionGesture && mQsExpanded;
+ }
+
+ public void notifyVisibleChildrenChanged() {
+ if (mNotificationStackScroller.getNotGoneChildCount() != 0) {
+ mReserveNotificationSpace.setVisibility(View.VISIBLE);
+ } else {
+ mReserveNotificationSpace.setVisibility(View.GONE);
+ }
+ }
+
+ public boolean isQsExpanded() {
+ return mQsExpanded;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java
index ea5b309..45f3632 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java
@@ -31,6 +31,7 @@ public class ObservableScrollView extends ScrollView {
private int mLastOverscrollAmount;
private boolean mDispatchingTouchEvent;
private boolean mTouchEnabled = true;
+ private boolean mInTouchEvent;
public ObservableScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -49,7 +50,7 @@ public class ObservableScrollView extends ScrollView {
}
public boolean isDispatchingTouchEvent() {
- return mDispatchingTouchEvent;
+ return mDispatchingTouchEvent || mInTouchEvent;
}
private int getMaxScrollY() {
@@ -63,6 +64,22 @@ public class ObservableScrollView extends ScrollView {
}
@Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ mInTouchEvent = true;
+ boolean result = super.onTouchEvent(ev);
+ mInTouchEvent = false;
+ return result;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ mInTouchEvent = true;
+ boolean result = super.onInterceptTouchEvent(ev);
+ mInTouchEvent = false;
+ return result;
+ }
+
+ @Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (!mTouchEnabled) {
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 7d5d99d..2c5ece6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -289,7 +289,7 @@ public abstract class PanelView extends FrameLayout {
}
mJustPeeked = false;
}
- if (!mJustPeeked && (!waitForTouchSlop || mTracking)) {
+ if (!mJustPeeked && (!waitForTouchSlop || mTracking) && !isTrackingBlocked()) {
setExpandedHeightInternal(newHeight);
}
@@ -475,7 +475,8 @@ public abstract class PanelView extends FrameLayout {
// Make it shorter if we run a canned animation
if (vel == 0) {
- animator.setDuration((long) (animator.getDuration() / 1.75f));
+ animator.setDuration((long)
+ (animator.getDuration() * getCannedFlingDurationFactor()));
}
}
animator.addListener(new AnimatorListenerAdapter() {
@@ -546,9 +547,12 @@ public abstract class PanelView extends FrameLayout {
float currentMaxPanelHeight = getMaxPanelHeight();
// If the user isn't actively poking us, let's update the height
- if (!mTracking && mHeightAnimator == null
- && mExpandedHeight > 0 && currentMaxPanelHeight != mExpandedHeight
- && !mPeekPending && mPeekAnimator == null) {
+ if ((!mTracking || isTrackingBlocked())
+ && mHeightAnimator == null
+ && mExpandedHeight > 0
+ && currentMaxPanelHeight != mExpandedHeight
+ && !mPeekPending
+ && mPeekAnimator == null) {
setExpandedHeight(currentMaxPanelHeight);
}
}
@@ -576,6 +580,12 @@ public abstract class PanelView extends FrameLayout {
notifyBarPanelExpansionChanged();
}
+ /**
+ * @return true if the panel tracking should be temporarily blocked; this is used when a
+ * conflicting gesture (opening QS) is happening
+ */
+ protected abstract boolean isTrackingBlocked();
+
protected abstract void setOverExpansion(float overExpansion, boolean isPixels);
protected abstract void onHeightUpdated(float expandedHeight);
@@ -866,4 +876,6 @@ public abstract class PanelView extends FrameLayout {
public abstract void resetViews();
protected abstract float getPeekHeight();
+
+ protected abstract float getCannedFlingDurationFactor();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 387f5a7..a6a8e0c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -32,7 +32,6 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARE
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.TimeInterpolator;
-import android.animation.ValueAnimator;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
@@ -78,7 +77,6 @@ import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
-import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewPropertyAnimator;
@@ -101,7 +99,6 @@ import com.android.systemui.EventLogTags;
import com.android.systemui.R;
import com.android.systemui.doze.DozeService;
import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.qs.CircularClipper;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.ActivatableNotificationView;
@@ -717,14 +714,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
// Set up the quick settings tile panel
mQSPanel = (QSPanel) mStatusBarWindow.findViewById(R.id.quick_settings_panel);
if (mQSPanel != null) {
- mQSPanel.setUtils(new CircularClipper.Utils() {
- @Override
- public ValueAnimator createRevealAnimator(View v, int centerX, int centerY,
- float startRadius, float endRadius) {
- return ViewAnimationUtils.createCircularReveal(v, centerX, centerY,
- startRadius, endRadius);
- }
- });
final QSTileHost qsh = new QSTileHost(mContext, this,
mBluetoothController, mLocationController, mRotationLockController,
mNetworkController, mZenModeController, null /*tethering*/,
@@ -1181,13 +1170,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
ent.row.setShowingPublic(showingPublic);
if (ent.autoRedacted && ent.legacy) {
if (showingPublic) {
- ent.row.setBackgroundResourceIds(
- com.android.internal.R.drawable.notification_material_bg,
- com.android.internal.R.drawable.notification_material_bg_dim);
+ ent.row.setShowingLegacyBackground(false);
} else {
- ent.row.setBackgroundResourceIds(
- com.android.internal.R.drawable.notification_bg,
- com.android.internal.R.drawable.notification_bg_dim);
+ ent.row.setShowingLegacyBackground(true);
}
}
toShow.add(ent.row);
@@ -1319,6 +1304,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
}
+ @Override
+ protected void updateRowStates() {
+ super.updateRowStates();
+ mNotificationPanel.notifyVisibleChildrenChanged();
+ }
+
protected void updateCarrierLabelVisibility(boolean force) {
// TODO: Handle this for the notification stack scroller as well
if (!mShowCarrierInPanel) return;
@@ -1691,9 +1682,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mStatusBarWindow.cancelExpandHelper();
mStatusBarView.collapseAllPanels(true);
- if (isFlippedToSettings()) {
- flipToNotifications(true /*animate*/);
- }
}
}
@@ -1751,18 +1739,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
mNotificationPanel.expand();
- if (mStackScroller.getVisibility() != View.VISIBLE) {
- flipToNotifications(true /*animate*/);
- }
if (false) postStartTracing();
}
- public void flipToNotifications(boolean animate) {
- // TODO: Animation
- mNotificationPanel.closeQs();
- }
-
@Override
public void animateExpandSettingsPanel() {
if (SPEW) Log.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible);
@@ -1779,13 +1759,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (false) postStartTracing();
}
- public boolean isFlippedToSettings() {
- if (mNotificationPanel != null) {
- return mNotificationPanel.isQsExpanded();
- }
- return false;
- }
-
public void animateCollapseQuickSettings() {
mStatusBarView.collapseAllPanels(true);
}
@@ -2863,14 +2836,13 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
mKeyguardBottomArea.setVisibility(View.VISIBLE);
mHeader.setKeyguardShowing(true);
- mNotificationPanel.setKeyguardShowing(true);
mScrimController.setKeyguardShowing(true);
} else {
mKeyguardBottomArea.setVisibility(View.GONE);
mHeader.setKeyguardShowing(false);
- mNotificationPanel.setKeyguardShowing(false);
mScrimController.setKeyguardShowing(false);
}
+ mNotificationPanel.setBarState(mState);
updateDozingState();
updateStackScrollerState();
updatePublicMode();
@@ -2905,7 +2877,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mStackScroller.setDimmed(onKeyguard, false /* animate */);
mStackScroller.setVisibility(!mShowLockscreenNotifications && onKeyguard
? View.INVISIBLE : View.VISIBLE);
- mStackScroller.setScrollingEnabled(!onKeyguard);
mStackScroller.setExpandingEnabled(!onKeyguard);
ActivatableNotificationView activatedChild = mStackScroller.getActivatedChild();
mStackScroller.setActivatedChild(null);
@@ -2930,9 +2901,20 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
public boolean onBackPressed() {
if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
- return mStatusBarKeyguardViewManager.onBackPressed();
+ if (mStatusBarKeyguardViewManager.onBackPressed()) {
+ return true;
+ }
+ if (mNotificationPanel.isQsExpanded()) {
+ mNotificationPanel.animateCloseQs();
+ return true;
+ }
+ return false;
} else {
- animateCollapsePanels();
+ if (mNotificationPanel.isQsExpanded()) {
+ mNotificationPanel.animateCloseQs();
+ } else {
+ animateCollapsePanels();
+ }
return true;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 60f38b5..04b1443 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -65,7 +65,6 @@ public class QSTileHost implements QSTile.Host {
private final CurrentUserTracker mUserTracker;
private final VolumeComponent mVolume;
private final ArrayList<QSTile<?>> mTiles = new ArrayList<QSTile<?>>();
- private final int mFeedbackStartDelay;
private final FlashlightController mFlashlight;
public QSTileHost(Context context, PhoneStatusBar statusBar,
@@ -110,7 +109,6 @@ public class QSTileHost implements QSTile.Host {
}
};
mUserTracker.startTracking();
- mFeedbackStartDelay = mContext.getResources().getInteger(R.integer.feedback_start_delay);
}
@Override
@@ -120,7 +118,7 @@ public class QSTileHost implements QSTile.Host {
@Override
public void startSettingsActivity(final Intent intent) {
- mStatusBar.postStartSettingsActivity(intent, mFeedbackStartDelay);
+ mStatusBar.postStartSettingsActivity(intent, 0);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index 3e2dcef..2119316 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.phone;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.content.Intent;
import android.graphics.Outline;
@@ -26,10 +28,12 @@ import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
+import android.widget.Switch;
import android.widget.TextView;
import com.android.systemui.R;
import com.android.systemui.qs.QSPanel;
+import com.android.systemui.qs.QSTile;
import com.android.systemui.settings.BrightnessController;
import com.android.systemui.settings.ToggleSlider;
import com.android.systemui.statusbar.policy.UserInfoController;
@@ -60,6 +64,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
private View mSignalCluster;
private View mSettingsButton;
private View mBrightnessContainer;
+ private View mQsDetailHeader;
private View mEmergencyCallsOnly;
private TextView mChargingInfo;
@@ -104,6 +109,8 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
mBrightnessController = new BrightnessController(getContext(),
(ImageView) findViewById(R.id.brightness_icon),
(ToggleSlider) findViewById(R.id.brightness_slider));
+ mQsDetailHeader = findViewById(R.id.qs_detail_header);
+ mQsDetailHeader.setAlpha(0);
mEmergencyCallsOnly = findViewById(R.id.header_emergency_calls_only);
mChargingInfo = (TextView) findViewById(R.id.header_charging_info);
loadDimens();
@@ -219,6 +226,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
mDate.setVisibility(mExpanded ? View.VISIBLE : View.GONE);
mSettingsButton.setVisibility(mExpanded && !mOverscrolled ? View.VISIBLE : View.GONE);
mBrightnessContainer.setVisibility(mExpanded ? View.VISIBLE : View.GONE);
+ mQsDetailHeader.setVisibility(mExpanded ? View.VISIBLE : View.GONE);
if (mStatusIcons != null) {
mStatusIcons.setVisibility(!mExpanded || mOverscrolled ? View.VISIBLE : View.GONE);
}
@@ -300,8 +308,8 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
}
}
- public void setExpansion(float height) {
- height = (height - mCollapsedHeight) * EXPANSION_RUBBERBAND_FACTOR + mCollapsedHeight;
+ public void setExpansion(float t) {
+ float height = mCollapsedHeight + t * (mExpandedHeight - mCollapsedHeight);
if (height < mCollapsedHeight) {
height = mCollapsedHeight;
}
@@ -375,13 +383,6 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
}
}
- private final QSPanel.Callback mQsPanelCallback = new QSPanel.Callback() {
- @Override
- public void onShowingDetail(boolean showingDetail) {
- mBrightnessContainer.animate().alpha(showingDetail ? 0 : 1).withLayer().start();
- }
- };
-
@Override
public boolean shouldDelayChildPressedState() {
return true;
@@ -418,4 +419,69 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
public boolean hasOverlappingRendering() {
return !mKeyguardShowing || mExpanded;
}
+
+ private final QSPanel.Callback mQsPanelCallback = new QSPanel.Callback() {
+ @Override
+ public void onToggleStateChanged(final boolean state) {
+ post(new Runnable() {
+ @Override
+ public void run() {
+ handleToggleStateChanged(state);
+ }
+ });
+ }
+
+ @Override
+ public void onShowingDetail(final QSTile.DetailAdapter detail) {
+ post(new Runnable() {
+ @Override
+ public void run() {
+ handleShowingDetail(detail);
+ }
+ });
+ }
+
+ private void handleToggleStateChanged(boolean state) {
+ final Switch headerSwitch = (Switch)
+ mQsDetailHeader.findViewById(android.R.id.toggle);
+ headerSwitch.setChecked(state);
+ }
+
+ private void handleShowingDetail(final QSTile.DetailAdapter detail) {
+ final boolean showingDetail = detail != null;
+ transition(mBrightnessContainer, !showingDetail);
+ transition(mQsDetailHeader, showingDetail);
+ if (showingDetail) {
+ final TextView headerTitle = (TextView)
+ mQsDetailHeader.findViewById(android.R.id.title);
+ headerTitle.setText(detail.getTitle());
+ final Switch headerSwitch = (Switch)
+ mQsDetailHeader.findViewById(android.R.id.toggle);
+ final Boolean toggleState = detail.getToggleState();
+ if (toggleState == null) {
+ headerSwitch.setVisibility(INVISIBLE);
+ mQsDetailHeader.setClickable(false);
+ } else {
+ headerSwitch.setVisibility(VISIBLE);
+ headerSwitch.setChecked(toggleState);
+ mQsDetailHeader.setClickable(true);
+ mQsDetailHeader.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ detail.setToggleState(!toggleState);
+ }
+ });
+ }
+ } else {
+ mQsDetailHeader.setClickable(false);
+ }
+ }
+
+ private void transition(final View v, final boolean in) {
+ if (in) {
+ v.bringToFront();
+ }
+ v.animate().alpha(in ? 1 : 0).withLayer().start();
+ }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 1f68860..7e11369 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -33,4 +33,23 @@ public interface NetworkController {
String dataTypeContentDescriptionId, String description, boolean noSim);
void onAirplaneModeChanged(boolean enabled);
}
+
+ void addAccessPointCallback(AccessPointCallback callback);
+ void removeAccessPointCallback(AccessPointCallback callback);
+ void scanForAccessPoints();
+ void connect(AccessPoint ap);
+
+ public interface AccessPointCallback {
+ void onAccessPointsChanged(AccessPoint[] accessPoints);
+ }
+
+ public static class AccessPoint {
+ public static final int NO_NETWORK = -1; // see WifiManager
+
+ public int networkId;
+ public int iconId;
+ public String ssid;
+ public boolean isConnected;
+ public int level; // 0 - 5
+ }
}
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 4e54e41..4b94ebd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -169,6 +169,8 @@ public class NetworkControllerImpl extends BroadcastReceiver
void setIsAirplaneMode(boolean is, int airplaneIcon);
}
+ private final WifiAccessPointController mAccessPoints;
+
/**
* Construct this controller object and register for updates.
*/
@@ -237,6 +239,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
updateAirplaneMode();
mLastLocale = mContext.getResources().getConfiguration().locale;
+ mAccessPoints = new WifiAccessPointController(mContext);
}
public boolean hasMobileDataFeature() {
@@ -282,6 +285,26 @@ public class NetworkControllerImpl extends BroadcastReceiver
}
@Override
+ public void addAccessPointCallback(AccessPointCallback callback) {
+ mAccessPoints.addCallback(callback);
+ }
+
+ @Override
+ public void removeAccessPointCallback(AccessPointCallback callback) {
+ mAccessPoints.removeCallback(callback);
+ }
+
+ @Override
+ public void scanForAccessPoints() {
+ mAccessPoints.scan();
+ }
+
+ @Override
+ public void connect(AccessPoint ap) {
+ mAccessPoints.connect(ap);
+ }
+
+ @Override
public void setWifiEnabled(final boolean enabled) {
new AsyncTask<Void, Void, Void>() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiAccessPointController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiAccessPointController.java
new file mode 100644
index 0000000..09e7472
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiAccessPointController.java
@@ -0,0 +1,200 @@
+/*
+ * 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.statusbar.policy;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiManager.ActionListener;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Log;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.NetworkController.AccessPoint;
+import com.android.systemui.statusbar.policy.NetworkController.AccessPointCallback;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+public class WifiAccessPointController {
+ private static final String TAG = "WifiAccessPointController";
+ private static final boolean DEBUG = false;
+
+ private static final int[] ICONS = {
+ R.drawable.ic_qs_wifi_0,
+ R.drawable.ic_qs_wifi_full_1,
+ R.drawable.ic_qs_wifi_full_2,
+ R.drawable.ic_qs_wifi_full_3,
+ R.drawable.ic_qs_wifi_full_4,
+ };
+
+ private final Context mContext;
+ private final ArrayList<AccessPointCallback> mCallbacks = new ArrayList<AccessPointCallback>();
+ private final WifiManager mWifiManager;
+ private final Receiver mReceiver = new Receiver();
+
+ private boolean mScanning;
+
+ public WifiAccessPointController(Context context) {
+ mContext = context;
+ mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+ }
+
+ public void addCallback(AccessPointCallback callback) {
+ if (callback == null || mCallbacks.contains(callback)) return;
+ if (DEBUG) Log.d(TAG, "addCallback " + callback);
+ mCallbacks.add(callback);
+ mReceiver.setListening(!mCallbacks.isEmpty());
+ }
+
+ public void removeCallback(AccessPointCallback callback) {
+ if (callback == null) return;
+ if (DEBUG) Log.d(TAG, "removeCallback " + callback);
+ mCallbacks.remove(callback);
+ mReceiver.setListening(!mCallbacks.isEmpty());
+ }
+
+ public void scan() {
+ if (mScanning) return;
+ if (DEBUG) Log.d(TAG, "scan!");
+ mScanning = mWifiManager.startScan();
+ }
+
+ public void connect(AccessPoint ap) {
+ if (ap == null || ap.networkId < 0) return;
+ if (DEBUG) Log.d(TAG, "connect networkId=" + ap.networkId);
+ mWifiManager.connect(ap.networkId, new ActionListener() {
+ @Override
+ public void onSuccess() {
+ if (DEBUG) Log.d(TAG, "connect success");
+ }
+
+ @Override
+ public void onFailure(int reason) {
+ if (DEBUG) Log.d(TAG, "connect failure reason=" + reason);
+ }
+ });
+ }
+
+ private void fireCallback(AccessPoint[] aps) {
+ for (AccessPointCallback callback : mCallbacks) {
+ callback.onAccessPointsChanged(aps);
+ }
+ }
+
+ private static String trimDoubleQuotes(String v) {
+ return v != null && v.length() >= 2 && v.charAt(0) == '\"'
+ && v.charAt(v.length() - 1) == '\"' ? v.substring(1, v.length() - 1) : v;
+ }
+
+ private int getConnectedNetworkId() {
+ final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+ return wifiInfo != null ? wifiInfo.getNetworkId() : AccessPoint.NO_NETWORK;
+ }
+
+ private ArrayMap<String, WifiConfiguration> getConfiguredNetworksBySsid() {
+ final List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
+ if (configs == null || configs.size() == 0) return ArrayMap.EMPTY;
+ final ArrayMap<String, WifiConfiguration> rt = new ArrayMap<String, WifiConfiguration>();
+ for (WifiConfiguration config : configs) {
+ rt.put(trimDoubleQuotes(config.SSID), config);
+ }
+ return rt;
+ }
+
+ private void updateAccessPoints() {
+ final int connectedNetworkId = getConnectedNetworkId();
+ if (DEBUG) Log.d(TAG, "connectedNetworkId: " + connectedNetworkId);
+ final List<ScanResult> scanResults = mWifiManager.getScanResults();
+ final ArrayMap<String, WifiConfiguration> configured = getConfiguredNetworksBySsid();
+ if (DEBUG) Log.d(TAG, "scanResults: " + scanResults);
+ final List<AccessPoint> aps = new ArrayList<AccessPoint>(scanResults.size());
+ final ArraySet<String> ssids = new ArraySet<String>();
+ for (ScanResult scanResult : scanResults) {
+ final String ssid = scanResult.SSID;
+ if (TextUtils.isEmpty(ssid) || ssids.contains(ssid)) continue;
+ if (!configured.containsKey(ssid)) continue;
+ ssids.add(ssid);
+ final WifiConfiguration config = configured.get(ssid);
+ final int level = WifiManager.calculateSignalLevel(scanResult.level, ICONS.length);
+ final AccessPoint ap = new AccessPoint();
+ ap.networkId = config != null ? config.networkId : AccessPoint.NO_NETWORK;
+ ap.ssid = ssid;
+ ap.iconId = ICONS[level];
+ ap.isConnected = ap.networkId != AccessPoint.NO_NETWORK
+ && ap.networkId == connectedNetworkId;
+ ap.level = level;
+ aps.add(ap);
+ }
+ Collections.sort(aps, mByStrength);
+ fireCallback(aps.toArray(new AccessPoint[aps.size()]));
+ }
+
+ private final Comparator<AccessPoint> mByStrength = new Comparator<AccessPoint> () {
+ @Override
+ public int compare(AccessPoint lhs, AccessPoint rhs) {
+ return -Integer.compare(score(lhs), score(rhs));
+ }
+
+ private int score(AccessPoint ap) {
+ return ap.level + (ap.isConnected ? 10 : 0);
+ }
+ };
+
+ private final class Receiver extends BroadcastReceiver {
+ private boolean mRegistered;
+
+ public void setListening(boolean listening) {
+ if (listening && !mRegistered) {
+ if (DEBUG) Log.d(TAG, "Registering receiver");
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+ filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
+ filter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);
+ filter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
+ filter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
+ filter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);
+ filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+ filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
+ mContext.registerReceiver(this, filter);
+ mRegistered = true;
+ } else if (!listening && mRegistered) {
+ if (DEBUG) Log.d(TAG, "Unregistering receiver");
+ mContext.unregisterReceiver(this);
+ mRegistered = false;
+ }
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (DEBUG) Log.d(TAG, "onReceive " + intent.getAction());
+ if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(intent.getAction())) {
+ updateAccessPoints();
+ mScanning = false;
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 94fdd1f..4086022 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -30,6 +30,8 @@ import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.animation.AnimationUtils;
import android.widget.OverScroller;
+import android.widget.ScrollView;
+
import com.android.systemui.ExpandHelper;
import com.android.systemui.R;
import com.android.systemui.SwipeHelper;
@@ -150,7 +152,7 @@ public class NotificationStackScrollLayout extends ViewGroup
private float mMinTopOverScrollToEscape;
private int mIntrinsicPadding;
private int mNotificationTopPadding;
- private int mMinStackHeight;
+ private float mTopPaddingOverflow;
private boolean mDontReportNextOverScroll;
/**
@@ -166,7 +168,10 @@ public class NotificationStackScrollLayout extends ViewGroup
* animating.
*/
private boolean mOnlyScrollingInThisMotion;
- private boolean mTouchEnabled = true;
+ private ViewGroup mScrollView;
+ private boolean mInterceptDelegateEnabled;
+ private boolean mDelegateToScrollView;
+
private ViewTreeObserver.OnPreDrawListener mChildrenUpdater
= new ViewTreeObserver.OnPreDrawListener() {
@Override
@@ -258,7 +263,6 @@ public class NotificationStackScrollLayout extends ViewGroup
R.dimen.min_top_overscroll_to_qs);
mNotificationTopPadding = getResources().getDimensionPixelSize(
R.dimen.notifications_top_padding);
- mMinStackHeight = getResources().getDimensionPixelSize(R.dimen.collapsed_stack_height);
}
private void updatePadding(boolean dimmed) {
@@ -421,7 +425,7 @@ public class NotificationStackScrollLayout extends ViewGroup
int minStackHeight = itemHeight + bottomStackPeekSize;
int stackHeight;
if (newStackHeight - mTopPadding >= minStackHeight || getNotGoneChildCount() == 0) {
- setTranslationY(0);
+ setTranslationY(mTopPaddingOverflow);
stackHeight = newStackHeight;
} else {
@@ -466,6 +470,14 @@ public class NotificationStackScrollLayout extends ViewGroup
mLongClickListener = listener;
}
+ public void setScrollView(ViewGroup scrollView) {
+ mScrollView = scrollView;
+ }
+
+ public void setInterceptDelegateEnabled(boolean interceptDelegateEnabled) {
+ mInterceptDelegateEnabled = interceptDelegateEnabled;
+ }
+
public void onChildDismissed(View v) {
if (DEBUG) Log.v(TAG, "onChildDismissed: " + v);
final View veto = v.findViewById(R.id.veto);
@@ -536,7 +548,7 @@ public class NotificationStackScrollLayout extends ViewGroup
}
float childTop = slidingChild.getTranslationY();
float top = childTop + slidingChild.getClipTopAmount();
- float bottom = childTop + slidingChild.getActualHeight();
+ float bottom = top + slidingChild.getActualHeight();
int left = slidingChild.getLeft();
int right = slidingChild.getRight();
@@ -619,13 +631,17 @@ public class NotificationStackScrollLayout extends ViewGroup
@Override
public boolean onTouchEvent(MotionEvent ev) {
- if (!isEnabled()) {
- return false;
- }
boolean isCancelOrUp = ev.getActionMasked() == MotionEvent.ACTION_CANCEL
|| ev.getActionMasked()== MotionEvent.ACTION_UP;
+ if (mDelegateToScrollView) {
+ if (isCancelOrUp) {
+ mDelegateToScrollView = false;
+ }
+ transformTouchEvent(ev, this, mScrollView);
+ return mScrollView.onTouchEvent(ev);
+ }
boolean expandWantsIt = false;
- if (!mSwipingInProgress && !mOnlyScrollingInThisMotion) {
+ if (!mSwipingInProgress && !mOnlyScrollingInThisMotion && isScrollingEnabled()) {
if (isCancelOrUp) {
mExpandHelper.onlyObserveMovements(false);
}
@@ -1195,7 +1211,7 @@ public class NotificationStackScrollLayout extends ViewGroup
return view.getHeight();
}
- private int getContentHeight() {
+ public int getContentHeight() {
return mContentHeight;
}
@@ -1271,17 +1287,32 @@ public class NotificationStackScrollLayout extends ViewGroup
public void updateTopPadding(float qsHeight, int scrollY, boolean animate) {
float start = qsHeight - scrollY + mNotificationTopPadding;
float stackHeight = getHeight() - start;
- if (stackHeight <= mMinStackHeight) {
- float overflow = mMinStackHeight - stackHeight;
- stackHeight = mMinStackHeight;
+ int minStackHeight = getMinStackHeight();
+ if (stackHeight <= minStackHeight) {
+ float overflow = minStackHeight - stackHeight;
+ stackHeight = minStackHeight;
start = getHeight() - stackHeight;
setTranslationY(overflow);
+ mTopPaddingOverflow = overflow;
} else {
setTranslationY(0);
+ mTopPaddingOverflow = 0;
}
setTopPadding(clampPadding((int) start), animate);
}
+ public int getNotificationTopPadding() {
+ return mNotificationTopPadding;
+ }
+
+ public int getMinStackHeight() {
+ return mCollapsedSize + mBottomStackPeekSize;
+ }
+
+ public float getTopPaddingOverflow() {
+ return mTopPaddingOverflow;
+ }
+
public int getPeekHeight() {
return mIntrinsicPadding + mCollapsedSize + mBottomStackPeekSize;
}
@@ -1327,11 +1358,25 @@ public class NotificationStackScrollLayout extends ViewGroup
}
}
+ private void transformTouchEvent(MotionEvent ev, View sourceView, View targetView) {
+ ev.offsetLocation(sourceView.getX(), sourceView.getY());
+ ev.offsetLocation(-targetView.getX(), -targetView.getY());
+ }
+
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
+ if (mInterceptDelegateEnabled) {
+ transformTouchEvent(ev, this, mScrollView);
+ if (mScrollView.onInterceptTouchEvent(ev)) {
+ mDelegateToScrollView = true;
+ removeLongPressCallback();
+ return true;
+ }
+ transformTouchEvent(ev, mScrollView, this);
+ }
initDownStates(ev);
boolean expandWantsIt = false;
- if (!mSwipingInProgress && !mOnlyScrollingInThisMotion) {
+ if (!mSwipingInProgress && !mOnlyScrollingInThisMotion && isScrollingEnabled()) {
expandWantsIt = mExpandHelper.onInterceptTouchEvent(ev);
}
boolean scrollWantsIt = false;
@@ -1854,6 +1899,10 @@ public class NotificationStackScrollLayout extends ViewGroup
mIntrinsicPadding = intrinsicPadding;
}
+ public int getIntrinsicPadding() {
+ return mIntrinsicPadding;
+ }
+
/**
* @return the y position of the first notification
*/
@@ -1861,18 +1910,6 @@ public class NotificationStackScrollLayout extends ViewGroup
return mTopPadding + getTranslationY();
}
- public void setTouchEnabled(boolean touchEnabled) {
- mTouchEnabled = touchEnabled;
- }
-
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- if (!mTouchEnabled) {
- return false;
- }
- return super.dispatchTouchEvent(ev);
- }
-
@Override
public boolean shouldDelayChildPressedState() {
return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index a8c25d8..7c522d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -113,7 +113,7 @@ public class StackScrollAlgorithm {
mBottomStackSlowDownLength = context.getResources()
.getDimensionPixelSize(R.dimen.bottom_stack_slow_down_length);
mRoundedRectCornerRadius = context.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.notification_material_rounded_rect_radius);
+ R.dimen.notification_material_rounded_rect_radius);
}
@@ -155,6 +155,17 @@ public class StackScrollAlgorithm {
updateDimmedActivated(ambientState, resultState, algorithmState);
updateClipping(resultState, algorithmState);
updateScrimAmount(resultState, algorithmState, ambientState.getScrimAmount());
+ updateSpeedBumpState(resultState, algorithmState, ambientState.getSpeedBumpIndex());
+ }
+
+ private void updateSpeedBumpState(StackScrollState resultState,
+ StackScrollAlgorithmState algorithmState, int speedBumpIndex) {
+ int childCount = algorithmState.visibleChildren.size();
+ for (int i = 0; i < childCount; i++) {
+ View child = algorithmState.visibleChildren.get(i);
+ StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
+ childViewState.belowSpeedBump = speedBumpIndex != -1 && i > speedBumpIndex;
+ }
}
private void updateScrimAmount(StackScrollState resultState,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
index 9ae038a..f48739c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -151,6 +151,9 @@ public class StackScrollState {
// apply dark
child.setDark(state.dark, false /* animate */);
+ // apply speed bump state
+ child.setBelowSpeedBump(state.belowSpeedBump);
+
// apply scrimming
child.setScrimAmount(state.scrimAmount);
@@ -224,6 +227,7 @@ public class StackScrollState {
float scale;
boolean dimmed;
boolean dark;
+ boolean belowSpeedBump;
/**
* A value between 0 and 1 indicating how much the view should be scrimmed.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index f732cf0..0c84675 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -179,6 +179,9 @@ public class StackStateAnimator {
// start dark animation
child.setDark(viewState.dark, mAnimationFilter.animateDark);
+ // apply speed bump state
+ child.setBelowSpeedBump(viewState.belowSpeedBump);
+
// apply scrimming
child.setScrimAmount(viewState.scrimAmount);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index 99cba4d..53daaae 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -358,7 +358,7 @@ public class VolumePanel extends Handler {
// embedded mode
mDialog = null;
mView = LayoutInflater.from(mContext).inflate(
- com.android.systemui.R.layout.volume_panel, parent, true);
+ com.android.systemui.R.layout.volume_panel, parent, false);
}
mPanel = (ViewGroup) mView.findViewById(com.android.systemui.R.id.visible_panel);
mSliderPanel = (ViewGroup) mView.findViewById(com.android.systemui.R.id.slider_panel);
@@ -384,6 +384,10 @@ public class VolumePanel extends Handler {
listenToRingerMode();
}
+ public View getContentView() {
+ return mView;
+ }
+
private void setLayoutDirection(int layoutDirection) {
mPanel.setLayoutDirection(layoutDirection);
updateStates();
@@ -628,7 +632,8 @@ public class VolumePanel extends Handler {
if (LOGD) Log.d(mTag, "expand mZenPanel=" + mZenPanel);
if (mZenPanel == null) {
mZenPanel = (ZenModePanel) mZenPanelStub.inflate();
- mZenPanel.init(mZenController, mDialog != null ? 'D' : 'E');
+ final boolean isDialog = mDialog != null;
+ mZenPanel.init(mZenController, isDialog ? 'D' : 'E', isDialog);
mZenPanel.setCallback(new ZenModePanel.Callback() {
@Override
public void onMoreSettings() {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index 798e7fa..9917944 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -67,6 +67,7 @@ public class ZenModePanel extends LinearLayout {
private char mLogTag = '?';
private String mTag;
private LinearLayout mConditions;
+ private View mMoreSettings;
private Callback mCallback;
private ZenModeController mController;
private boolean mRequestingConditions;
@@ -91,7 +92,8 @@ public class ZenModePanel extends LinearLayout {
protected void onFinishInflate() {
super.onFinishInflate();
mConditions = (LinearLayout) findViewById(android.R.id.content);
- findViewById(android.R.id.button2).setOnClickListener(new View.OnClickListener() {
+ mMoreSettings = findViewById(android.R.id.button2);
+ mMoreSettings.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
fireMoreSettings();
@@ -154,12 +156,13 @@ public class ZenModePanel extends LinearLayout {
}
}
- public void init(ZenModeController controller, char logTag) {
+ public void init(ZenModeController controller, char logTag, boolean moreSettings) {
mController = controller;
mLogTag = logTag;
updateTag();
mExitConditionId = mController.getExitConditionId();
if (DEBUG) Log.d(mTag, "init mExitConditionId=" + mExitConditionId);
+ mMoreSettings.setVisibility(moreSettings ? VISIBLE : GONE);
mConditions.removeAllViews();
mController.addCallback(mZenCallback);
if (mShowing) {
diff --git a/services/core/java/com/android/server/hdmi/FeatureAction.java b/services/core/java/com/android/server/hdmi/FeatureAction.java
index cf28f05..3595f79 100644
--- a/services/core/java/com/android/server/hdmi/FeatureAction.java
+++ b/services/core/java/com/android/server/hdmi/FeatureAction.java
@@ -207,7 +207,7 @@ abstract class FeatureAction {
protected final void pollDevices(DevicePollingCallback callback, int pickStrategy,
int retryCount) {
- mService.pollDevices(callback, pickStrategy, retryCount);
+ mService.pollDevices(callback, getSourceAddress(), pickStrategy, retryCount);
}
/**
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index 49f2d6f..7dfea6a 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -200,7 +200,8 @@ final class HdmiCecController {
int curAddress = (startAddress + i) % NUM_LOGICAL_ADDRESS;
if (curAddress != HdmiCec.ADDR_UNREGISTERED
&& deviceType == HdmiCec.getTypeFromAddress(curAddress)) {
- if (!sendPollMessage(curAddress, RETRY_COUNT_FOR_LOGICAL_ADDRESS_ALLOCATION)) {
+ if (!sendPollMessage(curAddress, curAddress,
+ RETRY_COUNT_FOR_LOGICAL_ADDRESS_ALLOCATION)) {
logicalAddress = curAddress;
break;
}
@@ -358,16 +359,18 @@ final class HdmiCecController {
* <p>Declared as package-private. accessed by {@link HdmiControlService} only.
*
* @param callback an interface used to get a list of all remote devices' address
+ * @param sourceAddress a logical address of source device where sends polling message
* @param pickStrategy strategy how to pick polling candidates
* @param retryCount the number of retry used to send polling message to remote devices
*/
@ServiceThreadOnly
- void pollDevices(DevicePollingCallback callback, int pickStrategy, int retryCount) {
+ void pollDevices(DevicePollingCallback callback, int sourceAddress, int pickStrategy,
+ int retryCount) {
assertRunOnServiceThread();
// Extract polling candidates. No need to poll against local devices.
List<Integer> pollingCandidates = pickPollCandidates(pickStrategy);
- runDevicePolling(pollingCandidates, retryCount, callback);
+ runDevicePolling(sourceAddress, pollingCandidates, retryCount, callback);
}
/**
@@ -428,7 +431,8 @@ final class HdmiCecController {
}
@ServiceThreadOnly
- private void runDevicePolling(final List<Integer> candidates, final int retryCount,
+ private void runDevicePolling(final int sourceAddress,
+ final List<Integer> candidates, final int retryCount,
final DevicePollingCallback callback) {
assertRunOnServiceThread();
runOnIoThread(new Runnable() {
@@ -436,7 +440,7 @@ final class HdmiCecController {
public void run() {
final ArrayList<Integer> allocated = new ArrayList<>();
for (Integer address : candidates) {
- if (sendPollMessage(address, retryCount)) {
+ if (sendPollMessage(sourceAddress, address, retryCount)) {
allocated.add(address);
}
}
@@ -453,15 +457,14 @@ final class HdmiCecController {
}
@IoThreadOnly
- private boolean sendPollMessage(int address, int retryCount) {
+ private boolean sendPollMessage(int sourceAddress, int destinationAddress, int retryCount) {
assertRunOnIoThread();
for (int i = 0; i < retryCount; ++i) {
- // <Polling Message> is a message which has empty body and
- // uses same address for both source and destination address.
+ // <Polling Message> is a message which has empty body.
// If sending <Polling Message> failed (NAK), it becomes
// new logical address for the device because no device uses
// it as logical address of the device.
- if (nativeSendCecCommand(mNativePtr, address, address, EMPTY_BODY)
+ if (nativeSendCecCommand(mNativePtr, sourceAddress, destinationAddress, EMPTY_BODY)
== HdmiConstants.SEND_RESULT_SUCCESS) {
return true;
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index a2df852..63df9a2 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -448,14 +448,17 @@ public final class HdmiControlService extends SystemService {
* devices.
*
* @param callback an interface used to get a list of all remote devices' address
+ * @param sourceAddress a logical address of source device where sends polling message
* @param pickStrategy strategy how to pick polling candidates
* @param retryCount the number of retry used to send polling message to remote devices
* @throw IllegalArgumentException if {@code pickStrategy} is invalid value
*/
@ServiceThreadOnly
- void pollDevices(DevicePollingCallback callback, int pickStrategy, int retryCount) {
+ void pollDevices(DevicePollingCallback callback, int sourceAddress, int pickStrategy,
+ int retryCount) {
assertRunOnServiceThread();
- mCecController.pollDevices(callback, checkPollStrategy(pickStrategy), retryCount);
+ mCecController.pollDevices(callback, sourceAddress, checkPollStrategy(pickStrategy),
+ retryCount);
}
private int checkPollStrategy(int pickStrategy) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index bc14888..c8496e4 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1551,8 +1551,16 @@ public class NotificationManagerService extends SystemService {
mNotificationsByKey.remove(old.sbn.getKey());
r.isUpdate = true;
}
+
mNotificationsByKey.put(n.getKey(), r);
+ // Ensure if this is a foreground service that the proper additional
+ // flags are set.
+ if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
+ notification.flags |= Notification.FLAG_ONGOING_EVENT
+ | Notification.FLAG_NO_CLEAR;
+ }
+
applyZenModeLocked(r);
Collections.sort(mNotificationList, mRankingComparator);
@@ -1571,13 +1579,6 @@ public class NotificationManagerService extends SystemService {
+ n.getPackageName());
}
- // Ensure if this is a foreground service that the proper additional
- // flags are set.
- if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
- notification.flags |= Notification.FLAG_ONGOING_EVENT
- | Notification.FLAG_NO_CLEAR;
- }
-
buzzBeepBlinkLocked(r);
}
}
@@ -1872,10 +1873,9 @@ public class NotificationManagerService extends SystemService {
}
}
- // let zen mode evaluate this record and then make note of that for the future
+ // let zen mode evaluate this record
private void applyZenModeLocked(NotificationRecord record) {
- record.setIntercepted(mZenModeHelper.shouldIntercept(record, record.wasTouchedByZen()));
- record.setTouchedByZen();
+ record.setIntercepted(mZenModeHelper.shouldIntercept(record));
}
// lock on mNotificationList
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 13fb986..6b60ea4 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -51,8 +51,6 @@ public final class NotificationRecord {
// is this notification currently being intercepted by Zen Mode?
private boolean mIntercept;
- // InterceptedNotifications needs to know if this has been previously evaluated.
- private boolean mTouchedByZen;
// The timestamp used for ranking.
private long mRankingTimeMs;
@@ -71,7 +69,6 @@ public final class NotificationRecord {
public void copyRankingInformation(NotificationRecord previous) {
mContactAffinity = previous.mContactAffinity;
mRecentlyIntrusive = previous.mRecentlyIntrusive;
- mTouchedByZen = previous.mTouchedByZen;
mIntercept = previous.mIntercept;
mRankingTimeMs = calculateRankingTimeMs(previous.getRankingTimeMs());
}
@@ -204,14 +201,6 @@ public final class NotificationRecord {
return mIntercept;
}
- public boolean wasTouchedByZen() {
- return mTouchedByZen;
- }
-
- public void setTouchedByZen() {
- mTouchedByZen = true;
- }
-
/**
* Returns the timestamp to use for time-based sorting in the ranker.
*/
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index b95db9c..7bac3dc 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -129,12 +129,8 @@ public class ZenModeHelper {
mCallbacks.add(callback);
}
- public boolean shouldIntercept(NotificationRecord record, boolean previouslySeen) {
+ public boolean shouldIntercept(NotificationRecord record) {
if (mZenMode != Global.ZEN_MODE_OFF) {
- if (previouslySeen && !record.isIntercepted()) {
- // notifications never transition from not intercepted to intercepted
- return false;
- }
if (isSystem(record)) {
return false;
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 0658eee..11e546f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -41,6 +41,7 @@ import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.SELinux;
+import android.os.UserHandle;
import android.system.ErrnoException;
import android.system.OsConstants;
import android.system.StructStat;
@@ -272,7 +273,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
};
- mPm.installStage(mPackageName, this.sessionDir, localObserver, params.installFlags);
+ mPm.installStage(mPackageName, this.sessionDir, localObserver, params, installerPackageName,
+ installerUid, new UserHandle(userId));
}
/**
diff --git a/services/core/java/com/android/server/pm/PackageKeySetData.java b/services/core/java/com/android/server/pm/PackageKeySetData.java
index d470807..11ed5d2 100644
--- a/services/core/java/com/android/server/pm/PackageKeySetData.java
+++ b/services/core/java/com/android/server/pm/PackageKeySetData.java
@@ -18,7 +18,6 @@ package com.android.server.pm;
import com.android.internal.util.ArrayUtils;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -35,19 +34,17 @@ public class PackageKeySetData {
private long[] mDefinedKeySets;
- private final Map<String, Long> mKeySetAliases;
+ private final Map<String, Long> mKeySetAliases = new HashMap<String, Long>();
PackageKeySetData() {
mProperSigningKeySet = KEYSET_UNASSIGNED;
- mKeySetAliases = new HashMap<String, Long>();
}
PackageKeySetData(PackageKeySetData original) {
- mSigningKeySets = original.getSigningKeySets().clone();
- mUpgradeKeySets = original.getUpgradeKeySets().clone();
- mDefinedKeySets = original.getDefinedKeySets().clone();
- mKeySetAliases = new HashMap<String, Long>();
- mKeySetAliases.putAll(original.getAliases());
+ mSigningKeySets = ArrayUtils.cloneOrNull(original.mSigningKeySets);
+ mUpgradeKeySets = ArrayUtils.cloneOrNull(original.mUpgradeKeySets);
+ mDefinedKeySets = ArrayUtils.cloneOrNull(original.mDefinedKeySets);
+ mKeySetAliases.putAll(original.mKeySetAliases);
}
protected void setProperSigningKeySet(long ks) {
@@ -149,4 +146,4 @@ public class PackageKeySetData {
/* should never be the case that mUpgradeKeySets.length == 0 */
return (mUpgradeKeySets != null && mUpgradeKeySets.length > 0);
}
-} \ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index bc45ae0..2d9176d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -24,6 +24,7 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static android.content.pm.PackageParser.isPackageFilename;
import static android.os.Process.PACKAGE_INFO_GID;
import static android.os.Process.SYSTEM_UID;
import static android.system.OsConstants.S_IRGRP;
@@ -46,6 +47,7 @@ import com.android.internal.content.PackageHelper;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.server.EventLogTags;
import com.android.server.IntentResolver;
@@ -92,6 +94,7 @@ import android.content.pm.ManifestDigest;
import android.content.pm.PackageCleanItem;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInfoLite;
+import android.content.pm.PackageInstallerParams;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser.ActivityIntentInfo;
import android.content.pm.PackageParser.PackageParserException;
@@ -349,6 +352,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// LOCK HELD. Can be called with mInstallLock held.
final Installer mInstaller;
+ /** Directory where installed third-party apps stored */
final File mAppInstallDir;
/**
@@ -361,6 +365,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// apps.
final File mDrmAppPrivateInstallDir;
+ /** Directory where third-party apps are staged before install */
final File mAppStagingDir;
// ----------------------------------------------------------------
@@ -1143,17 +1148,18 @@ public class PackageManagerService extends IPackageManager.Stub {
if ((state != null) && !state.timeoutExtended()) {
final InstallArgs args = state.getInstallArgs();
- Slog.i(TAG, "Verification timed out for " + args.packageURI.toString());
+ final Uri fromUri = Uri.fromFile(args.fromFile);
+
+ Slog.i(TAG, "Verification timed out for " + fromUri);
mPendingVerification.remove(verificationId);
int ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
if (getDefaultVerificationResponse() == PackageManager.VERIFICATION_ALLOW) {
- Slog.i(TAG, "Continuing with installation of "
- + args.packageURI.toString());
+ Slog.i(TAG, "Continuing with installation of " + fromUri);
state.setVerifierResponse(Binder.getCallingUid(),
PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT);
- broadcastPackageVerified(verificationId, args.packageURI,
+ broadcastPackageVerified(verificationId, fromUri,
PackageManager.VERIFICATION_ALLOW,
state.getInstallArgs().getUser());
try {
@@ -1162,7 +1168,7 @@ public class PackageManagerService extends IPackageManager.Stub {
Slog.e(TAG, "Could not contact the ContainerService");
}
} else {
- broadcastPackageVerified(verificationId, args.packageURI,
+ broadcastPackageVerified(verificationId, fromUri,
PackageManager.VERIFICATION_REJECT,
state.getInstallArgs().getUser());
}
@@ -1189,11 +1195,12 @@ public class PackageManagerService extends IPackageManager.Stub {
mPendingVerification.remove(verificationId);
final InstallArgs args = state.getInstallArgs();
+ final Uri fromUri = Uri.fromFile(args.fromFile);
int ret;
if (state.isInstallAllowed()) {
ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
- broadcastPackageVerified(verificationId, args.packageURI,
+ broadcastPackageVerified(verificationId, fromUri,
response.code, state.getInstallArgs().getUser());
try {
ret = args.copyApk(mContainerService, true);
@@ -1528,14 +1535,14 @@ public class PackageManagerService extends IPackageManager.Stub {
// overlay packages if they reside in VENDOR_OVERLAY_DIR.
File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
mVendorOverlayInstallObserver = new AppDirObserver(
- vendorOverlayDir.getPath(), OBSERVER_EVENTS, true, false);
+ vendorOverlayDir.getPath(), OBSERVER_EVENTS, true, false);
mVendorOverlayInstallObserver.startWatching();
scanDirLI(vendorOverlayDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode | SCAN_TRUSTED_OVERLAY, 0);
// Find base frameworks (resource packages without code).
mFrameworkInstallObserver = new AppDirObserver(
- frameworkDir.getPath(), OBSERVER_EVENTS, true, false);
+ frameworkDir.getPath(), OBSERVER_EVENTS, true, false);
mFrameworkInstallObserver.startWatching();
scanDirLI(frameworkDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
@@ -1547,14 +1554,14 @@ public class PackageManagerService extends IPackageManager.Stub {
mPrivilegedInstallObserver = new AppDirObserver(
privilegedAppDir.getPath(), OBSERVER_EVENTS, true, true);
mPrivilegedInstallObserver.startWatching();
- scanDirLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM
- | PackageParser.PARSE_IS_SYSTEM_DIR
- | PackageParser.PARSE_IS_PRIVILEGED, scanMode, 0);
+ scanDirLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM
+ | PackageParser.PARSE_IS_SYSTEM_DIR
+ | PackageParser.PARSE_IS_PRIVILEGED, scanMode, 0);
// Collect ordinary system packages.
File systemAppDir = new File(Environment.getRootDirectory(), "app");
mSystemInstallObserver = new AppDirObserver(
- systemAppDir.getPath(), OBSERVER_EVENTS, true, false);
+ systemAppDir.getPath(), OBSERVER_EVENTS, true, false);
mSystemInstallObserver.startWatching();
scanDirLI(systemAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
@@ -1567,7 +1574,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// failed to look up canonical path, continue with original one
}
mVendorInstallObserver = new AppDirObserver(
- vendorAppDir.getPath(), OBSERVER_EVENTS, true, false);
+ vendorAppDir.getPath(), OBSERVER_EVENTS, true, false);
mVendorInstallObserver.startWatching();
scanDirLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
@@ -1825,6 +1832,10 @@ public class PackageManagerService extends IPackageManager.Stub {
void cleanupInstallFailedPackage(PackageSetting ps) {
Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
removeDataDirsLI(ps.name);
+
+ // TODO: try cleaning up codePath directory contents first, since it
+ // might be a cluster
+
if (ps.codePath != null) {
if (!ps.codePath.delete()) {
Slog.w(TAG, "Unable to remove old code file: " + ps.codePath);
@@ -2071,15 +2082,12 @@ public class PackageManagerService extends IPackageManager.Stub {
if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) == 0) {
return null;
}
- // App code is gone, so we aren't worried about split paths
+ // Only data remains, so we aren't worried about code paths
pkg = new PackageParser.Package(packageName);
pkg.applicationInfo.packageName = packageName;
pkg.applicationInfo.flags = ps.pkgFlags | ApplicationInfo.FLAG_IS_DATA_ONLY;
- pkg.applicationInfo.sourceDir = ps.codePathString;
- pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
pkg.applicationInfo.dataDir =
getDataPathForPackage(packageName, 0).getPath();
- pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString;
pkg.applicationInfo.cpuAbi = ps.cpuAbiString;
}
return generatePackageInfo(pkg, flags, userId);
@@ -4041,20 +4049,21 @@ public class PackageManagerService extends IPackageManager.Stub {
private boolean createIdmapForPackagePairLI(PackageParser.Package pkg,
PackageParser.Package opkg) {
if (!opkg.mTrustedOverlay) {
- Slog.w(TAG, "Skipping target and overlay pair " + pkg.codePath + " and " +
- opkg.codePath + ": overlay not trusted");
+ Slog.w(TAG, "Skipping target and overlay pair " + pkg.baseCodePath + " and " +
+ opkg.baseCodePath + ": overlay not trusted");
return false;
}
HashMap<String, PackageParser.Package> overlaySet = mOverlays.get(pkg.packageName);
if (overlaySet == null) {
- Slog.e(TAG, "was about to create idmap for " + pkg.codePath + " and " +
- opkg.codePath + " but target package has no known overlays");
+ Slog.e(TAG, "was about to create idmap for " + pkg.baseCodePath + " and " +
+ opkg.baseCodePath + " but target package has no known overlays");
return false;
}
final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
// TODO: generate idmap for split APKs
- if (mInstaller.idmap(pkg.codePath, opkg.codePath, sharedGid) != 0) {
- Slog.e(TAG, "Failed to generate idmap for " + pkg.codePath + " and " + opkg.codePath);
+ if (mInstaller.idmap(pkg.baseCodePath, opkg.baseCodePath, sharedGid) != 0) {
+ Slog.e(TAG, "Failed to generate idmap for " + pkg.baseCodePath + " and "
+ + opkg.baseCodePath);
return false;
}
PackageParser.Package[] overlayArray =
@@ -4075,8 +4084,8 @@ public class PackageManagerService extends IPackageManager.Stub {
}
private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
- String[] files = dir.list();
- if (files == null) {
+ final File[] files = dir.listFiles();
+ if (ArrayUtils.isEmpty(files)) {
Log.d(TAG, "No files in app dir " + dir);
return;
}
@@ -4086,10 +4095,8 @@ public class PackageManagerService extends IPackageManager.Stub {
+ " flags=0x" + Integer.toHexString(flags));
}
- int i;
- for (i=0; i<files.length; i++) {
- File file = new File(dir, files[i]);
- if (!isPackageFilename(files[i])) {
+ for (File file : files) {
+ if (!isPackageFilename(file)) {
// Ignore entries which are not apk's
continue;
}
@@ -4258,7 +4265,7 @@ public class PackageManagerService extends IPackageManager.Stub {
+ ": new version " + pkg.mVersionCode
+ " better than installed " + ps.versionCode);
- InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
+ InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString,
getAppInstructionSetFromSettings(ps));
synchronized (mInstallLock) {
@@ -4323,7 +4330,7 @@ public class PackageManagerService extends IPackageManager.Stub {
Slog.w(TAG, "Package " + ps.name + " at " + scanFile + "reverting from "
+ ps.codePathString + ": new version " + pkg.mVersionCode
+ " better than installed " + ps.versionCode);
- InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
+ InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString,
getAppInstructionSetFromSettings(ps));
synchronized (mInstallLock) {
@@ -4343,29 +4350,27 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- final String codePath = pkg.codePath;
+ final String baseCodePath = pkg.baseCodePath;
final String[] splitCodePaths = pkg.splitCodePaths;
- String resPath = null;
- String[] splitResPaths = null;
+ // TODO: extend to support forward-locked splits
+ String baseResPath = null;
if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !updatedPkgBetter) {
if (ps != null && ps.resourcePathString != null) {
- resPath = ps.resourcePathString;
- splitResPaths = deriveSplitResPaths(pkg.splitCodePaths);
+ baseResPath = ps.resourcePathString;
} else {
// Should not happen at all. Just log an error.
Slog.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
}
} else {
- resPath = pkg.codePath;
- splitResPaths = pkg.splitCodePaths;
+ baseResPath = pkg.baseCodePath;
}
// Set application objects path explicitly.
- pkg.applicationInfo.sourceDir = codePath;
- pkg.applicationInfo.publicSourceDir = resPath;
+ pkg.applicationInfo.sourceDir = baseCodePath;
+ pkg.applicationInfo.publicSourceDir = baseResPath;
pkg.applicationInfo.splitSourceDirs = splitCodePaths;
- pkg.applicationInfo.splitPublicSourceDirs = splitResPaths;
+ pkg.applicationInfo.splitPublicSourceDirs = splitCodePaths;
// Note that we invoke the following method only if we are about to unpack an application
PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanMode
@@ -6419,10 +6424,6 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- private static final boolean isPackageFilename(String name) {
- return name != null && name.endsWith(".apk");
- }
-
private static boolean hasPermission(PackageParser.Package pkgInfo, String perm) {
for (int i=pkgInfo.permissions.size()-1; i>=0; i--) {
if (pkgInfo.permissions.get(i).info.name.equals(perm)) {
@@ -7701,8 +7702,13 @@ public class PackageManagerService extends IPackageManager.Stub {
verificationParams.setInstallerUid(uid);
+ if (!"file".equals(packageURI.getScheme())) {
+ throw new UnsupportedOperationException("Only file:// URIs are supported");
+ }
+ final File fromFile = new File(packageURI.getPath());
+
final Message msg = mHandler.obtainMessage(INIT_COPY);
- msg.obj = new InstallParams(packageURI, observer, observer2, filteredFlags,
+ msg.obj = new InstallParams(fromFile, observer, observer2, filteredFlags,
installerPackageName, verificationParams, encryptionParams, user,
packageAbiOverride);
mHandler.sendMessage(msg);
@@ -7820,11 +7826,12 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- void installStage(String basePackageName, File stageDir, IPackageInstallObserver2 observer,
- int flags) {
- // TODO: install stage!
+ void installStage(String packageName, File stageDir, IPackageInstallObserver2 observer2,
+ PackageInstallerParams params, String installerPackageName, int installerUid,
+ UserHandle user) {
+ Slog.e(TAG, "TODO: install stage!");
try {
- observer.packageInstalled(basePackageName, null,
+ observer2.packageInstalled(packageName, null,
PackageManager.INSTALL_FAILED_INTERNAL_ERROR);
} catch (RemoteException ignored) {
}
@@ -8407,30 +8414,38 @@ public class PackageManagerService extends IPackageManager.Stub {
}
class InstallParams extends HandlerParams {
+ /**
+ * Location where install is coming from, before it has been
+ * copied/renamed into place. This could be a single monolithic APK
+ * file, or a cluster directory. This location may be untrusted.
+ */
+ private final File mFromFile;
+
+ /**
+ * Local copy of {@link #mFromFile}, if generated.
+ */
+ private File mLocalFromFile;
+
final IPackageInstallObserver observer;
final IPackageInstallObserver2 observer2;
int flags;
-
- private final Uri mPackageURI;
final String installerPackageName;
final VerificationParams verificationParams;
private InstallArgs mArgs;
private int mRet;
- private File mTempPackage;
final ContainerEncryptionParams encryptionParams;
final String packageAbiOverride;
final String packageInstructionSetOverride;
- InstallParams(Uri packageURI,
- IPackageInstallObserver observer, IPackageInstallObserver2 observer2,
- int flags, String installerPackageName, VerificationParams verificationParams,
- ContainerEncryptionParams encryptionParams, UserHandle user,
- String packageAbiOverride) {
+ InstallParams(File fromFile, IPackageInstallObserver observer,
+ IPackageInstallObserver2 observer2, int flags, String installerPackageName,
+ VerificationParams verificationParams, ContainerEncryptionParams encryptionParams,
+ UserHandle user, String packageAbiOverride) {
super(user);
- this.mPackageURI = packageURI;
- this.flags = flags;
+ mFromFile = Preconditions.checkNotNull(fromFile);
this.observer = observer;
this.observer2 = observer2;
+ this.flags = flags;
this.installerPackageName = installerPackageName;
this.verificationParams = verificationParams;
this.encryptionParams = encryptionParams;
@@ -8443,7 +8458,7 @@ public class PackageManagerService extends IPackageManager.Stub {
public String toString() {
return "InstallParams{"
+ Integer.toHexString(System.identityHashCode(this))
- + " " + mPackageURI + "}";
+ + " " + mFromFile + "}";
}
public ManifestDigest getManifestDigest() {
@@ -8543,76 +8558,55 @@ public class PackageManagerService extends IPackageManager.Stub {
Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed");
}
- try {
- mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, mPackageURI,
- Intent.FLAG_GRANT_READ_URI_PERMISSION);
-
- final File packageFile;
- if (encryptionParams != null || !"file".equals(mPackageURI.getScheme())) {
- mTempPackage = createTempPackageFile(mDrmAppPrivateInstallDir);
- if (mTempPackage != null) {
- ParcelFileDescriptor out;
- try {
- out = ParcelFileDescriptor.open(mTempPackage,
- ParcelFileDescriptor.MODE_READ_WRITE);
- } catch (FileNotFoundException e) {
- out = null;
- Slog.e(TAG, "Failed to create temporary file for : " + mPackageURI);
- }
-
- // Make a temporary file for decryption.
- ret = mContainerService
- .copyResource(mPackageURI, encryptionParams, out);
+ if (encryptionParams != null) {
+ // Make a temporary file for decryption.
+ mLocalFromFile = createTempPackageFile(mDrmAppPrivateInstallDir);
+ if (mLocalFromFile != null) {
+ ParcelFileDescriptor out = null;
+ try {
+ out = ParcelFileDescriptor.open(mLocalFromFile,
+ ParcelFileDescriptor.MODE_READ_WRITE);
+ ret = mContainerService.copyResource(mFromFile.getAbsolutePath(),
+ encryptionParams, out);
+ } catch (FileNotFoundException e) {
+ Slog.e(TAG, "Failed to create temporary file for: " + mFromFile);
+ } finally {
IoUtils.closeQuietly(out);
-
- packageFile = mTempPackage;
-
- FileUtils.setPermissions(packageFile.getAbsolutePath(),
- FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP
- | FileUtils.S_IROTH,
- -1, -1);
- } else {
- packageFile = null;
}
- } else {
- packageFile = new File(mPackageURI.getPath());
+
+ FileUtils.setPermissions(mLocalFromFile, 0644, -1, -1);
}
+ }
- if (packageFile != null) {
- // Remote call to find out default install location
- final String packageFilePath = packageFile.getAbsolutePath();
- pkgLite = mContainerService.getMinimalPackageInfo(packageFilePath, flags,
- lowThreshold, packageAbiOverride);
+ // Remote call to find out default install location
+ final String fromPath = getFromFile().getAbsolutePath();
+ pkgLite = mContainerService.getMinimalPackageInfo(fromPath, flags, lowThreshold,
+ packageAbiOverride);
- /*
- * If we have too little free space, try to free cache
- * before giving up.
- */
- if (pkgLite.recommendedInstallLocation
- == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
- final long size = mContainerService.calculateInstalledSize(
- packageFilePath, isForwardLocked(), packageAbiOverride);
- if (mInstaller.freeCache(size + lowThreshold) >= 0) {
- pkgLite = mContainerService.getMinimalPackageInfo(packageFilePath,
- flags, lowThreshold, packageAbiOverride);
- }
- /*
- * The cache free must have deleted the file we
- * downloaded to install.
- *
- * TODO: fix the "freeCache" call to not delete
- * the file we care about.
- */
- if (pkgLite.recommendedInstallLocation
- == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
- pkgLite.recommendedInstallLocation
- = PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
- }
- }
+ /*
+ * If we have too little free space, try to free cache
+ * before giving up.
+ */
+ if (pkgLite.recommendedInstallLocation
+ == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
+ final long size = mContainerService.calculateInstalledSize(
+ fromPath, isForwardLocked(), packageAbiOverride);
+ if (mInstaller.freeCache(size + lowThreshold) >= 0) {
+ pkgLite = mContainerService.getMinimalPackageInfo(fromPath,
+ flags, lowThreshold, packageAbiOverride);
+ }
+ /*
+ * The cache free must have deleted the file we
+ * downloaded to install.
+ *
+ * TODO: fix the "freeCache" call to not delete
+ * the file we care about.
+ */
+ if (pkgLite.recommendedInstallLocation
+ == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
+ pkgLite.recommendedInstallLocation
+ = PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
}
- } finally {
- mContext.revokeUriPermission(mPackageURI,
- Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
}
@@ -8672,9 +8666,10 @@ public class PackageManagerService extends IPackageManager.Stub {
final int requiredUid = mRequiredVerifierPackage == null ? -1
: getPackageUid(mRequiredVerifierPackage, userIdentifier);
if (requiredUid != -1 && isVerificationEnabled(userIdentifier, flags)) {
+ // TODO: send verifier the install session instead of uri
final Intent verification = new Intent(
Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
- verification.setDataAndType(getPackageUri(), PACKAGE_MIME_TYPE);
+ verification.setDataAndType(Uri.fromFile(getFromFile()), PACKAGE_MIME_TYPE);
verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
final List<ResolveInfo> receivers = queryIntentReceivers(verification,
@@ -8802,10 +8797,9 @@ public class PackageManagerService extends IPackageManager.Stub {
if (mArgs != null) {
processPendingInstall(mArgs, mRet);
- if (mTempPackage != null) {
- if (!mTempPackage.delete()) {
- Slog.w(TAG, "Couldn't delete temporary file: " +
- mTempPackage.getAbsolutePath());
+ if (mLocalFromFile != null) {
+ if (!mLocalFromFile.delete()) {
+ Slog.w(TAG, "Couldn't delete temporary file: " + mLocalFromFile);
}
}
}
@@ -8821,11 +8815,11 @@ public class PackageManagerService extends IPackageManager.Stub {
return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
}
- public Uri getPackageUri() {
- if (mTempPackage != null) {
- return Uri.fromFile(mTempPackage);
+ public File getFromFile() {
+ if (mLocalFromFile != null) {
+ return mLocalFromFile;
} else {
- return mPackageURI;
+ return mFromFile;
}
}
}
@@ -8856,8 +8850,9 @@ public class PackageManagerService extends IPackageManager.Stub {
this.packageName = packageName;
this.uid = uid;
if (srcArgs != null) {
- Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath()));
- targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir, instructionSet);
+ final String codePath = srcArgs.getCodePath();
+ targetArgs = createInstallArgsForMoveTarget(codePath, flags, packageName, dataDir,
+ instructionSet);
} else {
targetArgs = null;
}
@@ -8958,6 +8953,8 @@ public class PackageManagerService extends IPackageManager.Stub {
}
private InstallArgs createInstallArgs(InstallParams params) {
+ // TODO: extend to support incoming zero-copy locations
+
if (installOnSd(params.flags) || params.isForwardLocked()) {
return new AsecInstallArgs(params);
} else {
@@ -8965,14 +8962,18 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath,
- String nativeLibraryPath, String instructionSet) {
+ /**
+ * Create args that describe an existing installed package. Typically used
+ * when cleaning up old installs, or used as a move source.
+ */
+ private InstallArgs createInstallArgsForExisting(int flags, String codePath,
+ String resourcePath, String nativeLibraryPath, String instructionSet) {
final boolean isInAsec;
if (installOnSd(flags)) {
/* Apps on SD card are always in ASEC containers. */
isInAsec = true;
} else if (installForwardLocked(flags)
- && !fullCodePath.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath())) {
+ && !codePath.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath())) {
/*
* Forward-locked apps are only in ASEC containers if they're the
* new style
@@ -8983,44 +8984,49 @@ public class PackageManagerService extends IPackageManager.Stub {
}
if (isInAsec) {
- return new AsecInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath,
+ return new AsecInstallArgs(codePath, resourcePath, nativeLibraryPath,
instructionSet, installOnSd(flags), installForwardLocked(flags));
} else {
- return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath,
- instructionSet);
+ return new FileInstallArgs(codePath, resourcePath, nativeLibraryPath, instructionSet);
}
}
- // Used by package mover
- private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir,
- String instructionSet) {
+ private InstallArgs createInstallArgsForMoveTarget(String codePath, int flags, String pkgName,
+ String dataDir, String instructionSet) {
+ final File codeFile = new File(codePath);
if (installOnSd(flags) || installForwardLocked(flags)) {
- String cid = getNextCodePath(packageURI.getPath(), pkgName, "/"
+ String cid = getNextCodePath(codePath, pkgName, "/"
+ AsecInstallArgs.RES_FILE_NAME);
- return new AsecInstallArgs(packageURI, cid, instructionSet, installOnSd(flags),
+ return new AsecInstallArgs(codeFile, cid, instructionSet, installOnSd(flags),
installForwardLocked(flags));
} else {
- return new FileInstallArgs(packageURI, pkgName, dataDir, instructionSet);
+ return new FileInstallArgs(codeFile, pkgName, dataDir, instructionSet);
}
}
static abstract class InstallArgs {
+ /**
+ * Location where install is coming from, before it has been
+ * copied/renamed into place. This could be a single monolithic APK
+ * file, or a cluster directory. This location is typically untrusted.
+ */
+ final File fromFile;
+
final IPackageInstallObserver observer;
final IPackageInstallObserver2 observer2;
// Always refers to PackageManager flags only
final int flags;
- final Uri packageURI;
final String installerPackageName;
final ManifestDigest manifestDigest;
final UserHandle user;
final String instructionSet;
final String abiOverride;
- InstallArgs(Uri packageURI,
- IPackageInstallObserver observer, IPackageInstallObserver2 observer2,
- int flags, String installerPackageName, ManifestDigest manifestDigest,
- UserHandle user, String instructionSet, String abiOverride) {
- this.packageURI = packageURI;
+ InstallArgs(File fromFile, IPackageInstallObserver observer,
+ IPackageInstallObserver2 observer2, int flags, String installerPackageName,
+ ManifestDigest manifestDigest, UserHandle user, String instructionSet,
+ String abiOverride) {
+ this.fromFile = fromFile;
this.flags = flags;
this.observer = observer;
this.observer2 = observer2;
@@ -9031,24 +9037,23 @@ public class PackageManagerService extends IPackageManager.Stub {
this.abiOverride = abiOverride;
}
- abstract void createCopyFile();
abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
abstract int doPreInstall(int status);
abstract boolean doRename(int status, String pkgName, String oldCodePath);
-
abstract int doPostInstall(int status, int uid);
+
+ /** @see PackageSettingBase#codePathString */
abstract String getCodePath();
+ /** @see PackageSettingBase#resourcePathString */
abstract String getResourcePath();
+ /** @see PackageSettingBase#nativeLibraryPathString */
abstract String getNativeLibraryPath();
+
// Need installer lock especially for dex file removal.
abstract void cleanUpResourcesLI();
abstract boolean doPostDeleteLI(boolean delete);
abstract boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException;
- String[] getSplitCodePaths() {
- return null;
- }
-
/**
* Called before the source arguments are copied. This is used mostly
* for MoveParams when it needs to read the source file to put it in the
@@ -9078,20 +9083,27 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
+ /**
+ * Logic to handle installation of non-ASEC applications, including copying
+ * and renaming logic.
+ */
class FileInstallArgs extends InstallArgs {
+ // TODO: teach about handling cluster directories
+
File installDir;
String codeFileName;
String resourceFileName;
String libraryPath;
boolean created = false;
+ /** New install */
FileInstallArgs(InstallParams params) {
- super(params.getPackageUri(), params.observer, params.observer2, params.flags,
- params.installerPackageName, params.getManifestDigest(),
- params.getUser(), params.packageInstructionSetOverride,
- params.packageAbiOverride);
+ super(params.getFromFile(), params.observer, params.observer2, params.flags,
+ params.installerPackageName, params.getManifestDigest(), params.getUser(),
+ params.packageInstructionSetOverride, params.packageAbiOverride);
}
+ /** Existing install */
FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
String instructionSet) {
super(null, null, null, 0, null, null, null, instructionSet, null);
@@ -9102,8 +9114,9 @@ public class PackageManagerService extends IPackageManager.Stub {
libraryPath = nativeLibraryPath;
}
- FileInstallArgs(Uri packageURI, String pkgName, String dataDir, String instructionSet) {
- super(packageURI, null, null, 0, null, null, null, instructionSet, null);
+ /** New install from existing */
+ FileInstallArgs(File fromFile, String pkgName, String dataDir, String instructionSet) {
+ super(fromFile, null, null, 0, null, null, null, instructionSet, null);
installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
String apkName = getNextCodePath(null, pkgName, ".apk");
codeFileName = new File(installDir, apkName + ".apk").getPath();
@@ -9128,13 +9141,8 @@ public class PackageManagerService extends IPackageManager.Stub {
lowThreshold = dsm.getMemoryLowThreshold();
}
- try {
- mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
- Intent.FLAG_GRANT_READ_URI_PERMISSION);
- return imcs.checkInternalFreeStorage(packageURI, isFwdLocked(), lowThreshold);
- } finally {
- mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
- }
+ return imcs.checkInternalFreeStorage(fromFile.getAbsolutePath(), isFwdLocked(),
+ lowThreshold);
}
void createCopyFile() {
@@ -9175,12 +9183,9 @@ public class PackageManagerService extends IPackageManager.Stub {
// Copy the resource now
int ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
try {
- mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
- Intent.FLAG_GRANT_READ_URI_PERMISSION);
- ret = imcs.copyResource(packageURI, null, out);
+ ret = imcs.copyResource(fromFile.getAbsolutePath(), null, out);
} finally {
IoUtils.closeQuietly(out);
- mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
if (isFwdLocked()) {
@@ -9432,7 +9437,13 @@ public class PackageManagerService extends IPackageManager.Stub {
return subStr1.substring(sidx+1, eidx);
}
+ /**
+ * Logic to handle installation of ASEC applications, including copying and
+ * renaming logic.
+ */
class AsecInstallArgs extends InstallArgs {
+ // TODO: teach about handling cluster directories
+
static final String RES_FILE_NAME = "pkg.apk";
static final String PUBLIC_RES_FILE_NAME = "res.zip";
@@ -9441,13 +9452,14 @@ public class PackageManagerService extends IPackageManager.Stub {
String resourcePath;
String libraryPath;
+ /** New install */
AsecInstallArgs(InstallParams params) {
- super(params.getPackageUri(), params.observer, params.observer2, params.flags,
- params.installerPackageName, params.getManifestDigest(),
- params.getUser(), params.packageInstructionSetOverride,
- params.packageAbiOverride);
+ super(params.getFromFile(), params.observer, params.observer2, params.flags,
+ params.installerPackageName, params.getManifestDigest(), params.getUser(),
+ params.packageInstructionSetOverride, params.packageAbiOverride);
}
+ /** Existing install */
AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
String instructionSet, boolean isExternal, boolean isForwardLocked) {
super(null, null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
@@ -9469,9 +9481,10 @@ public class PackageManagerService extends IPackageManager.Stub {
setCachePath(PackageHelper.getSdDir(cid));
}
- AsecInstallArgs(Uri packageURI, String cid, String instructionSet,
+ /** New install from existing */
+ AsecInstallArgs(File fromFile, String cid, String instructionSet,
boolean isExternal, boolean isForwardLocked) {
- super(packageURI, null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
+ super(fromFile, null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
| (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
null, null, null, instructionSet, null);
this.cid = cid;
@@ -9482,13 +9495,8 @@ public class PackageManagerService extends IPackageManager.Stub {
}
boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
- try {
- mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
- Intent.FLAG_GRANT_READ_URI_PERMISSION);
- return imcs.checkExternalFreeStorage(packageURI, isFwdLocked(), abiOverride);
- } finally {
- mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
- }
+ return imcs.checkExternalFreeStorage(fromFile.getAbsolutePath(), isFwdLocked(),
+ abiOverride);
}
private final boolean isExternal() {
@@ -9506,16 +9514,9 @@ public class PackageManagerService extends IPackageManager.Stub {
PackageHelper.destroySdDir(cid);
}
- final String newCachePath;
- try {
- mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
- Intent.FLAG_GRANT_READ_URI_PERMISSION);
- newCachePath = imcs.copyResourceToContainer(packageURI, cid, getEncryptKey(),
- RES_FILE_NAME, PUBLIC_RES_FILE_NAME, isExternal(), isFwdLocked(),
- abiOverride);
- } finally {
- mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
- }
+ final String newCachePath = imcs.copyResourceToContainer(fromFile.getAbsolutePath(),
+ cid, getEncryptKey(), RES_FILE_NAME, PUBLIC_RES_FILE_NAME, isExternal(),
+ isFwdLocked(), abiOverride);
if (newCachePath != null) {
setCachePath(newCachePath);
@@ -10078,7 +10079,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// We didn't need to disable the .apk as a current system package,
// which means we are replacing another update that is already
// installed. We need to make sure to delete the older one's .apk.
- res.removedInfo.args = createInstallArgs(0,
+ res.removedInfo.args = createInstallArgsForExisting(0,
deletedPackage.applicationInfo.sourceDir,
deletedPackage.applicationInfo.publicSourceDir,
deletedPackage.applicationInfo.nativeLibraryDir,
@@ -10143,7 +10144,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// TODO: extend to move split APK dex files
if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
final String instructionSet = getAppInstructionSet(newPackage.applicationInfo);
- int retCode = mInstaller.movedex(oldCodePath, newPackage.codePath,
+ int retCode = mInstaller.movedex(oldCodePath, newPackage.baseCodePath,
instructionSet);
if (retCode != 0) {
/*
@@ -10156,7 +10157,7 @@ public class PackageManagerService extends IPackageManager.Stub {
*/
newPackage.mDexOptNeeded = true;
mInstaller.rmdex(oldCodePath, instructionSet);
- mInstaller.rmdex(newPackage.codePath, instructionSet);
+ mInstaller.rmdex(newPackage.baseCodePath, instructionSet);
}
}
return PackageManager.INSTALL_SUCCEEDED;
@@ -10221,8 +10222,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- private void installPackageLI(InstallArgs args,
- boolean newInstall, PackageInstalledInfo res) {
+ private void installPackageLI(InstallArgs args, boolean newInstall, PackageInstalledInfo res) {
int pFlags = args.flags;
String installerPackageName = args.installerPackageName;
File tmpPackageFile = new File(args.getCodePath());
@@ -10367,14 +10367,18 @@ public class PackageManagerService extends IPackageManager.Stub {
res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
return;
}
+
// Set application objects path explicitly after the rename
+ // TODO: derive split paths from original scan after rename
pkg.codePath = args.getCodePath();
+ pkg.baseCodePath = args.getCodePath();
+ pkg.splitCodePaths = null;
pkg.applicationInfo.sourceDir = args.getCodePath();
pkg.applicationInfo.publicSourceDir = args.getResourcePath();
- pkg.applicationInfo.splitSourceDirs = args.getSplitCodePaths();
- pkg.applicationInfo.splitPublicSourceDirs = deriveSplitResPaths(
- pkg.applicationInfo.splitSourceDirs);
+ pkg.applicationInfo.splitSourceDirs = null;
+ pkg.applicationInfo.splitPublicSourceDirs = null;
pkg.applicationInfo.nativeLibraryDir = args.getNativeLibraryPath();
+
if (replace) {
replacePackageLI(pkg, parseFlags, scanMode, args.user,
installerPackageName, res, args.abiOverride);
@@ -10847,8 +10851,8 @@ public class PackageManagerService extends IPackageManager.Stub {
// Delete application code and resources
if (deleteCodeAndResources && (outInfo != null)) {
- outInfo.args = createInstallArgs(packageFlagsToInstallFlags(ps), ps.codePathString,
- ps.resourcePathString, ps.nativeLibraryPathString,
+ outInfo.args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
+ ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString,
getAppInstructionSetFromSettings(ps));
}
return true;
@@ -11253,7 +11257,8 @@ public class PackageManagerService extends IPackageManager.Stub {
publicSrcDir = applicationInfo.publicSourceDir;
}
}
- int res = mInstaller.getSizeInfo(packageName, userHandle, p.codePath, libDirPath,
+ // TODO: extend to measure size of split APKs
+ int res = mInstaller.getSizeInfo(packageName, userHandle, p.baseCodePath, libDirPath,
publicSrcDir, asecPath, getAppInstructionSetFromSettings(ps),
pStats);
if (res < 0) {
@@ -12843,9 +12848,9 @@ public class PackageManagerService extends IPackageManager.Stub {
} else {
Message msg = mHandler.obtainMessage(INIT_COPY);
final String instructionSet = getAppInstructionSet(pkg.applicationInfo);
- InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir,
- pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir,
- instructionSet);
+ InstallArgs srcArgs = createInstallArgsForExisting(currFlags,
+ pkg.applicationInfo.sourceDir, pkg.applicationInfo.publicSourceDir,
+ pkg.applicationInfo.nativeLibraryDir, instructionSet);
MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName,
pkg.applicationInfo.dataDir, instructionSet, pkg.applicationInfo.uid, user);
msg.obj = mp;
@@ -12943,11 +12948,13 @@ public class PackageManagerService extends IPackageManager.Stub {
if (returnCode == PackageManager.MOVE_SUCCEEDED) {
pkg.codePath = newCodePath;
+ pkg.baseCodePath = newCodePath;
// Move dex files around
if (moveDexFilesLI(oldCodePath, pkg) != PackageManager.INSTALL_SUCCEEDED) {
// Moving of dex files failed. Set
// error code and abort move.
pkg.codePath = oldCodePath;
+ pkg.baseCodePath = oldCodePath;
returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
}
}
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 7fee372..2091c16 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -45,6 +45,12 @@ class PackageSettingBase extends GrantedPermissions {
final String name;
final String realName;
+
+ /**
+ * Path where this package was found on disk. For monolithic packages
+ * this is path to single base APK file; for cluster packages this is
+ * path to the cluster directory.
+ */
File codePath;
String codePathString;
File resourcePath;
diff --git a/telecomm/java/android/telecomm/CallCapabilities.java b/telecomm/java/android/telecomm/CallCapabilities.java
index 5aff19c..2e0152a 100644
--- a/telecomm/java/android/telecomm/CallCapabilities.java
+++ b/telecomm/java/android/telecomm/CallCapabilities.java
@@ -42,11 +42,8 @@ public final class CallCapabilities {
/** Call supports generic conference mode. */
public static final int GENERIC_CONFERENCE = 0x00000080;
- /** Call currently supports switch between connections. */
- public static final int CONNECTION_HANDOFF = 0x00000100;
-
public static final int ALL = HOLD | SUPPORT_HOLD | MERGE_CALLS | SWAP_CALLS | ADD_CALL
- | RESPOND_VIA_TEXT | MUTE | GENERIC_CONFERENCE | CONNECTION_HANDOFF;
+ | RESPOND_VIA_TEXT | MUTE | GENERIC_CONFERENCE;
public static String toString(int capabilities) {
StringBuilder builder = new StringBuilder();
@@ -75,9 +72,6 @@ public final class CallCapabilities {
if ((capabilities & GENERIC_CONFERENCE) != 0) {
builder.append(" GENERIC_CONFERENCE");
}
- if ((capabilities & CONNECTION_HANDOFF) != 0) {
- builder.append(" HANDOFF");
- }
builder.append("]");
return builder.toString();
}
diff --git a/telecomm/java/android/telecomm/CallService.java b/telecomm/java/android/telecomm/CallService.java
index 44380e2..e77fb23 100644
--- a/telecomm/java/android/telecomm/CallService.java
+++ b/telecomm/java/android/telecomm/CallService.java
@@ -31,11 +31,6 @@ import com.android.internal.telecomm.ICallServiceAdapter;
* Base implementation of CallService which can be used to provide calls for the system
* in-call UI. CallService is a one-way service from the framework's CallsManager to any app
* that would like to provide calls managed by the default system in-call user interface.
- * When the service is bound by the framework, CallsManager will call setCallServiceAdapter
- * which will provide CallService with an instance of {@link CallServiceAdapter} to be used
- * for communicating back to CallsManager. Subsequently, more specific methods of the service
- * will be called to perform various call actions including making an outgoing call and
- * disconnected existing calls.
* TODO(santoscordon): Needs more about AndroidManifest.xml service registrations before
* we can unhide this API.
*
@@ -61,6 +56,7 @@ public abstract class CallService extends Service {
private static final int MSG_CONFERENCE = 13;
private static final int MSG_SPLIT_FROM_CONFERENCE = 14;
private static final int MSG_ON_POST_DIAL_CONTINUE = 15;
+ private static final int MSG_ON_PHONE_ACCOUNT_CLICKED = 16;
/**
* Default Handler used to consolidate binder method calls onto a single thread.
@@ -147,6 +143,9 @@ public abstract class CallService extends Service {
case MSG_SPLIT_FROM_CONFERENCE:
splitFromConference((String) msg.obj);
break;
+ case MSG_ON_PHONE_ACCOUNT_CLICKED:
+ onPhoneAccountClicked((String) msg.obj);
+ break;
default:
break;
}
@@ -244,6 +243,12 @@ public abstract class CallService extends Service {
args.argi1 = proceed ? 1 : 0;
mMessageHandler.obtainMessage(MSG_ON_POST_DIAL_CONTINUE, args).sendToTarget();
}
+
+ @Override
+ public void onPhoneAccountClicked(String callId) {
+ mMessageHandler.obtainMessage(MSG_ON_PHONE_ACCOUNT_CLICKED, callId).sendToTarget();
+ }
+
}
/**
@@ -272,152 +277,59 @@ public abstract class CallService extends Service {
return mBinder;
}
- /**
- * @return The attached {@link CallServiceAdapter} if the service is bound, null otherwise.
- */
+ /** @hide */
protected final CallServiceAdapter getAdapter() {
return mAdapter;
}
- /**
- * Lifecycle callback which is called when this {@link CallService} has been attached to a
- * {@link CallServiceAdapter}, indicating {@link #getAdapter()} is now safe to use.
- *
- * @param adapter The adapter now attached to this call service.
- */
- protected void onAdapterAttached(CallServiceAdapter adapter) {
- }
+ /** @hide */
+ protected abstract void onAdapterAttached(CallServiceAdapter adapter);
- /**
- * Attempts to call the relevant party using the specified call's handle, be it a phone number,
- * SIP address, or some other kind of user ID. Note that the set of handle types is
- * dynamically extensible since call providers should be able to implement arbitrary
- * handle-calling systems.
- *
- * @param callInfo The details of the relevant call.
- */
- public abstract void call(CallInfo callInfo);
+ /** @hide */
+ protected abstract void call(CallInfo callInfo);
- /**
- * Aborts the outgoing call attempt. Invoked in the unlikely event that Telecomm decides to
- * abort an attempt to place a call. Only ever be invoked after {@link #call} invocations.
- * After this is invoked, Telecomm does not expect any more updates about the call and will
- * actively ignore any such update. This is different from {@link #disconnect} where Telecomm
- * expects confirmation via CallServiceAdapter.markCallAsDisconnected.
- *
- * @param callId The identifier of the call to abort.
- */
- public abstract void abort(String callId);
+ /** @hide */
+ protected abstract void abort(String callId);
- /**
- * Receives a new call ID to use with an incoming call. Invoked by Telecomm after it is notified
- * that this call service has a pending incoming call, see
- * {@link TelecommConstants#ACTION_INCOMING_CALL}. The call service must first give Telecomm
- * additional information about the call through {@link CallServiceAdapter#notifyIncomingCall}.
- * Following that, the call service can update the call at will using the specified call ID.
- *
- * If a {@link Bundle} was passed (via {@link TelecommConstants#EXTRA_INCOMING_CALL_EXTRAS}) in
- * with the {@link TelecommConstants#ACTION_INCOMING_CALL} intent, <code>extras</code> will be
- * populated with this {@link Bundle}. Otherwise, an empty Bundle will be returned.
- *
- * @param callId The ID of the call.
- * @param extras The optional extras which were passed in with the intent, or an empty Bundle.
- */
- public abstract void setIncomingCallId(String callId, Bundle extras);
+ /** @hide */
+ protected abstract void setIncomingCallId(String callId, Bundle extras);
- /**
- * Answers a ringing call identified by callId. Telecomm invokes this method as a result of the
- * user hitting the "answer" button in the incoming call screen.
- *
- * @param callId The ID of the call.
- */
- public abstract void answer(String callId);
+ /** @hide */
+ protected abstract void answer(String callId);
- /**
- * Rejects a ringing call identified by callId. Telecomm invokes this method as a result of the
- * user hitting the "reject" button in the incoming call screen.
- *
- * @param callId The ID of the call.
- */
- public abstract void reject(String callId);
+ /** @hide */
+ protected abstract void reject(String callId);
- /**
- * Disconnects the specified call.
- *
- * @param callId The ID of the call to disconnect.
- */
- public abstract void disconnect(String callId);
+ /** @hide */
+ protected abstract void disconnect(String callId);
- /**
- * Puts the specified call on hold.
- *
- * @param callId The ID of the call to put on hold.
- */
- public abstract void hold(String callId);
+ /** @hide */
+ protected abstract void hold(String callId);
- /**
- * Removes the specified call from hold.
- *
- * @param callId The ID of the call to unhold.
- */
- public abstract void unhold(String callId);
+ /** @hide */
+ protected abstract void unhold(String callId);
- /**
- * Plays a dual-tone multi-frequency signaling (DTMF) tone in a call.
- *
- * @param callId The unique ID of the call in which the tone will be played.
- * @param digit A character representing the DTMF digit for which to play the tone. This
- * value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
- */
- public abstract void playDtmfTone(String callId, char digit);
+ /** @hide */
+ protected abstract void playDtmfTone(String callId, char digit);
- /**
- * Stops any dual-tone multi-frequency sinaling (DTMF) tone currently playing.
- *
- * DTMF tones are played by calling {@link #playDtmfTone(String,char)}. If no DTMF tone is
- * currently playing, this method will do nothing.
- *
- * @param callId The unique ID of the call in which any currently playing tone will be stopped.
- */
- public abstract void stopDtmfTone(String callId);
+ /** @hide */
+ protected abstract void stopDtmfTone(String callId);
- /**
- * Called when the audio state changes.
- *
- * @param activeCallId The identifier of the call that was active during the state change.
- * @param audioState The new {@link CallAudioState}.
- */
- public abstract void onAudioStateChanged(String activeCallId, CallAudioState audioState);
+ /** @hide */
+ protected abstract void onAudioStateChanged(String activeCallId, CallAudioState audioState);
- /**
- * Conferences the specified call.
- *
- * @param conferenceCallId The unique ID of the conference call onto which the specified calls
- * should be added.
- * @param callId The call to conference.
- * @hide
- */
- public abstract void conference(String conferenceCallId, String callId);
+ /** @hide */
+ protected abstract void conference(String conferenceCallId, String callId);
- /**
- * Removes the specified call from a conference call.
- *
- * @param callId The call to remove from the conference call
- * @hide
- */
- public abstract void splitFromConference(String callId);
+ /** @hide */
+ protected abstract void splitFromConference(String callId);
- public void onPostDialContinue(String callId, boolean proceed) {}
+ /** @hide */
+ protected abstract void onPostDialContinue(String callId, boolean proceed);
- public void onPostDialWait(Connection conn, String remaining) {}
+ /** @hide */
+ protected abstract void onFeaturesChanged(String callId, int features);
- /**
- * Called when changes to the features of a call occurs. Features are defined in
- * {@link android.telecomm.CallFeatures}. The active features for the call are represented as
- * bits in the features bit-mask.
- *
- * @param callId The call to set the features for.
- * @param features The new features of the call.
- */
- public abstract void onFeaturesChanged(String callId, int features);
+ /** @hide */
+ protected abstract void onPhoneAccountClicked(String callId);
}
diff --git a/telecomm/java/android/telecomm/CallServiceAdapter.java b/telecomm/java/android/telecomm/CallServiceAdapter.java
index 1b3c0a3..dcab566 100644
--- a/telecomm/java/android/telecomm/CallServiceAdapter.java
+++ b/telecomm/java/android/telecomm/CallServiceAdapter.java
@@ -33,8 +33,9 @@ import java.util.Set;
/**
* Provides methods for ICallService implementations to interact with the system phone app.
- * TODO(santoscordon): Need final public-facing comments in this file.
* TODO(santoscordon): Rename this to CallServiceAdapterDemultiplexer (or something).
+ *
+ * @hide
*/
public final class CallServiceAdapter implements DeathRecipient {
private final Set<ICallServiceAdapter> mAdapters = new HashSet<>();
@@ -298,20 +299,6 @@ public final class CallServiceAdapter implements DeathRecipient {
}
/**
- * Instructs Telecomm to handoff the call to another call service.
- *
- * @param callId The identifier of the call to handoff.
- */
- public void handoffCall(String callId) {
- for (ICallServiceAdapter adapter : mAdapters) {
- try {
- adapter.handoffCall(callId);
- } catch (RemoteException e) {
- }
- }
- }
-
- /**
* Indicates that a new conference call has been created.
*
* @param callId The unique ID of the conference call.
diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java
index 73aac2c..32dcf6c 100644
--- a/telecomm/java/android/telecomm/Connection.java
+++ b/telecomm/java/android/telecomm/Connection.java
@@ -611,6 +611,12 @@ public abstract class Connection {
*/
protected void onChildrenChanged(List<Connection> children) {}
+ /**
+ * Called when the phone account UI was clicked.
+ */
+ protected void onPhoneAccountClicked() {}
+
+
private void addChild(Connection connection) {
Log.d(this, "adding child %s", connection);
mChildConnections.add(connection);
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index 693e9fb..d6970e2 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -180,7 +180,7 @@ public abstract class ConnectionService extends CallService {
/** @hide */
@Override
- public final void call(final CallInfo callInfo) {
+ protected final void call(final CallInfo callInfo) {
Log.d(this, "call %s", callInfo);
onCreateConnections(
new ConnectionRequest(
@@ -211,14 +211,14 @@ public abstract class ConnectionService extends CallService {
/** @hide */
@Override
- public final void abort(String callId) {
+ protected final void abort(String callId) {
Log.d(this, "abort %s", callId);
findConnectionForAction(callId, "abort").abort();
}
/** @hide */
@Override
- public final void setIncomingCallId(final String callId, Bundle extras) {
+ protected final void setIncomingCallId(final String callId, Bundle extras) {
Log.d(this, "setIncomingCallId %s %s", callId, extras);
onCreateIncomingConnection(
new ConnectionRequest(
@@ -261,63 +261,63 @@ public abstract class ConnectionService extends CallService {
/** @hide */
@Override
- public final void answer(String callId) {
+ protected final void answer(String callId) {
Log.d(this, "answer %s", callId);
findConnectionForAction(callId, "answer").answer();
}
/** @hide */
@Override
- public final void reject(String callId) {
+ protected final void reject(String callId) {
Log.d(this, "reject %s", callId);
findConnectionForAction(callId, "reject").reject();
}
/** @hide */
@Override
- public final void disconnect(String callId) {
+ protected final void disconnect(String callId) {
Log.d(this, "disconnect %s", callId);
findConnectionForAction(callId, "disconnect").disconnect();
}
/** @hide */
@Override
- public final void hold(String callId) {
+ protected final void hold(String callId) {
Log.d(this, "hold %s", callId);
findConnectionForAction(callId, "hold").hold();
}
/** @hide */
@Override
- public final void unhold(String callId) {
+ protected final void unhold(String callId) {
Log.d(this, "unhold %s", callId);
findConnectionForAction(callId, "unhold").unhold();
}
/** @hide */
@Override
- public final void playDtmfTone(String callId, char digit) {
+ protected final void playDtmfTone(String callId, char digit) {
Log.d(this, "playDtmfTone %s %c", callId, digit);
findConnectionForAction(callId, "playDtmfTone").playDtmfTone(digit);
}
/** @hide */
@Override
- public final void stopDtmfTone(String callId) {
+ protected final void stopDtmfTone(String callId) {
Log.d(this, "stopDtmfTone %s", callId);
findConnectionForAction(callId, "stopDtmfTone").stopDtmfTone();
}
/** @hide */
@Override
- public final void onAudioStateChanged(String callId, CallAudioState audioState) {
+ protected final void onAudioStateChanged(String callId, CallAudioState audioState) {
Log.d(this, "onAudioStateChanged %s %s", callId, audioState);
findConnectionForAction(callId, "onAudioStateChanged").setAudioState(audioState);
}
/** @hide */
@Override
- public final void conference(final String conferenceCallId, String callId) {
+ protected final void conference(final String conferenceCallId, String callId) {
Log.d(this, "conference %s, %s", conferenceCallId, callId);
Connection connection = findConnectionForAction(callId, "conference");
@@ -352,7 +352,7 @@ public abstract class ConnectionService extends CallService {
/** @hide */
@Override
- public final void splitFromConference(String callId) {
+ protected final void splitFromConference(String callId) {
Log.d(this, "splitFromConference(%s)", callId);
Connection connection = findConnectionForAction(callId, "splitFromConference");
@@ -366,7 +366,7 @@ public abstract class ConnectionService extends CallService {
/** @hide */
@Override
- public final void onPostDialContinue(String callId, boolean proceed) {
+ protected final void onPostDialContinue(String callId, boolean proceed) {
Log.d(this, "onPostDialContinue(%s)", callId);
Connection connection = findConnectionForAction(callId, "onPostDialContinue");
@@ -377,9 +377,21 @@ public abstract class ConnectionService extends CallService {
connection.onPostDialContinue(proceed);
}
- /**
- * @hide
- */
+ /** @hide */
+ @Override
+ protected final void onFeaturesChanged(String callId, int features) {
+ Log.d(this, "onFeaturesChanged %s %d", callId, features);
+ findConnectionForAction(callId, "onFeaturesChanged").setFeatures(features);
+ }
+
+ /** @hide */
+ @Override
+ protected void onPhoneAccountClicked(String callId) {
+ Log.d(this, "onPhoneAccountClicked %s", callId);
+ findConnectionForAction(callId, "onPhoneAccountClicked").onPhoneAccountClicked();
+ }
+
+ /** @hide */
@Override
protected final void onAdapterAttached(CallServiceAdapter adapter) {
if (mAreAccountsInitialized) {
@@ -569,18 +581,4 @@ public abstract class ConnectionService extends CallService {
Log.w(this, "%s - Cannot find Connection %s", action, callId);
return NULL_CONNECTION;
}
-
- /**
- * Handles changes to the features of a connection.
- * Features are defined in {@link android.telecomm.CallFeatures} and are passed in as a
- * bit-mask.
- *
- * @param callId The call to set the features for.
- * @param features The new features of the call.
- */
- @Override
- public final void onFeaturesChanged(String callId, int features) {
- Log.d(this, "onFeaturesChanged %s %d", callId, features);
- findConnectionForAction(callId, "onFeaturesChanged").setFeatures(features);
- }
}
diff --git a/telecomm/java/android/telecomm/InCallAdapter.java b/telecomm/java/android/telecomm/InCallAdapter.java
index ce52d19..aef05fd 100644
--- a/telecomm/java/android/telecomm/InCallAdapter.java
+++ b/telecomm/java/android/telecomm/InCallAdapter.java
@@ -189,13 +189,13 @@ public final class InCallAdapter {
}
/**
- * Instructs Telecomm to handoff the call to another call service.
+ * Instructs Telecomm that the phone account UI was clicked.
*
- * @param callId The identifier of the call to handoff.
+ * @param callId The identifier of the call.
*/
- public void handoffCall(String callId) {
+ public void phoneAccountClicked(String callId) {
try {
- mAdapter.handoffCall(callId);
+ mAdapter.phoneAccountClicked(callId);
} catch (RemoteException e) {
}
}
diff --git a/telecomm/java/android/telecomm/InCallCall.java b/telecomm/java/android/telecomm/InCallCall.java
index fc96f55..e08d450 100644
--- a/telecomm/java/android/telecomm/InCallCall.java
+++ b/telecomm/java/android/telecomm/InCallCall.java
@@ -43,7 +43,6 @@ public final class InCallCall implements Parcelable {
private final GatewayInfo mGatewayInfo;
private final PhoneAccount mAccount;
private final CallServiceDescriptor mCurrentCallServiceDescriptor;
- private final CallServiceDescriptor mHandoffCallServiceDescriptor;
private final ICallVideoProvider mCallVideoProvider;
private RemoteCallVideoProvider mRemoteCallVideoProvider;
private final String mParentCallId;
@@ -61,9 +60,8 @@ public final class InCallCall implements Parcelable {
long connectTimeMillis,
Uri handle,
GatewayInfo gatewayInfo,
- PhoneAccount subscription,
+ PhoneAccount account,
CallServiceDescriptor descriptor,
- CallServiceDescriptor handoffDescriptor,
ICallVideoProvider callVideoProvider,
String parentCallId,
List<String> childCallIds,
@@ -77,9 +75,8 @@ public final class InCallCall implements Parcelable {
mConnectTimeMillis = connectTimeMillis;
mHandle = handle;
mGatewayInfo = gatewayInfo;
- mAccount = subscription;
+ mAccount = account;
mCurrentCallServiceDescriptor = descriptor;
- mHandoffCallServiceDescriptor = handoffDescriptor;
mCallVideoProvider = callVideoProvider;
mParentCallId = parentCallId;
mChildCallIds = childCallIds;
@@ -150,14 +147,6 @@ public final class InCallCall implements Parcelable {
}
/**
- * The descriptor for the call service that this call is being switched to, null if handoff is
- * not in progress.
- */
- public CallServiceDescriptor getHandoffCallServiceDescriptor() {
- return mHandoffCallServiceDescriptor;
- }
-
- /**
* Returns an object for remotely communicating through the call video provider's binder.
* @return The call video provider.
*/
@@ -217,7 +206,6 @@ public final class InCallCall implements Parcelable {
GatewayInfo gatewayInfo = source.readParcelable(classLoader);
PhoneAccount account = source.readParcelable(classLoader);
CallServiceDescriptor descriptor = source.readParcelable(classLoader);
- CallServiceDescriptor handoffDescriptor = source.readParcelable(classLoader);
ICallVideoProvider callVideoProvider =
ICallVideoProvider.Stub.asInterface(source.readStrongBinder());
String parentCallId = source.readString();
@@ -226,8 +214,7 @@ public final class InCallCall implements Parcelable {
int features = source.readInt();
return new InCallCall(id, state, disconnectCauseCode, disconnectCauseMsg,
cannedSmsResponses, capabilities, connectTimeMillis, handle, gatewayInfo,
- account, descriptor, handoffDescriptor, callVideoProvider, parentCallId,
- childCallIds, features);
+ account, descriptor, callVideoProvider, parentCallId, childCallIds, features);
}
@Override
@@ -256,7 +243,6 @@ public final class InCallCall implements Parcelable {
destination.writeParcelable(mGatewayInfo, 0);
destination.writeParcelable(mAccount, 0);
destination.writeParcelable(mCurrentCallServiceDescriptor, 0);
- destination.writeParcelable(mHandoffCallServiceDescriptor, 0);
destination.writeStrongBinder(
mCallVideoProvider != null ? mCallVideoProvider.asBinder() : null);
destination.writeString(mParentCallId);
diff --git a/telecomm/java/android/telecomm/RemoteConnectionService.java b/telecomm/java/android/telecomm/RemoteConnectionService.java
index b3ef927..81bee98 100644
--- a/telecomm/java/android/telecomm/RemoteConnectionService.java
+++ b/telecomm/java/android/telecomm/RemoteConnectionService.java
@@ -177,12 +177,6 @@ public final class RemoteConnectionService implements DeathRecipient {
}
/** ${inheritDoc} */
- @Override
- public void handoffCall(String connectionId) {
- // unnecessary.
- }
-
- /** ${inheritDoc} */
@Override
public void queryRemoteConnectionServices(RemoteServiceCallback callback) {
try {
diff --git a/telecomm/java/android/telecomm/TelecommConstants.java b/telecomm/java/android/telecomm/TelecommConstants.java
index 616c4a9..80901cf 100644
--- a/telecomm/java/android/telecomm/TelecommConstants.java
+++ b/telecomm/java/android/telecomm/TelecommConstants.java
@@ -27,13 +27,13 @@ public final class TelecommConstants {
/**
* <p>Activity action: Starts the UI for handing an incoming call. This intent starts the
* in-call UI by notifying the Telecomm system that an incoming call exists for a specific call
- * service (see {@link android.telecomm.CallService}). Telecomm reads the Intent extras to find
- * and bind to the appropriate {@link android.telecomm.CallService} which Telecomm will
- * ultimately use to control and get information about the call.</p>
+ * service (see {@link android.telecomm.ConnectionService}). Telecomm reads the Intent extras
+ * to find and bind to the appropriate {@link android.telecomm.ConnectionService} which
+ * Telecomm will ultimately use to control and get information about the call.</p>
*
* <p>Input: get*Extra field {@link #EXTRA_CALL_SERVICE_DESCRIPTOR} contains the component name
- * of the {@link android.telecomm.CallService} that Telecomm should bind to. Telecomm will then
- * ask the call service for more information about the call prior to showing any UI.
+ * of the {@link android.telecomm.ConnectionService} that Telecomm should bind to. Telecomm
+ * will then ask the call service for more information about the call prior to showing any UI.
*
* TODO(santoscordon): Needs permissions.
* TODO(santoscordon): Consider moving this into a simple method call on a system service.
@@ -46,7 +46,7 @@ public final class TelecommConstants {
public static final String ACTION_CALL_SERVICE_PROVIDER = CallServiceProvider.class.getName();
/**
- * The service action used to bind to {@link CallService} implementations.
+ * The service action used to bind to {@link ConnectionService} implementations.
*/
public static final String ACTION_CALL_SERVICE = CallService.class.getName();
@@ -73,8 +73,8 @@ public final class TelecommConstants {
/**
* Optional extra for {@link #ACTION_INCOMING_CALL} containing a {@link Bundle} which contains
- * metadata about the call. This {@link Bundle} will be returned to the {@link CallService} as
- * part of {@link CallService#setIncomingCallId(String,Bundle)}.
+ * metadata about the call. This {@link Bundle} will be returned to the
+ * {@link ConnectionService}.
*/
public static final String EXTRA_INCOMING_CALL_EXTRAS =
"android.intent.extra.INCOMING_CALL_EXTRAS";
diff --git a/telecomm/java/com/android/internal/telecomm/ICallService.aidl b/telecomm/java/com/android/internal/telecomm/ICallService.aidl
index 62ebd54..ac4e66c 100644
--- a/telecomm/java/com/android/internal/telecomm/ICallService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/ICallService.aidl
@@ -59,4 +59,6 @@ oneway interface ICallService {
void splitFromConference(String callId);
void onPostDialContinue(String callId, boolean proceed);
+
+ void onPhoneAccountClicked(String callId);
}
diff --git a/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl b/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl
index e78762d..eee64da 100644
--- a/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl
@@ -60,8 +60,6 @@ oneway interface ICallServiceAdapter {
void onPostDialWait(String callId, String remaining);
- void handoffCall(String callId);
-
void queryRemoteConnectionServices(RemoteServiceCallback callback);
void setCallVideoProvider(String callId, ICallVideoProvider callVideoProvider);
diff --git a/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
index b66995a..7f3767c 100644
--- a/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
@@ -46,7 +46,7 @@ oneway interface IInCallAdapter {
void postDialContinue(String callId, boolean proceed);
- void handoffCall(String callId);
+ void phoneAccountClicked(String callId);
void conference(String callId);
diff --git a/telephony/java/com/android/internal/telephony/IMms.aidl b/telephony/java/com/android/internal/telephony/IMms.aidl
index a745420..4da90a5 100644
--- a/telephony/java/com/android/internal/telephony/IMms.aidl
+++ b/telephony/java/com/android/internal/telephony/IMms.aidl
@@ -44,4 +44,25 @@ interface IMms {
* broadcast when the message is downloaded, or the download is failed
*/
void downloadMessage(String callingPkg, String locationUrl, in PendingIntent downloadedIntent);
+
+ /**
+ * Update the status of a pending (send-by-IP) MMS message handled by the carrier app.
+ * If the carrier app fails to send this message, it would be resent via carrier network.
+ *
+ * @param messageRef the reference number of the MMS message.
+ * @param success True if and only if the message was sent successfully. If its value is
+ * false, this message should be resent via carrier network
+ */
+ void updateMmsSendStatus(int messageRef, boolean success);
+
+ /**
+ * Update the status of a pending (download-by-IP) MMS message handled by the carrier app.
+ * If the carrier app fails to download this message, it would be re-downloaded via carrier
+ * network.
+ *
+ * @param messageRef the reference number of the MMS message.
+ * @param pdu non-empty if downloaded successfully, otherwise, it is empty and the message
+ * will be downloaded via carrier network
+ */
+ void updateMmsDownloadStatus(int messageRef, in byte[] pdu);
}