Merge "Update comment of ACTION_PROFILE_PROVISIONING_COMPLETE."
diff --git a/Android.mk b/Android.mk
index 9828ea6..58509a7 100644
--- a/Android.mk
+++ b/Android.mk
@@ -171,7 +171,6 @@
core/java/android/nfc/INfcAdapterExtras.aidl \
core/java/android/nfc/INfcTag.aidl \
core/java/android/nfc/INfcCardEmulation.aidl \
- core/java/android/nfc/INfcUnlockSettings.aidl \
core/java/android/os/IBatteryPropertiesListener.aidl \
core/java/android/os/IBatteryPropertiesRegistrar.aidl \
core/java/android/os/ICancellationSignal.aidl \
@@ -334,7 +333,7 @@
telephony/java/com/android/internal/telephony/ISms.aidl \
telephony/java/com/android/internal/telephony/IWapPushManager.aidl \
wifi/java/android/net/wifi/IWifiManager.aidl \
- wifi/java/android/net/wifi/passpoint/IPasspointManager.aidl \
+ wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl \
wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \
wifi/java/android/net/wifi/IWifiScanner.aidl \
packages/services/PacProcessor/com/android/net/IProxyService.aidl \
diff --git a/api/current.txt b/api/current.txt
index e7f75f7..def0755 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -864,6 +864,7 @@
field public static final int paddingBottom = 16842969; // 0x10100d9
field public static final int paddingEnd = 16843700; // 0x10103b4
field public static final int paddingLeft = 16842966; // 0x10100d6
+ field public static final int paddingMode = 16843866; // 0x101045a
field public static final int paddingRight = 16842968; // 0x10100d8
field public static final int paddingStart = 16843699; // 0x10103b3
field public static final int paddingTop = 16842967; // 0x10100d7
@@ -1640,7 +1641,6 @@
field public static final int selectAll = 16908319; // 0x102001f
field public static final int selectTextMode = 16908333; // 0x102002d
field public static final int selectedIcon = 16908302; // 0x102000e
- field public static final int shared_element = 16908354; // 0x1020042
field public static final int startSelectingText = 16908328; // 0x1020028
field public static final int stopSelectingText = 16908329; // 0x1020029
field public static final int summary = 16908304; // 0x1020010
@@ -2830,6 +2830,12 @@
method public java.lang.Object evaluate(float, java.lang.Object, java.lang.Object);
}
+ public abstract class BidirectionalTypeConverter extends android.animation.TypeConverter {
+ ctor public BidirectionalTypeConverter(java.lang.Class<T>, java.lang.Class<V>);
+ method public abstract T convertBack(V);
+ method public android.animation.BidirectionalTypeConverter<V, T> invert();
+ }
+
public class FloatArrayEvaluator implements android.animation.TypeEvaluator {
ctor public FloatArrayEvaluator();
ctor public FloatArrayEvaluator(float[]);
@@ -3008,7 +3014,6 @@
public abstract class TypeConverter {
ctor public TypeConverter(java.lang.Class<T>, java.lang.Class<V>);
method public abstract V convert(T);
- method public T convertBack(V);
}
public abstract interface TypeEvaluator {
@@ -3336,6 +3341,8 @@
method public void setContentView(android.view.View);
method public void setContentView(android.view.View, android.view.ViewGroup.LayoutParams);
method public final void setDefaultKeyMode(int);
+ method public void setEnterSharedElementListener(android.app.SharedElementListener);
+ method public void setExitSharedElementListener(android.app.SharedElementListener);
method public final void setFeatureDrawable(int, android.graphics.drawable.Drawable);
method public final void setFeatureDrawableAlpha(int, int);
method public final void setFeatureDrawableResource(int, int);
@@ -3351,7 +3358,6 @@
method public final void setResult(int);
method public final void setResult(int, android.content.Intent);
method public final void setSecondaryProgress(int);
- method public void setSharedElementListener(android.app.SharedElementListener);
method public void setTaskDescription(android.app.ActivityManager.TaskDescription);
method public void setTitle(java.lang.CharSequence);
method public void setTitle(int);
@@ -4418,6 +4424,8 @@
ctor public Notification(android.os.Parcel);
method public android.app.Notification clone();
method public int describeContents();
+ method public java.lang.String getGroup();
+ method public java.lang.String getSortKey();
method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
method public void writeToParcel(android.os.Parcel, int);
field public static final java.lang.String CATEGORY_ALARM = "alarm";
@@ -4460,6 +4468,7 @@
field public static final java.lang.String EXTRA_TITLE_BIG = "android.title.big";
field public static final int FLAG_AUTO_CANCEL = 16; // 0x10
field public static final int FLAG_FOREGROUND_SERVICE = 64; // 0x40
+ field public static final int FLAG_GROUP_SUMMARY = 512; // 0x200
field public static final deprecated int FLAG_HIGH_PRIORITY = 128; // 0x80
field public static final int FLAG_INSISTENT = 4; // 0x4
field public static final int FLAG_LOCAL_ONLY = 256; // 0x100
@@ -4510,6 +4519,7 @@
method public android.app.Notification.Action clone();
method public int describeContents();
method public android.os.Bundle getExtras();
+ method public android.app.RemoteInput[] getRemoteInputs();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
field public android.app.PendingIntent actionIntent;
@@ -4517,14 +4527,20 @@
field public java.lang.CharSequence title;
}
- public static class Notification.Action.Builder {
+ public static final class Notification.Action.Builder {
ctor public Notification.Action.Builder(int, java.lang.CharSequence, android.app.PendingIntent);
ctor public Notification.Action.Builder(android.app.Notification.Action);
method public android.app.Notification.Action.Builder addExtras(android.os.Bundle);
+ method public android.app.Notification.Action.Builder addRemoteInput(android.app.RemoteInput);
+ method public android.app.Notification.Action.Builder apply(android.app.Notification.Action.Builder.Extender);
method public android.app.Notification.Action build();
method public android.os.Bundle getExtras();
}
+ public static abstract interface Notification.Action.Builder.Extender {
+ method public abstract android.app.Notification.Action.Builder applyTo(android.app.Notification.Action.Builder);
+ }
+
public static class Notification.BigPictureStyle extends android.app.Notification.Style {
ctor public Notification.BigPictureStyle();
ctor public Notification.BigPictureStyle(android.app.Notification.Builder);
@@ -4548,6 +4564,7 @@
method public android.app.Notification.Builder addAction(android.app.Notification.Action);
method public android.app.Notification.Builder addExtras(android.os.Bundle);
method public android.app.Notification.Builder addPerson(java.lang.String);
+ method public android.app.Notification.Builder apply(android.app.Notification.Builder.Extender);
method public android.app.Notification build();
method public android.os.Bundle getExtras();
method public deprecated android.app.Notification getNotification();
@@ -4563,6 +4580,8 @@
method public android.app.Notification.Builder setDeleteIntent(android.app.PendingIntent);
method public android.app.Notification.Builder setExtras(android.os.Bundle);
method public android.app.Notification.Builder setFullScreenIntent(android.app.PendingIntent, boolean);
+ method public android.app.Notification.Builder setGroup(java.lang.String);
+ method public android.app.Notification.Builder setGroupSummary(boolean);
method public android.app.Notification.Builder setLargeIcon(android.graphics.Bitmap);
method public android.app.Notification.Builder setLights(int, int, int);
method public android.app.Notification.Builder setLocalOnly(boolean);
@@ -4575,6 +4594,7 @@
method public android.app.Notification.Builder setShowWhen(boolean);
method public android.app.Notification.Builder setSmallIcon(int);
method public android.app.Notification.Builder setSmallIcon(int, int);
+ method public android.app.Notification.Builder setSortKey(java.lang.String);
method public android.app.Notification.Builder setSound(android.net.Uri);
method public android.app.Notification.Builder setSound(android.net.Uri, int);
method public android.app.Notification.Builder setStyle(android.app.Notification.Style);
@@ -4587,6 +4607,10 @@
method public android.app.Notification.Builder setWhen(long);
}
+ public static abstract interface Notification.Builder.Extender {
+ method public abstract android.app.Notification.Builder applyTo(android.app.Notification.Builder);
+ }
+
public static class Notification.InboxStyle extends android.app.Notification.Style {
ctor public Notification.InboxStyle();
ctor public Notification.InboxStyle(android.app.Notification.Builder);
@@ -4690,6 +4714,31 @@
field public static final int STYLE_SPINNER = 0; // 0x0
}
+ public final class RemoteInput implements android.os.Parcelable {
+ method public static void addResultsToIntent(android.app.RemoteInput[], android.content.Intent, android.os.Bundle);
+ method public int describeContents();
+ method public boolean getAllowFreeFormInput();
+ method public java.lang.CharSequence[] getChoices();
+ method public android.os.Bundle getExtras();
+ method public java.lang.CharSequence getLabel();
+ method public java.lang.String getResultKey();
+ method public static android.os.Bundle getResultsFromIntent(android.content.Intent);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ field public static final java.lang.String EXTRA_RESULTS_DATA = "android.remoteinput.resultsData";
+ field public static final java.lang.String RESULTS_CLIP_LABEL = "android.remoteinput.results";
+ }
+
+ public static final class RemoteInput.Builder {
+ ctor public RemoteInput.Builder(java.lang.String);
+ method public android.app.RemoteInput.Builder addExtras(android.os.Bundle);
+ method public android.app.RemoteInput build();
+ method public android.os.Bundle getExtras();
+ method public android.app.RemoteInput.Builder setAllowFreeFormInput(boolean);
+ method public android.app.RemoteInput.Builder setChoices(java.lang.CharSequence[]);
+ method public android.app.RemoteInput.Builder setLabel(java.lang.CharSequence);
+ }
+
public class SearchManager implements android.content.DialogInterface.OnCancelListener android.content.DialogInterface.OnDismissListener {
method public android.content.ComponentName getGlobalSearchActivity();
method public android.app.SearchableInfo getSearchableInfo(android.content.ComponentName);
@@ -4810,7 +4859,7 @@
field public static final int START_STICKY_COMPATIBILITY = 0; // 0x0
}
- public class SharedElementListener {
+ public abstract class SharedElementListener {
ctor public SharedElementListener();
method public void handleRejectedSharedElements(java.util.List<android.view.View>);
method public void remapSharedElements(java.util.List<java.lang.String>, java.util.Map<java.lang.String, android.view.View>);
@@ -5047,6 +5096,7 @@
method public boolean hasGrantedPolicy(android.content.ComponentName, int);
method public boolean isActivePasswordSufficient();
method public boolean isAdminActive(android.content.ComponentName);
+ method public boolean isApplicationBlocked(android.content.ComponentName, java.lang.String);
method public boolean isDeviceOwnerApp(java.lang.String);
method public boolean isLockTaskPermitted(android.content.ComponentName);
method public boolean isProfileOwnerApp(java.lang.String);
@@ -5054,8 +5104,11 @@
method public void removeActiveAdmin(android.content.ComponentName);
method public boolean resetPassword(java.lang.String, int);
method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
+ method public boolean setApplicationBlocked(android.content.ComponentName, java.lang.String, boolean);
method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle);
+ method public int setApplicationsBlocked(android.content.ComponentName, android.content.Intent, boolean);
method public void setCameraDisabled(android.content.ComponentName, boolean);
+ method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
method public void setLockTaskComponents(android.content.ComponentName[]) throws java.lang.SecurityException;
method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
@@ -5071,6 +5124,7 @@
method public void setPasswordMinimumUpperCase(android.content.ComponentName, int);
method public void setPasswordQuality(android.content.ComponentName, int);
method public void setProfileEnabled(android.content.ComponentName);
+ method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
method public int setStorageEncryption(android.content.ComponentName, boolean);
method public void wipeData(int);
field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
@@ -5224,6 +5278,80 @@
}
+package android.app.wearable {
+
+ public final class WearableActionExtensions implements android.app.Notification.Action.Builder.Extender android.os.Parcelable {
+ method public android.app.Notification.Action.Builder applyTo(android.app.Notification.Action.Builder);
+ method public int describeContents();
+ method public static android.app.wearable.WearableActionExtensions from(android.app.Notification.Action);
+ method public boolean isAvailableOffline();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ }
+
+ public static final class WearableActionExtensions.Builder {
+ ctor public WearableActionExtensions.Builder();
+ ctor public WearableActionExtensions.Builder(android.app.wearable.WearableActionExtensions);
+ method public android.app.wearable.WearableActionExtensions build();
+ method public android.app.wearable.WearableActionExtensions.Builder setAvailableOffline(boolean);
+ }
+
+ public final class WearableNotificationExtensions implements android.app.Notification.Builder.Extender android.os.Parcelable {
+ method public android.app.Notification.Builder applyTo(android.app.Notification.Builder);
+ method public int describeContents();
+ method public static android.app.wearable.WearableNotificationExtensions from(android.app.Notification);
+ method public android.app.Notification.Action getAction(int);
+ method public int getActionCount();
+ method public android.app.Notification.Action[] getActions();
+ method public android.graphics.Bitmap getBackground();
+ method public int getContentAction();
+ method public int getContentIcon();
+ method public int getContentIconGravity();
+ method public boolean getContentIntentAvailableOffline();
+ method public int getCustomContentHeight();
+ method public int getCustomSizePreset();
+ method public android.app.PendingIntent getDisplayIntent();
+ method public int getGravity();
+ method public boolean getHintHideIcon();
+ method public boolean getHintShowBackgroundOnly();
+ method public android.app.Notification[] getPages();
+ method public boolean getStartScrollBottom();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ field public static final int SIZE_DEFAULT = 0; // 0x0
+ field public static final int SIZE_LARGE = 4; // 0x4
+ field public static final int SIZE_MEDIUM = 3; // 0x3
+ field public static final int SIZE_SMALL = 2; // 0x2
+ field public static final int SIZE_XSMALL = 1; // 0x1
+ field public static final int UNSET_ACTION_INDEX = -1; // 0xffffffff
+ }
+
+ public static final class WearableNotificationExtensions.Builder {
+ ctor public WearableNotificationExtensions.Builder();
+ ctor public WearableNotificationExtensions.Builder(android.app.wearable.WearableNotificationExtensions);
+ method public android.app.wearable.WearableNotificationExtensions.Builder addAction(android.app.Notification.Action);
+ method public android.app.wearable.WearableNotificationExtensions.Builder addActions(java.util.List<android.app.Notification.Action>);
+ method public android.app.wearable.WearableNotificationExtensions.Builder addPage(android.app.Notification);
+ method public android.app.wearable.WearableNotificationExtensions.Builder addPages(java.util.List<android.app.Notification>);
+ method public android.app.wearable.WearableNotificationExtensions build();
+ method public android.app.wearable.WearableNotificationExtensions.Builder clearActions();
+ method public android.app.wearable.WearableNotificationExtensions.Builder clearPages();
+ method public android.app.wearable.WearableNotificationExtensions.Builder setBackground(android.graphics.Bitmap);
+ method public android.app.wearable.WearableNotificationExtensions.Builder setContentAction(int);
+ method public android.app.wearable.WearableNotificationExtensions.Builder setContentIcon(int);
+ method public android.app.wearable.WearableNotificationExtensions.Builder setContentIconGravity(int);
+ method public android.app.wearable.WearableNotificationExtensions.Builder setContentIntentAvailableOffline(boolean);
+ method public android.app.wearable.WearableNotificationExtensions.Builder setCustomContentHeight(int);
+ method public android.app.wearable.WearableNotificationExtensions.Builder setCustomSizePreset(int);
+ method public android.app.wearable.WearableNotificationExtensions.Builder setDisplayIntent(android.app.PendingIntent);
+ method public android.app.wearable.WearableNotificationExtensions.Builder setGravity(int);
+ method public android.app.wearable.WearableNotificationExtensions.Builder setHintHideIcon(boolean);
+ method public android.app.wearable.WearableNotificationExtensions.Builder setHintShowBackgroundOnly(boolean);
+ method public android.app.wearable.WearableNotificationExtensions.Builder setStartScrollBottom(boolean);
+ }
+
+}
+
package android.appwidget {
public class AppWidgetHost {
@@ -6012,6 +6140,7 @@
ctor public BluetoothLeAdvertiseScanData();
field public static final int ADVERTISING_DATA = 0; // 0x0
field public static final int PARSED_SCAN_RECORD = 2; // 0x2
+ field public static final int SCAN_RESPONSE_DATA = 1; // 0x1
}
public static abstract class BluetoothLeAdvertiseScanData.AdvertiseBaseData {
@@ -6055,6 +6184,7 @@
public class BluetoothLeAdvertiser {
method public void startAdvertising(android.bluetooth.BluetoothLeAdvertiser.Settings, android.bluetooth.BluetoothLeAdvertiseScanData.AdvertisementData, android.bluetooth.BluetoothLeAdvertiser.AdvertiseCallback);
+ method public void startAdvertising(android.bluetooth.BluetoothLeAdvertiser.Settings, android.bluetooth.BluetoothLeAdvertiseScanData.AdvertisementData, android.bluetooth.BluetoothLeAdvertiseScanData.AdvertisementData, android.bluetooth.BluetoothLeAdvertiser.AdvertiseCallback);
method public void stopAdvertising(android.bluetooth.BluetoothLeAdvertiser.Settings, android.bluetooth.BluetoothLeAdvertiser.AdvertiseCallback);
}
@@ -8265,6 +8395,7 @@
field public static final java.lang.String FEATURE_USB_ACCESSORY = "android.hardware.usb.accessory";
field public static final java.lang.String FEATURE_USB_HOST = "android.hardware.usb.host";
field public static final java.lang.String FEATURE_WATCH = "android.hardware.type.watch";
+ field public static final java.lang.String FEATURE_WEBVIEW = "android.software.webview";
field public static final java.lang.String FEATURE_WIFI = "android.hardware.wifi";
field public static final java.lang.String FEATURE_WIFI_DIRECT = "android.hardware.wifi.direct";
field public static final int GET_ACTIVITIES = 1; // 0x1
@@ -10370,10 +10501,10 @@
ctor public Outline();
ctor public Outline(android.graphics.Outline);
method public boolean canClip();
- method public boolean isValid();
- method public void reset();
+ method public boolean isEmpty();
method public void set(android.graphics.Outline);
method public void setConvexPath(android.graphics.Path);
+ method public void setEmpty();
method public void setOval(int, int, int, int);
method public void setOval(android.graphics.Rect);
method public void setRect(int, int, int, int);
@@ -12821,15 +12952,14 @@
public class UsbConfiguration implements android.os.Parcelable {
method public int describeContents();
- method public int getAttributes();
method public int getId();
method public android.hardware.usb.UsbInterface getInterface(int);
method public int getInterfaceCount();
method public int getMaxPower();
method public java.lang.String getName();
+ method public boolean isRemoteWakeup();
+ method public boolean isSelfPowered();
method public void writeToParcel(android.os.Parcel, int);
- field public static final int ATTR_REMOTE_WAKEUP_MASK = 32; // 0x20
- field public static final int ATTR_SELF_POWERED_MASK = 64; // 0x40
field public static final android.os.Parcelable.Creator CREATOR;
}
@@ -14930,6 +15060,7 @@
ctor public RemoteControlClient(android.app.PendingIntent);
ctor public RemoteControlClient(android.app.PendingIntent, android.os.Looper);
method public android.media.RemoteControlClient.MetadataEditor editMetadata(boolean);
+ method public android.media.session.MediaSession getMediaSession();
method public void setMetadataUpdateListener(android.media.RemoteControlClient.OnMetadataUpdateListener);
method public void setOnGetPlaybackPositionListener(android.media.RemoteControlClient.OnGetPlaybackPositionListener);
method public void setPlaybackPositionUpdateListener(android.media.RemoteControlClient.OnPlaybackPositionUpdateListener);
@@ -16898,9 +17029,11 @@
}
public static final class WifiEnterpriseConfig.Eap {
+ field public static final int AKA = 5; // 0x5
field public static final int NONE = -1; // 0xffffffff
field public static final int PEAP = 0; // 0x0
field public static final int PWD = 3; // 0x3
+ field public static final int SIM = 4; // 0x4
field public static final int TLS = 1; // 0x1
field public static final int TTLS = 2; // 0x2
}
@@ -16934,6 +17067,7 @@
public class WifiManager {
method public int addNetwork(android.net.wifi.WifiConfiguration);
method public static int calculateSignalLevel(int, int);
+ method public void cancelWps(android.net.wifi.WifiManager.ActionListener);
method public static int compareSignalLevel(int, int);
method public android.net.wifi.WifiManager.MulticastLock createMulticastLock(java.lang.String);
method public android.net.wifi.WifiManager.WifiLock createWifiLock(int, java.lang.String);
@@ -16957,9 +17091,12 @@
method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
method public boolean setWifiEnabled(boolean);
method public boolean startScan();
+ method public void startWps(android.net.wifi.WpsInfo, android.net.wifi.WifiManager.WpsListener);
method public int updateNetwork(android.net.wifi.WifiConfiguration);
field public static final java.lang.String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
field public static final java.lang.String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE";
+ field public static final int BUSY = 2; // 0x2
+ field public static final int ERROR = 0; // 0x0
field public static final int ERROR_AUTHENTICATING = 1; // 0x1
field public static final java.lang.String EXTRA_BSSID = "bssid";
field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
@@ -16970,6 +17107,8 @@
field public static final java.lang.String EXTRA_SUPPLICANT_ERROR = "supplicantError";
field public static final java.lang.String EXTRA_WIFI_INFO = "wifiInfo";
field public static final java.lang.String EXTRA_WIFI_STATE = "wifi_state";
+ field public static final int INVALID_ARGS = 8; // 0x8
+ field public static final int IN_PROGRESS = 1; // 0x1
field public static final java.lang.String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED";
field public static final java.lang.String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE";
field public static final java.lang.String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED";
@@ -16985,6 +17124,16 @@
field public static final int WIFI_STATE_ENABLED = 3; // 0x3
field public static final int WIFI_STATE_ENABLING = 2; // 0x2
field public static final int WIFI_STATE_UNKNOWN = 4; // 0x4
+ field public static final int WPS_AUTH_FAILURE = 6; // 0x6
+ field public static final int WPS_OVERLAP_ERROR = 3; // 0x3
+ field public static final int WPS_TIMED_OUT = 7; // 0x7
+ field public static final int WPS_TKIP_ONLY_PROHIBITED = 5; // 0x5
+ field public static final int WPS_WEP_PROHIBITED = 4; // 0x4
+ }
+
+ public static abstract interface WifiManager.ActionListener {
+ method public abstract void onFailure(int);
+ method public abstract void onSuccess();
}
public class WifiManager.MulticastLock {
@@ -17002,6 +17151,12 @@
method public void setWorkSource(android.os.WorkSource);
}
+ public static abstract interface WifiManager.WpsListener {
+ method public abstract void onCompletion();
+ method public abstract void onFailure(int);
+ method public abstract void onStartSuccess(java.lang.String);
+ }
+
public class WifiScanner {
method public void configureWifiChange(int, int, int, int, int, android.net.wifi.WifiScanner.HotspotInfo[]);
method public void resetHotlist(android.net.wifi.WifiScanner.HotlistListener);
@@ -17087,6 +17242,7 @@
ctor public WpsInfo(android.net.wifi.WpsInfo);
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
+ field public java.lang.String BSSID;
field public static final android.os.Parcelable.Creator CREATOR;
field public static final int DISPLAY = 1; // 0x1
field public static final int INVALID = 4; // 0x4
@@ -17296,108 +17452,23 @@
package android.net.wifi.passpoint {
- public abstract interface IPasspointManager implements android.os.IInterface {
- method public abstract android.os.Messenger getMessenger() throws android.os.RemoteException;
- method public abstract int getPasspointState() throws android.os.RemoteException;
- }
-
- public class PasspointCredential implements android.os.Parcelable {
- ctor public PasspointCredential();
+ public class WifiPasspointCredential implements android.os.Parcelable {
+ ctor public WifiPasspointCredential(java.lang.String, android.net.wifi.WifiEnterpriseConfig);
method public int describeContents();
+ method public java.lang.String getClientCertPath();
+ method public int getEapMethod();
+ method public java.lang.String getFqdn();
+ method public java.lang.String getImsi();
+ method public java.lang.String getRealm();
+ method public java.lang.String getUserName();
method public void writeToParcel(android.os.Parcel, int);
}
- public class PasspointInfo implements android.os.Parcelable {
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int ANQP_CAPABILITY = 1; // 0x1
- field public static final int CELLULAR_NETWORK = 64; // 0x40
- field public static final int CONNECTION_CAPABILITY = 2048; // 0x800
- field public static final int DOMAIN_NAME = 128; // 0x80
- field public static final int HOTSPOT_CAPABILITY = 256; // 0x100
- field public static final int IP_ADDR_TYPE_AVAILABILITY = 16; // 0x10
- field public static final int NAI_REALM = 32; // 0x20
- field public static final int NETWORK_AUTH_TYPE = 4; // 0x4
- field public static final int OPERATOR_FRIENDLY_NAME = 512; // 0x200
- field public static final int OSU_PROVIDER = 4096; // 0x1000
- field public static final int PRESET_ALL = 8191; // 0x1fff
- field public static final int PRESET_CRED_MATCH = 481; // 0x1e1
- field public static final int ROAMING_CONSORTIUM = 8; // 0x8
- field public static final int VENUE_NAME = 2; // 0x2
- field public static final int WAN_METRICS = 1024; // 0x400
- field public java.lang.String bssid;
- field public java.lang.String cellularNetwork;
- field public java.lang.String connectionCapability;
- field public java.lang.String domainName;
- field public java.lang.String ipAddrTypeAvaibility;
- field public java.lang.String naiRealm;
- field public java.lang.String networkAuthType;
- field public java.lang.String operatorFriendlyName;
- field public java.util.List osuProviderList;
- field public java.lang.String roamingConsortium;
- field public java.lang.String venueName;
- field public java.lang.String wanMetrics;
- }
-
- public class PasspointManager {
- ctor public PasspointManager(android.content.Context, android.net.wifi.passpoint.IPasspointManager);
- method public boolean addCredential(android.net.wifi.passpoint.PasspointCredential);
- method public void connect(android.net.wifi.passpoint.PasspointPolicy);
- method public int getPasspointState();
- method public java.util.List<android.net.wifi.passpoint.PasspointCredential> getSavedCredentials();
- method public android.net.wifi.passpoint.PasspointManager.Channel initialize(android.content.Context, android.os.Looper, android.net.wifi.passpoint.PasspointManager.ChannelListener);
- method public boolean removeCredential(android.net.wifi.passpoint.PasspointCredential);
- method public java.util.List<android.net.wifi.passpoint.PasspointPolicy> requestCredentialMatch(java.util.List<android.net.wifi.ScanResult>);
- method public void requestOsuIcons(android.net.wifi.passpoint.PasspointManager.Channel, java.util.List<android.net.wifi.passpoint.PasspointOsuProvider>, int, android.net.wifi.passpoint.PasspointManager.ActionListener);
- method public boolean updateCredential(android.net.wifi.passpoint.PasspointCredential);
- field public static final int BUSY = 2; // 0x2
- field public static final int ERROR = 0; // 0x0
- field public static final java.lang.String PASSPOINT_CRED_CHANGED_ACTION = "android.net.wifi.passpoint.CRED_CHANGE";
- field public static final int PASSPOINT_STATE_ACCESS = 3; // 0x3
- field public static final java.lang.String PASSPOINT_STATE_CHANGED_ACTION = "android.net.wifi.passpoint.STATE_CHANGE";
- field public static final int PASSPOINT_STATE_DISABLED = 1; // 0x1
- field public static final int PASSPOINT_STATE_DISCOVERY = 2; // 0x2
- field public static final int PASSPOINT_STATE_PROVISION = 4; // 0x4
- field public static final int PASSPOINT_STATE_UNKNOWN = 0; // 0x0
- field public static final int WIFI_DISABLED = 1; // 0x1
- }
-
- public static abstract interface PasspointManager.ActionListener {
- method public abstract void onFailure(int);
- method public abstract void onSuccess();
- }
-
- public static class PasspointManager.Channel {
- }
-
- public static abstract interface PasspointManager.ChannelListener {
- method public abstract void onChannelDisconnected();
- }
-
- public class PasspointOsuProvider implements android.os.Parcelable {
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator CREATOR;
- field public static final int OSU_METHOD_OMADM = 0; // 0x0
- field public static final int OSU_METHOD_SOAP = 1; // 0x1
- field public static final int OSU_METHOD_UNKNOWN = -1; // 0xffffffff
- field public java.lang.String friendlyName;
- field public java.lang.Object icon;
- field public java.lang.String iconFileName;
- field public int iconHeight;
- field public java.lang.String iconType;
- field public int iconWidth;
- field public int osuMethod;
- field public java.lang.String osuNai;
- field public java.lang.String osuService;
- field public java.lang.String serverUri;
- field public java.lang.String ssid;
- }
-
- public class PasspointPolicy implements android.os.Parcelable {
- ctor public PasspointPolicy();
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
+ public class WifiPasspointManager {
+ method public boolean addCredential(android.net.wifi.passpoint.WifiPasspointCredential);
+ method public java.util.List<android.net.wifi.passpoint.WifiPasspointCredential> getSavedCredentials();
+ method public boolean removeCredential(android.net.wifi.passpoint.WifiPasspointCredential);
+ method public boolean updateCredential(android.net.wifi.passpoint.WifiPasspointCredential);
}
}
@@ -17519,11 +17590,6 @@
method public android.nfc.NfcAdapter getDefaultAdapter();
}
- public class NfcUnlock {
- method public static synchronized android.nfc.NfcUnlock getInstance(android.nfc.NfcAdapter);
- method public boolean getNfcUnlockEnabled();
- }
-
public final class Tag implements android.os.Parcelable {
method public int describeContents();
method public byte[] getId();
@@ -20987,6 +21053,7 @@
field public static final java.lang.String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media";
field public static final java.lang.String DISALLOW_REMOVE_USER = "no_remove_user";
field public static final java.lang.String DISALLOW_SHARE_LOCATION = "no_share_location";
+ field public static final java.lang.String DISALLOW_TELEPHONY = "no_telephony";
field public static final java.lang.String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps";
field public static final java.lang.String DISALLOW_UNMUTE_MICROPHONE = "no_unmute_microphone";
field public static final java.lang.String DISALLOW_USB_FILE_TRANSFER = "no_usb_file_transfer";
@@ -23883,7 +23950,6 @@
field public static final java.lang.String LOCK_PATTERN_VISIBLE = "lock_pattern_visible_pattern";
field public static final deprecated java.lang.String LOGGING_ID = "logging_id";
field public static final deprecated java.lang.String NETWORK_PREFERENCE = "network_preference";
- field public static final java.lang.String NFC_UNLOCK_ENABLED = "nfc_unlock_enabled";
field public static final java.lang.String PARENTAL_CONTROL_ENABLED = "parental_control_enabled";
field public static final java.lang.String PARENTAL_CONTROL_LAST_UPDATE = "parental_control_last_update";
field public static final java.lang.String PARENTAL_CONTROL_REDIRECT_URL = "parental_control_redirect_url";
@@ -25030,8 +25096,8 @@
method public void setErrorHandler(android.renderscript.RenderScript.RSErrorHandler);
method public void setMessageHandler(android.renderscript.RenderScript.RSMessageHandler);
method public void setPriority(android.renderscript.RenderScript.Priority);
- field public static final long CREATE_FLAG_LOW_LATENCY = 1L; // 0x1L
- field public static final long CREATE_FLAG_LOW_POWER = 2L; // 0x2L
+ field public static final long CREATE_FLAG_LOW_LATENCY = 2L; // 0x2L
+ field public static final long CREATE_FLAG_LOW_POWER = 4L; // 0x4L
field public static final long CREATE_FLAG_NONE = 0L; // 0x0L
}
@@ -25551,10 +25617,10 @@
public class FingerprintManager {
ctor public FingerprintManager(android.content.Context);
method public void enroll(long);
+ method public boolean enrolledAndEnabled();
method public void remove(int);
method public void startListening(android.service.fingerprint.FingerprintManagerReceiver);
method public void stopListening();
- field protected static final boolean DEBUG = true;
field public static final int FINGERPRINT_ERROR = -1; // 0xffffffff
field public static final int FINGERPRINT_ERROR_BAD_CAPTURE = 2; // 0x2
field public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; // 0x1
@@ -25584,20 +25650,24 @@
method public final deprecated void cancelNotification(java.lang.String, java.lang.String, int);
method public final void cancelNotification(java.lang.String);
method public final void cancelNotifications(java.lang.String[]);
+ method public java.lang.String[] getActiveNotificationKeys();
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
method public android.service.notification.StatusBarNotification[] getActiveNotifications(java.lang.String[]);
- method public java.lang.String[] getOrderedNotificationKeys();
+ method public android.service.notification.NotificationListenerService.Ranking getCurrentRanking();
method public android.os.IBinder onBind(android.content.Intent);
method public void onListenerConnected(java.lang.String[]);
- method public void onNotificationOrderUpdate();
method public abstract void onNotificationPosted(android.service.notification.StatusBarNotification);
+ method public void onNotificationRankingUpdate();
method public abstract void onNotificationRemoved(android.service.notification.StatusBarNotification);
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationListenerService";
}
- public class NotificationOrderUpdate implements android.os.Parcelable {
- ctor public NotificationOrderUpdate(android.os.Parcel);
+ public static class NotificationListenerService.Ranking implements android.os.Parcelable {
method public int describeContents();
+ method public int getIndexOfKey(java.lang.String);
+ method public java.lang.String[] getOrderedKeys();
+ method public boolean isAmbient(java.lang.String);
+ method public boolean isInterceptedByDoNotDisturb(java.lang.String);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
}
diff --git a/core/java/android/animation/BidirectionalTypeConverter.java b/core/java/android/animation/BidirectionalTypeConverter.java
new file mode 100644
index 0000000..960650e
--- /dev/null
+++ b/core/java/android/animation/BidirectionalTypeConverter.java
@@ -0,0 +1,73 @@
+/*
+ * 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.animation;
+
+/**
+ * Abstract base class used convert type T to another type V and back again. This
+ * is necessary when the value types of in animation are different from the property
+ * type. BidirectionalTypeConverter is needed when only the final value for the
+ * animation is supplied to animators.
+ * @see PropertyValuesHolder#setConverter(TypeConverter)
+ */
+public abstract class BidirectionalTypeConverter<T, V> extends TypeConverter<T, V> {
+ private BidirectionalTypeConverter mInvertedConverter;
+
+ public BidirectionalTypeConverter(Class<T> fromClass, Class<V> toClass) {
+ super(fromClass, toClass);
+ }
+
+ /**
+ * Does a conversion from the target type back to the source type. The subclass
+ * must implement this when a TypeConverter is used in animations and current
+ * values will need to be read for an animation.
+ * @param value The Object to convert.
+ * @return A value of type T, converted from <code>value</code>.
+ */
+ public abstract T convertBack(V value);
+
+ /**
+ * Returns the inverse of this converter, where the from and to classes are reversed.
+ * The inverted converter uses this convert to call {@link #convertBack(Object)} for
+ * {@link #convert(Object)} calls and {@link #convert(Object)} for
+ * {@link #convertBack(Object)} calls.
+ * @return The inverse of this converter, where the from and to classes are reversed.
+ */
+ public BidirectionalTypeConverter<V, T> invert() {
+ if (mInvertedConverter == null) {
+ mInvertedConverter = new InvertedConverter(this);
+ }
+ return mInvertedConverter;
+ }
+
+ private static class InvertedConverter<From, To> extends BidirectionalTypeConverter<From, To> {
+ private BidirectionalTypeConverter<To, From> mConverter;
+
+ public InvertedConverter(BidirectionalTypeConverter<To, From> converter) {
+ super(converter.getTargetType(), converter.getSourceType());
+ mConverter = converter;
+ }
+
+ @Override
+ public From convertBack(To value) {
+ return mConverter.convert(value);
+ }
+
+ @Override
+ public To convert(From value) {
+ return mConverter.convertBack(value);
+ }
+ }
+}
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index c0ce795..130754e 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -610,8 +610,8 @@
* along the way, and an ending value (these values will be distributed evenly across
* the duration of the animation). This variant supplies a <code>TypeConverter</code> to
* convert from the animated values to the type of the property. If only one value is
- * supplied, the <code>TypeConverter</code> must implement
- * {@link TypeConverter#convertBack(Object)} to retrieve the current value.
+ * supplied, the <code>TypeConverter</code> must be a
+ * {@link android.animation.BidirectionalTypeConverter} to retrieve the current value.
*
* @param target The object whose property is to be animated.
* @param property The property being animated.
diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java
index 8fce80a..bf2924c 100644
--- a/core/java/android/animation/PropertyValuesHolder.java
+++ b/core/java/android/animation/PropertyValuesHolder.java
@@ -456,7 +456,7 @@
* cannot automatically interpolate between objects of unknown type. This variant also
* takes a <code>TypeConverter</code> to convert from animated values to the type
* of the property. If only one value is supplied, the <code>TypeConverter</code>
- * must implement {@link TypeConverter#convertBack(Object)} to retrieve the current
+ * must be a {@link android.animation.BidirectionalTypeConverter} to retrieve the current
* value.
*
* @param property The property being animated. Should not be null.
@@ -635,6 +635,8 @@
/**
* Sets the converter to convert from the values type to the setter's parameter type.
+ * If only one value is supplied, <var>converter</var> must be a
+ * {@link android.animation.BidirectionalTypeConverter}.
* @param converter The converter to use to convert values.
*/
public void setConverter(TypeConverter converter) {
@@ -816,12 +818,12 @@
private Object convertBack(Object value) {
if (mConverter != null) {
- value = mConverter.convertBack(value);
- if (value == null) {
+ if (!(mConverter instanceof BidirectionalTypeConverter)) {
throw new IllegalArgumentException("Converter "
+ mConverter.getClass().getName()
- + " must implement convertBack and not return null.");
+ + " must be a BidirectionalTypeConverter");
}
+ value = ((BidirectionalTypeConverter) mConverter).convertBack(value);
}
return value;
}
diff --git a/core/java/android/animation/TypeConverter.java b/core/java/android/animation/TypeConverter.java
index 03b3eb5..9ead2ad 100644
--- a/core/java/android/animation/TypeConverter.java
+++ b/core/java/android/animation/TypeConverter.java
@@ -53,16 +53,4 @@
* @return A value of type V, converted from <code>value</code>.
*/
public abstract V convert(T value);
-
- /**
- * Does a conversion from the target type back to the source type. The subclass
- * must implement this when a TypeConverter is used in animations and current
- * values will need to be read for an animation. By default, this will return null,
- * indicating that back-conversion is not supported.
- * @param value The Object to convert.
- * @return A value of type T, converted from <code>value</code>.
- */
- public T convertBack(V value) {
- return null;
- }
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index e1a94d7..3de971c 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -779,7 +779,8 @@
final Handler mHandler = new Handler();
private ActivityTransitionState mActivityTransitionState = new ActivityTransitionState();
- SharedElementListener mTransitionListener = new SharedElementListener();
+ SharedElementListener mEnterTransitionListener = SharedElementListener.NULL_LISTENER;
+ SharedElementListener mExitTransitionListener = SharedElementListener.NULL_LISTENER;
/** Return the intent that started this activity. */
public Intent getIntent() {
@@ -5557,16 +5558,32 @@
/**
* When {@link android.app.ActivityOptions#makeSceneTransitionAnimation(Activity,
* android.view.View, String)} was used to start an Activity, <var>listener</var>
- * will be called to handle shared elements. This requires
+ * will be called to handle shared elements on the <i>launched</i> Activity. This requires
* {@link Window#FEATURE_CONTENT_TRANSITIONS}.
*
- * @param listener Used to manipulate how shared element transitions function.
+ * @param listener Used to manipulate shared element transitions on the launched Activity.
*/
- public void setSharedElementListener(SharedElementListener listener) {
+ public void setEnterSharedElementListener(SharedElementListener listener) {
if (listener == null) {
- listener = new SharedElementListener();
+ listener = SharedElementListener.NULL_LISTENER;
}
- mTransitionListener = listener;
+ mEnterTransitionListener = listener;
+ }
+
+ /**
+ * When {@link android.app.ActivityOptions#makeSceneTransitionAnimation(Activity,
+ * android.view.View, String)} was used to start an Activity, <var>listener</var>
+ * will be called to handle shared elements on the <i>launching</i> Activity. Most
+ * calls will only come when returning from the started Activity.
+ * This requires {@link Window#FEATURE_CONTENT_TRANSITIONS}.
+ *
+ * @param listener Used to manipulate shared element transitions on the launching Activity.
+ */
+ public void setExitSharedElementListener(SharedElementListener listener) {
+ if (listener == null) {
+ listener = SharedElementListener.NULL_LISTENER;
+ }
+ mExitTransitionListener = listener;
}
// ------------------ Internal API ------------------
@@ -5882,7 +5899,8 @@
* have completed drawing. This is necessary only after an {@link Activity} has been made
* opaque using {@link Activity#convertFromTranslucent()} and before it has been drawn
* translucent again following a call to {@link
- * Activity#convertToTranslucent(TranslucentConversionListener)}.
+ * Activity#convertToTranslucent(android.app.Activity.TranslucentConversionListener,
+ * ActivityOptions)}
*
* @hide
*/
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index 6c6a52f..2acf5b2 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -189,15 +189,17 @@
final protected SharedElementListener mListener;
protected ResultReceiver mResultReceiver;
final private FixedEpicenterCallback mEpicenterCallback = new FixedEpicenterCallback();
+ final protected boolean mIsReturning;
public ActivityTransitionCoordinator(Window window,
ArrayList<String> allSharedElementNames,
ArrayList<String> accepted, ArrayList<String> localNames,
- SharedElementListener listener) {
+ SharedElementListener listener, boolean isReturning) {
super(new Handler());
mWindow = window;
mListener = listener;
mAllSharedElementNames = allSharedElementNames;
+ mIsReturning = isReturning;
setSharedElements(accepted, localNames);
if (getViewsTransition() != null) {
getDecor().captureTransitioningViews(mTransitioningViews);
@@ -330,7 +332,21 @@
mResultReceiver = resultReceiver;
}
- protected abstract Transition getViewsTransition();
+ protected Transition getViewsTransition() {
+ if (mIsReturning) {
+ return getWindow().getExitTransition();
+ } else {
+ return getWindow().getEnterTransition();
+ }
+ }
+
+ protected Transition getSharedElementTransition() {
+ if (mIsReturning) {
+ return getWindow().getSharedElementExitTransition();
+ } else {
+ return getWindow().getSharedElementEnterTransition();
+ }
+ }
private static class FixedEpicenterCallback extends Transition.EpicenterCallback {
private Rect mEpicenter;
@@ -342,4 +358,5 @@
return mEpicenter;
}
}
+
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 6324d4c..9053af2 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -81,8 +81,8 @@
import android.net.nsd.NsdManager;
import android.net.wifi.IWifiManager;
import android.net.wifi.WifiManager;
-import android.net.wifi.passpoint.IPasspointManager;
-import android.net.wifi.passpoint.PasspointManager;
+import android.net.wifi.passpoint.IWifiPasspointManager;
+import android.net.wifi.passpoint.WifiPasspointManager;
import android.net.wifi.p2p.IWifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager;
import android.nfc.NfcManager;
@@ -581,8 +581,8 @@
registerService(WIFI_PASSPOINT_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(WIFI_PASSPOINT_SERVICE);
- IPasspointManager service = IPasspointManager.Stub.asInterface(b);
- return new PasspointManager(ctx.getOuterContext(), service);
+ IWifiPasspointManager service = IWifiPasspointManager.Stub.asInterface(b);
+ return new WifiPasspointManager(ctx.getOuterContext(), service);
}});
registerService(WIFI_P2P_SERVICE, new ServiceFetcher() {
@@ -1377,7 +1377,7 @@
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, rd,
initialCode, initialData, initialExtras, receiverPermission,
- AppOpsManager.OP_NONE, true, false, user.getIdentifier());
+ appOp, true, false, user.getIdentifier());
} catch (RemoteException e) {
}
}
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index 636205b..b40d16c 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -51,7 +51,6 @@
private static final long MAX_WAIT_MS = 1500;
private boolean mSharedElementTransitionStarted;
- private boolean mIsReturning;
private Activity mActivity;
private boolean mHasStopped;
private Handler mHandler;
@@ -61,9 +60,8 @@
ArrayList<String> sharedElementNames,
ArrayList<String> acceptedNames, ArrayList<String> mappedNames) {
super(activity.getWindow(), sharedElementNames, acceptedNames, mappedNames,
- activity.mTransitionListener);
+ getListener(activity, acceptedNames), acceptedNames != null);
mActivity = activity;
- mIsReturning = acceptedNames != null;
setResultReceiver(resultReceiver);
prepareEnter();
Bundle resultReceiverBundle = new Bundle();
@@ -80,6 +78,12 @@
}
}
+ private static SharedElementListener getListener(Activity activity,
+ ArrayList<String> acceptedNames) {
+ boolean isReturning = acceptedNames != null;
+ return isReturning ? activity.mExitTransitionListener : activity.mEnterTransitionListener;
+ }
+
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
switch (resultCode) {
@@ -299,7 +303,6 @@
if (sharedElementBundle != null) {
Bitmap bitmap = sharedElementBundle.getParcelable(KEY_BITMAP);
View snapshot = new View(context);
- snapshot.setId(com.android.internal.R.id.shared_element);
Resources resources = getWindow().getContext().getResources();
snapshot.setBackground(new BitmapDrawable(resources, bitmap));
snapshot.setViewName(name);
@@ -420,12 +423,4 @@
}
}
- @Override
- protected Transition getViewsTransition() {
- return getWindow().getEnterTransition();
- }
-
- protected Transition getSharedElementTransition() {
- return getWindow().getSharedElementEnterTransition();
- }
}
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index 43a60a3..1d78b30 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -53,20 +53,22 @@
private boolean mIsBackgroundReady;
- private boolean mIsReturning;
-
private boolean mIsCanceled;
private Handler mHandler;
public ExitTransitionCoordinator(Activity activity, ArrayList<String> names,
ArrayList<String> accepted, ArrayList<String> mapped, boolean isReturning) {
- super(activity.getWindow(), names, accepted, mapped, activity.mTransitionListener);
- mIsReturning = isReturning;
+ super(activity.getWindow(), names, accepted, mapped, getListener(activity, isReturning),
+ isReturning);
mIsBackgroundReady = !mIsReturning;
mActivity = activity;
}
+ private static SharedElementListener getListener(Activity activity, boolean isReturning) {
+ return isReturning ? activity.mExitTransitionListener : activity.mEnterTransitionListener;
+ }
+
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
switch (resultCode) {
@@ -271,13 +273,4 @@
}
return -1;
}
-
- @Override
- protected Transition getViewsTransition() {
- return getWindow().getExitTransition();
- }
-
- protected Transition getSharedElementTransition() {
- return getWindow().getSharedElementExitTransition();
- }
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index fd76b9c4..59b3a27 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -45,6 +45,7 @@
import java.lang.annotation.RetentionPolicy;
import java.text.NumberFormat;
import java.util.ArrayList;
+import java.util.Collections;
/**
* A class that represents how a persistent notification is to be presented to
@@ -370,6 +371,14 @@
*/
public static final int FLAG_LOCAL_ONLY = 0x00000100;
+ /**
+ * Bit to be bitswise-ored into the {@link #flags} field that should be
+ * set if this notification is the group summary for a group of notifications.
+ * Grouped notifications may display in a cluster or stack on devices which
+ * support such rendering. Requires a group key also be set using {@link Builder#setGroup}.
+ */
+ public static final int FLAG_GROUP_SUMMARY = 0x00000200;
+
public int flags;
/** @hide */
@@ -539,6 +548,34 @@
*/
public String category;
+ private String mGroupKey;
+
+ /**
+ * Get the key used to group this notification into a cluster or stack
+ * with other notifications on devices which support such rendering.
+ */
+ public String getGroup() {
+ return mGroupKey;
+ }
+
+ private String mSortKey;
+
+ /**
+ * Get a sort key that orders this notification among other notifications from the
+ * same package. This can be useful if an external sort was already applied and an app
+ * would like to preserve this. Notifications will be sorted lexicographically using this
+ * value, although providing different priorities in addition to providing sort key may
+ * cause this value to be ignored.
+ *
+ * <p>This sort key can also be used to order members of a notification group. See
+ * {@link Builder#setGroup}.
+ *
+ * @see String#compareTo(String)
+ */
+ public String getSortKey() {
+ return mSortKey;
+ }
+
/**
* Additional semantic data to be carried around with this Notification.
* <p>
@@ -706,15 +743,18 @@
*/
public static class Action implements Parcelable {
private final Bundle mExtras;
+ private RemoteInput[] mRemoteInputs;
/**
* Small icon representing the action.
*/
public int icon;
+
/**
* Title of the action.
*/
public CharSequence title;
+
/**
* Intent to send when the user invokes this action. May be null, in which case the action
* may be rendered in a disabled presentation by the system UI.
@@ -728,19 +768,23 @@
actionIntent = PendingIntent.CREATOR.createFromParcel(in);
}
mExtras = in.readBundle();
+ mRemoteInputs = in.createTypedArray(RemoteInput.CREATOR);
}
+
/**
* Use {@link Notification.Builder#addAction(int, CharSequence, PendingIntent)}.
*/
public Action(int icon, CharSequence title, PendingIntent intent) {
- this(icon, title, intent, new Bundle());
+ this(icon, title, intent, new Bundle(), null);
}
- private Action(int icon, CharSequence title, PendingIntent intent, Bundle extras) {
+ private Action(int icon, CharSequence title, PendingIntent intent, Bundle extras,
+ RemoteInput[] remoteInputs) {
this.icon = icon;
this.title = title;
this.actionIntent = intent;
this.mExtras = extras != null ? extras : new Bundle();
+ this.mRemoteInputs = remoteInputs;
}
/**
@@ -751,13 +795,22 @@
}
/**
+ * Get the list of inputs to be collected from the user when this action is sent.
+ * May return null if no remote inputs were added.
+ */
+ public RemoteInput[] getRemoteInputs() {
+ return mRemoteInputs;
+ }
+
+ /**
* Builder class for {@link Action} objects.
*/
- public static class Builder {
+ public static final class Builder {
private final int mIcon;
private final CharSequence mTitle;
private final PendingIntent mIntent;
private final Bundle mExtras;
+ private ArrayList<RemoteInput> mRemoteInputs;
/**
* Construct a new builder for {@link Action} object.
@@ -766,7 +819,7 @@
* @param intent the {@link PendingIntent} to fire when users trigger this action
*/
public Builder(int icon, CharSequence title, PendingIntent intent) {
- this(icon, title, intent, new Bundle());
+ this(icon, title, intent, new Bundle(), null);
}
/**
@@ -775,14 +828,20 @@
* @param action the action to read fields from.
*/
public Builder(Action action) {
- this(action.icon, action.title, action.actionIntent, new Bundle(action.mExtras));
+ this(action.icon, action.title, action.actionIntent, new Bundle(action.mExtras),
+ action.getRemoteInputs());
}
- private Builder(int icon, CharSequence title, PendingIntent intent, Bundle extras) {
+ private Builder(int icon, CharSequence title, PendingIntent intent, Bundle extras,
+ RemoteInput[] remoteInputs) {
mIcon = icon;
mTitle = title;
mIntent = intent;
mExtras = extras;
+ if (remoteInputs != null) {
+ mRemoteInputs = new ArrayList<RemoteInput>(remoteInputs.length);
+ Collections.addAll(mRemoteInputs, remoteInputs);
+ }
}
/**
@@ -809,22 +868,62 @@
}
/**
+ * Add an input to be collected from the user when this action is sent.
+ * Response values can be retrieved from the fired intent by using the
+ * {@link RemoteInput#getResultsFromIntent} function.
+ * @param remoteInput a {@link RemoteInput} to add to the action
+ * @return this object for method chaining
+ */
+ public Builder addRemoteInput(RemoteInput remoteInput) {
+ if (mRemoteInputs == null) {
+ mRemoteInputs = new ArrayList<RemoteInput>();
+ }
+ mRemoteInputs.add(remoteInput);
+ return this;
+ }
+
+ /**
+ * Apply an extender to this action builder. Extenders may be used to add
+ * metadata or change options on this builder.
+ */
+ public Builder apply(Extender extender) {
+ extender.applyTo(this);
+ return this;
+ }
+
+ /**
+ * Extender interface for use with {@link #apply}. Extenders may be used to add
+ * metadata or change options on this builder.
+ */
+ public interface Extender {
+ /**
+ * Apply this extender to a notification action builder.
+ * @param builder the builder to be modified.
+ * @return the build object for chaining.
+ */
+ public Builder applyTo(Builder builder);
+ }
+
+ /**
* Combine all of the options that have been set and return a new {@link Action}
* object.
* @return the built action
*/
public Action build() {
- return new Action(mIcon, mTitle, mIntent, mExtras);
+ RemoteInput[] remoteInputs = mRemoteInputs != null
+ ? mRemoteInputs.toArray(new RemoteInput[mRemoteInputs.size()]) : null;
+ return new Action(mIcon, mTitle, mIntent, mExtras, remoteInputs);
}
}
@Override
public Action clone() {
return new Action(
- this.icon,
- this.title,
- this.actionIntent, // safe to alias
- new Bundle(this.mExtras));
+ icon,
+ title,
+ actionIntent, // safe to alias
+ new Bundle(mExtras),
+ getRemoteInputs());
}
@Override
public int describeContents() {
@@ -841,6 +940,7 @@
out.writeInt(0);
}
out.writeBundle(mExtras);
+ out.writeTypedArray(mRemoteInputs, flags);
}
public static final Parcelable.Creator<Action> CREATOR =
new Parcelable.Creator<Action>() {
@@ -960,6 +1060,10 @@
category = parcel.readString();
+ mGroupKey = parcel.readString();
+
+ mSortKey = parcel.readString();
+
extras = parcel.readBundle(); // may be null
actions = parcel.createTypedArray(Action.CREATOR); // may be null
@@ -1037,6 +1141,10 @@
that.category = this.category;
+ that.mGroupKey = this.mGroupKey;
+
+ that.mSortKey = this.mSortKey;
+
if (this.extras != null) {
try {
that.extras = new Bundle(this.extras);
@@ -1188,6 +1296,10 @@
parcel.writeString(category);
+ parcel.writeString(mGroupKey);
+
+ parcel.writeString(mSortKey);
+
parcel.writeBundle(extras); // null ok
parcel.writeTypedArray(actions, 0); // null ok
@@ -1325,7 +1437,18 @@
sb.append(" flags=0x");
sb.append(Integer.toHexString(this.flags));
sb.append(String.format(" color=0x%08x", this.color));
- sb.append(" category="); sb.append(this.category);
+ if (this.category != null) {
+ sb.append(" category=");
+ sb.append(this.category);
+ }
+ if (this.mGroupKey != null) {
+ sb.append(" groupKey=");
+ sb.append(this.mGroupKey);
+ }
+ if (this.mSortKey != null) {
+ sb.append(" sortKey=");
+ sb.append(this.mSortKey);
+ }
if (actions != null) {
sb.append(" ");
sb.append(actions.length);
@@ -1408,6 +1531,8 @@
private int mProgress;
private boolean mProgressIndeterminate;
private String mCategory;
+ private String mGroupKey;
+ private String mSortKey;
private Bundle mExtras;
private int mPriority;
private ArrayList<Action> mActions = new ArrayList<Action>(MAX_ACTION_BUTTONS);
@@ -1839,6 +1964,51 @@
}
/**
+ * Set this notification to be part of a group of notifications sharing the same key.
+ * Grouped notifications may display in a cluster or stack on devices which
+ * support such rendering.
+ *
+ * <p>To make this notification the summary for its group, also call
+ * {@link #setGroupSummary}. A sort order can be specified for group members by using
+ * {@link #setSortKey}.
+ * @param groupKey The group key of the group.
+ * @return this object for method chaining
+ */
+ public Builder setGroup(String groupKey) {
+ mGroupKey = groupKey;
+ return this;
+ }
+
+ /**
+ * Set this notification to be the group summary for a group of notifications.
+ * Grouped notifications may display in a cluster or stack on devices which
+ * support such rendering. Requires a group key also be set using {@link #setGroup}.
+ * @param isGroupSummary Whether this notification should be a group summary.
+ * @return this object for method chaining
+ */
+ public Builder setGroupSummary(boolean isGroupSummary) {
+ setFlag(FLAG_GROUP_SUMMARY, isGroupSummary);
+ return this;
+ }
+
+ /**
+ * Set a sort key that orders this notification among other notifications from the
+ * same package. This can be useful if an external sort was already applied and an app
+ * would like to preserve this. Notifications will be sorted lexicographically using this
+ * value, although providing different priorities in addition to providing sort key may
+ * cause this value to be ignored.
+ *
+ * <p>This sort key can also be used to order members of a notification group. See
+ * {@link #setGroup}.
+ *
+ * @see String#compareTo(String)
+ */
+ public Builder setSortKey(String sortKey) {
+ mSortKey = sortKey;
+ return this;
+ }
+
+ /**
* Merge additional metadata into this notification.
*
* <p>Values within the Bundle will replace existing extras values in this Builder.
@@ -1949,7 +2119,7 @@
/**
* Specify the value of {@link #visibility}.
-
+ *
* @param visibility One of {@link #VISIBILITY_PRIVATE} (the default),
* {@link #VISIBILITY_SECRET}, or {@link #VISIBILITY_PUBLIC}.
*
@@ -1971,6 +2141,28 @@
return this;
}
+ /**
+ * Apply an extender to this notification builder. Extenders may be used to add
+ * metadata or change options on this builder.
+ */
+ public Builder apply(Extender extender) {
+ extender.applyTo(this);
+ return this;
+ }
+
+ /**
+ * Extender interface for use with {@link #apply}. Extenders may be used to add
+ * metadata or change options on this builder.
+ */
+ public interface Extender {
+ /**
+ * Apply this extender to a notification builder.
+ * @param builder the builder to be modified.
+ * @return the build object for chaining.
+ */
+ public Builder applyTo(Builder builder);
+ }
+
private void setFlag(int mask, boolean value) {
if (value) {
mFlags |= mask;
@@ -2298,6 +2490,8 @@
n.flags |= FLAG_SHOW_LIGHTS;
}
n.category = mCategory;
+ n.mGroupKey = mGroupKey;
+ n.mSortKey = mSortKey;
n.priority = mPriority;
if (mActions.size() > 0) {
n.actions = new Action[mActions.size()];
diff --git a/core/java/android/app/RemoteInput.java b/core/java/android/app/RemoteInput.java
new file mode 100644
index 0000000..9cfc541
--- /dev/null
+++ b/core/java/android/app/RemoteInput.java
@@ -0,0 +1,297 @@
+/*
+ * 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.app;
+
+import android.content.ClipData;
+import android.content.ClipDescription;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A {@code RemoteInput} object specifies input to be collected from a user to be passed along with
+ * an intent inside a {@link android.app.PendingIntent} that is sent.
+ * Always use {@link RemoteInput.Builder} to create instances of this class.
+ * <p class="note"> See
+ * <a href="{@docRoot}wear/notifications/remote-input.html">Receiving Voice Input from
+ * a Notification</a> for more information on how to use this class.
+ *
+ * <p>The following example adds a {@code RemoteInput} to a {@link Notification.Action},
+ * sets the result key as {@code quick_reply}, and sets the label as {@code Quick reply}.
+ * Users are prompted to input a response when they trigger the action. The results are sent along
+ * with the intent and can be retrieved with the result key (provided to the {@link Builder}
+ * constructor) from the Bundle returned by {@link #getResultsFromIntent}.
+ *
+ * <pre class="prettyprint">
+ * public static final String KEY_QUICK_REPLY_TEXT = "quick_reply";
+ * Notification.Action action = new Notification.Action.Builder(
+ * R.drawable.reply, "Reply", actionIntent)
+ * <b>.addRemoteInput(new RemoteInput.Builder(KEY_QUICK_REPLY_TEXT)
+ * .setLabel("Quick reply").build()</b>)
+ * .build();</pre>
+ *
+ * <p>When the {@link android.app.PendingIntent} is fired, the intent inside will contain the
+ * input results if collected. To access these results, use the {@link #getResultsFromIntent}
+ * function. The result values will present under the result key passed to the {@link Builder}
+ * constructor.
+ *
+ * <pre class="prettyprint">
+ * public static final String KEY_QUICK_REPLY_TEXT = "quick_reply";
+ * Bundle results = RemoteInput.getResultsFromIntent(intent);
+ * if (results != null) {
+ * CharSequence quickReplyResult = results.getCharSequence(KEY_QUICK_REPLY_TEXT);
+ * }</pre>
+ */
+public final class RemoteInput implements Parcelable {
+ /** Label used to denote the clip data type used for remote input transport */
+ public static final String RESULTS_CLIP_LABEL = "android.remoteinput.results";
+
+ /** Extra added to a clip data intent object to hold the results bundle. */
+ public static final String EXTRA_RESULTS_DATA = "android.remoteinput.resultsData";
+
+ private final String mResultKey;
+ private final CharSequence mLabel;
+ private final CharSequence[] mChoices;
+ private final boolean mAllowFreeFormInput;
+ private final Bundle mExtras;
+
+ private RemoteInput(String resultKey, CharSequence label, CharSequence[] choices,
+ boolean allowFreeFormInput, Bundle extras) {
+ this.mResultKey = resultKey;
+ this.mLabel = label;
+ this.mChoices = choices;
+ this.mAllowFreeFormInput = allowFreeFormInput;
+ this.mExtras = extras;
+ }
+
+ /**
+ * Get the key that the result of this input will be set in from the Bundle returned by
+ * {@link #getResultsFromIntent} when the {@link android.app.PendingIntent} is sent.
+ */
+ public String getResultKey() {
+ return mResultKey;
+ }
+
+ /**
+ * Get the label to display to users when collecting this input.
+ */
+ public CharSequence getLabel() {
+ return mLabel;
+ }
+
+ /**
+ * Get possible input choices. This can be {@code null} if there are no choices to present.
+ */
+ public CharSequence[] getChoices() {
+ return mChoices;
+ }
+
+ /**
+ * Get whether or not users can provide an arbitrary value for
+ * input. If you set this to {@code false}, users must select one of the
+ * choices in {@link #getChoices}. An {@link IllegalArgumentException} is thrown
+ * if you set this to false and {@link #getChoices} returns {@code null} or empty.
+ */
+ public boolean getAllowFreeFormInput() {
+ return mAllowFreeFormInput;
+ }
+
+ /**
+ * Get additional metadata carried around with this remote input.
+ */
+ public Bundle getExtras() {
+ return mExtras;
+ }
+
+ /**
+ * Builder class for {@link RemoteInput} objects.
+ */
+ public static final class Builder {
+ private final String mResultKey;
+ private CharSequence mLabel;
+ private CharSequence[] mChoices;
+ private boolean mAllowFreeFormInput = true;
+ private Bundle mExtras = new Bundle();
+
+ /**
+ * Create a builder object for {@link RemoteInput} objects.
+ * @param resultKey the Bundle key that refers to this input when collected from the user
+ */
+ public Builder(String resultKey) {
+ if (resultKey == null) {
+ throw new IllegalArgumentException("Result key can't be null");
+ }
+ mResultKey = resultKey;
+ }
+
+ /**
+ * Set a label to be displayed to the user when collecting this input.
+ * @param label The label to show to users when they input a response.
+ * @return this object for method chaining
+ */
+ public Builder setLabel(CharSequence label) {
+ mLabel = Notification.safeCharSequence(label);
+ return this;
+ }
+
+ /**
+ * Specifies choices available to the user to satisfy this input.
+ * @param choices an array of pre-defined choices for users input.
+ * You must provide a non-null and non-empty array if
+ * you disabled free form input using {@link #setAllowFreeFormInput}.
+ * @return this object for method chaining
+ */
+ public Builder setChoices(CharSequence[] choices) {
+ if (choices == null) {
+ mChoices = null;
+ } else {
+ mChoices = new CharSequence[choices.length];
+ for (int i = 0; i < choices.length; i++) {
+ mChoices[i] = Notification.safeCharSequence(choices[i]);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Specifies whether the user can provide arbitrary values.
+ *
+ * @param allowFreeFormInput The default is {@code true}.
+ * If you specify {@code false}, you must provide a non-null
+ * and non-empty array to {@link #setChoices} or an
+ * {@link IllegalArgumentException} is thrown.
+ * @return this object for method chaining
+ */
+ public Builder setAllowFreeFormInput(boolean allowFreeFormInput) {
+ mAllowFreeFormInput = allowFreeFormInput;
+ return this;
+ }
+
+ /**
+ * Merge additional metadata into this builder.
+ *
+ * <p>Values within the Bundle will replace existing extras values in this Builder.
+ *
+ * @see RemoteInput#getExtras
+ */
+ public Builder addExtras(Bundle extras) {
+ if (extras != null) {
+ mExtras.putAll(extras);
+ }
+ return this;
+ }
+
+ /**
+ * Get the metadata Bundle used by this Builder.
+ *
+ * <p>The returned Bundle is shared with this Builder.
+ */
+ public Bundle getExtras() {
+ return mExtras;
+ }
+
+ /**
+ * Combine all of the options that have been set and return a new {@link RemoteInput}
+ * object.
+ */
+ public RemoteInput build() {
+ return new RemoteInput(mResultKey, mLabel, mChoices, mAllowFreeFormInput, mExtras);
+ }
+ }
+
+ private RemoteInput(Parcel in) {
+ mResultKey = in.readString();
+ mLabel = in.readCharSequence();
+ mChoices = in.readCharSequenceArray();
+ mAllowFreeFormInput = in.readInt() != 0;
+ mExtras = in.readBundle();
+ }
+
+ /**
+ * Get the remote input results bundle from an intent. The returned Bundle will
+ * contain a key/value for every result key populated by remote input collector.
+ * Use the {@link Bundle#getCharSequence(String)} method to retrieve a value.
+ * @param intent The intent object that fired in response to an action or content intent
+ * which also had one or more remote input requested.
+ */
+ public static Bundle getResultsFromIntent(Intent intent) {
+ ClipData clipData = intent.getClipData();
+ if (clipData == null) {
+ return null;
+ }
+ ClipDescription clipDescription = clipData.getDescription();
+ if (!clipDescription.hasMimeType(ClipDescription.MIMETYPE_TEXT_INTENT)) {
+ return null;
+ }
+ if (clipDescription.getLabel().equals(RESULTS_CLIP_LABEL)) {
+ return clipData.getItemAt(0).getIntent().getExtras().getParcelable(EXTRA_RESULTS_DATA);
+ }
+ return null;
+ }
+
+ /**
+ * Populate an intent object with the results gathered from remote input. This method
+ * should only be called by remote input collection services when sending results to a
+ * pending intent.
+ * @param remoteInputs The remote inputs for which results are being provided
+ * @param intent The intent to add remote inputs to. The {@link ClipData}
+ * field of the intent will be modified to contain the results.
+ * @param results A bundle holding the remote input results. This bundle should
+ * be populated with keys matching the result keys specified in
+ * {@code remoteInputs} with values being the result per key.
+ */
+ public static void addResultsToIntent(RemoteInput[] remoteInputs, Intent intent,
+ Bundle results) {
+ Bundle resultsBundle = new Bundle();
+ for (RemoteInput remoteInput : remoteInputs) {
+ Object result = results.get(remoteInput.getResultKey());
+ if (result instanceof CharSequence) {
+ resultsBundle.putCharSequence(remoteInput.getResultKey(), (CharSequence) result);
+ }
+ }
+ Intent clipIntent = new Intent();
+ clipIntent.putExtra(EXTRA_RESULTS_DATA, resultsBundle);
+ intent.setClipData(ClipData.newIntent(RESULTS_CLIP_LABEL, clipIntent));
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(mResultKey);
+ out.writeCharSequence(mLabel);
+ out.writeCharSequenceArray(mChoices);
+ out.writeInt(mAllowFreeFormInput ? 1 : 0);
+ out.writeBundle(mExtras);
+ }
+
+ public static final Creator<RemoteInput> CREATOR = new Creator<RemoteInput>() {
+ @Override
+ public RemoteInput createFromParcel(Parcel in) {
+ return new RemoteInput(in);
+ }
+
+ @Override
+ public RemoteInput[] newArray(int size) {
+ return new RemoteInput[size];
+ }
+ };
+}
diff --git a/core/java/android/app/SharedElementListener.java b/core/java/android/app/SharedElementListener.java
index d4bc019..e03e42e 100644
--- a/core/java/android/app/SharedElementListener.java
+++ b/core/java/android/app/SharedElementListener.java
@@ -22,15 +22,27 @@
/**
* Listener provided in
- * {@link Activity#setSharedElementListener(SharedElementListener)}
- * to monitor the Activity transitions. The events can be used to customize or override Activity
+ * {@link Activity#setEnterSharedElementListener(SharedElementListener)} and
+ * {@link Activity#setExitSharedElementListener(SharedElementListener)}
+ * to monitor the Activity transitions. The events can be used to customize Activity
* Transition behavior.
*/
-public class SharedElementListener {
+public abstract class SharedElementListener {
+
+ static final SharedElementListener NULL_LISTENER = new SharedElementListener() {
+ };
+
/**
- * Called to allow the listener to customize the start state of the shared element for
- * the shared element entering transition. By default, the shared element is placed in
- * the position and with the size of the shared element in the calling Activity or Fragment.
+ * Called to allow the listener to customize the start state of the shared element when
+ * transferring in shared element state.
+ * <p>
+ * The shared element will start at the size and position of the shared element
+ * in the launching Activity or Fragment. It will also transfer ImageView scaleType
+ * and imageMatrix if the shared elements in the calling and called Activities are
+ * ImageViews. Some applications may want to make additional changes, such as
+ * changing the clip bounds, scaling, or rotation if the shared element end state
+ * does not map well to the start state.
+ * </p>
*
* @param sharedElementNames The names of the shared elements that were accepted into
* the View hierarchy.
@@ -44,8 +56,17 @@
List<View> sharedElements, List<View> sharedElementSnapshots) {}
/**
- * Called to allow the listener to customize the end state of the shared element for
- * the shared element entering transition.
+ * Called to allow the listener to customize the end state of the shared element when
+ * transferring in shared element state.
+ * <p>
+ * Any customization done in
+ * {@link #setSharedElementStart(java.util.List, java.util.List, java.util.List)}
+ * may need to be modified to the final state of the shared element if it is not
+ * automatically corrected by layout. For example, rotation or scale will not
+ * be affected by layout and if changed in {@link #setSharedElementStart(java.util.List,
+ * java.util.List, java.util.List)}, it will also have to be set here again to correct
+ * the end state.
+ * </p>
*
* @param sharedElementNames The names of the shared elements that were accepted into
* the View hierarchy.
@@ -59,13 +80,18 @@
List<View> sharedElements, List<View> sharedElementSnapshots) {}
/**
- * If nothing is done, all shared elements that were not accepted by
- * {@link #remapSharedElements(java.util.List, java.util.Map)} will be Transitioned
- * out of the entering scene automatically. Any elements removed from
- * rejectedSharedElements must be handled by the ActivityTransitionListener.
- * <p>Views in rejectedSharedElements will have their position and size set to the
- * position of the calling shared element, relative to the Window decor View. This
- * view may be safely added to the decor View's overlay to remain in position.</p>
+ * Called after {@link #remapSharedElements(java.util.List, java.util.Map)} when
+ * transferring shared elements in. Any shared elements that have no mapping will be in
+ * <var>rejectedSharedElements</var>. The elements remaining in
+ * <var>rejectedSharedElements</var> will be transitioned out of the Scene. If a
+ * View is removed from <var>rejectedSharedElements</var>, it must be handled by the
+ * <code>SharedElementListener</code>.
+ * <p>
+ * Views in rejectedSharedElements will have their position and size set to the
+ * position of the calling shared element, relative to the Window decor View and contain
+ * snapshots of the View from the calling Activity or Fragment. This
+ * view may be safely added to the decor View's overlay to remain in position.
+ * </p>
*
* @param rejectedSharedElements Views containing visual information of shared elements
* that are not part of the entering scene. These Views
@@ -78,6 +104,7 @@
/**
* Lets the ActivityTransitionListener adjust the mapping of shared element names to
* Views.
+ *
* @param names The names of all shared elements transferred from the calling Activity
* to the started Activity.
* @param sharedElements The mapping of shared element names to Views. The best guess
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 58d707c..48ff5b6 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -911,6 +911,35 @@
*/
public void suggestDesiredDimensions(int minimumWidth, int minimumHeight) {
try {
+ /**
+ * The framework makes no attempt to limit the window size
+ * to the maximum texture size. Any window larger than this
+ * cannot be composited.
+ *
+ * Read maximum texture size from system property and scale down
+ * minimumWidth and minimumHeight accordingly.
+ */
+ int maximumTextureSize;
+ try {
+ maximumTextureSize = SystemProperties.getInt("sys.max_texture_size", 0);
+ } catch (Exception e) {
+ maximumTextureSize = 0;
+ }
+
+ if (maximumTextureSize > 0) {
+ if ((minimumWidth > maximumTextureSize) ||
+ (minimumHeight > maximumTextureSize)) {
+ float aspect = (float)minimumHeight / (float)minimumWidth;
+ if (minimumWidth > minimumHeight) {
+ minimumWidth = maximumTextureSize;
+ minimumHeight = (int)((minimumWidth * aspect) + 0.5);
+ } else {
+ minimumHeight = maximumTextureSize;
+ minimumWidth = (int)((minimumHeight / aspect) + 0.5);
+ }
+ }
+ }
+
if (sGlobals.mService == null) {
Log.w(TAG, "WallpaperService not running");
} else {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 8884446..18e2a95 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -32,6 +32,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
+import android.provider.Settings;
import android.service.trust.TrustAgentService;
import android.util.Log;
@@ -2050,6 +2051,68 @@
}
/**
+ * Called by device or profile owner to block or unblock packages. When a package is blocked it
+ * is unavailable for use, but the data and actual package file remain.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param packageName The name of the package to block or unblock.
+ * @param blocked {@code true} if the package should be blocked, {@code false} if it should be
+ * unblocked.
+ * @return boolean Whether the blocked setting of the package was successfully updated.
+ */
+ public boolean setApplicationBlocked(ComponentName admin, String packageName,
+ boolean blocked) {
+ if (mService != null) {
+ try {
+ return mService.setApplicationBlocked(admin, packageName, blocked);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Called by profile or device owner to block or unblock currently installed packages. This
+ * should only be called by a profile or device owner running within a managed profile.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param intent An intent matching the app(s) to be updated. All apps that resolve for this
+ * intent will be updated in the current profile.
+ * @param blocked {@code true} if the packages should be blocked, {@code false} if they should
+ * be unblocked.
+ * @return int The number of activities that matched the intent and were updated.
+ */
+ public int setApplicationsBlocked(ComponentName admin, Intent intent, boolean blocked) {
+ if (mService != null) {
+ try {
+ return mService.setApplicationsBlocked(admin, intent, blocked);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Called by device or profile owner to determine if a package is blocked.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param packageName The name of the package to retrieve the blocked status of.
+ * @return boolean {@code true} if the package is blocked, {@code false} otherwise.
+ */
+ public boolean isApplicationBlocked(ComponentName admin, String packageName) {
+ if (mService != null) {
+ try {
+ return mService.isApplicationBlocked(admin, packageName);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return false;
+ }
+
+ /**
* Called by profile or device owner to re-enable a system app that was disabled by default
* when the managed profile was created. This should only be called from a profile or device
* owner running within a managed profile.
@@ -2181,4 +2244,42 @@
}
return false;
}
+
+ /**
+ * Called by device owners to update {@link Settings.Global} settings. Validation that the value
+ * of the setting is in the correct form for the setting type should be performed by the caller.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param setting The name of the setting to update.
+ * @param value The value to update the setting to.
+ */
+ public void setGlobalSetting(ComponentName admin, String setting, String value) {
+ if (mService != null) {
+ try {
+ mService.setGlobalSetting(admin, setting, value);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ }
+
+ /**
+ * Called by profile or device owners to update {@link Settings.Secure} settings. Validation
+ * that the value of the setting is in the correct form for the setting type should be performed
+ * by the caller.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param setting The name of the setting to update.
+ * @param value The value to update the setting to.
+ */
+ public void setSecureSetting(ComponentName admin, String setting, String value) {
+ if (mService != null) {
+ try {
+ mService.setSecureSetting(admin, setting, value);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ }
+
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 03ced0f..7257158 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -124,6 +124,10 @@
void addForwardingIntentFilter(in ComponentName admin, in IntentFilter filter, int flags);
void clearForwardingIntentFilters(in ComponentName admin);
+ boolean setApplicationBlocked(in ComponentName admin, in String packageName, boolean blocked);
+ int setApplicationsBlocked(in ComponentName admin, in Intent intent, boolean blocked);
+ boolean isApplicationBlocked(in ComponentName admin, in String packageName);
+
void enableSystemApp(in ComponentName admin, in String packageName);
int enableSystemAppWithIntent(in ComponentName admin, in Intent intent);
@@ -133,4 +137,7 @@
void setLockTaskComponents(in ComponentName[] components);
ComponentName[] getLockTaskComponents();
boolean isLockTaskPermitted(in ComponentName component);
+
+ void setGlobalSetting(in ComponentName who, in String setting, in String value);
+ void setSecureSetting(in ComponentName who, in String setting, in String value);
}
diff --git a/core/java/android/app/wearable/WearableActionExtensions.java b/core/java/android/app/wearable/WearableActionExtensions.java
new file mode 100644
index 0000000..c296ef2
--- /dev/null
+++ b/core/java/android/app/wearable/WearableActionExtensions.java
@@ -0,0 +1,176 @@
+/*
+ * 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.app.wearable;
+
+import android.app.Notification;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Wearable extensions to notification actions. To add extensions to an action,
+ * create a new {@link WearableActionExtensions} object using
+ * {@link WearableActionExtensions.Builder} and apply it to a
+ * {@link android.app.Notification.Action.Builder}.
+ *
+ * <pre class="prettyprint">
+ * Notification.Action action = new Notification.Action.Builder(
+ * R.drawable.archive_all, "Archive all", actionIntent)
+ * .apply(new WearableActionExtensions.Builder()
+ * .setAvailableOffline(false)
+ * .build())
+ * .build();
+ * </pre>
+ */
+public final class WearableActionExtensions implements Notification.Action.Builder.Extender,
+ Parcelable {
+ /** Notification action extra which contains wearable extensions */
+ private static final String EXTRA_WEARABLE_EXTENSIONS = "android.wearable.EXTENSIONS";
+
+ // Flags bitwise-ored to mFlags
+ private static final int FLAG_AVAILABLE_OFFLINE = 1 << 0;
+
+ // Default value for flags integer
+ private static final int DEFAULT_FLAGS = FLAG_AVAILABLE_OFFLINE;
+
+ private final int mFlags;
+
+ private WearableActionExtensions(int flags) {
+ mFlags = flags;
+ }
+
+ private WearableActionExtensions(Parcel in) {
+ mFlags = in.readInt();
+ }
+
+ /**
+ * Create a {@link WearableActionExtensions} by reading wearable extensions present on an
+ * existing notification action.
+ * @param action the notification action to inspect.
+ * @return a new {@link WearableActionExtensions} object.
+ */
+ public static WearableActionExtensions from(Notification.Action action) {
+ WearableActionExtensions extensions = action.getExtras().getParcelable(
+ EXTRA_WEARABLE_EXTENSIONS);
+ if (extensions != null) {
+ return extensions;
+ } else {
+ // Return a WearableActionExtensions with default values.
+ return new Builder().build();
+ }
+ }
+
+ /**
+ * Get whether this action is available when the wearable device is not connected to
+ * a companion device. The user can still trigger this action when the wearable device is
+ * offline, but a visual hint will indicate that the action may not be available.
+ * Defaults to true.
+ */
+ public boolean isAvailableOffline() {
+ return (mFlags & FLAG_AVAILABLE_OFFLINE) != 0;
+ }
+
+ @Override
+ public Notification.Action.Builder applyTo(Notification.Action.Builder builder) {
+ builder.getExtras().putParcelable(EXTRA_WEARABLE_EXTENSIONS, this);
+ return builder;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mFlags);
+ }
+
+ /**
+ * Builder for {@link WearableActionExtensions} objects, which adds wearable extensions to
+ * notification actions. To extend an action, create an instance of this class, call the set
+ * methods present, call {@link #build}, and finally apply the options to a
+ * {@link Notification.Action.Builder} using its
+ * {@link android.app.Notification.Action.Builder#apply} method.
+ */
+ public static final class Builder {
+ private int mFlags = DEFAULT_FLAGS;
+
+ /**
+ * Construct a builder to be used for adding wearable extensions to notification actions.
+ *
+ * <pre class="prettyprint">
+ * Notification.Action action = new Notification.Action.Builder(
+ * R.drawable.archive_all, "Archive all", actionIntent)
+ * .apply(new WearableActionExtensions.Builder()
+ * .setAvailableOffline(false)
+ * .build())
+ * .build();</pre>
+ */
+ public Builder() {
+ }
+
+ /**
+ * Create a {@link Builder} by reading wearable extensions present on an
+ * existing {@code WearableActionExtensions} object.
+ * @param other the existing extensions to inspect.
+ */
+ public Builder(WearableActionExtensions other) {
+ mFlags = other.mFlags;
+ }
+
+ /**
+ * Set whether this action is available when the wearable device is not connected to
+ * a companion device. The user can still trigger this action when the wearable device is
+ * offline, but a visual hint will indicate that the action may not be available.
+ * Defaults to true.
+ */
+ public Builder setAvailableOffline(boolean availableOffline) {
+ setFlag(FLAG_AVAILABLE_OFFLINE, availableOffline);
+ return this;
+ }
+
+ /**
+ * Build a new {@link WearableActionExtensions} object with the extensions
+ * currently present on this builder.
+ * @return the extensions object.
+ */
+ public WearableActionExtensions build() {
+ return new WearableActionExtensions(mFlags);
+ }
+
+ private void setFlag(int mask, boolean value) {
+ if (value) {
+ mFlags |= mask;
+ } else {
+ mFlags &= ~mask;
+ }
+ }
+ }
+
+ public static final Creator<WearableActionExtensions> CREATOR =
+ new Creator<WearableActionExtensions>() {
+ @Override
+ public WearableActionExtensions createFromParcel(Parcel in) {
+ return new WearableActionExtensions(in);
+ }
+
+ @Override
+ public WearableActionExtensions[] newArray(int size) {
+ return new WearableActionExtensions[size];
+ }
+ };
+}
diff --git a/core/java/android/app/wearable/WearableNotificationExtensions.java b/core/java/android/app/wearable/WearableNotificationExtensions.java
new file mode 100644
index 0000000..d433613
--- /dev/null
+++ b/core/java/android/app/wearable/WearableNotificationExtensions.java
@@ -0,0 +1,702 @@
+/*
+ * 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.app.wearable;
+
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.graphics.Bitmap;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.Gravity;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Helper class that contains wearable extensions for notifications.
+ * <p class="note"> See
+ * <a href="{@docRoot}wear/notifications/creating.html">Creating Notifications
+ * for Android Wear</a> for more information on how to use this class.
+ * <p>
+ * To create a notification with wearable extensions:
+ * <ol>
+ * <li>Create a {@link Notification.Builder}, setting any desired
+ * properties.
+ * <li>Create a {@link WearableNotificationExtensions.Builder}.
+ * <li>Set wearable-specific properties using the
+ * {@code add} and {@code set} methods of {@link WearableNotificationExtensions.Builder}.
+ * <li>Call {@link WearableNotificationExtensions.Builder#build} to build the extensions
+ * object.
+ * <li>Call {@link Notification.Builder#apply} to apply the extensions to a notification.
+ * <li>Post the notification to the notification system with the
+ * {@code NotificationManager.notify(...)} methods.
+ * </ol>
+ *
+ * <pre class="prettyprint">
+ * Notification notif = new Notification.Builder(mContext)
+ * .setContentTitle("New mail from " + sender.toString())
+ * .setContentText(subject)
+ * .setSmallIcon(R.drawable.new_mail)
+ * .apply(new new WearableNotificationExtensions.Builder()
+ * .setContentIcon(R.drawable.new_mail)
+ * .build())
+ * .build();
+ * NotificationManager notificationManger =
+ * (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+ * notificationManger.notify(0, notif);</pre>
+ *
+ * <p>Wearable extensions can be accessed on an existing notification by using the
+ * {@link WearableNotificationExtensions#from} function.
+ *
+ * <pre class="prettyprint">
+ * WearableNotificationExtensions wearableExtensions = WearableNotificationExtensions.from(
+ * notification);
+ * Notification[] pages = wearableExtensions.getPages();
+ * </pre>
+ */
+public final class WearableNotificationExtensions implements Notification.Builder.Extender,
+ Parcelable {
+ /**
+ * Sentinel value for an action index that is unset.
+ */
+ public static final int UNSET_ACTION_INDEX = -1;
+
+ /**
+ * Size value for use with {@link Builder#setCustomSizePreset} to show this notification with
+ * default sizing.
+ * <p>For custom display notifications created using {@link Builder#setDisplayIntent},
+ * the default is {@link #SIZE_LARGE}. All other notifications size automatically based
+ * on their content.
+ */
+ public static final int SIZE_DEFAULT = 0;
+
+ /**
+ * Size value for use with {@link Builder#setCustomSizePreset} to show this notification
+ * with an extra small size.
+ * <p>This value is only applicable for custom display notifications created using
+ * {@link Builder#setDisplayIntent}.
+ */
+ public static final int SIZE_XSMALL = 1;
+
+ /**
+ * Size value for use with {@link Builder#setCustomSizePreset} to show this notification
+ * with a small size.
+ * <p>This value is only applicable for custom display notifications created using
+ * {@link Builder#setDisplayIntent}.
+ */
+ public static final int SIZE_SMALL = 2;
+
+ /**
+ * Size value for use with {@link Builder#setCustomSizePreset} to show this notification
+ * with a medium size.
+ * <p>This value is only applicable for custom display notifications created using
+ * {@link Builder#setDisplayIntent}.
+ */
+ public static final int SIZE_MEDIUM = 3;
+
+ /**
+ * Size value for use with {@link Builder#setCustomSizePreset} to show this notification
+ * with a large size.
+ * <p>This value is only applicable for custom display notifications created using
+ * {@link Builder#setDisplayIntent}.
+ */
+ public static final int SIZE_LARGE = 4;
+
+ /** Notification extra which contains wearable extensions */
+ static final String EXTRA_WEARABLE_EXTENSIONS = "android.wearable.EXTENSIONS";
+
+ // Flags bitwise-ored to mFlags
+ static final int FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE = 1 << 0;
+ static final int FLAG_HINT_HIDE_ICON = 1 << 1;
+ static final int FLAG_HINT_SHOW_BACKGROUND_ONLY = 1 << 2;
+ static final int FLAG_START_SCROLL_BOTTOM = 1 << 3;
+
+ // Default value for flags integer
+ static final int DEFAULT_FLAGS = FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE;
+
+ private final Notification.Action[] mActions;
+ private final int mFlags;
+ private final PendingIntent mDisplayIntent;
+ private final Notification[] mPages;
+ private final Bitmap mBackground;
+ private final int mContentIcon;
+ private final int mContentIconGravity;
+ private final int mContentActionIndex;
+ private final int mCustomSizePreset;
+ private final int mCustomContentHeight;
+ private final int mGravity;
+
+ private WearableNotificationExtensions(Notification.Action[] actions, int flags,
+ PendingIntent displayIntent, Notification[] pages, Bitmap background,
+ int contentIcon, int contentIconGravity, int contentActionIndex,
+ int customSizePreset, int customContentHeight, int gravity) {
+ mActions = actions;
+ mFlags = flags;
+ mDisplayIntent = displayIntent;
+ mPages = pages;
+ mBackground = background;
+ mContentIcon = contentIcon;
+ mContentIconGravity = contentIconGravity;
+ mContentActionIndex = contentActionIndex;
+ mCustomSizePreset = customSizePreset;
+ mCustomContentHeight = customContentHeight;
+ mGravity = gravity;
+ }
+
+ private WearableNotificationExtensions(Parcel in) {
+ mActions = in.createTypedArray(Notification.Action.CREATOR);
+ mFlags = in.readInt();
+ mDisplayIntent = in.readParcelable(PendingIntent.class.getClassLoader());
+ mPages = in.createTypedArray(Notification.CREATOR);
+ mBackground = in.readParcelable(Bitmap.class.getClassLoader());
+ mContentIcon = in.readInt();
+ mContentIconGravity = in.readInt();
+ mContentActionIndex = in.readInt();
+ mCustomSizePreset = in.readInt();
+ mCustomContentHeight = in.readInt();
+ mGravity = in.readInt();
+ }
+
+ /**
+ * Create a {@link WearableNotificationExtensions} by reading wearable extensions present on an
+ * existing notification.
+ * @param notif the notification to inspect.
+ * @return a new {@link WearableNotificationExtensions} object.
+ */
+ public static WearableNotificationExtensions from(Notification notif) {
+ WearableNotificationExtensions extensions = notif.extras.getParcelable(
+ EXTRA_WEARABLE_EXTENSIONS);
+ if (extensions != null) {
+ return extensions;
+ } else {
+ // Return a WearableNotificationExtensions with default values.
+ return new Builder().build();
+ }
+ }
+
+ /**
+ * Apply wearable extensions to a notification that is being built. This is typically
+ * called by {@link Notification.Builder#apply} method of {@link Notification.Builder}.
+ */
+ @Override
+ public Notification.Builder applyTo(Notification.Builder builder) {
+ builder.getExtras().putParcelable(EXTRA_WEARABLE_EXTENSIONS, this);
+ return builder;
+ }
+
+ /**
+ * Get the number of wearable actions present on this notification.
+ *
+ * @return the number of wearable actions for this notification
+ */
+ public int getActionCount() {
+ return mActions.length;
+ }
+
+ /**
+ * Get a {@link Notification.Action} for the wearable action at {@code actionIndex}.
+ * @param actionIndex the index of the desired wearable action
+ */
+ public Notification.Action getAction(int actionIndex) {
+ return mActions[actionIndex];
+ }
+
+ /**
+ * Get the wearable actions present on this notification.
+ */
+ public Notification.Action[] getActions() {
+ return mActions;
+ }
+
+ /**
+ * Get the intent to launch inside of an activity view when displaying this
+ * notification. This {@code PendingIntent} should be for an activity.
+ */
+ public PendingIntent getDisplayIntent() {
+ return mDisplayIntent;
+ }
+
+ /**
+ * Get the array of additional pages of content for displaying this notification. The
+ * current notification forms the first page, and elements within this array form
+ * subsequent pages. This field can be used to separate a notification into multiple
+ * sections.
+ * @return the pages for this notification
+ */
+ public Notification[] getPages() {
+ return mPages;
+ }
+
+ /**
+ * Get a background image to be displayed behind the notification content.
+ * Contrary to the {@link Notification.BigPictureStyle}, this background
+ * will work with any notification style.
+ *
+ * @return the background image
+ * @see Builder#setBackground
+ */
+ public Bitmap getBackground() {
+ return mBackground;
+ }
+
+ /**
+ * Get an icon that goes with the content of this notification.
+ */
+ public int getContentIcon() {
+ return mContentIcon;
+ }
+
+ /**
+ * Get the gravity that the content icon should have within the notification display.
+ * Supported values include {@link Gravity#START} and {@link Gravity#END}. The default
+ * value is {@link android.view.Gravity#END}.
+ * @see #getContentIcon
+ */
+ public int getContentIconGravity() {
+ return mContentIconGravity;
+ }
+
+ /**
+ * Get the action index of an action from this notification to show as clickable with
+ * the content of this notification page. When the user clicks this notification page,
+ * this action will trigger. This action will no longer display separately from the
+ * notification content. The action's icon will display with optional subtext provided
+ * by the action's title.
+ *
+ * <p>If wearable specific actions are present, this index will apply to that list,
+ * otherwise it will apply to the main notification's actions list.
+ */
+ public int getContentAction() {
+ return mContentActionIndex;
+ }
+
+ /**
+ * Get the gravity that this notification should have within the available viewport space.
+ * Supported values include {@link Gravity#TOP}, {@link Gravity#CENTER_VERTICAL} and
+ * {@link android.view.Gravity#BOTTOM}. The default value is
+ * {@link android.view.Gravity#BOTTOM}.
+ */
+ public int getGravity() {
+ return mGravity;
+ }
+
+ /**
+ * Get the custom size preset for the display of this notification out of the available
+ * presets found in {@link WearableNotificationExtensions}, e.g. {@link #SIZE_LARGE}.
+ * <p>Some custom size presets are only applicable for custom display notifications created
+ * using {@link Builder#setDisplayIntent}. Check the documentation for the preset in question.
+ * See also {@link Builder#setCustomContentHeight} and {@link Builder#setCustomSizePreset}.
+ */
+ public int getCustomSizePreset() {
+ return mCustomSizePreset;
+ }
+
+ /**
+ * Get the custom height in pixels for the display of this notification's content.
+ * <p>This option is only available for custom display notifications created
+ * using {@link Builder#setDisplayIntent}. See also {@link Builder#setCustomSizePreset} and
+ * {@link Builder#setCustomContentHeight}.
+ */
+ public int getCustomContentHeight() {
+ return mCustomContentHeight;
+ }
+
+ /**
+ * Get whether the scrolling position for the contents of this notification should start
+ * at the bottom of the contents instead of the top when the contents are too long to
+ * display within the screen. Default is false (start scroll at the top).
+ */
+ public boolean getStartScrollBottom() {
+ return (mFlags & FLAG_START_SCROLL_BOTTOM) != 0;
+ }
+
+ /**
+ * Get whether the content intent is available when the wearable device is not connected
+ * to a companion device. The user can still trigger this intent when the wearable device is
+ * offline, but a visual hint will indicate that the content intent may not be available.
+ * Defaults to true.
+ */
+ public boolean getContentIntentAvailableOffline() {
+ return (mFlags & FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE) != 0;
+ }
+
+ /**
+ * Get a hint that this notification's icon should not be displayed.
+ * @return {@code true} if this icon should not be displayed, false otherwise.
+ * The default value is {@code false} if this was never set.
+ */
+ public boolean getHintHideIcon() {
+ return (mFlags & FLAG_HINT_HIDE_ICON) != 0;
+ }
+
+ /**
+ * Get a visual hint that only the background image of this notification should be
+ * displayed, and other semantic content should be hidden. This hint is only applicable
+ * to sub-pages added using {@link Builder#addPage}.
+ */
+ public boolean getHintShowBackgroundOnly() {
+ return (mFlags & FLAG_HINT_SHOW_BACKGROUND_ONLY) != 0;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeTypedArray(mActions, flags);
+ out.writeInt(mFlags);
+ out.writeParcelable(mDisplayIntent, flags);
+ out.writeTypedArray(mPages, flags);
+ out.writeParcelable(mBackground, flags);
+ out.writeInt(mContentIcon);
+ out.writeInt(mContentIconGravity);
+ out.writeInt(mContentActionIndex);
+ out.writeInt(mCustomSizePreset);
+ out.writeInt(mCustomContentHeight);
+ out.writeInt(mGravity);
+ }
+
+ /**
+ * Builder to apply wearable notification extensions to a {@link Notification.Builder}
+ * object.
+ *
+ * <p>You can chain the "set" methods for this builder in any order,
+ * but you must call the {@link #build} method and then the {@link Notification.Builder#apply}
+ * method to apply your extensions to a notification.
+ *
+ * <pre class="prettyprint">
+ * Notification notif = new Notification.Builder(mContext)
+ * .setContentTitle("New mail from " + sender.toString())
+ * .setContentText(subject)
+ * .setSmallIcon(R.drawable.new_mail);
+ * .apply(new WearableNotificationExtensions.Builder()
+ * .setContentIcon(R.drawable.new_mail)
+ * .build())
+ * .build();
+ * NotificationManager notificationManger =
+ * (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+ * notificationManager.notify(0, notif);</pre>
+ */
+ public static final class Builder {
+ private final List<Notification.Action> mActions =
+ new ArrayList<Notification.Action>();
+ private int mFlags = DEFAULT_FLAGS;
+ private PendingIntent mDisplayIntent;
+ private final List<Notification> mPages = new ArrayList<Notification>();
+ private Bitmap mBackground;
+ private int mContentIcon;
+ private int mContentIconGravity = Gravity.END;
+ private int mContentActionIndex = UNSET_ACTION_INDEX;
+ private int mCustomContentHeight;
+ private int mCustomSizePreset = SIZE_DEFAULT;
+ private int mGravity = Gravity.BOTTOM;
+
+ /**
+ * Construct a builder to be used for adding wearable extensions to notifications.
+ *
+ * <pre class="prettyprint">
+ * Notification notif = new Notification.Builder(mContext)
+ * .setContentTitle("New mail from " + sender.toString())
+ * .setContentText(subject)
+ * .setSmallIcon(R.drawable.new_mail);
+ * .apply(new WearableNotificationExtensions.Builder()
+ * .setContentIcon(R.drawable.new_mail)
+ * .build())
+ * .build();
+ * NotificationManager notificationManger =
+ * (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+ * notificationManager.notify(0, notif);</pre>
+ */
+ public Builder() {
+ }
+
+ /**
+ * Create a {@link Builder} by reading wearable extensions present on an
+ * existing {@code WearableNotificationExtensions} object.
+ * @param other the existing extensions to inspect.
+ */
+ public Builder(WearableNotificationExtensions other) {
+ Collections.addAll(mActions, other.mActions);
+ mFlags = other.mFlags;
+ mDisplayIntent = other.mDisplayIntent;
+ Collections.addAll(mPages, other.mPages);
+ mBackground = other.mBackground;
+ mContentIcon = other.mContentIcon;
+ mContentIconGravity = other.mContentIconGravity;
+ mContentActionIndex = other.mContentActionIndex;
+ mCustomContentHeight = other.mCustomContentHeight;
+ mCustomSizePreset = other.mCustomSizePreset;
+ mGravity = other.mGravity;
+ }
+
+ /**
+ * Add a wearable action to this notification.
+ *
+ * <p>When wearable actions are added using this method, the set of actions that
+ * show on a wearable device splits from devices that only show actions added
+ * using {@link android.app.Notification.Builder#addAction}. This allows for customization
+ * of which actions display on different devices.
+ *
+ * @param action the action to add to this notification
+ * @return this object for method chaining
+ * @see Notification.Action
+ */
+ public Builder addAction(Notification.Action action) {
+ mActions.add(action);
+ return this;
+ }
+
+ /**
+ * Adds wearable actions to this notification.
+ *
+ * <p>When wearable actions are added using this method, the set of actions that
+ * show on a wearable device splits from devices that only show actions added
+ * using {@link android.app.Notification.Builder#addAction}. This allows for customization
+ * of which actions display on different devices.
+ *
+ * @param actions the actions to add to this notification
+ * @return this object for method chaining
+ * @see Notification.Action
+ */
+ public Builder addActions(List<Notification.Action> actions) {
+ mActions.addAll(actions);
+ return this;
+ }
+
+ /**
+ * Clear all wearable actions present on this builder.
+ * @return this object for method chaining.
+ * @see #addAction
+ */
+ public Builder clearActions() {
+ mActions.clear();
+ return this;
+ }
+
+ /**
+ * Set an intent to launch inside of an activity view when displaying
+ * this notification. This {@link android.app.PendingIntent} should be for an activity.
+ *
+ * @param intent the {@link android.app.PendingIntent} for an activity
+ * @return this object for method chaining
+ * @see WearableNotificationExtensions#getDisplayIntent
+ */
+ public Builder setDisplayIntent(PendingIntent intent) {
+ mDisplayIntent = intent;
+ return this;
+ }
+
+ /**
+ * Add an additional page of content to display with this notification. The current
+ * notification forms the first page, and pages added using this function form
+ * subsequent pages. This field can be used to separate a notification into multiple
+ * sections.
+ *
+ * @param page the notification to add as another page
+ * @return this object for method chaining
+ * @see WearableNotificationExtensions#getPages
+ */
+ public Builder addPage(Notification page) {
+ mPages.add(page);
+ return this;
+ }
+
+ /**
+ * Add additional pages of content to display with this notification. The current
+ * notification forms the first page, and pages added using this function form
+ * subsequent pages. This field can be used to separate a notification into multiple
+ * sections.
+ *
+ * @param pages a list of notifications
+ * @return this object for method chaining
+ * @see WearableNotificationExtensions#getPages
+ */
+ public Builder addPages(List<Notification> pages) {
+ mPages.addAll(pages);
+ return this;
+ }
+
+ /**
+ * Clear all additional pages present on this builder.
+ * @return this object for method chaining.
+ * @see #addPage
+ */
+ public Builder clearPages() {
+ mPages.clear();
+ return this;
+ }
+
+ /**
+ * Set a background image to be displayed behind the notification content.
+ * Contrary to the {@link Notification.BigPictureStyle}, this background
+ * will work with any notification style.
+ *
+ * @param background the background bitmap
+ * @return this object for method chaining
+ * @see WearableNotificationExtensions#getBackground
+ */
+ public Builder setBackground(Bitmap background) {
+ mBackground = background;
+ return this;
+ }
+
+ /**
+ * Set an icon that goes with the content of this notification.
+ */
+ public Builder setContentIcon(int icon) {
+ mContentIcon = icon;
+ return this;
+ }
+
+ /**
+ * Set the gravity that the content icon should have within the notification display.
+ * Supported values include {@link Gravity#START} and {@link Gravity#END}. The default
+ * value is {@link android.view.Gravity#END}.
+ * @see #setContentIcon
+ */
+ public Builder setContentIconGravity(int contentIconGravity) {
+ mContentIconGravity = contentIconGravity;
+ return this;
+ }
+
+ /**
+ * Set an action from this notification's actions to be clickable with the content of
+ * this notification page. This action will no longer display separately from the
+ * notification content. This action's icon will display with optional subtext provided
+ * by the action's title.
+ * @param actionIndex The index of the action to hoist on the current notification page.
+ * If wearable actions are present, this index will apply to that list,
+ * otherwise it will apply to the main notification's actions list.
+ */
+ public Builder setContentAction(int actionIndex) {
+ mContentActionIndex = actionIndex;
+ return this;
+ }
+
+ /**
+ * Set the gravity that this notification should have within the available viewport space.
+ * Supported values include {@link Gravity#TOP}, {@link Gravity#CENTER_VERTICAL} and
+ * {@link Gravity#BOTTOM}. The default value is {@link Gravity#BOTTOM}.
+ */
+ public Builder setGravity(int gravity) {
+ mGravity = gravity;
+ return this;
+ }
+
+ /**
+ * Set the custom size preset for the display of this notification out of the available
+ * presets found in {@link WearableNotificationExtensions}, e.g. {@link #SIZE_LARGE}.
+ * <p>Some custom size presets are only applicable for custom display notifications created
+ * using {@link Builder#setDisplayIntent}. Check the documentation for the preset in
+ * question. See also {@link Builder#setCustomContentHeight} and
+ * {@link #getCustomSizePreset}.
+ */
+ public Builder setCustomSizePreset(int sizePreset) {
+ mCustomSizePreset = sizePreset;
+ return this;
+ }
+
+ /**
+ * Set the custom height in pixels for the display of this notification's content.
+ * <p>This option is only available for custom display notifications created
+ * using {@link Builder#setDisplayIntent}. See also {@link Builder#setCustomSizePreset} and
+ * {@link #getCustomContentHeight}.
+ */
+ public Builder setCustomContentHeight(int height) {
+ mCustomContentHeight = height;
+ return this;
+ }
+
+ /**
+ * Set whether the scrolling position for the contents of this notification should start
+ * at the bottom of the contents instead of the top when the contents are too long to
+ * display within the screen. Default is false (start scroll at the top).
+ */
+ public Builder setStartScrollBottom(boolean startScrollBottom) {
+ setFlag(FLAG_START_SCROLL_BOTTOM, startScrollBottom);
+ return this;
+ }
+
+ /**
+ * Set whether the content intent is available when the wearable device is not connected
+ * to a companion device. The user can still trigger this intent when the wearable device
+ * is offline, but a visual hint will indicate that the content intent may not be available.
+ * Defaults to true.
+ */
+ public Builder setContentIntentAvailableOffline(boolean contentIntentAvailableOffline) {
+ setFlag(FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE, contentIntentAvailableOffline);
+ return this;
+ }
+
+ /**
+ * Set a hint that this notification's icon should not be displayed.
+ * @param hintHideIcon {@code true} to hide the icon, {@code false} otherwise.
+ * @return this object for method chaining
+ */
+ public Builder setHintHideIcon(boolean hintHideIcon) {
+ setFlag(FLAG_HINT_HIDE_ICON, hintHideIcon);
+ return this;
+ }
+
+ /**
+ * Set a visual hint that only the background image of this notification should be
+ * displayed, and other semantic content should be hidden. This hint is only applicable
+ * to sub-pages added using {@link #addPage}.
+ */
+ public Builder setHintShowBackgroundOnly(boolean hintShowBackgroundOnly) {
+ setFlag(FLAG_HINT_SHOW_BACKGROUND_ONLY, hintShowBackgroundOnly);
+ return this;
+ }
+
+ /**
+ * Build a new {@link WearableNotificationExtensions} object with the extensions
+ * currently present on this builder.
+ * @return the extensions object.
+ */
+ public WearableNotificationExtensions build() {
+ return new WearableNotificationExtensions(
+ mActions.toArray(new Notification.Action[mActions.size()]), mFlags,
+ mDisplayIntent, mPages.toArray(new Notification[mPages.size()]),
+ mBackground, mContentIcon, mContentIconGravity, mContentActionIndex,
+ mCustomSizePreset, mCustomContentHeight, mGravity);
+ }
+
+ private void setFlag(int mask, boolean value) {
+ if (value) {
+ mFlags |= mask;
+ } else {
+ mFlags &= ~mask;
+ }
+ }
+ }
+
+ public static final Creator<WearableNotificationExtensions> CREATOR =
+ new Creator<WearableNotificationExtensions>() {
+ @Override
+ public WearableNotificationExtensions createFromParcel(Parcel in) {
+ return new WearableNotificationExtensions(in);
+ }
+
+ @Override
+ public WearableNotificationExtensions[] newArray(int size) {
+ return new WearableNotificationExtensions[size];
+ }
+ };
+}
diff --git a/core/java/android/bluetooth/BluetoothLeAdvertiseScanData.java b/core/java/android/bluetooth/BluetoothLeAdvertiseScanData.java
index 3d85810..2fa5e49 100644
--- a/core/java/android/bluetooth/BluetoothLeAdvertiseScanData.java
+++ b/core/java/android/bluetooth/BluetoothLeAdvertiseScanData.java
@@ -53,9 +53,6 @@
* Bluetooth LE scan response data, the data will be placed in ScanRspData field of advertising
* packet.
* <p>
- * TODO: unhide when stack supports setting scan response data.
- *
- * @hide
*/
public static final int SCAN_RESPONSE_DATA = 1;
/**
@@ -298,8 +295,7 @@
* Set data type.
*
* @param dataType Data type, could only be
- * {@link BluetoothLeAdvertiseScanData#ADVERTISING_DATA} or
- * {@link BluetoothLeAdvertiseScanData#SCAN_RESPONSE_DATA}
+ * {@link BluetoothLeAdvertiseScanData#ADVERTISING_DATA}
* @throws IllegalArgumentException If the {@code dataType} is invalid.
*/
public Builder dataType(int dataType) {
diff --git a/core/java/android/bluetooth/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/BluetoothLeAdvertiser.java
index 2a8aa23..30c90c4 100644
--- a/core/java/android/bluetooth/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/BluetoothLeAdvertiser.java
@@ -328,6 +328,7 @@
private static final int LE_CALLBACK_TIMEOUT_MILLIS = 2000;
private final AdvertiseCallback mAdvertiseCallback;
private final AdvertisementData mAdvertisement;
+ private final AdvertisementData mScanResponse;
private final Settings mSettings;
private final IBluetoothGatt mBluetoothGatt;
@@ -338,10 +339,11 @@
private boolean isAdvertising = false;
public AdvertiseCallbackWrapper(AdvertiseCallback advertiseCallback,
- AdvertisementData advertiseData, Settings settings,
+ AdvertisementData advertiseData, AdvertisementData scanResponse, Settings settings,
IBluetoothGatt bluetoothGatt) {
mAdvertiseCallback = advertiseCallback;
mAdvertisement = advertiseData;
+ mScanResponse = scanResponse;
mSettings = settings;
mBluetoothGatt = bluetoothGatt;
mLeHandle = 0;
@@ -384,7 +386,8 @@
if (status == BluetoothGatt.GATT_SUCCESS) {
mLeHandle = clientIf;
try {
- mBluetoothGatt.startMultiAdvertising(mLeHandle, mAdvertisement, mSettings);
+ mBluetoothGatt.startMultiAdvertising(mLeHandle, mAdvertisement,
+ mScanResponse, mSettings);
} catch (RemoteException e) {
Log.e(TAG, "fail to start le advertise: " + e);
mLeHandle = -1;
@@ -540,6 +543,19 @@
*/
public void startAdvertising(Settings settings,
AdvertisementData advertiseData, final AdvertiseCallback callback) {
+ startAdvertising(settings, advertiseData, null, callback);
+ }
+
+ /**
+ * Start Bluetooth LE Advertising.
+ * @param settings {@link Settings} for Bluetooth LE advertising.
+ * @param advertiseData {@link AdvertisementData} to be advertised in advertisement packet.
+ * @param scanResponse {@link AdvertisementData} for scan response.
+ * @param callback {@link AdvertiseCallback} for advertising status.
+ */
+ public void startAdvertising(Settings settings,
+ AdvertisementData advertiseData, AdvertisementData scanResponse,
+ final AdvertiseCallback callback) {
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");
}
@@ -548,8 +564,7 @@
return;
}
AdvertiseCallbackWrapper wrapper = new AdvertiseCallbackWrapper(callback, advertiseData,
- settings,
- mBluetoothGatt);
+ scanResponse, settings, mBluetoothGatt);
UUID uuid = UUID.randomUUID();
try {
mBluetoothGatt.registerClient(new ParcelUuid(uuid), wrapper);
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index 091b806..ceed52b 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -41,7 +41,9 @@
in BluetoothLeScanner.Settings settings,
in List<BluetoothLeScanFilter> filters);
void stopScan(in int appIf, in boolean isServer);
- void startMultiAdvertising(in int appIf, in BluetoothLeAdvertiseScanData.AdvertisementData data,
+ void startMultiAdvertising(in int appIf,
+ in BluetoothLeAdvertiseScanData.AdvertisementData advertiseData,
+ in BluetoothLeAdvertiseScanData.AdvertisementData scanResponse,
in BluetoothLeAdvertiser.Settings settings);
void stopMultiAdvertising(in int appIf);
void registerClient(in ParcelUuid appId, in IBluetoothGattCallback callback);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index c11b04c..9e02e4b 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2352,11 +2352,11 @@
/**
* Use with {@link #getSystemService} to retrieve a {@link
- * android.net.wifi.passpoint.PasspointManager} for handling management of
+ * android.net.wifi.passpoint.WifiPasspointManager} for handling management of
* Wi-Fi passpoint access.
*
* @see #getSystemService
- * @see android.net.wifi.passpoint.PasspointManager
+ * @see android.net.wifi.passpoint.WifiPasspointManager
*/
public static final String WIFI_PASSPOINT_SERVICE = "wifipasspoint";
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 0e2eab7..35bcc02 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1405,6 +1405,14 @@
public static final String FEATURE_MANAGEDPROFILES = "android.software.managedprofiles";
/**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+ * The device has a full implementation of the android.webkit.* APIs. Devices
+ * lacking this feature will not have a functioning WebView implementation.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_WEBVIEW = "android.software.webview";
+
+ /**
* Action to external storage service to clean out removed apps.
* @hide
*/
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 5674154..3f01dd2 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -64,7 +64,6 @@
* List Resource</a>.</p>
*/
public class ColorStateList implements Parcelable {
-
private int[][] mStateSpecs; // must be parallel to mColors
private int[] mColors; // must be parallel to mStateSpecs
private int mDefaultColor = 0xffff0000;
@@ -100,9 +99,9 @@
public static ColorStateList valueOf(int color) {
// TODO: should we collect these eventually?
synchronized (sCache) {
- WeakReference<ColorStateList> ref = sCache.get(color);
- ColorStateList csl = ref != null ? ref.get() : null;
+ final WeakReference<ColorStateList> ref = sCache.get(color);
+ ColorStateList csl = ref != null ? ref.get() : null;
if (csl != null) {
return csl;
}
@@ -118,8 +117,7 @@
*/
public static ColorStateList createFromXml(Resources r, XmlPullParser parser)
throws XmlPullParserException, IOException {
-
- AttributeSet attrs = Xml.asAttributeSet(parser);
+ final AttributeSet attrs = Xml.asAttributeSet(parser);
int type;
while ((type=parser.next()) != XmlPullParser.START_TAG
@@ -133,22 +131,22 @@
return createFromXmlInner(r, parser, attrs);
}
- /* Create from inside an XML document. Called on a parser positioned at
- * a tag in an XML document, tries to create a ColorStateList from that tag.
- * Returns null if the tag is not a valid ColorStateList.
+ /**
+ * Create from inside an XML document. Called on a parser positioned at a
+ * tag in an XML document, tries to create a ColorStateList from that tag.
+ *
+ * @throws XmlPullParserException if the current tag is not <selector>
+ * @return A color state list for the current tag.
*/
private static ColorStateList createFromXmlInner(Resources r, XmlPullParser parser,
AttributeSet attrs) throws XmlPullParserException, IOException {
-
- ColorStateList colorStateList;
-
+ final ColorStateList colorStateList;
final String name = parser.getName();
-
if (name.equals("selector")) {
colorStateList = new ColorStateList();
} else {
throw new XmlPullParserException(
- parser.getPositionDescription() + ": invalid drawable tag " + name);
+ parser.getPositionDescription() + ": invalid drawable tag " + name);
}
colorStateList.inflate(r, parser, attrs);
@@ -161,9 +159,8 @@
* (0-255).
*/
public ColorStateList withAlpha(int alpha) {
- int[] colors = new int[mColors.length];
-
- int len = colors.length;
+ final int[] colors = new int[mColors.length];
+ final int len = colors.length;
for (int i = 0; i < len; i++) {
colors[i] = (mColors[i] & 0xFFFFFF) | (alpha << 24);
}
@@ -176,7 +173,6 @@
*/
private void inflate(Resources r, XmlPullParser parser, AttributeSet attrs)
throws XmlPullParserException, IOException {
-
int type;
final int innerDepth = parser.getDepth()+1;
@@ -259,10 +255,25 @@
System.arraycopy(stateSpecList, 0, mStateSpecs, 0, listSize);
}
+ /**
+ * Indicates whether this color state list contains more than one state spec
+ * and will change color based on state.
+ *
+ * @return True if this color state list changes color based on state, false
+ * otherwise.
+ * @see #getColorForState(int[], int)
+ */
public boolean isStateful() {
return mStateSpecs.length > 1;
}
+ /**
+ * Indicates whether this color state list is opaque, which means that every
+ * color returned from {@link #getColorForState(int[], int)} has an alpha
+ * value of 255.
+ *
+ * @return True if this color state list is opaque.
+ */
public boolean isOpaque() {
final int n = mColors.length;
for (int i = 0; i < n; i++) {
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 1692a79..a78f8e2 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -21,6 +21,7 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import android.annotation.Nullable;
import android.content.pm.ActivityInfo;
import android.graphics.Movie;
import android.graphics.drawable.Drawable;
@@ -719,12 +720,12 @@
* @param id The desired resource identifier, as generated by the aapt
* tool. This integer encodes the package, type, and resource
* entry. The value 0 is an invalid identifier.
- * @param theme The theme used to style the drawable attributes.
+ * @param theme The theme used to style the drawable attributes, may be {@code null}.
* @return Drawable An object that can be used to draw this resource.
* @throws NotFoundException Throws NotFoundException if the given ID does
* not exist.
*/
- public Drawable getDrawable(int id, Theme theme) throws NotFoundException {
+ public Drawable getDrawable(int id, @Nullable Theme theme) throws NotFoundException {
TypedValue value;
synchronized (mAccessLock) {
value = mTmpValue;
@@ -777,12 +778,12 @@
* The value 0 is an invalid identifier.
* @param density The desired screen density indicated by the resource as
* found in {@link DisplayMetrics}.
- * @param theme The theme used to style the drawable attributes.
+ * @param theme The theme used to style the drawable attributes, may be {@code null}.
* @return Drawable An object that can be used to draw this resource.
* @throws NotFoundException Throws NotFoundException if the given ID does
* not exist.
*/
- public Drawable getDrawableForDensity(int id, int density, Theme theme) {
+ public Drawable getDrawableForDensity(int id, int density, @Nullable Theme theme) {
TypedValue value;
synchronized (mAccessLock) {
value = mTmpValue;
diff --git a/core/java/android/hardware/usb/UsbConfiguration.java b/core/java/android/hardware/usb/UsbConfiguration.java
index 92d6f75..da5c128 100644
--- a/core/java/android/hardware/usb/UsbConfiguration.java
+++ b/core/java/android/hardware/usb/UsbConfiguration.java
@@ -44,13 +44,13 @@
* Mask for "self-powered" bit in the configuration's attributes.
* @see #getAttributes
*/
- public static final int ATTR_SELF_POWERED_MASK = 1 << 6;
+ private static final int ATTR_SELF_POWERED = 1 << 6;
/**
* Mask for "remote wakeup" bit in the configuration's attributes.
* @see #getAttributes
*/
- public static final int ATTR_REMOTE_WAKEUP_MASK = 1 << 5;
+ private static final int ATTR_REMOTE_WAKEUP = 1 << 5;
/**
* UsbConfiguration should only be instantiated by UsbService implementation
@@ -83,19 +83,23 @@
}
/**
- * Returns the configuration's attributes field.
- * This field contains a bit field with the following flags:
+ * Returns the self-powered attribute value configuration's attributes field.
+ * This attribute indicates that the device has a power source other than the USB connection.
*
- * Bit 7: always set to 1
- * Bit 6: self-powered
- * Bit 5: remote wakeup enabled
- * Bit 0-4: reserved
- * @see #ATTR_SELF_POWERED_MASK
- * @see #ATTR_REMOTE_WAKEUP_MASK
- * @return the configuration's attributes
+ * @return the configuration's self-powered attribute
*/
- public int getAttributes() {
- return mAttributes;
+ public boolean isSelfPowered() {
+ return (mAttributes & ATTR_SELF_POWERED) != 0;
+ }
+
+ /**
+ * Returns the remote-wakeup attribute value configuration's attributes field.
+ * This attributes that the device may signal the host to wake from suspend.
+ *
+ * @return the configuration's remote-wakeup attribute
+ */
+ public boolean isRemoteWakeup() {
+ return (mAttributes & ATTR_REMOTE_WAKEUP) != 0;
}
/**
diff --git a/core/java/android/hardware/usb/UsbDeviceConnection.java b/core/java/android/hardware/usb/UsbDeviceConnection.java
index 6283951..c062b3a 100644
--- a/core/java/android/hardware/usb/UsbDeviceConnection.java
+++ b/core/java/android/hardware/usb/UsbDeviceConnection.java
@@ -104,7 +104,7 @@
* Sets the current {@link android.hardware.usb.UsbInterface}.
* Used to select between two interfaces with the same ID but different alternate setting.
*
- * @return true if the interface was successfully released
+ * @return true if the interface was successfully selected
*/
public boolean setInterface(UsbInterface intf) {
return native_set_interface(intf.getId(), intf.getAlternateSetting());
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 1837335..80a9598 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1655,9 +1655,16 @@
}
/** {@hide} */
- public void registerNetworkFactory(Messenger messenger) {
+ public void registerNetworkFactory(Messenger messenger, String name) {
try {
- mService.registerNetworkFactory(messenger);
+ mService.registerNetworkFactory(messenger, name);
+ } catch (RemoteException e) { }
+ }
+
+ /** {@hide} */
+ public void unregisterNetworkFactory(Messenger messenger) {
+ try {
+ mService.unregisterNetworkFactory(messenger);
} catch (RemoteException e) { }
}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 885b8b6..d97b1e9 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -153,7 +153,9 @@
void setAirplaneMode(boolean enable);
- void registerNetworkFactory(in Messenger messenger);
+ void registerNetworkFactory(in Messenger messenger, in String name);
+
+ void unregisterNetworkFactory(in Messenger messenger);
void registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp,
in NetworkCapabilities nc, int score);
diff --git a/core/java/android/net/IpConfiguration.java b/core/java/android/net/IpConfiguration.java
new file mode 100644
index 0000000..4730bab
--- /dev/null
+++ b/core/java/android/net/IpConfiguration.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.net.LinkProperties;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * A class representing a configured network.
+ * @hide
+ */
+public class IpConfiguration implements Parcelable {
+ private static final String TAG = "IpConfiguration";
+
+ public enum IpAssignment {
+ /* Use statically configured IP settings. Configuration can be accessed
+ * with linkProperties */
+ STATIC,
+ /* Use dynamically configured IP settigns */
+ DHCP,
+ /* no IP details are assigned, this is used to indicate
+ * that any existing IP settings should be retained */
+ UNASSIGNED
+ }
+
+ public IpAssignment ipAssignment;
+
+ public enum ProxySettings {
+ /* No proxy is to be used. Any existing proxy settings
+ * should be cleared. */
+ NONE,
+ /* Use statically configured proxy. Configuration can be accessed
+ * with linkProperties */
+ STATIC,
+ /* no proxy details are assigned, this is used to indicate
+ * that any existing proxy settings should be retained */
+ UNASSIGNED,
+ /* Use a Pac based proxy.
+ */
+ PAC
+ }
+
+ public ProxySettings proxySettings;
+
+ public LinkProperties linkProperties;
+
+ public IpConfiguration(IpConfiguration source) {
+ if (source != null) {
+ ipAssignment = source.ipAssignment;
+ proxySettings = source.proxySettings;
+ linkProperties = new LinkProperties(source.linkProperties);
+ } else {
+ ipAssignment = IpAssignment.UNASSIGNED;
+ proxySettings = ProxySettings.UNASSIGNED;
+ linkProperties = new LinkProperties();
+ }
+ }
+
+ public IpConfiguration() {
+ this(null);
+ }
+
+ public IpConfiguration(IpAssignment ipAssignment,
+ ProxySettings proxySettings,
+ LinkProperties linkProperties) {
+ this.ipAssignment = ipAssignment;
+ this.proxySettings = proxySettings;
+ this.linkProperties = new LinkProperties(linkProperties);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sbuf = new StringBuilder();
+ sbuf.append("IP assignment: " + ipAssignment.toString());
+ sbuf.append("\n");
+ sbuf.append("Proxy settings: " + proxySettings.toString());
+ sbuf.append("\n");
+ sbuf.append(linkProperties.toString());
+ sbuf.append("\n");
+
+ return sbuf.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+
+ if (!(o instanceof IpConfiguration)) {
+ return false;
+ }
+
+ IpConfiguration other = (IpConfiguration) o;
+ return this.ipAssignment == other.ipAssignment &&
+ this.proxySettings == other.proxySettings &&
+ Objects.equals(this.linkProperties, other.linkProperties);
+ }
+
+ @Override
+ public int hashCode() {
+ return 13 + (linkProperties != null ? linkProperties.hashCode() : 0) +
+ 17 * ipAssignment.ordinal() +
+ 47 * proxySettings.ordinal();
+ }
+
+ /** Implement the Parcelable interface */
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface */
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(ipAssignment.name());
+ dest.writeString(proxySettings.name());
+ dest.writeParcelable(linkProperties, flags);
+ }
+
+ /** Implement the Parcelable interface */
+ public static final Creator<IpConfiguration> CREATOR =
+ new Creator<IpConfiguration>() {
+ public IpConfiguration createFromParcel(Parcel in) {
+ IpConfiguration config = new IpConfiguration();
+ config.ipAssignment = IpAssignment.valueOf(in.readString());
+ config.proxySettings = ProxySettings.valueOf(in.readString());
+ config.linkProperties = in.readParcelable(null);
+ return config;
+ }
+
+ public IpConfiguration[] newArray(int size) {
+ return new IpConfiguration[size];
+ }
+ };
+}
diff --git a/core/java/android/net/ProxyInfo.java b/core/java/android/net/ProxyInfo.java
index ceedd98..7ea6bae 100644
--- a/core/java/android/net/ProxyInfo.java
+++ b/core/java/android/net/ProxyInfo.java
@@ -155,9 +155,6 @@
mHost = source.getHost();
mPort = source.getPort();
mPacFileUrl = source.mPacFileUrl;
- if (mPacFileUrl == null) {
- mPacFileUrl = Uri.EMPTY;
- }
mExclusionList = source.getExclusionListAsString();
mParsedExclusionList = source.mParsedExclusionList;
} else {
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index 635a50f..9218c11 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -25,7 +25,6 @@
import android.nfc.INfcAdapterExtras;
import android.nfc.INfcTag;
import android.nfc.INfcCardEmulation;
-import android.nfc.INfcUnlockSettings;
import android.os.Bundle;
/**
@@ -36,7 +35,6 @@
INfcTag getNfcTagInterface();
INfcCardEmulation getNfcCardEmulationInterface();
INfcAdapterExtras getNfcAdapterExtrasInterface(in String pkg);
- INfcUnlockSettings getNfcUnlockSettingsInterface();
int getState();
boolean disable(boolean saveState);
diff --git a/core/java/android/nfc/INfcUnlockSettings.aidl b/core/java/android/nfc/INfcUnlockSettings.aidl
deleted file mode 100644
index 649eeed..0000000
--- a/core/java/android/nfc/INfcUnlockSettings.aidl
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2013 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.nfc;
-
-import android.nfc.Tag;
-import java.util.List;
-
-/**
- * Interface to NFC unlock functionality.
- *
- * @hide
- */
-interface INfcUnlockSettings {
-
- /**
- * Checks the validity of the tag and attempts to unlock the screen.
- *
- * @return true if the screen was successfuly unlocked.
- */
- boolean tryUnlock(int userId, in Tag tag);
-
- /**
- * Registers the given tag as an unlock tag. Subsequent calls to {@code tryUnlock}
- * with the same {@code tag} should succeed.
- *
- * @return true if the tag was successfully registered.
- */
- boolean registerTag(int userId, in Tag tag);
-
- /**
- * Deregisters the tag with the corresponding timestamp.
- * Subsequent calls to {@code tryUnlock} with the same tag should fail.
- *
- * @return true if the tag was successfully deleted.
- */
- boolean deregisterTag(int userId, long timestamp);
-
- /**
- * Used for user-visible rendering of registered tags.
- *
- * @return a list of the times in millis since epoch when the registered tags were paired.
- */
- long[] getTagRegistryTimes(int userId);
-
- /**
- * Determines the state of the NFC unlock feature.
- *
- * @return true if NFC unlock is enabled.
- */
- boolean getNfcUnlockEnabled(int userId);
-
- /**
- * Sets the state [ON | OFF] of the NFC unlock feature.
- */
- void setNfcUnlockEnabled(int userId, boolean enabled);
-}
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 96a3947..dd8e41c 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -292,7 +292,6 @@
static INfcAdapter sService;
static INfcTag sTagService;
static INfcCardEmulation sCardEmulationService;
- static INfcUnlockSettings sNfcUnlockSettingsService;
/**
* The NfcAdapter object for each application context.
@@ -433,13 +432,6 @@
throw new UnsupportedOperationException();
}
- try {
- sNfcUnlockSettingsService = sService.getNfcUnlockSettingsInterface();
- } catch (RemoteException e) {
- Log.e(TAG, "could not retrieve NFC unlock settings service");
- sNfcUnlockSettingsService = null;
- }
-
sIsInitialized = true;
}
if (context == null) {
@@ -557,22 +549,6 @@
}
/**
- * Returns the binder interface to the NFC unlock service.
- *
- * @throws UnsupportedOperationException if the service is not available.
- * @hide
- */
- public INfcUnlockSettings getNfcUnlockSettingsService() throws UnsupportedOperationException {
- isEnabled();
-
- if (sNfcUnlockSettingsService == null) {
- throw new UnsupportedOperationException("NfcUnlockSettingsService not available");
- }
-
- return sNfcUnlockSettingsService;
- }
-
- /**
* NFC service dead - attempt best effort recovery
* @hide
*/
diff --git a/core/java/android/nfc/NfcUnlock.java b/core/java/android/nfc/NfcUnlock.java
deleted file mode 100644
index 82dcd96..0000000
--- a/core/java/android/nfc/NfcUnlock.java
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Copyright (C) 2013 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.nfc;
-
-import static com.android.internal.util.Preconditions.checkNotNull;
-
-import android.annotation.Nullable;
-import android.app.ActivityManager;
-import android.content.Context;
-import android.os.RemoteException;
-import android.os.SystemProperties;
-import android.util.Log;
-
-import java.util.HashMap;
-
-/**
- * Provides an interface to read and update NFC unlock settings.
- * <p/>
- * Allows system services (currently exclusively LockSettingsService) to
- * register NFC tags to be used to unlock the device, as well as the ability
- * to enable/disable the service entirely.
- *
- */
-public class NfcUnlock {
-
- /**
- * Action to unlock the device.
- *
- * @hide
- */
- public static final String ACTION_NFC_UNLOCK = "android.nfc.ACTION_NFC_UNLOCK";
- /**
- * Permission to unlock the device.
- *
- * @hide
- */
- public static final String NFC_UNLOCK_PERMISSION = "android.permission.NFC_UNLOCK";
-
- /**
- * Property to enable NFC Unlock
- *
- * @hide
- */
- public static final String PROPERTY = "ro.com.android.nfc.unlock";
-
- private static final String TAG = "NfcUnlock";
- private static HashMap<Context, NfcUnlock> sNfcUnlocks = new HashMap<Context, NfcUnlock>();
-
- private final Context mContext;
- private final boolean mEnabled;
- private INfcUnlockSettings sService;
-
- private NfcUnlock(Context context, INfcUnlockSettings service) {
- this.mContext = checkNotNull(context);
- this.sService = checkNotNull(service);
- this.mEnabled = getPropertyEnabled();
- }
-
- /**
- * Returns an instance of {@link NfcUnlock}.
- */
- public static synchronized NfcUnlock getInstance(NfcAdapter nfcAdapter) {
- Context context = nfcAdapter.getContext();
- if (context == null) {
- Log.e(TAG, "NfcAdapter context is null");
- throw new UnsupportedOperationException();
- }
-
- NfcUnlock manager = sNfcUnlocks.get(context);
- if (manager == null) {
- INfcUnlockSettings service = nfcAdapter.getNfcUnlockSettingsService();
- manager = new NfcUnlock(context, service);
- sNfcUnlocks.put(context, manager);
- }
-
- return manager;
- }
-
- /**
- * Registers the given {@code tag} as an unlock tag.
- *
- * @return true if the tag was successfully registered.
- * @hide
- */
- public boolean registerTag(Tag tag) {
- enforcePropertyEnabled();
-
- int currentUser = ActivityManager.getCurrentUser();
-
- try {
- return sService.registerTag(currentUser, tag);
- } catch (RemoteException e) {
- recoverService();
- if (sService == null) {
- Log.e(TAG, "Failed to recover NfcUnlockSettingsService");
- return false;
- }
-
- try {
- return sService.registerTag(currentUser, tag);
- } catch (RemoteException ee) {
- Log.e(TAG, "Failed to reach NfcUnlockSettingsService", ee);
- return false;
- }
- }
- }
-
- /**
- * Deregisters the given {@code tag} as an unlock tag.
- *
- * @return true if the tag was successfully deregistered.
- * @hide
- */
- public boolean deregisterTag(long timestamp) {
- enforcePropertyEnabled();
- int currentUser = ActivityManager.getCurrentUser();
-
- try {
- return sService.deregisterTag(currentUser, timestamp);
- } catch (RemoteException e) {
- recoverService();
- if (sService == null) {
- Log.e(TAG, "Failed to recover NfcUnlockSettingsService");
- return false;
- }
-
- try {
- return sService.deregisterTag(currentUser, timestamp);
- } catch (RemoteException ee) {
- Log.e(TAG, "Failed to reach NfcUnlockSettingsService", ee);
- return false;
- }
- }
- }
-
- /**
- * Determines the enable state of the NFC unlock feature.
- *
- * @return true if NFC unlock is enabled.
- */
- public boolean getNfcUnlockEnabled() {
- enforcePropertyEnabled();
- int currentUser = ActivityManager.getCurrentUser();
-
- try {
- return sService.getNfcUnlockEnabled(currentUser);
- } catch (RemoteException e) {
- recoverService();
- if (sService == null) {
- Log.e(TAG, "Failed to recover NfcUnlockSettingsService");
- return false;
- }
-
- try {
- return sService.getNfcUnlockEnabled(currentUser);
- } catch (RemoteException ee) {
- Log.e(TAG, "Failed to reach NfcUnlockSettingsService", ee);
- return false;
- }
- }
- }
-
- /**
- * Set the enable state of the NFC unlock feature.
- *
- * @return true if the setting was successfully persisted.
- * @hide
- */
- public boolean setNfcUnlockEnabled(boolean enabled) {
- enforcePropertyEnabled();
- int currentUser = ActivityManager.getCurrentUser();
-
- try {
- sService.setNfcUnlockEnabled(currentUser, enabled);
- return true;
- } catch (RemoteException e) {
- recoverService();
- if (sService == null) {
- Log.e(TAG, "Failed to recover NfcUnlockSettingsService");
- return false;
- }
-
- try {
- sService.setNfcUnlockEnabled(currentUser, enabled);
- return true;
- } catch (RemoteException ee) {
- Log.e(TAG, "Failed to reach NfcUnlockSettingsService", ee);
- return false;
- }
-
- }
- }
-
- /**
- * Returns a list of times (in millis since epoch) corresponding to when
- * unlock tags were registered.
- *
- * @hide
- */
- @Nullable
- public long[] getTagRegistryTimes() {
- enforcePropertyEnabled();
- int currentUser = ActivityManager.getCurrentUser();
-
- try {
- return sService.getTagRegistryTimes(currentUser);
- } catch (RemoteException e) {
- recoverService();
- if (sService == null) {
- Log.e(TAG, "Failed to recover NfcUnlockSettingsService");
- return null;
- }
-
- try {
- return sService.getTagRegistryTimes(currentUser);
- } catch (RemoteException ee) {
- Log.e(TAG, "Failed to reach NfcUnlockSettingsService", ee);
- return null;
- }
- }
- }
-
- /**
- * @hide
- */
- public static boolean getPropertyEnabled() {
- return SystemProperties.get(PROPERTY).equals("ON");
- }
-
- private void recoverService() {
- NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
- sService = adapter.getNfcUnlockSettingsService();
- }
-
-
- private void enforcePropertyEnabled() {
- if (!mEnabled) {
- throw new UnsupportedOperationException("NFC Unlock property is not enabled");
- }
- }
-}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 312cdbe..ee219e3 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -266,6 +266,17 @@
*/
public static final String DISALLOW_ADJUST_VOLUME = "no_adjust_volume";
+ /**
+ * Key for user restrictions. Specifies that the user is not allowed to send or receive
+ * phone calls or text messages. Emergency calls may still be permitted.
+ * The default value is <code>false</code>.
+ * <p/>
+ * Type: Boolean
+ * @see #setUserRestrictions(Bundle)
+ * @see #getUserRestrictions()
+ */
+ public static final String DISALLOW_TELEPHONY = "no_telephony";
+
/** @hide */
public static final int PIN_VERIFICATION_FAILED_INCORRECT = -3;
/** @hide */
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 2d03e1d..e9ffc52 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3477,11 +3477,6 @@
public static final String LOCK_PATTERN_VISIBLE = "lock_pattern_visible_pattern";
/**
- * Whether the NFC unlock feature is enabled (0 = false, 1 = true)
- */
- public static final String NFC_UNLOCK_ENABLED = "nfc_unlock_enabled";
-
- /**
* Whether lock pattern will vibrate as user enters (0 = false, 1 =
* true)
*
diff --git a/core/java/android/service/fingerprint/FingerprintManager.java b/core/java/android/service/fingerprint/FingerprintManager.java
index 0d14c59..2fcec52 100644
--- a/core/java/android/service/fingerprint/FingerprintManager.java
+++ b/core/java/android/service/fingerprint/FingerprintManager.java
@@ -18,6 +18,7 @@
import android.app.ActivityManagerNative;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
@@ -25,6 +26,7 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.provider.Settings;
import android.util.Log;
/**
@@ -33,7 +35,7 @@
public class FingerprintManager {
private static final String TAG = "FingerprintManager";
- protected static final boolean DEBUG = true;
+ private static final boolean DEBUG = true;
private static final String FINGERPRINT_SERVICE_PACKAGE = "com.android.service.fingerprint";
private static final String FINGERPRINT_SERVICE_CLASS =
"com.android.service.fingerprint.FingerprintService";
@@ -58,6 +60,7 @@
private IFingerprintService mService;
private FingerprintManagerReceiver mClientReceiver;
+ private Context mContext;
private Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
@@ -80,6 +83,7 @@
};
public FingerprintManager(Context context) {
+ mContext = context;
// Connect to service...
Intent intent = new Intent();
intent.setClassName(FINGERPRINT_SERVICE_PACKAGE, FINGERPRINT_SERVICE_CLASS);
@@ -129,6 +133,17 @@
};
/**
+ * Determine whether the user has at least one fingerprint enrolled and enabled.
+ *
+ * @return true if at least one is enrolled and enabled
+ */
+ public boolean enrolledAndEnabled() {
+ ContentResolver res = mContext.getContentResolver();
+ return Settings.Secure.getInt(res, "fingerprint_enabled", 0) != 0
+ && FingerprintUtils.getFingerprintIdsForUser(res, getCurrentUserId()).length > 0;
+ }
+
+ /**
* Start the enrollment process. Timeout dictates how long to wait for the user to
* enroll a fingerprint.
*
diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index d4919eb..b3705d8 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -17,15 +17,15 @@
package android.service.notification;
import android.service.notification.StatusBarNotification;
-import android.service.notification.NotificationOrderUpdate;
+import android.service.notification.NotificationRankingUpdate;
/** @hide */
oneway interface INotificationListener
{
- void onListenerConnected(in NotificationOrderUpdate update);
+ void onListenerConnected(in NotificationRankingUpdate update);
void onNotificationPosted(in StatusBarNotification notification,
- in NotificationOrderUpdate update);
+ in NotificationRankingUpdate update);
void onNotificationRemoved(in StatusBarNotification notification,
- in NotificationOrderUpdate update);
- void onNotificationOrderUpdate(in NotificationOrderUpdate update);
+ in NotificationRankingUpdate update);
+ void onNotificationRankingUpdate(in NotificationRankingUpdate update);
}
\ No newline at end of file
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index e2e9ff4..7f84877 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -24,12 +24,15 @@
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
/**
- * A service that receives calls from the system when new notifications are posted or removed.
+ * A service that receives calls from the system when new notifications are
+ * posted or removed, or their ranking changed.
* <p>To extend this class, you must declare the service in your manifest file with
* the {@link android.Manifest.permission#BIND_NOTIFICATION_LISTENER_SERVICE} permission
* and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
@@ -48,7 +51,7 @@
+ "[" + getClass().getSimpleName() + "]";
private INotificationListenerWrapper mWrapper = null;
- private String[] mNotificationKeys;
+ private Ranking mRanking;
private INotificationManager mNoMan;
@@ -102,11 +105,11 @@
}
/**
- * Implement this method to be notified when the notification order cahnges.
- *
- * Call {@link #getOrderedNotificationKeys()} to retrieve the new order.
+ * Implement this method to be notified when the notification ranking changes.
+ * <P>
+ * Call {@link #getCurrentRanking()} to retrieve the new ranking.
*/
- public void onNotificationOrderUpdate() {
+ public void onNotificationRankingUpdate() {
// optional
}
@@ -224,6 +227,19 @@
}
/**
+ * Request the list of notification keys in their current ranking order.
+ * <p>
+ * You can use the notification keys for subsequent retrieval via
+ * {@link #getActiveNotifications(String[]) or dismissal via
+ * {@link #cancelNotifications(String[]).
+ *
+ * @return An array of active notification keys, in their ranking order.
+ */
+ public String[] getActiveNotificationKeys() {
+ return mRanking.getOrderedKeys();
+ }
+
+ /**
* Request the list of outstanding notifications (that is, those that are visible to the
* current user). Useful when you don't know what's already been posted.
*
@@ -242,15 +258,20 @@
}
/**
- * Request the list of notification keys in their current natural order.
- * You can use the notification keys for subsequent retrieval via
- * {@link #getActiveNotifications(String[]) or dismissal via
- * {@link #cancelNotifications(String[]).
+ * Returns current ranking information.
*
- * @return An array of active notification keys, in their natural order.
+ * <p>
+ * The returned object represents the current ranking snapshot and only
+ * applies for currently active notifications. Hence you must retrieve a
+ * new Ranking after each notification event such as
+ * {@link #onNotificationPosted(StatusBarNotification)},
+ * {@link #onNotificationRemoved(StatusBarNotification)}, etc.
+ *
+ * @return A {@link NotificationListenerService.Ranking} object providing
+ * access to ranking information
*/
- public String[] getOrderedNotificationKeys() {
- return mNotificationKeys;
+ public Ranking getCurrentRanking() {
+ return mRanking;
}
@Override
@@ -308,59 +329,163 @@
private class INotificationListenerWrapper extends INotificationListener.Stub {
@Override
public void onNotificationPosted(StatusBarNotification sbn,
- NotificationOrderUpdate update) {
- try {
- // protect subclass from concurrent modifications of (@link mNotificationKeys}.
- synchronized (mWrapper) {
- updateNotificationKeys(update);
+ NotificationRankingUpdate update) {
+ // protect subclass from concurrent modifications of (@link mNotificationKeys}.
+ synchronized (mWrapper) {
+ applyUpdate(update);
+ try {
NotificationListenerService.this.onNotificationPosted(sbn);
+ } catch (Throwable t) {
+ Log.w(TAG, "Error running onNotificationPosted", t);
}
- } catch (Throwable t) {
- Log.w(TAG, "Error running onOrderedNotificationPosted", t);
}
}
@Override
public void onNotificationRemoved(StatusBarNotification sbn,
- NotificationOrderUpdate update) {
- try {
- // protect subclass from concurrent modifications of (@link mNotificationKeys}.
- synchronized (mWrapper) {
- updateNotificationKeys(update);
+ NotificationRankingUpdate update) {
+ // protect subclass from concurrent modifications of (@link mNotificationKeys}.
+ synchronized (mWrapper) {
+ applyUpdate(update);
+ try {
NotificationListenerService.this.onNotificationRemoved(sbn);
+ } catch (Throwable t) {
+ Log.w(TAG, "Error running onNotificationRemoved", t);
}
- } catch (Throwable t) {
- Log.w(TAG, "Error running onNotificationRemoved", t);
}
}
@Override
- public void onListenerConnected(NotificationOrderUpdate update) {
- try {
- // protect subclass from concurrent modifications of (@link mNotificationKeys}.
- synchronized (mWrapper) {
- updateNotificationKeys(update);
- NotificationListenerService.this.onListenerConnected(mNotificationKeys);
+ public void onListenerConnected(NotificationRankingUpdate update) {
+ // protect subclass from concurrent modifications of (@link mNotificationKeys}.
+ synchronized (mWrapper) {
+ applyUpdate(update);
+ try {
+ NotificationListenerService.this.onListenerConnected(
+ mRanking.getOrderedKeys());
+ } catch (Throwable t) {
+ Log.w(TAG, "Error running onListenerConnected", t);
}
- } catch (Throwable t) {
- Log.w(TAG, "Error running onListenerConnected", t);
}
}
@Override
- public void onNotificationOrderUpdate(NotificationOrderUpdate update)
+ public void onNotificationRankingUpdate(NotificationRankingUpdate update)
throws RemoteException {
- try {
- // protect subclass from concurrent modifications of (@link mNotificationKeys}.
- synchronized (mWrapper) {
- updateNotificationKeys(update);
- NotificationListenerService.this.onNotificationOrderUpdate();
+ // protect subclass from concurrent modifications of (@link mNotificationKeys}.
+ synchronized (mWrapper) {
+ applyUpdate(update);
+ try {
+ NotificationListenerService.this.onNotificationRankingUpdate();
+ } catch (Throwable t) {
+ Log.w(TAG, "Error running onNotificationRankingUpdate", t);
}
- } catch (Throwable t) {
- Log.w(TAG, "Error running onNotificationOrderUpdate", t);
}
}
}
- private void updateNotificationKeys(NotificationOrderUpdate update) {
- // TODO: avoid garbage by comparing the lists
- mNotificationKeys = update.getOrderedKeys();
+ private void applyUpdate(NotificationRankingUpdate update) {
+ mRanking = new Ranking(update);
+ }
+
+ /**
+ * Provides access to ranking information on currently active
+ * notifications.
+ *
+ * <p>
+ * Note that this object represents a ranking snapshot that only applies to
+ * notifications active at the time of retrieval.
+ */
+ public static class Ranking implements Parcelable {
+ private final NotificationRankingUpdate mRankingUpdate;
+
+ private Ranking(NotificationRankingUpdate rankingUpdate) {
+ mRankingUpdate = rankingUpdate;
+ }
+
+ /**
+ * Request the list of notification keys in their current ranking
+ * order.
+ *
+ * @return An array of active notification keys, in their ranking order.
+ */
+ public String[] getOrderedKeys() {
+ return mRankingUpdate.getOrderedKeys();
+ }
+
+ /**
+ * Returns the rank of the notification with the given key, that is the
+ * index of <code>key</code> in the array of keys returned by
+ * {@link #getOrderedKeys()}.
+ *
+ * @return The rank of the notification with the given key; -1 when the
+ * given key is unknown.
+ */
+ public int getIndexOfKey(String key) {
+ // TODO: Optimize.
+ String[] orderedKeys = mRankingUpdate.getOrderedKeys();
+ for (int i = 0; i < orderedKeys.length; i++) {
+ if (orderedKeys[i].equals(key)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns whether the notification with the given key was intercepted
+ * by "Do not disturb".
+ */
+ public boolean isInterceptedByDoNotDisturb(String key) {
+ // TODO: Optimize.
+ for (String interceptedKey : mRankingUpdate.getDndInterceptedKeys()) {
+ if (interceptedKey.equals(key)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns whether the notification with the given key is an ambient
+ * notification, that is a notification that doesn't require the user's
+ * immediate attention.
+ */
+ public boolean isAmbient(String key) {
+ // TODO: Optimize.
+ int firstAmbientIndex = mRankingUpdate.getFirstAmbientIndex();
+ if (firstAmbientIndex < 0) {
+ return false;
+ }
+ String[] orderedKeys = mRankingUpdate.getOrderedKeys();
+ for (int i = firstAmbientIndex; i < orderedKeys.length; i++) {
+ if (orderedKeys[i].equals(key)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // ----------- Parcelable
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(mRankingUpdate, flags);
+ }
+
+ public static final Creator<Ranking> CREATOR = new Creator<Ranking>() {
+ @Override
+ public Ranking createFromParcel(Parcel source) {
+ NotificationRankingUpdate rankingUpdate = source.readParcelable(null);
+ return new Ranking(rankingUpdate);
+ }
+
+ @Override
+ public Ranking[] newArray(int size) {
+ return new Ranking[size];
+ }
+ };
}
}
diff --git a/core/java/android/service/notification/NotificationOrderUpdate.java b/core/java/android/service/notification/NotificationOrderUpdate.java
deleted file mode 100644
index 20e19a3..0000000
--- a/core/java/android/service/notification/NotificationOrderUpdate.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.service.notification;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-public class NotificationOrderUpdate implements Parcelable {
- // TODO replace this with an update instead of the whole array
- private final String[] mKeys;
-
- /** @hide */
- public NotificationOrderUpdate(String[] keys) {
- this.mKeys = keys;
- }
-
- public NotificationOrderUpdate(Parcel in) {
- this.mKeys = in.readStringArray();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeStringArray(this.mKeys);
- }
-
- public static final Parcelable.Creator<NotificationOrderUpdate> CREATOR
- = new Parcelable.Creator<NotificationOrderUpdate>() {
- public NotificationOrderUpdate createFromParcel(Parcel parcel) {
- return new NotificationOrderUpdate(parcel);
- }
-
- public NotificationOrderUpdate[] newArray(int size) {
- return new NotificationOrderUpdate[size];
- }
- };
-
- /**
- * @hide
- * @return ordered list of keys
- */
- String[] getOrderedKeys() {
- return mKeys;
- }
-}
diff --git a/core/java/android/service/notification/NotificationOrderUpdate.aidl b/core/java/android/service/notification/NotificationRankingUpdate.aidl
similarity index 94%
rename from core/java/android/service/notification/NotificationOrderUpdate.aidl
rename to core/java/android/service/notification/NotificationRankingUpdate.aidl
index 5d50641..1393cb9 100644
--- a/core/java/android/service/notification/NotificationOrderUpdate.aidl
+++ b/core/java/android/service/notification/NotificationRankingUpdate.aidl
@@ -16,4 +16,4 @@
package android.service.notification;
-parcelable NotificationOrderUpdate;
+parcelable NotificationRankingUpdate;
diff --git a/core/java/android/service/notification/NotificationRankingUpdate.java b/core/java/android/service/notification/NotificationRankingUpdate.java
new file mode 100644
index 0000000..4b13d95
--- /dev/null
+++ b/core/java/android/service/notification/NotificationRankingUpdate.java
@@ -0,0 +1,77 @@
+/*
+ * 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.service.notification;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * @hide
+ */
+public class NotificationRankingUpdate implements Parcelable {
+ // TODO: Support incremental updates.
+ private final String[] mKeys;
+ private final String[] mDndInterceptedKeys;
+ private final int mFirstAmbientIndex;
+
+ public NotificationRankingUpdate(String[] keys, String[] dndInterceptedKeys,
+ int firstAmbientIndex) {
+ mKeys = keys;
+ mFirstAmbientIndex = firstAmbientIndex;
+ mDndInterceptedKeys = dndInterceptedKeys;
+ }
+
+ public NotificationRankingUpdate(Parcel in) {
+ mKeys = in.readStringArray();
+ mFirstAmbientIndex = in.readInt();
+ mDndInterceptedKeys = in.readStringArray();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeStringArray(mKeys);
+ out.writeInt(mFirstAmbientIndex);
+ out.writeStringArray(mDndInterceptedKeys);
+ }
+
+ public static final Parcelable.Creator<NotificationRankingUpdate> CREATOR
+ = new Parcelable.Creator<NotificationRankingUpdate>() {
+ public NotificationRankingUpdate createFromParcel(Parcel parcel) {
+ return new NotificationRankingUpdate(parcel);
+ }
+
+ public NotificationRankingUpdate[] newArray(int size) {
+ return new NotificationRankingUpdate[size];
+ }
+ };
+
+ public String[] getOrderedKeys() {
+ return mKeys;
+ }
+
+ public int getFirstAmbientIndex() {
+ return mFirstAmbientIndex;
+ }
+
+ public String[] getDndInterceptedKeys() {
+ return mDndInterceptedKeys;
+ }
+}
diff --git a/core/java/android/text/method/QwertyKeyListener.java b/core/java/android/text/method/QwertyKeyListener.java
index 0bd46bc..b17f502 100644
--- a/core/java/android/text/method/QwertyKeyListener.java
+++ b/core/java/android/text/method/QwertyKeyListener.java
@@ -115,7 +115,7 @@
if (count > 0 && selStart == selEnd && selStart > 0) {
char c = content.charAt(selStart - 1);
- if (c == i || c == Character.toUpperCase(i) && view != null) {
+ if ((c == i || c == Character.toUpperCase(i)) && view != null) {
if (showCharacterPicker(view, content, c, false, count)) {
resetMetaState(content);
return true;
diff --git a/core/java/android/tv/TvInputManager.java b/core/java/android/tv/TvInputManager.java
index c5f179a..dfa84f8 100644
--- a/core/java/android/tv/TvInputManager.java
+++ b/core/java/android/tv/TvInputManager.java
@@ -414,8 +414,9 @@
*
* @param surface A {@link android.view.Surface} used to render video.
* @throws IllegalStateException if the session has been already released.
+ * @hide
*/
- void setSurface(Surface surface) {
+ public void setSurface(Surface surface) {
if (mToken == null) {
throw new IllegalStateException("the session has been already released");
}
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index b2839cb..cf125bc 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -366,10 +366,8 @@
* Deep copies the data into native to simplify reference ownership.
*/
public void setOutline(Outline outline) {
- if (outline == null) {
+ if (outline == null || outline.isEmpty()) {
nSetOutlineEmpty(mNativeRenderNode);
- } else if (!outline.isValid()) {
- throw new IllegalArgumentException("Outline must be valid");
} else if (outline.mRect != null) {
nSetOutlineRoundRect(mNativeRenderNode, outline.mRect.left, outline.mRect.top,
outline.mRect.right, outline.mRect.bottom, outline.mRadius);
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index c1a4fee..e918119 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -48,6 +48,8 @@
public static final int Y = 9;
public static final int Z = 10;
public static final int ALPHA = 11;
+ // The last value in the enum, used for array size initialization
+ public static final int LAST_VALUE = ALPHA;
// Keep in sync with enum PaintFields in Animator.h
public static final int PAINT_STROKE_WIDTH = 0;
@@ -86,7 +88,7 @@
private boolean mStarted = false;
private boolean mFinished = false;
- public int mapViewPropertyToRenderProperty(int viewProperty) {
+ public static int mapViewPropertyToRenderProperty(int viewProperty) {
return sViewPropertyAnimatorMap.get(viewProperty);
}
@@ -125,11 +127,15 @@
}
}
+ static boolean isNativeInterpolator(TimeInterpolator interpolator) {
+ return interpolator.getClass().isAnnotationPresent(HasNativeInterpolator.class);
+ }
+
private void applyInterpolator() {
if (mInterpolator == null) return;
long ni;
- if (mInterpolator.getClass().isAnnotationPresent(HasNativeInterpolator.class)) {
+ if (isNativeInterpolator(mInterpolator)) {
ni = ((NativeInterpolatorFactory)mInterpolator).createNativeInterpolator();
} else {
long duration = nGetDuration(mNativePtr.get());
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 6dc7286..0f21c1d 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10680,24 +10680,30 @@
}
/**
- * Sets the outline of the view, which defines the shape of the shadow it
- * casts.
+ * Sets the {@link Outline} of the view, which defines the shape of the shadow it
+ * casts, and enables outline clipping.
* <p>
- * If the outline is not set or is null, shadows will be cast from the
+ * By default, a View queries its Outline from its background drawable, via
+ * {@link Drawable#getOutline(Outline)}. Manually setting the Outline with this method allows
+ * this behavior to be overridden.
+ * <p>
+ * If the outline is empty or is null, shadows will be cast from the
* bounds of the View.
+ * <p>
+ * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
*
* @param outline The new outline of the view.
- * Must be {@link android.graphics.Outline#isValid() valid.}
+ *
+ * @see #setClipToOutline(boolean)
+ * @see #getClipToOutline()
*/
public void setOutline(@Nullable Outline outline) {
- if (outline != null && !outline.isValid()) {
- throw new IllegalArgumentException("Outline must not be invalid");
- }
-
mPrivateFlags3 |= PFLAG3_OUTLINE_DEFINED;
- if (outline == null) {
- mOutline = null;
+ if (outline == null || outline.isEmpty()) {
+ if (mOutline != null) {
+ mOutline.setEmpty();
+ }
} else {
// always copy the path since caller may reuse
if (mOutline == null) {
@@ -10708,12 +10714,30 @@
mRenderNode.setOutline(mOutline);
}
+ /**
+ * Returns whether the Outline should be used to clip the contents of the View.
+ * <p>
+ * Note that this flag will only be respected if the View's Outline returns true from
+ * {@link Outline#canClip()}.
+ *
+ * @see #setOutline(Outline)
+ * @see #setClipToOutline(boolean)
+ */
public final boolean getClipToOutline() {
return mRenderNode.getClipToOutline();
}
+ /**
+ * Sets whether the View's Outline should be used to clip the contents of the View.
+ * <p>
+ * Note that this flag will only be respected if the View's Outline returns true from
+ * {@link Outline#canClip()}.
+ *
+ * @see #setOutline(Outline)
+ * @see #getClipToOutline()
+ */
public void setClipToOutline(boolean clipToOutline) {
- // TODO: add a fast invalidation here
+ damageInParent();
if (getClipToOutline() != clipToOutline) {
mRenderNode.setClipToOutline(clipToOutline);
}
@@ -10726,10 +10750,10 @@
mOutline = new Outline();
} else {
//invalidate outline, to ensure background calculates it
- mOutline.reset();
+ mOutline.setEmpty();
}
if (mBackground.getOutline(mOutline)) {
- if (!mOutline.isValid()) {
+ if (mOutline.isEmpty()) {
throw new IllegalStateException("Background drawable failed to build outline");
}
mRenderNode.setOutline(mOutline);
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index 11d2622..3104862 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -19,6 +19,7 @@
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.animation.TimeInterpolator;
+import android.os.Build;
import java.util.ArrayList;
import java.util.HashMap;
@@ -109,6 +110,11 @@
private ValueAnimator mTempValueAnimator;
/**
+ * A RenderThread-driven backend that may intercept startAnimation
+ */
+ private ViewPropertyAnimatorRT mRTBackend;
+
+ /**
* This listener is the mechanism by which the underlying Animator causes changes to the
* properties currently being animated, as well as the cleanup after an animation is
* complete.
@@ -227,7 +233,7 @@
* values are used to calculate the animated value for a given animation fraction
* during the animation.
*/
- private static class NameValuesHolder {
+ static class NameValuesHolder {
int mNameConstant;
float mFromValue;
float mDeltaValue;
@@ -247,6 +253,9 @@
ViewPropertyAnimator(View view) {
mView = view;
view.ensureTransformationInfo();
+ if (view.getContext().getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.L) {
+ mRTBackend = new ViewPropertyAnimatorRT(view);
+ }
}
/**
@@ -371,6 +380,10 @@
return this;
}
+ Animator.AnimatorListener getListener() {
+ return mListener;
+ }
+
/**
* Sets a listener for update events in the underlying ValueAnimator that runs
* the property animations. Note that the underlying animator is animating between
@@ -390,6 +403,10 @@
return this;
}
+ ValueAnimator.AnimatorUpdateListener getUpdateListener() {
+ return mUpdateListener;
+ }
+
/**
* Starts the currently pending property animations immediately. Calling <code>start()</code>
* is optional because all animations start automatically at the next opportunity. However,
@@ -825,12 +842,22 @@
return this;
}
+ boolean hasActions() {
+ return mPendingSetupAction != null
+ || mPendingCleanupAction != null
+ || mPendingOnStartAction != null
+ || mPendingOnEndAction != null;
+ }
+
/**
* Starts the underlying Animator for a set of properties. We use a single animator that
* simply runs from 0 to 1, and then use that fractional value to set each property
* value accordingly.
*/
private void startAnimation() {
+ if (mRTBackend != null && mRTBackend.startAnimation(this)) {
+ return;
+ }
mView.setHasTransientState(true);
ValueAnimator animator = ValueAnimator.ofFloat(1.0f);
ArrayList<NameValuesHolder> nameValueList =
diff --git a/core/java/android/view/ViewPropertyAnimatorRT.java b/core/java/android/view/ViewPropertyAnimatorRT.java
new file mode 100644
index 0000000..709efdb
--- /dev/null
+++ b/core/java/android/view/ViewPropertyAnimatorRT.java
@@ -0,0 +1,118 @@
+/*
+ * 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.view;
+
+import android.animation.TimeInterpolator;
+import android.view.ViewPropertyAnimator.NameValuesHolder;
+
+import com.android.internal.view.animation.FallbackLUTInterpolator;
+
+import java.util.ArrayList;
+
+
+/**
+ * This is a RenderThread driven backend for ViewPropertyAnimator.
+ */
+class ViewPropertyAnimatorRT {
+
+ private final View mView;
+
+ private RenderNodeAnimator mAnimators[] = new RenderNodeAnimator[RenderNodeAnimator.LAST_VALUE + 1];
+
+ ViewPropertyAnimatorRT(View view) {
+ mView = view;
+ }
+
+ /**
+ * @return true if ViewPropertyAnimatorRT handled the animation,
+ * false if ViewPropertyAnimator needs to handle it
+ */
+ public boolean startAnimation(ViewPropertyAnimator parent) {
+ cancelAnimators(parent.mPendingAnimations);
+ if (!canHandleAnimator(parent)) {
+ return false;
+ }
+ doStartAnimation(parent);
+ return true;
+ }
+
+ private void doStartAnimation(ViewPropertyAnimator parent) {
+ int size = parent.mPendingAnimations.size();
+
+ long startDelay = parent.getStartDelay();
+ long duration = parent.getDuration();
+ TimeInterpolator interpolator = parent.getInterpolator();
+ if (!RenderNodeAnimator.isNativeInterpolator(interpolator)) {
+ interpolator = new FallbackLUTInterpolator(interpolator, duration);
+ }
+ for (int i = 0; i < size; i++) {
+ NameValuesHolder holder = parent.mPendingAnimations.get(i);
+ int property = RenderNodeAnimator.mapViewPropertyToRenderProperty(holder.mNameConstant);
+
+ RenderNodeAnimator animator = new RenderNodeAnimator(property, holder.mFromValue + holder.mDeltaValue);
+ animator.setStartDelay(startDelay);
+ animator.setDuration(duration);
+ animator.setInterpolator(interpolator);
+ animator.setTarget(mView);
+ animator.start();
+ }
+
+ parent.mPendingAnimations.clear();
+ }
+
+ private boolean canHandleAnimator(ViewPropertyAnimator parent) {
+ // TODO: Can we eliminate this entirely?
+ // If RenderNode.animatorProperties() can be toggled to point at staging
+ // instead then RNA can be used as the animators for software as well
+ // as the updateListener fallback paths. If this can be toggled
+ // at the top level somehow, combined with requiresUiRedraw, we could
+ // ensure that RT does not self-animate, allowing for safe driving of
+ // the animators from the UI thread using the same mechanisms
+ // ViewPropertyAnimator does, just with everything sitting on a single
+ // animator subsystem instead of multiple.
+
+ if (parent.getUpdateListener() != null) {
+ return false;
+ }
+ if (parent.getListener() != null) {
+ // TODO support
+ return false;
+ }
+ if (!mView.isHardwareAccelerated()) {
+ // TODO handle this maybe?
+ return false;
+ }
+ if (parent.hasActions()) {
+ return false;
+ }
+ // Here goes nothing...
+ return true;
+ }
+
+ private void cancelAnimators(ArrayList<NameValuesHolder> mPendingAnimations) {
+ int size = mPendingAnimations.size();
+ for (int i = 0; i < size; i++) {
+ NameValuesHolder holder = mPendingAnimations.get(i);
+ int property = RenderNodeAnimator.mapViewPropertyToRenderProperty(holder.mNameConstant);
+ if (mAnimators[property] != null) {
+ mAnimators[property].cancel();
+ mAnimators[property] = null;
+ }
+ }
+ }
+
+}
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 34967df..d5f0834 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -995,13 +995,12 @@
public void addAction(int action) {
enforceNotSealed();
- AccessibilityAction newAction = getActionSingleton(action);
- if (newAction == null) {
- // This means it is not one of the standard actions
- throw new IllegalArgumentException("Argument is not one of the standard actions");
+ if ((action & ACTION_TYPE_MASK) != 0) {
+ throw new IllegalArgumentException("Action is not a combination of the standard " +
+ "actions: " + action);
}
- addAction(newAction);
+ addLegacyStandardActions(action);
}
/**
diff --git a/core/java/com/android/internal/view/animation/FallbackLUTInterpolator.java b/core/java/com/android/internal/view/animation/FallbackLUTInterpolator.java
index 1feb943..06838c9 100644
--- a/core/java/com/android/internal/view/animation/FallbackLUTInterpolator.java
+++ b/core/java/com/android/internal/view/animation/FallbackLUTInterpolator.java
@@ -24,10 +24,13 @@
* Interpolator that builds a lookup table to use. This is a fallback for
* building a native interpolator from a TimeInterpolator that is not marked
* with {@link HasNativeInterpolator}
+ *
+ * This implements TimeInterpolator to allow for easier interop with Animators
*/
@HasNativeInterpolator
-public class FallbackLUTInterpolator implements NativeInterpolatorFactory {
+public class FallbackLUTInterpolator implements NativeInterpolatorFactory, TimeInterpolator {
+ private TimeInterpolator mSourceInterpolator;
private final float mLut[];
/**
@@ -35,6 +38,7 @@
* interpolator creation
*/
public FallbackLUTInterpolator(TimeInterpolator interpolator, long duration) {
+ mSourceInterpolator = interpolator;
mLut = createLUT(interpolator, duration);
}
@@ -63,4 +67,9 @@
float[] lut = createLUT(interpolator, duration);
return NativeInterpolatorFactoryHelper.createLutInterpolator(lut);
}
+
+ @Override
+ public float getInterpolation(float input) {
+ return mSourceInterpolator.getInterpolation(input);
+ }
}
diff --git a/core/jni/android_hardware_UsbRequest.cpp b/core/jni/android_hardware_UsbRequest.cpp
index 01eaec4..a3c7b0a 100644
--- a/core/jni/android_hardware_UsbRequest.cpp
+++ b/core/jni/android_hardware_UsbRequest.cpp
@@ -100,18 +100,19 @@
}
request->buffer_length = length;
+ // save a reference to ourselves so UsbDeviceConnection.waitRequest() can find us
+ request->client_data = (void *)env->NewGlobalRef(thiz);
+
if (usb_request_queue(request)) {
if (request->buffer) {
// free our buffer if usb_request_queue fails
free(request->buffer);
request->buffer = NULL;
}
+ env->DeleteGlobalRef((jobject)request->client_data);
return false;
- } else {
- // save a reference to ourselves so UsbDeviceConnection.waitRequest() can find us
- request->client_data = (void *)env->NewGlobalRef(thiz);
- return true;
}
+ return true;
}
static jint
@@ -152,16 +153,17 @@
}
request->buffer_length = length;
+ // save a reference to ourselves so UsbDeviceConnection.waitRequest() can find us
+ // we also need this to make sure our native buffer is not deallocated
+ // while IO is active
+ request->client_data = (void *)env->NewGlobalRef(thiz);
+
if (usb_request_queue(request)) {
request->buffer = NULL;
+ env->DeleteGlobalRef((jobject)request->client_data);
return false;
- } else {
- // save a reference to ourselves so UsbDeviceConnection.waitRequest() can find us
- // we also need this to make sure our native buffer is not deallocated
- // while IO is active
- request->client_data = (void *)env->NewGlobalRef(thiz);
- return true;
}
+ return true;
}
static jint
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a97d5fc..7b200c4 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -833,15 +833,8 @@
<!-- Allows access to the loop radio (Android@Home mesh network) device.
@hide -->
<permission android:name="android.permission.LOOP_RADIO"
- android:permissionGroup="android.permission-group.NETWORK"
- android:protectionLevel="signature|system" />
-
- <!-- Allows for the NFC process to unlock the device
- @hide This should only be used by the Nfc apk
- -->
- <permission android:name="android.permission.NFC_UNLOCK"
- android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
- android:protectionLevel="signature" />
+ android:permissionGroup="android.permission-group.NETWORK"
+ android:protectionLevel="signature|system" />
<!-- ================================== -->
<!-- Permissions for accessing accounts -->
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 55e2983..4b03f31 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4497,7 +4497,7 @@
RTL (right-to-left). -->
<attr name="autoMirrored" />
<!-- Indicates how layer padding should affect the bounds of subsequent layers.
- The default value is nest. -->
+ The default padding mode value is nest. -->
<attr name="paddingMode">
<!-- Nest each layer inside the padding of the previous layer. -->
<enum name="nest" value="0" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 463dda2..c3efb69 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1215,6 +1215,49 @@
-->
<bool name="config_powerDecoupleInteractiveModeFromDisplay">false</bool>
+ <!-- User activity timeout: Minimum screen off timeout in milliseconds.
+
+ Sets a lower bound for the {@link Settings.System#SCREEN_OFF_TIMEOUT} setting
+ which determines how soon the device will go to sleep when there is no
+ user activity.
+
+ This value must be greater than zero, otherwise the device will immediately
+ fall asleep again as soon as it is awoken.
+ -->
+ <integer name="config_minimumScreenOffTimeout">10000</integer>
+
+ <!-- User activity timeout: Maximum screen dim duration in milliseconds.
+
+ Sets an upper bound for how long the screen will dim before the device goes
+ to sleep when there is no user activity. The dim duration is subtracted from
+ the overall screen off timeout to determine the screen dim timeout.
+ When the screen dim timeout expires, the screen will dim, shortly thereafter
+ the device will go to sleep.
+
+ If the screen off timeout is very short, the dim duration may be reduced
+ proportionally. See config_maximumScreenDimRatio.
+
+ This value may be zero in which case the screen will not dim before the
+ device goes to sleep.
+ -->
+ <integer name="config_maximumScreenDimDuration">7000</integer>
+
+ <!-- User activity timeout: Maximum screen dim duration as a percentage of screen off timeout.
+
+ This resource is similar to config_maximumScreenDimDuration but the maximum
+ screen dim duration is defined as a ratio of the overall screen off timeout
+ instead of as an absolute value in milliseconds. This is useful for reducing
+ the dim duration when the screen off timeout is very short.
+
+ When computing the screen dim duration, the power manager uses the lesser
+ of the effective durations expressed by config_maximumScreenDimDuration and
+ config_maximumScreenDimRatio.
+
+ This value must be between 0% and 100%. If the value is zero, the screen will not
+ dim before the device goes to sleep.
+ -->
+ <fraction name="config_maximumScreenDimRatio">20%</fraction>
+
<!-- Base "touch slop" value used by ViewConfiguration as a
movement threshold where scrolling should begin. -->
<dimen name="config_viewConfigurationTouchSlop">8dp</dimen>
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index 6ea0fae..c966a12 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -83,5 +83,4 @@
<item type="id" name="current_scene" />
<item type="id" name="scene_layoutid_cache" />
<item type="id" name="mask" />
- <item type="id" name="shared_element" />
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 44b25f2b..32ce568 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2177,6 +2177,7 @@
<public type="attr" name="contentInsetEnd" />
<public type="attr" name="contentInsetLeft" />
<public type="attr" name="contentInsetRight" />
+ <public type="attr" name="paddingMode" />
<public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
@@ -2186,7 +2187,6 @@
<public-padding type="id" name="l_resource_pad" end="0x01020040" />
<public type="id" name="mask" />
- <public type="id" name="shared_element" />
<public-padding type="style" name="l_resource_pad" end="0x01030200" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 2d60b86..a4e80bc1 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1639,6 +1639,9 @@
<java-symbol type="string" name="enable_explore_by_touch_warning_message" />
<java-symbol type="bool" name="config_powerDecoupleAutoSuspendModeFromDisplay" />
<java-symbol type="bool" name="config_powerDecoupleInteractiveModeFromDisplay" />
+ <java-symbol type="integer" name="config_minimumScreenOffTimeout" />
+ <java-symbol type="integer" name="config_maximumScreenDimDuration" />
+ <java-symbol type="fraction" name="config_maximumScreenDimRatio" />
<java-symbol type="string" name="config_customAdbPublicKeyConfirmationComponent" />
<java-symbol type="string" name="config_defaultNetworkScorerPackageName" />
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
index cad030a..db125e6 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
@@ -23,15 +23,15 @@
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiConfiguration.AuthAlgorithm;
-import android.net.wifi.WifiConfiguration.IpAssignment;
-import android.net.wifi.WifiConfiguration.KeyMgmt;
-import android.net.wifi.WifiConfiguration.ProxySettings;
-import android.net.wifi.WifiEnterpriseConfig;
+import android.net.IpConfiguration.IpAssignment;
+import android.net.IpConfiguration.ProxySettings;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.RouteInfo;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.AuthAlgorithm;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.net.wifi.WifiEnterpriseConfig;
import java.io.InputStream;
import java.net.InetAddress;
@@ -174,12 +174,12 @@
public void endElement(String uri, String localName, String tagName) throws SAXException {
if (tagName.equalsIgnoreCase("accesspoint")) {
if (mLinkProperties != null) {
- config.ipAssignment = IpAssignment.STATIC;
- config.linkProperties = mLinkProperties;
+ config.setIpAssignment(IpAssignment.STATIC);
+ config.setLinkProperties(mLinkProperties);
} else {
- config.ipAssignment = IpAssignment.DHCP;
+ config.setIpAssignment(IpAssignment.DHCP);
}
- config.proxySettings = ProxySettings.NONE;
+ config.setProxySettings(ProxySettings.NONE);
networks.add(config);
mLinkProperties = null;
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
index 91c3093..08618d6 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
@@ -18,12 +18,12 @@
import android.content.Context;
import android.net.ConnectivityManager;
+import android.net.IpConfiguration.IpAssignment;
+import android.net.IpConfiguration.ProxySettings;
import android.net.NetworkInfo.State;
import android.net.wifi.ScanResult;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiConfiguration.IpAssignment;
import android.net.wifi.WifiConfiguration.KeyMgmt;
-import android.net.wifi.WifiConfiguration.ProxySettings;
+import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Environment;
import android.os.PowerManager;
@@ -233,8 +233,8 @@
} else {
config.preSharedKey = '"' + mPassword + '"';
}
- config.ipAssignment = IpAssignment.DHCP;
- config.proxySettings = ProxySettings.NONE;
+ config.setIpAssignment(IpAssignment.DHCP);
+ config.setProxySettings(ProxySettings.NONE);
assertTrue("Failed to connect to Wi-Fi network: " + mSsid,
connectToWifiWithConfiguration(config));
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java
index 67203b2..22dce39 100644
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java
@@ -20,6 +20,8 @@
import android.content.Context;
import android.os.Bundle;
+import java.util.Set;
+
public class BluetoothInstrumentation extends Instrumentation {
private BluetoothTestUtils mUtils = null;
@@ -66,6 +68,8 @@
getName();
} else if ("getAddress".equals(command)) {
getAddress();
+ } else if ("getBondedDevices".equals(command)) {
+ getBondedDevices();
} else {
finish(null);
}
@@ -98,6 +102,16 @@
finish(mSuccessResult);
}
+ public void getBondedDevices() {
+ Set<BluetoothDevice> devices = getBluetoothAdapter().getBondedDevices();
+ int i = 0;
+ for (BluetoothDevice device : devices) {
+ mSuccessResult.putString(String.format("device-%02d", i), device.getAddress());
+ i++;
+ }
+ finish(mSuccessResult);
+ }
+
public void finish(Bundle result) {
if (result == null) {
result = new Bundle();
diff --git a/docs/html/distribute/essentials/gpfe-guidelines.jd b/docs/html/distribute/essentials/gpfe-guidelines.jd
index 8b47671..799009f 100644
--- a/docs/html/distribute/essentials/gpfe-guidelines.jd
+++ b/docs/html/distribute/essentials/gpfe-guidelines.jd
@@ -115,10 +115,6 @@
<hr>
</div>
-<div class="figure">
- <img src="{@docRoot}images/gp-edu-monetize.png">
-</div>
-
<p>
In-app purchase is currently not supported with Google Play for Education, so
a student device will block any transactions. To avoid confusion, be sure to
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index c6ba75c..d87c3cb 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -23,9 +23,9 @@
/**
* Defines a simple shape, used for bounding graphical regions.
- *
+ * <p>
* Can be used with a View, or computed by a Drawable, to drive the shape of shadows cast by a
- * View.
+ * View, or to clip the contents of the View.
*
* @see View#setOutline(Outline)
* @see Drawable#getOutline(Outline)
@@ -41,7 +41,7 @@
public Path mPath;
/**
- * Constructs an invalid Outline. Call one of the setter methods to make
+ * Constructs an empty Outline. Call one of the setter methods to make
* the outline valid for use with a View.
*/
public Outline() {}
@@ -49,23 +49,31 @@
/**
* Constructs an Outline with a copy of the data in src.
*/
- public Outline(@Nullable Outline src) {
+ public Outline(@NonNull Outline src) {
set(src);
}
- public void reset() {
+ /**
+ * Sets the outline to be empty.
+ *
+ * @see #isEmpty()
+ */
+ public void setEmpty() {
mRadius = 0;
mRect = null;
mPath = null;
}
/**
- * Returns whether the Outline is valid for use with a View.
+ * Returns whether the Outline is empty.
* <p>
- * Outlines are invalid when constructed until a setter method is called.
+ * Outlines are empty when constructed, or if {@link #setEmpty()} is called,
+ * until a setter method is called
+ *
+ * @see #setEmpty()
*/
- public boolean isValid() {
- return mRect != null || mPath != null;
+ public boolean isEmpty() {
+ return mRect == null && mPath == null;
}
/**
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index c78096a..3ef1d68 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -16,6 +16,7 @@
package android.graphics.drawable;
+import android.annotation.NonNull;
import android.graphics.Insets;
import android.graphics.Xfermode;
import android.os.Trace;
@@ -512,13 +513,12 @@
}
/**
- * Indicates whether this view will change its appearance based on state.
- * Clients can use this to determine whether it is necessary to calculate
- * their state and call setState.
+ * Indicates whether this drawable will change its appearance based on
+ * state. Clients can use this to determine whether it is necessary to
+ * calculate their state and call setState.
*
- * @return True if this view changes its appearance based on state, false
- * otherwise.
- *
+ * @return True if this drawable changes its appearance based on state,
+ * false otherwise.
* @see #setState(int[])
*/
public boolean isStateful() {
@@ -817,11 +817,12 @@
/**
* Return in padding the insets suggested by this Drawable for placing
* content inside the drawable's bounds. Positive values move toward the
- * center of the Drawable (set Rect.inset). Returns true if this drawable
- * actually has a padding, else false. When false is returned, the padding
- * is always set to 0.
+ * center of the Drawable (set Rect.inset).
+ *
+ * @return true if this drawable actually has a padding, else false. When false is returned,
+ * the padding is always set to 0.
*/
- public boolean getPadding(Rect padding) {
+ public boolean getPadding(@NonNull Rect padding) {
padding.set(0, 0, 0, 0);
return false;
}
@@ -842,13 +843,16 @@
* This method will be called by a View on its background Drawable after bounds change, or its
* Drawable is invalidated, if the View's Outline isn't set explicitly. This allows the
* background Drawable to define the shape of the shadow cast by the View.
- *
+ * <p>
* The default behavior defines the outline to be the bounding rectangle. Subclasses that wish
* to convey a different shape must override this method.
*
+ * @return true if this drawable actually has an outline, else false. The outline must be
+ * populated by the drawable if true is returned.
+ *
* @see View#setOutline(android.graphics.Outline)
*/
- public boolean getOutline(Outline outline) {
+ public boolean getOutline(@NonNull Outline outline) {
outline.setRect(getBounds());
return true;
}
@@ -1005,6 +1009,11 @@
return createFromXmlInnerThemed(r, parser, attrs, null);
}
+ /**
+ * Create a themed drawable from inside an XML document. Called on a parser
+ * positioned at a tag in an XML document, tries to create a Drawable from
+ * that tag. Returns null if the tag is not a valid drawable.
+ */
public static Drawable createFromXmlInnerThemed(Resources r, XmlPullParser parser,
AttributeSet attrs, Theme theme) throws XmlPullParserException, IOException {
final Drawable drawable;
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 373d894..f446000 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -38,10 +38,12 @@
* order, so the element with the largest index will be drawn on top.
* <p>
* It can be defined in an XML file with the <code><layer-list></code> element.
- * Each Drawable in the layer is defined in a nested <code><item></code>. For more
- * information, see the guide to <a
- * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p>
+ * Each Drawable in the layer is defined in a nested <code><item></code>.
+ * <p>
+ * For more information, see the guide to
+ * <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.
*
+ * @attr ref android.R.styleable#LayerDrawable_paddingMode
* @attr ref android.R.styleable#LayerDrawableItem_left
* @attr ref android.R.styleable#LayerDrawableItem_top
* @attr ref android.R.styleable#LayerDrawableItem_right
@@ -53,10 +55,16 @@
/**
* Padding mode used to nest each layer inside the padding of the previous
* layer.
+ *
+ * @see #setPaddingMode(int)
*/
public static final int PADDING_MODE_NEST = 0;
- /** Padding mode used to stack each layer directly atop the previous layer. */
+ /**
+ * Padding mode used to stack each layer directly atop the previous layer.
+ *
+ * @see #setPaddingMode(int)
+ */
public static final int PADDING_MODE_STACK = 1;
LayerState mLayerState;
@@ -127,9 +135,8 @@
throws XmlPullParserException, IOException {
super.inflate(r, parser, attrs, theme);
- final TypedArray a = obtainAttributes(
- r, theme, attrs, R.styleable.LayerDrawable);
- inflateStateFromTypedArray(a);
+ final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.LayerDrawable);
+ updateStateFromTypedArray(a);
a.recycle();
inflateLayers(r, parser, attrs, theme);
@@ -141,25 +148,19 @@
/**
* Initializes the constant state from the values in the typed array.
*/
- private void inflateStateFromTypedArray(TypedArray a) {
+ private void updateStateFromTypedArray(TypedArray a) {
final LayerState state = mLayerState;
// Extract the theme attributes, if any.
final int[] themeAttrs = a.extractThemeAttrs();
state.mThemeAttrs = themeAttrs;
- if (themeAttrs == null || themeAttrs[R.styleable.LayerDrawable_opacity] == 0) {
- mOpacityOverride = a.getInt(R.styleable.LayerDrawable_opacity, PixelFormat.UNKNOWN);
- }
+ mOpacityOverride = a.getInt(R.styleable.LayerDrawable_opacity, mOpacityOverride);
- if (themeAttrs == null || themeAttrs[R.styleable.LayerDrawable_autoMirrored] == 0) {
- state.mAutoMirrored = a.getBoolean(R.styleable.LayerDrawable_autoMirrored, false);
- }
-
- if (themeAttrs == null || themeAttrs[R.styleable.LayerDrawableItem_drawable] == 0) {
- state.mPaddingMode = a.getInteger(
- R.styleable.LayerDrawableItem_drawable, PADDING_MODE_NEST);
- }
+ state.mAutoMirrored = a.getBoolean(R.styleable.LayerDrawable_autoMirrored,
+ state.mAutoMirrored);
+ state.mPaddingMode = a.getInteger(R.styleable.LayerDrawable_paddingMode,
+ state.mPaddingMode);
}
/**
@@ -181,9 +182,9 @@
continue;
}
- a = obtainAttributes(
- r, theme, attrs, R.styleable.LayerDrawableItem);
+ a = obtainAttributes(r, theme, attrs, R.styleable.LayerDrawableItem);
+ final int[] themeAttrs = a.extractThemeAttrs();
final int left = a.getDimensionPixelOffset(
R.styleable.LayerDrawableItem_left, 0);
final int top = a.getDimensionPixelOffset(
@@ -197,7 +198,6 @@
final int id = a.getResourceId(
R.styleable.LayerDrawableItem_id, View.NO_ID);
- // TODO: Cache typed array, if necessary.
a.recycle();
final Drawable dr;
@@ -214,7 +214,7 @@
dr = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme);
}
- addLayer(dr, id, left, top, right, bottom);
+ addLayer(dr, themeAttrs, id, left, top, right, bottom);
}
}
@@ -224,7 +224,7 @@
final LayerState state = mLayerState;
if (state == null) {
- throw new RuntimeException("Can't apply theme to <layer-list> with no constant state");
+ return;
}
final int[] themeAttrs = state.mThemeAttrs;
@@ -239,9 +239,10 @@
final ChildDrawable[] array = mLayerState.mChildren;
final int N = mLayerState.mNum;
for (int i = 0; i < N; i++) {
- final Drawable layer = array[i].mDrawable;
- if (layer.canApplyTheme()) {
- layer.applyTheme(t);
+ final ChildDrawable layer = array[i];
+ final Drawable d = layer.mDrawable;
+ if (d.canApplyTheme()) {
+ d.applyTheme(t);
}
}
@@ -249,26 +250,6 @@
onStateChange(getState());
}
- /**
- * Updates the constant state from the values in the typed array.
- */
- private void updateStateFromTypedArray(TypedArray a) {
- final LayerState state = mLayerState;
-
- if (a.hasValue(R.styleable.LayerDrawable_opacity)) {
- mOpacityOverride = a.getInt(R.styleable.LayerDrawable_opacity, PixelFormat.UNKNOWN);
- }
-
- if (a.hasValue(R.styleable.LayerDrawable_autoMirrored)) {
- state.mAutoMirrored = a.getBoolean(R.styleable.LayerDrawable_autoMirrored, false);
- }
-
- if (a.hasValue(R.styleable.LayerDrawableItem_drawable)) {
- state.mPaddingMode = a.getInteger(
- R.styleable.LayerDrawableItem_drawable, PADDING_MODE_NEST);
- }
- }
-
@Override
public boolean canApplyTheme() {
final LayerState state = mLayerState;
@@ -283,14 +264,15 @@
final ChildDrawable[] array = state.mChildren;
final int N = state.mNum;
for (int i = 0; i < N; i++) {
- if (array[i].mDrawable.canApplyTheme()) {
+ final ChildDrawable layer = array[i];
+ if (layer.mThemeAttrs != null || layer.mDrawable.canApplyTheme()) {
return true;
}
}
return false;
}
-
+
/**
* @hide
*/
@@ -315,13 +297,15 @@
* Add a new layer to this drawable. The new layer is identified by an id.
*
* @param layer The drawable to add as a layer.
+ * @param themeAttrs Theme attributes extracted from the layer.
* @param id The id of the new layer.
* @param left The left padding of the new layer.
* @param top The top padding of the new layer.
* @param right The right padding of the new layer.
* @param bottom The bottom padding of the new layer.
*/
- private void addLayer(Drawable layer, int id, int left, int top, int right, int bottom) {
+ private void addLayer(Drawable layer, int[] themeAttrs, int id, int left, int top, int right,
+ int bottom) {
final LayerState st = mLayerState;
final int N = st.mChildren != null ? st.mChildren.length : 0;
final int i = st.mNum;
@@ -339,6 +323,7 @@
final ChildDrawable childDrawable = new ChildDrawable();
st.mChildren[i] = childDrawable;
childDrawable.mId = id;
+ childDrawable.mThemeAttrs = themeAttrs;
childDrawable.mDrawable = layer;
childDrawable.mDrawable.setAutoMirrored(isAutoMirrored());
childDrawable.mInsetL = left;
@@ -471,8 +456,14 @@
*
* @param mode padding mode, one of:
* <ul>
- * <li>{@link #PADDING_MODE_NEST} <li>{@link #PADDING_MODE_STACK}
+ * <li>{@link #PADDING_MODE_NEST} to nest each layer inside the
+ * padding of the previous layer
+ * <li>{@link #PADDING_MODE_STACK} to stack each layer directly
+ * atop the previous layer
* </ul>
+ *
+ * @see #getPaddingMode()
+ * @attr ref android.R.styleable#LayerDrawable_paddingMode
*/
public void setPaddingMode(int mode) {
if (mLayerState.mPaddingMode != mode) {
@@ -482,7 +473,9 @@
/**
* @return the current padding mode
+ *
* @see #setPaddingMode(int)
+ * @attr ref android.R.styleable#LayerDrawable_paddingMode
*/
public int getPaddingMode() {
return mLayerState.mPaddingMode;
@@ -905,7 +898,7 @@
private boolean mHaveIsStateful;
private boolean mIsStateful;
- private boolean mAutoMirrored;
+ private boolean mAutoMirrored = false;
private int mPaddingMode = PADDING_MODE_NEST;
diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java
index edf1091..5f9d1cd 100644
--- a/graphics/java/android/graphics/drawable/RotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/RotateDrawable.java
@@ -145,6 +145,9 @@
* Sets the start angle for rotation.
*
* @param fromDegrees Starting angle in degrees
+ *
+ * @see #getFromDegrees()
+ * @attr ref android.R.styleable#RotateDrawable_fromDegrees
*/
public void setFromDegrees(float fromDegrees) {
if (mState.mFromDegrees != fromDegrees) {
@@ -155,6 +158,9 @@
/**
* @return The starting angle for rotation in degrees
+ *
+ * @see #setFromDegrees(float)
+ * @attr ref android.R.styleable#RotateDrawable_fromDegrees
*/
public float getFromDegrees() {
return mState.mFromDegrees;
@@ -164,6 +170,9 @@
* Sets the end angle for rotation.
*
* @param toDegrees Ending angle in degrees
+ *
+ * @see #getToDegrees()
+ * @attr ref android.R.styleable#RotateDrawable_toDegrees
*/
public void setToDegrees(float toDegrees) {
if (mState.mToDegrees != toDegrees) {
@@ -174,6 +183,9 @@
/**
* @return The ending angle for rotation in degrees
+ *
+ * @see #setToDegrees(float)
+ * @attr ref android.R.styleable#RotateDrawable_toDegrees
*/
public float getToDegrees() {
return mState.mToDegrees;
@@ -186,7 +198,9 @@
* relative, the position represents a fraction of the drawable
* width. Otherwise, the position represents an absolute value in
* pixels.
+ *
* @see #setPivotXRelative(boolean)
+ * @attr ref android.R.styleable#RotateDrawable_pivotX
*/
public void setPivotX(float pivotX) {
if (mState.mPivotX == pivotX) {
@@ -197,7 +211,9 @@
/**
* @return X position around which to rotate
+ *
* @see #setPivotX(float)
+ * @attr ref android.R.styleable#RotateDrawable_pivotX
*/
public float getPivotX() {
return mState.mPivotX;
@@ -209,6 +225,8 @@
*
* @param relative True if the X pivot represents a fraction of the drawable
* width, or false if it represents an absolute value in pixels
+ *
+ * @see #isPivotXRelative()
*/
public void setPivotXRelative(boolean relative) {
if (mState.mPivotXRel == relative) {
@@ -220,6 +238,7 @@
/**
* @return True if the X pivot represents a fraction of the drawable width,
* or false if it represents an absolute value in pixels
+ *
* @see #setPivotXRelative(boolean)
*/
public boolean isPivotXRelative() {
@@ -233,7 +252,9 @@
* relative, the position represents a fraction of the drawable
* height. Otherwise, the position represents an absolute value
* in pixels.
- * @see #setPivotYRelative(boolean)
+ *
+ * @see #getPivotY()
+ * @attr ref android.R.styleable#RotateDrawable_pivotY
*/
public void setPivotY(float pivotY) {
if (mState.mPivotY == pivotY) {
@@ -244,7 +265,9 @@
/**
* @return Y position around which to rotate
+ *
* @see #setPivotY(float)
+ * @attr ref android.R.styleable#RotateDrawable_pivotY
*/
public float getPivotY() {
return mState.mPivotY;
@@ -256,6 +279,8 @@
*
* @param relative True if the Y pivot represents a fraction of the drawable
* height, or false if it represents an absolute value in pixels
+ *
+ * @see #isPivotYRelative()
*/
public void setPivotYRelative(boolean relative) {
if (mState.mPivotYRel == relative) {
@@ -267,6 +292,7 @@
/**
* @return True if the Y pivot represents a fraction of the drawable height,
* or false if it represents an absolute value in pixels
+ *
* @see #setPivotYRelative(boolean)
*/
public boolean isPivotYRelative() {
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 3a3f76d..575667d 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2557,60 +2557,191 @@
// class is not used by other parts of the framework, which instead use definitions and methods
// from AudioManager. AudioSystem is an internal class used by AudioManager and AudioService.
- /** {@hide} The audio output device code for the small speaker at the front of the device used
+ /** @hide
+ * The audio output device code for the small speaker at the front of the device used
* when placing calls. Does not refer to an in-ear headphone without attached microphone,
* such as earbuds, earphones, or in-ear monitors (IEM). Those would be handled as a
* {@link #DEVICE_OUT_WIRED_HEADPHONE}.
*/
public static final int DEVICE_OUT_EARPIECE = AudioSystem.DEVICE_OUT_EARPIECE;
- /** {@hide} The audio output device code for the built-in speaker */
+ /** @hide
+ * The audio output device code for the built-in speaker */
public static final int DEVICE_OUT_SPEAKER = AudioSystem.DEVICE_OUT_SPEAKER;
- /** {@hide} The audio output device code for a wired headset with attached microphone */
+ /** @hide
+ * The audio output device code for a wired headset with attached microphone */
public static final int DEVICE_OUT_WIRED_HEADSET = AudioSystem.DEVICE_OUT_WIRED_HEADSET;
- /** {@hide} The audio output device code for a wired headphone without attached microphone */
+ /** @hide
+ * The audio output device code for a wired headphone without attached microphone */
public static final int DEVICE_OUT_WIRED_HEADPHONE = AudioSystem.DEVICE_OUT_WIRED_HEADPHONE;
- /** {@hide} The audio output device code for generic Bluetooth SCO, for voice */
+ /** @hide
+ * The audio output device code for generic Bluetooth SCO, for voice */
public static final int DEVICE_OUT_BLUETOOTH_SCO = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
- /** {@hide} The audio output device code for Bluetooth SCO Headset Profile (HSP) and
- * Hands-Free Profile (HFP), for voice
+ /** @hide
+ * The audio output device code for Bluetooth SCO Headset Profile (HSP) and
+ * Hands-Free Profile (HFP), for voice
*/
public static final int DEVICE_OUT_BLUETOOTH_SCO_HEADSET =
AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
- /** {@hide} The audio output device code for Bluetooth SCO car audio, for voice */
+ /** @hide
+ * The audio output device code for Bluetooth SCO car audio, for voice */
public static final int DEVICE_OUT_BLUETOOTH_SCO_CARKIT =
AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
- /** {@hide} The audio output device code for generic Bluetooth A2DP, for music */
+ /** @hide
+ * The audio output device code for generic Bluetooth A2DP, for music */
public static final int DEVICE_OUT_BLUETOOTH_A2DP = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
- /** {@hide} The audio output device code for Bluetooth A2DP headphones, for music */
+ /** @hide
+ * The audio output device code for Bluetooth A2DP headphones, for music */
public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES =
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
- /** {@hide} The audio output device code for Bluetooth A2DP external speaker, for music */
+ /** @hide
+ * The audio output device code for Bluetooth A2DP external speaker, for music */
public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER =
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
- /** {@hide} The audio output device code for S/PDIF or HDMI */
+ /** @hide
+ * The audio output device code for S/PDIF (legacy) or HDMI
+ * Deprecated: replaced by {@link #DEVICE_OUT_HDMI} */
public static final int DEVICE_OUT_AUX_DIGITAL = AudioSystem.DEVICE_OUT_AUX_DIGITAL;
- /** {@hide} The audio output device code for an analog wired headset attached via a
+ /** @hide
+ * The audio output device code for HDMI */
+ public static final int DEVICE_OUT_HDMI = AudioSystem.DEVICE_OUT_HDMI;
+ /** @hide
+ * The audio output device code for an analog wired headset attached via a
* docking station
*/
public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET;
- /** {@hide} The audio output device code for a digital wired headset attached via a
+ /** @hide
+ * The audio output device code for a digital wired headset attached via a
* docking station
*/
public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET;
- /** {@hide} The audio output device code for a USB audio accessory. The accessory is in USB host
+ /** @hide
+ * The audio output device code for a USB audio accessory. The accessory is in USB host
* mode and the Android device in USB device mode
*/
public static final int DEVICE_OUT_USB_ACCESSORY = AudioSystem.DEVICE_OUT_USB_ACCESSORY;
- /** {@hide} The audio output device code for a USB audio device. The device is in USB device
+ /** @hide
+ * The audio output device code for a USB audio device. The device is in USB device
* mode and the Android device in USB host mode
*/
public static final int DEVICE_OUT_USB_DEVICE = AudioSystem.DEVICE_OUT_USB_DEVICE;
- /** {@hide} This is not used as a returned value from {@link #getDevicesForStream}, but could be
+ /** @hide
+ * The audio output device code for projection output.
+ */
+ public static final int DEVICE_OUT_REMOTE_SUBMIX = AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
+ /** @hide
+ * The audio output device code the telephony voice TX path.
+ */
+ public static final int DEVICE_OUT_TELEPHONY_TX = AudioSystem.DEVICE_OUT_TELEPHONY_TX;
+ /** @hide
+ * The audio output device code for an analog jack with line impedance detected.
+ */
+ public static final int DEVICE_OUT_LINE = AudioSystem.DEVICE_OUT_LINE;
+ /** @hide
+ * The audio output device code for HDMI Audio Return Channel.
+ */
+ public static final int DEVICE_OUT_HDMI_ARC = AudioSystem.DEVICE_OUT_HDMI_ARC;
+ /** @hide
+ * The audio output device code for S/PDIF digital connection.
+ */
+ public static final int DEVICE_OUT_SPDIF = AudioSystem.DEVICE_OUT_SPDIF;
+ /** @hide
+ * The audio output device code for built-in FM transmitter.
+ */
+ public static final int DEVICE_OUT_FM = AudioSystem.DEVICE_OUT_FM;
+ /** @hide
+ * This is not used as a returned value from {@link #getDevicesForStream}, but could be
* used in the future in a set method to select whatever default device is chosen by the
* platform-specific implementation.
*/
public static final int DEVICE_OUT_DEFAULT = AudioSystem.DEVICE_OUT_DEFAULT;
+ /** @hide
+ * The audio input device code for default built-in microphone
+ */
+ public static final int DEVICE_IN_BUILTIN_MIC = AudioSystem.DEVICE_IN_BUILTIN_MIC;
+ /** @hide
+ * The audio input device code for a Bluetooth SCO headset
+ */
+ public static final int DEVICE_IN_BLUETOOTH_SCO_HEADSET =
+ AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+ /** @hide
+ * The audio input device code for wired headset microphone
+ */
+ public static final int DEVICE_IN_WIRED_HEADSET =
+ AudioSystem.DEVICE_IN_WIRED_HEADSET;
+ /** @hide
+ * The audio input device code for HDMI
+ */
+ public static final int DEVICE_IN_HDMI =
+ AudioSystem.DEVICE_IN_HDMI;
+ /** @hide
+ * The audio input device code for telephony voice RX path
+ */
+ public static final int DEVICE_IN_TELEPHONY_RX =
+ AudioSystem.DEVICE_IN_TELEPHONY_RX;
+ /** @hide
+ * The audio input device code for built-in microphone pointing to the back
+ */
+ public static final int DEVICE_IN_BACK_MIC =
+ AudioSystem.DEVICE_IN_BACK_MIC;
+ /** @hide
+ * The audio input device code for analog from a docking station
+ */
+ public static final int DEVICE_IN_ANLG_DOCK_HEADSET =
+ AudioSystem.DEVICE_IN_ANLG_DOCK_HEADSET;
+ /** @hide
+ * The audio input device code for digital from a docking station
+ */
+ public static final int DEVICE_IN_DGTL_DOCK_HEADSET =
+ AudioSystem.DEVICE_IN_DGTL_DOCK_HEADSET;
+ /** @hide
+ * The audio input device code for a USB audio accessory. The accessory is in USB host
+ * mode and the Android device in USB device mode
+ */
+ public static final int DEVICE_IN_USB_ACCESSORY =
+ AudioSystem.DEVICE_IN_USB_ACCESSORY;
+ /** @hide
+ * The audio input device code for a USB audio device. The device is in USB device
+ * mode and the Android device in USB host mode
+ */
+ public static final int DEVICE_IN_USB_DEVICE =
+ AudioSystem.DEVICE_IN_USB_DEVICE;
+ /** @hide
+ * The audio input device code for a FM radio tuner
+ */
+ public static final int DEVICE_IN_FM_TUNER = AudioSystem.DEVICE_IN_FM_TUNER;
+ /** @hide
+ * The audio input device code for a TV tuner
+ */
+ public static final int DEVICE_IN_TV_TUNER = AudioSystem.DEVICE_IN_TV_TUNER;
+ /** @hide
+ * The audio input device code for an analog jack with line impedance detected
+ */
+ public static final int DEVICE_IN_LINE = AudioSystem.DEVICE_IN_LINE;
+ /** @hide
+ * The audio input device code for a S/PDIF digital connection
+ */
+ public static final int DEVICE_IN_SPDIF = AudioSystem.DEVICE_IN_SPDIF;
+
+ /**
+ * Return true if the device code corresponds to an output device.
+ * @hide
+ */
+ public static boolean isOutputDevice(int device)
+ {
+ return (device & AudioSystem.DEVICE_BIT_IN) == 0;
+ }
+
+ /**
+ * Return true if the device code corresponds to an input device.
+ * @hide
+ */
+ public static boolean isInputDevice(int device)
+ {
+ return (device & AudioSystem.DEVICE_BIT_IN) == AudioSystem.DEVICE_BIT_IN;
+ }
+
+
/**
* Return the enabled devices for the specified output stream type.
*
@@ -2635,9 +2766,17 @@
* {@link #DEVICE_OUT_BLUETOOTH_A2DP},
* {@link #DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES},
* {@link #DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER},
- * {@link #DEVICE_OUT_AUX_DIGITAL},
+ * {@link #DEVICE_OUT_HDMI},
* {@link #DEVICE_OUT_ANLG_DOCK_HEADSET},
* {@link #DEVICE_OUT_DGTL_DOCK_HEADSET}.
+ * {@link #DEVICE_OUT_USB_ACCESSORY}.
+ * {@link #DEVICE_OUT_USB_DEVICE}.
+ * {@link #DEVICE_OUT_REMOTE_SUBMIX}.
+ * {@link #DEVICE_OUT_TELEPHONY_TX}.
+ * {@link #DEVICE_OUT_LINE}.
+ * {@link #DEVICE_OUT_HDMI_ARC}.
+ * {@link #DEVICE_OUT_SPDIF}.
+ * {@link #DEVICE_OUT_FM}.
* {@link #DEVICE_OUT_DEFAULT} is not used here.
*
* The implementation may support additional device codes beyond those listed, so
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index bb8cfa6..6e623a5 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -423,7 +423,7 @@
public final static int STREAM_REMOTE_MUSIC = -200;
// Devices for which the volume is fixed and VolumePanel slider should be disabled
- final int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_AUX_DIGITAL |
+ final int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_HDMI |
AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET |
AudioSystem.DEVICE_OUT_ALL_USB;
@@ -2895,7 +2895,7 @@
public String getSettingNameForDevice(int device) {
String name = mVolumeIndexSettingName;
- String suffix = AudioSystem.getDeviceName(device);
+ String suffix = AudioSystem.getOutputDeviceName(device);
if (suffix.isEmpty()) {
return name;
}
@@ -3935,7 +3935,7 @@
// sent if none of these devices is connected.
int mBecomingNoisyIntentDevices =
AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
- AudioSystem.DEVICE_OUT_ALL_A2DP | AudioSystem.DEVICE_OUT_AUX_DIGITAL |
+ AudioSystem.DEVICE_OUT_ALL_A2DP | AudioSystem.DEVICE_OUT_HDMI |
AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET | AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
AudioSystem.DEVICE_OUT_ALL_USB;
@@ -3992,7 +3992,7 @@
} else if (device == AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET) {
connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS;
intent.setAction(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG);
- } else if (device == AudioSystem.DEVICE_OUT_AUX_DIGITAL) {
+ } else if (device == AudioSystem.DEVICE_OUT_HDMI) {
connType = AudioRoutesInfo.MAIN_HDMI;
intent.setAction(Intent.ACTION_HDMI_AUDIO_PLUG);
}
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 5ddb198..0c45443 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -234,11 +234,17 @@
public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100;
public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200;
public static final int DEVICE_OUT_AUX_DIGITAL = 0x400;
+ public static final int DEVICE_OUT_HDMI = DEVICE_OUT_AUX_DIGITAL;
public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800;
public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000;
public static final int DEVICE_OUT_USB_ACCESSORY = 0x2000;
public static final int DEVICE_OUT_USB_DEVICE = 0x4000;
public static final int DEVICE_OUT_REMOTE_SUBMIX = 0x8000;
+ public static final int DEVICE_OUT_TELEPHONY_TX = 0x10000;
+ public static final int DEVICE_OUT_LINE = 0x20000;
+ public static final int DEVICE_OUT_HDMI_ARC = 0x40000;
+ public static final int DEVICE_OUT_SPDIF = 0x80000;
+ public static final int DEVICE_OUT_FM = 0x100000;
public static final int DEVICE_OUT_DEFAULT = DEVICE_BIT_DEFAULT;
@@ -252,12 +258,17 @@
DEVICE_OUT_BLUETOOTH_A2DP |
DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER |
- DEVICE_OUT_AUX_DIGITAL |
+ DEVICE_OUT_HDMI |
DEVICE_OUT_ANLG_DOCK_HEADSET |
DEVICE_OUT_DGTL_DOCK_HEADSET |
DEVICE_OUT_USB_ACCESSORY |
DEVICE_OUT_USB_DEVICE |
DEVICE_OUT_REMOTE_SUBMIX |
+ DEVICE_OUT_TELEPHONY_TX |
+ DEVICE_OUT_LINE |
+ DEVICE_OUT_HDMI_ARC |
+ DEVICE_OUT_SPDIF |
+ DEVICE_OUT_FM |
DEVICE_OUT_DEFAULT);
public static final int DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP |
DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
@@ -275,13 +286,20 @@
public static final int DEVICE_IN_BLUETOOTH_SCO_HEADSET = DEVICE_BIT_IN | 0x8;
public static final int DEVICE_IN_WIRED_HEADSET = DEVICE_BIT_IN | 0x10;
public static final int DEVICE_IN_AUX_DIGITAL = DEVICE_BIT_IN | 0x20;
+ public static final int DEVICE_IN_HDMI = DEVICE_IN_AUX_DIGITAL;
public static final int DEVICE_IN_VOICE_CALL = DEVICE_BIT_IN | 0x40;
+ public static final int DEVICE_IN_TELEPHONY_RX = DEVICE_IN_VOICE_CALL;
public static final int DEVICE_IN_BACK_MIC = DEVICE_BIT_IN | 0x80;
public static final int DEVICE_IN_REMOTE_SUBMIX = DEVICE_BIT_IN | 0x100;
public static final int DEVICE_IN_ANLG_DOCK_HEADSET = DEVICE_BIT_IN | 0x200;
public static final int DEVICE_IN_DGTL_DOCK_HEADSET = DEVICE_BIT_IN | 0x400;
public static final int DEVICE_IN_USB_ACCESSORY = DEVICE_BIT_IN | 0x800;
public static final int DEVICE_IN_USB_DEVICE = DEVICE_BIT_IN | 0x1000;
+ public static final int DEVICE_IN_FM_TUNER = DEVICE_BIT_IN | 0x2000;
+ public static final int DEVICE_IN_TV_TUNER = DEVICE_BIT_IN | 0x4000;
+ public static final int DEVICE_IN_LINE = DEVICE_BIT_IN | 0x8000;
+ public static final int DEVICE_IN_SPDIF = DEVICE_BIT_IN | 0x10000;
+
public static final int DEVICE_IN_DEFAULT = DEVICE_BIT_IN | DEVICE_BIT_DEFAULT;
public static final int DEVICE_IN_ALL = (DEVICE_IN_COMMUNICATION |
@@ -289,14 +307,18 @@
DEVICE_IN_BUILTIN_MIC |
DEVICE_IN_BLUETOOTH_SCO_HEADSET |
DEVICE_IN_WIRED_HEADSET |
- DEVICE_IN_AUX_DIGITAL |
- DEVICE_IN_VOICE_CALL |
+ DEVICE_IN_HDMI |
+ DEVICE_IN_TELEPHONY_RX |
DEVICE_IN_BACK_MIC |
DEVICE_IN_REMOTE_SUBMIX |
DEVICE_IN_ANLG_DOCK_HEADSET |
DEVICE_IN_DGTL_DOCK_HEADSET |
DEVICE_IN_USB_ACCESSORY |
DEVICE_IN_USB_DEVICE |
+ DEVICE_IN_FM_TUNER |
+ DEVICE_IN_TV_TUNER |
+ DEVICE_IN_LINE |
+ DEVICE_IN_SPDIF |
DEVICE_IN_DEFAULT);
public static final int DEVICE_IN_ALL_SCO = DEVICE_IN_BLUETOOTH_SCO_HEADSET;
public static final int DEVICE_IN_ALL_USB = (DEVICE_IN_USB_ACCESSORY |
@@ -318,13 +340,19 @@
public static final String DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES_NAME = "bt_a2dp_hp";
public static final String DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER_NAME = "bt_a2dp_spk";
public static final String DEVICE_OUT_AUX_DIGITAL_NAME = "aux_digital";
+ public static final String DEVICE_OUT_HDMI_NAME = "hdmi";
public static final String DEVICE_OUT_ANLG_DOCK_HEADSET_NAME = "analog_dock";
public static final String DEVICE_OUT_DGTL_DOCK_HEADSET_NAME = "digital_dock";
public static final String DEVICE_OUT_USB_ACCESSORY_NAME = "usb_accessory";
public static final String DEVICE_OUT_USB_DEVICE_NAME = "usb_device";
public static final String DEVICE_OUT_REMOTE_SUBMIX_NAME = "remote_submix";
+ public static final String DEVICE_OUT_TELEPHONY_TX_NAME = "telephony_tx";
+ public static final String DEVICE_OUT_LINE_NAME = "line";
+ public static final String DEVICE_OUT_HDMI_ARC_NAME = "hmdi_arc";
+ public static final String DEVICE_OUT_SPDIF_NAME = "spdif";
+ public static final String DEVICE_OUT_FM_NAME = "fm_transmitter";
- public static String getDeviceName(int device)
+ public static String getOutputDeviceName(int device)
{
switch(device) {
case DEVICE_OUT_EARPIECE:
@@ -347,8 +375,8 @@
return DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES_NAME;
case DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
return DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER_NAME;
- case DEVICE_OUT_AUX_DIGITAL:
- return DEVICE_OUT_AUX_DIGITAL_NAME;
+ case DEVICE_OUT_HDMI:
+ return DEVICE_OUT_HDMI_NAME;
case DEVICE_OUT_ANLG_DOCK_HEADSET:
return DEVICE_OUT_ANLG_DOCK_HEADSET_NAME;
case DEVICE_OUT_DGTL_DOCK_HEADSET:
@@ -359,12 +387,23 @@
return DEVICE_OUT_USB_DEVICE_NAME;
case DEVICE_OUT_REMOTE_SUBMIX:
return DEVICE_OUT_REMOTE_SUBMIX_NAME;
+ case DEVICE_OUT_TELEPHONY_TX:
+ return DEVICE_OUT_TELEPHONY_TX_NAME;
+ case DEVICE_OUT_LINE:
+ return DEVICE_OUT_LINE_NAME;
+ case DEVICE_OUT_HDMI_ARC:
+ return DEVICE_OUT_HDMI_ARC_NAME;
+ case DEVICE_OUT_SPDIF:
+ return DEVICE_OUT_SPDIF_NAME;
+ case DEVICE_OUT_FM:
+ return DEVICE_OUT_FM_NAME;
case DEVICE_OUT_DEFAULT:
default:
return "";
}
}
+
// phone state, match audio_mode???
public static final int PHONE_STATE_OFFCALL = 0;
public static final int PHONE_STATE_RINGING = 1;
diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java
index 37f45c2..26ae3cc 100644
--- a/media/java/android/media/RemoteControlClient.java
+++ b/media/java/android/media/RemoteControlClient.java
@@ -407,6 +407,19 @@
}
/**
+ * Get a {@link MediaSession} associated with this RCC. It will only have a
+ * session while it is registered with
+ * {@link AudioManager#registerRemoteControlClient}. The session returned
+ * should not be modified directly by the application but may be used with
+ * other APIs that require a session.
+ *
+ * @return A media session object or null.
+ */
+ public MediaSession getMediaSession() {
+ return mSession;
+ }
+
+ /**
* Class used to modify metadata in a {@link RemoteControlClient} object.
* Use {@link RemoteControlClient#editMetadata(boolean)} to create an instance of an editor,
* on which you set the metadata for the RemoteControlClient instance. Once all the information
diff --git a/media/jni/android_media_MediaScanner.cpp b/media/jni/android_media_MediaScanner.cpp
index 84028b7..d21b442 100644
--- a/media/jni/android_media_MediaScanner.cpp
+++ b/media/jni/android_media_MediaScanner.cpp
@@ -351,7 +351,7 @@
if (!data) {
return NULL;
}
- long len = *((long*)data);
+ jsize len = *((uint32_t*)data);
jbyteArray array = env->NewByteArray(len);
if (array != NULL) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index 2d17b7b..aae92e8 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -149,14 +149,16 @@
if (mLockPatternUtils.checkPassword(entry)) {
mCallback.reportUnlockAttempt(true);
mCallback.dismiss(true);
- } else if (entry.length() > MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT ) {
- // to avoid accidental lockout, only count attempts that are long enough to be a
- // real password. This may require some tweaking.
- mCallback.reportUnlockAttempt(false);
- int attempts = KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts();
- if (0 == (attempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
- long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
- handleAttemptLockout(deadline);
+ } else {
+ if (entry.length() > MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT ) {
+ // to avoid accidental lockout, only count attempts that are long enough to be a
+ // real password. This may require some tweaking.
+ mCallback.reportUnlockAttempt(false);
+ int attempts = KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts();
+ if (0 == (attempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
+ long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
+ handleAttemptLockout(deadline);
+ }
}
mSecurityMessageDisplay.setMessage(getWrongPasswordStringId(), true);
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index f85e29f..2685447 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -16,8 +16,6 @@
package com.android.keyguard;
-import android.nfc.NfcUnlock;
-
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.keyguard.KeyguardUpdateMonitor.DisplayClientState;
@@ -46,6 +44,7 @@
import android.provider.Settings;
import android.util.AttributeSet;
import android.util.Log;
+import android.util.Slog;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@@ -264,12 +263,6 @@
}
}
}
- @Override
- public void onNfcUnlock() {
- if (NfcUnlock.getPropertyEnabled()) {
- dismiss(true);
- }
- }
};
private static final boolean isMusicPlaying(int playbackState) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index d6351df..0bcd916 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -37,7 +37,6 @@
import static android.os.BatteryManager.EXTRA_HEALTH;
import android.media.AudioManager;
import android.media.IRemoteControlDisplay;
-import android.nfc.NfcUnlock;
import android.os.BatteryManager;
import android.os.Bundle;
import android.os.Handler;
@@ -98,7 +97,6 @@
protected static final int MSG_REPORT_EMERGENCY_CALL_ACTION = 318;
private static final int MSG_SCREEN_TURNED_ON = 319;
private static final int MSG_SCREEN_TURNED_OFF = 320;
- private static final int MSG_NFC_UNLOCK = 321;
private static final int MSG_KEYGUARD_BOUNCER_CHANGED = 322;
private static KeyguardUpdateMonitor sInstance;
@@ -204,9 +202,6 @@
case MSG_SCREEN_TURNED_ON:
handleScreenTurnedOn();
break;
- case MSG_NFC_UNLOCK:
- handleNfcUnlock();
- break;
}
}
};
@@ -356,15 +351,6 @@
}
};
- private final BroadcastReceiver mNfcUnlockReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (NfcUnlock.ACTION_NFC_UNLOCK.equals(intent.getAction())) {
- mHandler.sendEmptyMessage(MSG_NFC_UNLOCK);
- }
- }
- }
- ;
/**
* When we receive a
* {@link com.android.internal.telephony.TelephonyIntents#ACTION_SIM_STATE_CHANGED} broadcast,
@@ -549,15 +535,6 @@
}
}
- private void handleNfcUnlock() {
- for (int i = 0; i < mCallbacks.size(); i++) {
- KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
- if (cb != null) {
- cb.onNfcUnlock();
- }
- }
- }
-
private KeyguardUpdateMonitor(Context context) {
mContext = context;
@@ -587,11 +564,6 @@
filter.addAction(Intent.ACTION_USER_REMOVED);
context.registerReceiver(mBroadcastReceiver, filter);
- final IntentFilter nfcUnlockIntentFilter = new IntentFilter();
- nfcUnlockIntentFilter.addAction(NfcUnlock.ACTION_NFC_UNLOCK);
- context.registerReceiver(mNfcUnlockReceiver, nfcUnlockIntentFilter,
- NfcUnlock.NFC_UNLOCK_PERMISSION, null /* run on default scheduler */);
-
final IntentFilter bootCompleteFilter = new IntentFilter();
bootCompleteFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
bootCompleteFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 91a024f..76206f7 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -179,10 +179,4 @@
* {@link WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT}.
*/
public void onScreenTurnedOff(int why) { }
-
- /**
- * Called when the NFC Service has found a tag that is registered for NFC unlock.
- */
- public void onNfcUnlock() { }
-
}
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index da37803..6d101d7 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -6,10 +6,6 @@
public void setGlowAlpha(float);
public void setGlowScale(float);
}
--keep class com.android.systemui.recents.views.TaskInfoView {
- public void setCircularClipRadius(float);
- public float getCircularClipRadius();
-}
-keep class com.android.systemui.statusbar.phone.PhoneStatusBar
-keep class com.android.systemui.statusbar.tv.TvStatusBar
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index a68ad2f..97051ff 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -22,21 +22,6 @@
android:id="@+id/task_view_thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent" />
- <com.android.systemui.recents.views.TaskInfoView
- android:id="@+id/task_view_info_pane"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:visibility="invisible"
- android:background="@color/recents_task_bar_default_background_color">
- <Button
- android:id="@+id/task_view_app_info_button"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginStart="20dp"
- android:layout_marginEnd="20dp"
- android:layout_gravity="top|center_horizontal"
- android:text="@string/recents_app_info_button_label" />
- </com.android.systemui.recents.views.TaskInfoView>
<com.android.systemui.recents.views.TaskBarView
android:id="@+id/task_view_bar"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 6df2a19..ffd64d4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -64,10 +64,12 @@
mSingleCountFirstTaskRect.offset(0, (int) statusBarHeight);
mMultipleCountFirstTaskRect = replyData.getParcelable(KEY_MULTIPLE_TASK_STACK_RECT);
mMultipleCountFirstTaskRect.offset(0, (int) statusBarHeight);
- Console.log(Constants.Log.App.RecentsComponent,
- "[RecentsComponent|RecentsMessageHandler|handleMessage]",
- "singleTaskRect: " + mSingleCountFirstTaskRect +
- " multipleTaskRect: " + mMultipleCountFirstTaskRect);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.RecentsComponent,
+ "[RecentsComponent|RecentsMessageHandler|handleMessage]",
+ "singleTaskRect: " + mSingleCountFirstTaskRect +
+ " multipleTaskRect: " + mMultipleCountFirstTaskRect);
+ }
// If we had the update the animation rects as a result of onServiceConnected, then
// we check for whether we need to toggle the recents here.
@@ -83,9 +85,11 @@
class RecentsServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
- Console.log(Constants.Log.App.RecentsComponent,
- "[RecentsComponent|ServiceConnection|onServiceConnected]",
- "toggleRecents: " + mToggleRecentsUponServiceBound);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.RecentsComponent,
+ "[RecentsComponent|ServiceConnection|onServiceConnected]",
+ "toggleRecents: " + mToggleRecentsUponServiceBound);
+ }
mService = new Messenger(service);
mServiceIsBound = true;
@@ -103,8 +107,10 @@
@Override
public void onServiceDisconnected(ComponentName className) {
- Console.log(Constants.Log.App.RecentsComponent,
- "[RecentsComponent|ServiceConnection|onServiceDisconnected]");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.RecentsComponent,
+ "[RecentsComponent|ServiceConnection|onServiceDisconnected]");
+ }
mService = null;
mServiceIsBound = false;
}
@@ -159,7 +165,9 @@
}
public void onStart() {
- Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|start]");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|start]");
+ }
// Try to create a long-running connection to the recents service
bindToRecentsService(false);
@@ -167,7 +175,9 @@
/** Shows the recents */
public void onShowRecents(boolean triggeredFromAltTab, View statusBarView) {
- Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|showRecents]");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|showRecents]");
+ }
mStatusBarView = statusBarView;
mTriggeredFromAltTab = triggeredFromAltTab;
if (!mServiceIsBound) {
@@ -186,7 +196,9 @@
/** Hides the recents */
public void onHideRecents(boolean triggeredFromAltTab) {
- Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|hideRecents]");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|hideRecents]");
+ }
if (mServiceIsBound) {
// Notify recents to close it
try {
@@ -202,12 +214,14 @@
/** Toggles the alternate recents activity */
public void onToggleRecents(View statusBarView) {
- Console.logStartTracingTime(Constants.Log.App.TimeRecentsStartup,
- Constants.Log.App.TimeRecentsStartupKey);
- Console.logStartTracingTime(Constants.Log.App.TimeRecentsLaunchTask,
- Constants.Log.App.TimeRecentsLaunchKey);
- Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|toggleRecents]",
- "serviceIsBound: " + mServiceIsBound);
+ if (Console.Enabled) {
+ Console.logStartTracingTime(Constants.Log.App.TimeRecentsStartup,
+ Constants.Log.App.TimeRecentsStartupKey);
+ Console.logStartTracingTime(Constants.Log.App.TimeRecentsLaunchTask,
+ Constants.Log.App.TimeRecentsLaunchKey);
+ Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|toggleRecents]",
+ "serviceIsBound: " + mServiceIsBound);
+ }
mStatusBarView = statusBarView;
mTriggeredFromAltTab = false;
if (!mServiceIsBound) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Console.java b/packages/SystemUI/src/com/android/systemui/recents/Console.java
index c8d97cc..33e05dd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Console.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Console.java
@@ -42,6 +42,9 @@
public static final String AnsiCyan = "\u001B[36m"; // ClickEvents
public static final String AnsiWhite = "\u001B[37m";
+ // Console enabled state
+ public static final boolean Enabled = false;
+
/** Logs a key */
public static void log(String key) {
log(true, key, "", AnsiReset);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 79545b3..fcbd0f4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -31,8 +31,6 @@
public static final boolean EnableTaskStackClipping = false;
// Enables the use of theme colors as the task bar background
public static final boolean EnableTaskBarThemeColors = true;
- // Enables the info pane on long-pressing the task
- public static final boolean EnableInfoPane = false;
// Enables app-info pane on long-pressing the icon
public static final boolean EnableDevAppInfoOnLongPress = true;
// Enables the search bar layout
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index bae8a99..e7119f6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -80,8 +80,10 @@
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
- Console.log(Constants.Log.App.SystemUIHandshake,
- "[RecentsActivity|serviceBroadcast]", action, Console.AnsiRed);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.SystemUIHandshake,
+ "[RecentsActivity|serviceBroadcast]", action, Console.AnsiRed);
+ }
if (action.equals(RecentsService.ACTION_HIDE_RECENTS_ACTIVITY)) {
if (intent.getBooleanExtra(RecentsService.EXTRA_TRIGGERED_FROM_ALT_TAB, false)) {
// Dismiss recents, launching the focused task
@@ -164,10 +166,12 @@
ssp.unbindSearchAppWidget(mAppWidgetHost, appWidgetId);
appWidgetId = -1;
}
- Console.log(Constants.Log.App.SystemUIHandshake,
- "[RecentsActivity|onCreate|settings|appWidgetId]",
- "Id: " + appWidgetId,
- Console.AnsiBlue);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.SystemUIHandshake,
+ "[RecentsActivity|onCreate|settings|appWidgetId]",
+ "Id: " + appWidgetId,
+ Console.AnsiBlue);
+ }
}
// If there is no id, then bind a new search app widget
@@ -175,10 +179,12 @@
Pair<Integer, AppWidgetProviderInfo> widgetInfo =
ssp.bindSearchAppWidget(mAppWidgetHost);
if (widgetInfo != null) {
- Console.log(Constants.Log.App.SystemUIHandshake,
- "[RecentsActivity|onCreate|searchWidget]",
- "Id: " + widgetInfo.first + " Info: " + widgetInfo.second,
- Console.AnsiBlue);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.SystemUIHandshake,
+ "[RecentsActivity|onCreate|searchWidget]",
+ "Id: " + widgetInfo.first + " Info: " + widgetInfo.second,
+ Console.AnsiBlue);
+ }
// Save the app widget id into the settings
config.updateSearchBarAppWidgetId(this, widgetInfo.first);
@@ -194,10 +200,12 @@
RecentsConfiguration config = RecentsConfiguration.getInstance();
int appWidgetId = config.searchBarAppWidgetId;
if (appWidgetId >= 0) {
- Console.log(Constants.Log.App.SystemUIHandshake,
- "[RecentsActivity|onCreate|addSearchAppWidgetView]",
- "Id: " + appWidgetId,
- Console.AnsiBlue);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.SystemUIHandshake,
+ "[RecentsActivity|onCreate|addSearchAppWidgetView]",
+ "Id: " + appWidgetId,
+ Console.AnsiBlue);
+ }
mSearchAppWidgetHostView = mAppWidgetHost.createView(this, appWidgetId,
mSearchAppWidgetInfo);
Bundle opts = new Bundle();
@@ -230,11 +238,13 @@
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- Console.logDivider(Constants.Log.App.SystemUIHandshake);
- Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onCreate]",
- getIntent().getAction() + " visible: " + mVisible, Console.AnsiRed);
- Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
- Constants.Log.App.TimeRecentsStartupKey, "onCreate");
+ if (Console.Enabled) {
+ Console.logDivider(Constants.Log.App.SystemUIHandshake);
+ Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onCreate]",
+ getIntent().getAction() + " visible: " + mVisible, Console.AnsiRed);
+ Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
+ Constants.Log.App.TimeRecentsStartupKey, "onCreate");
+ }
// Initialize the loader and the configuration
RecentsTaskLoader.initialize(this);
@@ -277,11 +287,13 @@
// Reset the task launched flag if we encounter an onNewIntent() before onStop()
mTaskLaunched = false;
- Console.logDivider(Constants.Log.App.SystemUIHandshake);
- Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onNewIntent]",
- intent.getAction() + " visible: " + mVisible, Console.AnsiRed);
- Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
- Constants.Log.App.TimeRecentsStartupKey, "onNewIntent");
+ if (Console.Enabled) {
+ Console.logDivider(Constants.Log.App.SystemUIHandshake);
+ Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onNewIntent]",
+ intent.getAction() + " visible: " + mVisible, Console.AnsiRed);
+ Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
+ Constants.Log.App.TimeRecentsStartupKey, "onNewIntent");
+ }
// Initialize the loader and the configuration
RecentsTaskLoader.initialize(this);
@@ -296,8 +308,10 @@
@Override
protected void onStart() {
- Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onStart]", "",
- Console.AnsiRed);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onStart]", "",
+ Console.AnsiRed);
+ }
super.onStart();
mAppWidgetHost.startListening();
mVisible = true;
@@ -305,16 +319,20 @@
@Override
protected void onResume() {
- Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onResume]", "",
- Console.AnsiRed);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onResume]", "",
+ Console.AnsiRed);
+ }
super.onResume();
}
@Override
public void onAttachedToWindow() {
- Console.log(Constants.Log.App.SystemUIHandshake,
- "[RecentsActivity|onAttachedToWindow]", "",
- Console.AnsiRed);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.SystemUIHandshake,
+ "[RecentsActivity|onAttachedToWindow]", "",
+ Console.AnsiRed);
+ }
super.onAttachedToWindow();
// Register the broadcast receiver to handle messages from our service
@@ -334,9 +352,11 @@
@Override
public void onDetachedFromWindow() {
- Console.log(Constants.Log.App.SystemUIHandshake,
- "[RecentsActivity|onDetachedFromWindow]", "",
- Console.AnsiRed);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.SystemUIHandshake,
+ "[RecentsActivity|onDetachedFromWindow]", "",
+ Console.AnsiRed);
+ }
super.onDetachedFromWindow();
// Unregister any broadcast receivers we have registered
@@ -347,15 +367,19 @@
@Override
protected void onPause() {
- Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onPause]", "",
- Console.AnsiRed);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onPause]", "",
+ Console.AnsiRed);
+ }
super.onPause();
}
@Override
protected void onStop() {
- Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onStop]", "",
- Console.AnsiRed);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onStop]", "",
+ Console.AnsiRed);
+ }
super.onStop();
mAppWidgetHost.stopListening();
@@ -365,8 +389,10 @@
@Override
protected void onDestroy() {
- Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onDestroy]", "",
- Console.AnsiRed);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onDestroy]", "",
+ Console.AnsiRed);
+ }
super.onDestroy();
}
@@ -394,16 +420,9 @@
public void onBackPressed() {
boolean interceptedByInfoPanelClose = false;
- // Try and return from any open info panes
- if (Constants.DebugFlags.App.EnableInfoPane) {
- interceptedByInfoPanelClose = mRecentsView.closeOpenInfoPanes();
- }
-
- // If we haven't been intercepted already, then unfilter any stacks
- if (!interceptedByInfoPanelClose) {
- if (!mRecentsView.unfilterFilteredStacks()) {
- super.onBackPressed();
- }
+ // Unfilter any stacks
+ if (!mRecentsView.unfilterFilteredStacks()) {
+ super.onBackPressed();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 8399551..d899c7b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -95,9 +95,11 @@
Configuration.ORIENTATION_LANDSCAPE;
transposeSearchLayoutWithOrientation =
res.getBoolean(R.bool.recents_transpose_search_layout_with_orientation);
- Console.log(Constants.Log.UI.MeasureAndLayout,
- "[RecentsConfiguration|orientation]", isLandscape ? "Landscape" : "Portrait",
- Console.AnsiGreen);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.MeasureAndLayout,
+ "[RecentsConfiguration|orientation]", isLandscape ? "Landscape" : "Portrait",
+ Console.AnsiGreen);
+ }
displayRect.set(0, 0, dm.widthPixels, dm.heightPixels);
animationPxMovementPerSecond =
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
index 1c04cb1..4bdbb20 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
@@ -45,8 +45,10 @@
@Override
public void handleMessage(Message msg) {
- Console.log(Constants.Log.App.SystemUIHandshake,
- "[RecentsService|handleMessage]", msg);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.SystemUIHandshake,
+ "[RecentsService|handleMessage]", msg);
+ }
Context context = mContext.get();
if (context == null) return;
@@ -139,31 +141,41 @@
@Override
public void onCreate() {
- Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsService|onCreate]");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsService|onCreate]");
+ }
super.onCreate();
}
@Override
public IBinder onBind(Intent intent) {
- Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsService|onBind]");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsService|onBind]");
+ }
return mSystemUIMessenger.getBinder();
}
@Override
public boolean onUnbind(Intent intent) {
- Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsService|onUnbind]");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsService|onUnbind]");
+ }
return super.onUnbind(intent);
}
@Override
public void onRebind(Intent intent) {
- Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsService|onRebind]");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsService|onRebind]");
+ }
super.onRebind(intent);
}
@Override
public void onDestroy() {
- Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsService|onDestroy]");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsService|onDestroy]");
+ }
super.onDestroy();
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index 1c12ac2..4685186 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -50,7 +50,9 @@
/** Adds a new task to the load queue */
void addTask(Task t, boolean forceLoad) {
- Console.log(Constants.Log.App.TaskDataLoader, " [TaskResourceLoadQueue|addTask]");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TaskDataLoader, " [TaskResourceLoadQueue|addTask]");
+ }
if (!mQueue.contains(t)) {
mQueue.add(t);
}
@@ -67,7 +69,9 @@
* force reloaded.
*/
Pair<Task, Boolean> nextTask() {
- Console.log(Constants.Log.App.TaskDataLoader, " [TaskResourceLoadQueue|nextTask]");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TaskDataLoader, " [TaskResourceLoadQueue|nextTask]");
+ }
Task task = mQueue.poll();
Boolean forceLoadTask = null;
if (task != null) {
@@ -81,14 +85,18 @@
/** Removes a task from the load queue */
void removeTask(Task t) {
- Console.log(Constants.Log.App.TaskDataLoader, " [TaskResourceLoadQueue|removeTask]");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TaskDataLoader, " [TaskResourceLoadQueue|removeTask]");
+ }
mQueue.remove(t);
mForceLoadSet.remove(t.key);
}
/** Clears all the tasks from the load queue */
void clearTasks() {
- Console.log(Constants.Log.App.TaskDataLoader, " [TaskResourceLoadQueue|clearTasks]");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TaskDataLoader, " [TaskResourceLoadQueue|clearTasks]");
+ }
mQueue.clear();
mForceLoadSet.clear();
}
@@ -131,7 +139,9 @@
/** Restarts the loader thread */
void start(Context context) {
- Console.log(Constants.Log.App.TaskDataLoader, "[TaskResourceLoader|start]");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TaskDataLoader, "[TaskResourceLoader|start]");
+ }
mContext = context;
mCancelled = false;
mSystemServicesProxy = new SystemServicesProxy(context);
@@ -143,7 +153,9 @@
/** Requests the loader thread to stop after the current iteration */
void stop() {
- Console.log(Constants.Log.App.TaskDataLoader, "[TaskResourceLoader|stop]");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TaskDataLoader, "[TaskResourceLoader|stop]");
+ }
// Mark as cancelled for the thread to pick up
mCancelled = true;
mSystemServicesProxy = null;
@@ -157,19 +169,25 @@
@Override
public void run() {
while (true) {
- Console.log(Constants.Log.App.TaskDataLoader,
- "[TaskResourceLoader|run|" + Thread.currentThread().getId() + "]");
- if (mCancelled) {
+ if (Console.Enabled) {
Console.log(Constants.Log.App.TaskDataLoader,
- "[TaskResourceLoader|cancel|" + Thread.currentThread().getId() + "]");
+ "[TaskResourceLoader|run|" + Thread.currentThread().getId() + "]");
+ }
+ if (mCancelled) {
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TaskDataLoader,
+ "[TaskResourceLoader|cancel|" + Thread.currentThread().getId() + "]");
+ }
// We have to unset the context here, since the background thread may be using it
// when we call stop()
mContext = null;
// If we are cancelled, then wait until we are started again
synchronized(mLoadThread) {
try {
- Console.log(Constants.Log.App.TaskDataLoader,
- "[TaskResourceLoader|waitOnLoadThreadCancelled]");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TaskDataLoader,
+ "[TaskResourceLoader|waitOnLoadThreadCancelled]");
+ }
mLoadThread.wait();
} catch (InterruptedException ie) {
ie.printStackTrace();
@@ -185,10 +203,12 @@
if (t != null) {
Drawable loadIcon = mApplicationIconCache.get(t.key);
Bitmap loadThumbnail = mThumbnailCache.get(t.key);
- Console.log(Constants.Log.App.TaskDataLoader,
- " [TaskResourceLoader|load]",
- t + " icon: " + loadIcon + " thumbnail: " + loadThumbnail +
- " forceLoad: " + forceLoadTask);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TaskDataLoader,
+ " [TaskResourceLoader|load]",
+ t + " icon: " + loadIcon + " thumbnail: " + loadThumbnail +
+ " forceLoad: " + forceLoadTask);
+ }
// Load the application icon
if (loadIcon == null || forceLoadTask) {
ActivityInfo info = ssp.getActivityInfo(t.key.baseIntent.getComponent(),
@@ -196,9 +216,10 @@
Drawable icon = ssp.getActivityIcon(info, t.userId);
if (!mCancelled) {
if (icon != null) {
- Console.log(Constants.Log.App.TaskDataLoader,
- " [TaskResourceLoader|loadIcon]",
- icon);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TaskDataLoader,
+ " [TaskResourceLoader|loadIcon]", icon);
+ }
loadIcon = icon;
mApplicationIconCache.put(t.key, icon);
}
@@ -209,9 +230,10 @@
Bitmap thumbnail = ssp.getTaskThumbnail(t.key.id);
if (!mCancelled) {
if (thumbnail != null) {
- Console.log(Constants.Log.App.TaskDataLoader,
- " [TaskResourceLoader|loadThumbnail]",
- thumbnail);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TaskDataLoader,
+ " [TaskResourceLoader|loadThumbnail]", thumbnail);
+ }
thumbnail.setHasAlpha(false);
loadThumbnail = thumbnail;
mThumbnailCache.put(t.key, thumbnail);
@@ -239,8 +261,10 @@
if (!mCancelled && mLoadQueue.isEmpty()) {
synchronized(mLoadQueue) {
try {
- Console.log(Constants.Log.App.TaskDataLoader,
- "[TaskResourceLoader|waitOnLoadQueue]");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TaskDataLoader,
+ "[TaskResourceLoader|waitOnLoadQueue]");
+ }
mWaitingOnLoadQueue = true;
mLoadQueue.wait();
mWaitingOnLoadQueue = false;
@@ -320,9 +344,11 @@
int thumbnailCacheSize = Constants.DebugFlags.App.DisableBackgroundCache ? 1 :
mMaxThumbnailCacheSize;
- Console.log(Constants.Log.App.TaskDataLoader,
- "[RecentsTaskLoader|init]", "thumbnailCache: " + thumbnailCacheSize +
- " iconCache: " + iconCacheSize);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TaskDataLoader,
+ "[RecentsTaskLoader|init]", "thumbnailCache: " + thumbnailCacheSize +
+ " iconCache: " + iconCacheSize);
+ }
// Initialize the proxy, cache and loaders
mSystemServicesProxy = new SystemServicesProxy(context);
@@ -338,9 +364,11 @@
mDefaultThumbnail = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
mDefaultThumbnail.eraseColor(0x00000000);
mDefaultApplicationIcon = new BitmapDrawable(context.getResources(), icon);
- Console.log(Constants.Log.App.TaskDataLoader,
- "[RecentsTaskLoader|defaultBitmaps]",
- "icon: " + mDefaultApplicationIcon + " thumbnail: " + mDefaultThumbnail, Console.AnsiRed);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TaskDataLoader,
+ "[RecentsTaskLoader|defaultBitmaps]",
+ "icon: " + mDefaultApplicationIcon + " thumbnail: " + mDefaultThumbnail, Console.AnsiRed);
+ }
}
/** Initializes the recents task loader */
@@ -368,11 +396,13 @@
List<ActivityManager.RecentTaskInfo> tasks =
ssp.getRecentTasks(25, UserHandle.CURRENT.getIdentifier());
Collections.reverse(tasks);
- Console.log(Constants.Log.App.TimeSystemCalls,
- "[RecentsTaskLoader|getRecentTasks]",
- "" + (System.currentTimeMillis() - t1) + "ms");
- Console.log(Constants.Log.App.TaskDataLoader,
- "[RecentsTaskLoader|tasks]", "" + tasks.size());
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TimeSystemCalls,
+ "[RecentsTaskLoader|getRecentTasks]",
+ "" + (System.currentTimeMillis() - t1) + "ms");
+ Console.log(Constants.Log.App.TaskDataLoader,
+ "[RecentsTaskLoader|tasks]", "" + tasks.size());
+ }
return tasks;
}
@@ -381,7 +411,9 @@
SpaceNode reload(Context context, int preloadCount) {
long t1 = System.currentTimeMillis();
- Console.log(Constants.Log.App.TaskDataLoader, "[RecentsTaskLoader|reload]");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TaskDataLoader, "[RecentsTaskLoader|reload]");
+ }
Resources res = context.getResources();
ArrayList<Task> tasksToForceLoad = new ArrayList<Task>();
TaskStack stack = new TaskStack(context);
@@ -419,9 +451,11 @@
// Preload the specified number of apps
if (i >= (taskCount - preloadCount)) {
- Console.log(Constants.Log.App.TaskDataLoader,
- "[RecentsTaskLoader|preloadTask]",
- "i: " + i + " task: " + t.baseIntent.getComponent().getPackageName());
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TaskDataLoader,
+ "[RecentsTaskLoader|preloadTask]",
+ "i: " + i + " task: " + t.baseIntent.getComponent().getPackageName());
+ }
// Load the icon (if possible and not the foremost task, from the cache)
if (!isForemostTask) {
@@ -451,8 +485,10 @@
}
}
if (task.thumbnail == null) {
- Console.log(Constants.Log.App.TaskDataLoader,
- "[RecentsTaskLoader|loadingTaskThumbnail]");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TaskDataLoader,
+ "[RecentsTaskLoader|loadingTaskThumbnail]");
+ }
task.thumbnail = ssp.getTaskThumbnail(task.key.id);
if (task.thumbnail != null) {
task.thumbnail.setHasAlpha(false);
@@ -464,13 +500,17 @@
}
// Add the task to the stack
- Console.log(Constants.Log.App.TaskDataLoader,
- " [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TaskDataLoader,
+ " [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
+ }
stack.addTask(task);
}
- Console.log(Constants.Log.App.TimeSystemCalls,
- "[RecentsTaskLoader|getAllTaskTopThumbnail]",
- "" + (System.currentTimeMillis() - t1) + "ms");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TimeSystemCalls,
+ "[RecentsTaskLoader|getAllTaskTopThumbnail]",
+ "" + (System.currentTimeMillis() - t1) + "ms");
+ }
/*
// Get all the stacks
@@ -505,9 +545,11 @@
Drawable applicationIcon = mApplicationIconCache.get(t.key);
Bitmap thumbnail = mThumbnailCache.get(t.key);
- Console.log(Constants.Log.App.TaskDataLoader, "[RecentsTaskLoader|loadTask]",
- t + " applicationIcon: " + applicationIcon + " thumbnail: " + thumbnail +
- " thumbnailCacheSize: " + mThumbnailCache.size());
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TaskDataLoader, "[RecentsTaskLoader|loadTask]",
+ t + " applicationIcon: " + applicationIcon + " thumbnail: " + thumbnail +
+ " thumbnailCacheSize: " + mThumbnailCache.size());
+ }
boolean requiresLoad = false;
if (applicationIcon == null) {
@@ -526,9 +568,11 @@
/** Releases the task resource data back into the pool. */
public void unloadTaskData(Task t) {
- Console.log(Constants.Log.App.TaskDataLoader,
- "[RecentsTaskLoader|unloadTask]", t +
- " thumbnailCacheSize: " + mThumbnailCache.size());
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TaskDataLoader,
+ "[RecentsTaskLoader|unloadTask]", t +
+ " thumbnailCacheSize: " + mThumbnailCache.size());
+ }
mLoadQueue.removeTask(t);
t.notifyTaskDataUnloaded(mDefaultThumbnail, mDefaultApplicationIcon);
@@ -536,8 +580,10 @@
/** Completely removes the resource data from the pool. */
public void deleteTaskData(Task t, boolean notifyTaskDataUnloaded) {
- Console.log(Constants.Log.App.TaskDataLoader,
- "[RecentsTaskLoader|deleteTask]", t);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TaskDataLoader,
+ "[RecentsTaskLoader|deleteTask]", t);
+ }
mLoadQueue.removeTask(t);
mThumbnailCache.remove(t.key);
@@ -549,7 +595,9 @@
/** Stops the task loader and clears all pending tasks */
void stopLoader() {
- Console.log(Constants.Log.App.TaskDataLoader, "[RecentsTaskLoader|stopLoader]");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.TaskDataLoader, "[RecentsTaskLoader|stopLoader]");
+ }
mLoader.stop();
mLoadQueue.clearTasks();
}
@@ -570,8 +618,10 @@
* out of memory.
*/
void onTrimMemory(int level) {
- Console.log(Constants.Log.App.Memory, "[RecentsTaskLoader|onTrimMemory]",
- Console.trimMemoryLevelToString(level));
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.Memory, "[RecentsTaskLoader|onTrimMemory]",
+ Console.trimMemoryLevelToString(level));
+ }
switch (level) {
case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
diff --git a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
index 59d0ea6..7a3ffb8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
@@ -106,7 +106,8 @@
rti.description = description;
if (i % 2 == 0) {
rti.taskDescription = new ActivityManager.TaskDescription(description,
- Bitmap.createBitmap(mDummyIcon), new Random().nextInt());
+ Bitmap.createBitmap(mDummyIcon),
+ 0xFF000000 | (0xFFFFFF & new Random().nextInt()));
} else {
rti.taskDescription = new ActivityManager.TaskDescription();
}
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 c63e688..cad9ce5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -110,16 +110,20 @@
TaskView tv = (TaskView) stackView.getChildAt(j);
Task task = tv.getTask();
if (tv.isFocusedTask()) {
- Console.log(Constants.Log.UI.Focus, "[RecentsView|launchFocusedTask]",
- "Found focused Task");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.Focus, "[RecentsView|launchFocusedTask]",
+ "Found focused Task");
+ }
onTaskLaunched(stackView, tv, stack, task);
return true;
}
}
}
}
- Console.log(Constants.Log.UI.Focus, "[RecentsView|launchFocusedTask]",
- "No Tasks focused");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.Focus, "[RecentsView|launchFocusedTask]",
+ "No Tasks focused");
+ }
return false;
}
@@ -168,9 +172,11 @@
mSearchBar.setVisibility(mHasTasks ? View.VISIBLE : View.GONE);
addView(mSearchBar);
- Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsView|setSearchBar]",
- "" + (mSearchBar.getVisibility() == View.VISIBLE),
- Console.AnsiBlue);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsView|setSearchBar]",
+ "" + (mSearchBar.getVisibility() == View.VISIBLE),
+ Console.AnsiBlue);
+ }
}
}
}
@@ -185,10 +191,12 @@
int height = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- Console.log(Constants.Log.UI.MeasureAndLayout, "[RecentsView|measure]",
- "width: " + width + " height: " + height, Console.AnsiGreen);
- Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
- Constants.Log.App.TimeRecentsStartupKey, "RecentsView.onMeasure");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.MeasureAndLayout, "[RecentsView|measure]",
+ "width: " + width + " height: " + height, Console.AnsiGreen);
+ Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
+ Constants.Log.App.TimeRecentsStartupKey, "RecentsView.onMeasure");
+ }
// Get the search bar bounds and measure the search bar layout
RecentsConfiguration config = RecentsConfiguration.getInstance();
@@ -227,10 +235,12 @@
*/
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- Console.log(Constants.Log.UI.MeasureAndLayout, "[RecentsView|layout]",
- new Rect(left, top, right, bottom) + " changed: " + changed, Console.AnsiGreen);
- Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
- Constants.Log.App.TimeRecentsStartupKey, "RecentsView.onLayout");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.MeasureAndLayout, "[RecentsView|layout]",
+ new Rect(left, top, right, bottom) + " changed: " + changed, Console.AnsiGreen);
+ Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
+ Constants.Log.App.TimeRecentsStartupKey, "RecentsView.onLayout");
+ }
// Get the search bar bounds so that we lay it out
RecentsConfiguration config = RecentsConfiguration.getInstance();
@@ -283,15 +293,19 @@
@Override
protected void dispatchDraw(Canvas canvas) {
- Console.log(Constants.Log.UI.Draw, "[RecentsView|dispatchDraw]", "",
- Console.AnsiPurple);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.Draw, "[RecentsView|dispatchDraw]", "",
+ Console.AnsiPurple);
+ }
super.dispatchDraw(canvas);
}
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- Console.log(Constants.Log.UI.MeasureAndLayout,
- "[RecentsView|fitSystemWindows]", "insets: " + insets, Console.AnsiGreen);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.MeasureAndLayout,
+ "[RecentsView|fitSystemWindows]", "insets: " + insets, Console.AnsiGreen);
+ }
// Update the configuration with the latest system insets and trigger a relayout
RecentsConfiguration config = RecentsConfiguration.getInstance();
@@ -301,24 +315,6 @@
return insets.consumeSystemWindowInsets(false, false, false, true);
}
- /** Closes any open info panes */
- public boolean closeOpenInfoPanes() {
- if (mBSP != null) {
- // Get the first stack view
- int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- View child = getChildAt(i);
- if (child instanceof TaskStackView) {
- TaskStackView stackView = (TaskStackView) child;
- if (stackView.closeOpenInfoPanes()) {
- return true;
- }
- }
- }
- }
- return false;
- }
-
/** Unfilters any filtered stacks */
public boolean unfilterFilteredStacks() {
if (mBSP != null) {
@@ -346,9 +342,6 @@
mCb.onTaskLaunching();
}
- // Close any open info panes
- closeOpenInfoPanes();
-
final Runnable launchRunnable = new Runnable() {
@Override
public void run() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java
index c34300c..3ee0545 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java
@@ -178,9 +178,11 @@
}
public boolean onInterceptTouchEvent(MotionEvent ev) {
- Console.log(Constants.Log.UI.TouchEvents,
- "[SwipeHelper|interceptTouchEvent]",
- Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.TouchEvents,
+ "[SwipeHelper|interceptTouchEvent]",
+ Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+ }
final int action = ev.getAction();
switch (action) {
@@ -291,9 +293,11 @@
}
public boolean onTouchEvent(MotionEvent ev) {
- Console.log(Constants.Log.UI.TouchEvents,
- "[SwipeHelper|touchEvent]",
- Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.TouchEvents,
+ "[SwipeHelper|touchEvent]",
+ Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+ }
if (!mDragging) {
if (!onInterceptTouchEvent(ev)) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
deleted file mode 100644
index 7b6572b..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.Canvas;
-import android.graphics.Path;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.graphics.drawable.RippleDrawable;
-import android.util.AttributeSet;
-import android.widget.Button;
-import android.widget.FrameLayout;
-import com.android.systemui.R;
-import com.android.systemui.recents.Constants;
-import com.android.systemui.recents.RecentsConfiguration;
-import com.android.systemui.recents.Utilities;
-import com.android.systemui.recents.model.Task;
-
-
-/* The task info view */
-class TaskInfoView extends FrameLayout {
-
- Button mAppInfoButton;
-
- // Circular clip animation
- boolean mCircularClipEnabled;
- Path mClipPath = new Path();
- float mClipRadius;
- float mMaxClipRadius;
- Point mClipOrigin = new Point();
- ObjectAnimator mCircularClipAnimator;
-
- public TaskInfoView(Context context) {
- this(context, null);
- }
-
- public TaskInfoView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public TaskInfoView(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public TaskInfoView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- }
-
- @Override
- protected void onFinishInflate() {
- // Initialize the buttons on the info panel
- mAppInfoButton = (Button) findViewById(R.id.task_view_app_info_button);
- }
-
- /** Updates the positions of each of the items to fit in the rect specified */
- void updateContents(Rect visibleRect) {
- // Offset the app info button
- mAppInfoButton.setTranslationY(visibleRect.top +
- (visibleRect.height() - mAppInfoButton.getMeasuredHeight()) / 2);
- }
-
- /** Sets the circular clip radius on this panel */
- public void setCircularClipRadius(float r) {
- mClipRadius = r;
- invalidate();
- }
-
- /** Gets the circular clip radius on this panel */
- public float getCircularClipRadius() {
- return mClipRadius;
- }
-
- /** Animates the circular clip radius on the icon */
- void animateCircularClip(Point o, float fromRadius, float toRadius,
- final Runnable postRunnable, boolean animateInContent) {
- if (mCircularClipAnimator != null) {
- mCircularClipAnimator.cancel();
- }
-
- // Calculate the max clip radius to each of the corners
- int w = getMeasuredWidth() - o.x;
- int h = getMeasuredHeight() - o.y;
- // origin to tl, tr, br, bl
- mMaxClipRadius = (int) Math.ceil(Math.sqrt(o.x * o.x + o.y * o.y));
- mMaxClipRadius = (int) Math.max(mMaxClipRadius, Math.ceil(Math.sqrt(w * w + o.y * o.y)));
- mMaxClipRadius = (int) Math.max(mMaxClipRadius, Math.ceil(Math.sqrt(w * w + h * h)));
- mMaxClipRadius = (int) Math.max(mMaxClipRadius, Math.ceil(Math.sqrt(o.x * o.x + h * h)));
-
- mClipOrigin.set(o.x, o.y);
- mClipRadius = fromRadius;
- int duration = Utilities.calculateTranslationAnimationDuration((int) mMaxClipRadius);
- mCircularClipAnimator = ObjectAnimator.ofFloat(this, "circularClipRadius", toRadius);
- mCircularClipAnimator.setDuration(duration);
- mCircularClipAnimator.setInterpolator(
- RecentsConfiguration.getInstance().defaultBezierInterpolator);
- mCircularClipAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mCircularClipEnabled = false;
- if (postRunnable != null) {
- postRunnable.run();
- }
- }
- });
- mCircularClipAnimator.start();
- mCircularClipEnabled = true;
-
- if (animateInContent) {
- animateAppInfoButtonIn(duration);
- }
- }
-
- /** Cancels the circular clip animation. */
- void cancelCircularClipAnimation() {
- if (mCircularClipAnimator != null) {
- mCircularClipAnimator.cancel();
- }
- }
-
- void animateAppInfoButtonIn(int duration) {
- mAppInfoButton.setScaleX(0.75f);
- mAppInfoButton.setScaleY(0.75f);
- mAppInfoButton.animate()
- .scaleX(1f)
- .scaleY(1f)
- .setDuration(duration)
- .setInterpolator(RecentsConfiguration.getInstance().defaultBezierInterpolator)
- .withLayer()
- .start();
- }
-
- /** Binds the info view to the task */
- void rebindToTask(Task t, boolean animate) {
- RecentsConfiguration configuration = RecentsConfiguration.getInstance();
- if (Constants.DebugFlags.App.EnableTaskBarThemeColors && t.colorPrimary != 0) {
- setBackgroundColor(t.colorPrimary);
- // Workaround: The button currently doesn't support setting a custom background tint
- // not defined in the theme. Just lower the alpha on the button to make it blend more
- // into the background.
- if (mAppInfoButton.getBackground() instanceof RippleDrawable) {
- RippleDrawable d = (RippleDrawable) mAppInfoButton.getBackground();
- if (d != null) {
- d.setAlpha(96);
- }
- }
- } else {
- setBackgroundColor(configuration.taskBarViewDefaultBackgroundColor);
- }
- }
-
- @Override
- public void draw(Canvas canvas) {
- int saveCount = 0;
- if (mCircularClipEnabled) {
- saveCount = canvas.save(Canvas.CLIP_SAVE_FLAG);
- mClipPath.reset();
- mClipPath.addCircle(mClipOrigin.x, mClipOrigin.y, mClipRadius * mMaxClipRadius,
- Path.Direction.CW);
- canvas.clipPath(mClipPath);
- }
- super.draw(canvas);
- if (mCircularClipEnabled) {
- canvas.restoreToCount(saveCount);
- }
- }
-}
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 37c3c35..3e418ca 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -54,7 +54,7 @@
/* The visual representation of a task stack view */
public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCallbacks,
TaskView.TaskViewCallbacks, ViewPool.ViewPoolConsumer<TaskView, Task>,
- View.OnClickListener, View.OnLongClickListener, RecentsPackageMonitor.PackageCallbacks {
+ View.OnClickListener, RecentsPackageMonitor.PackageCallbacks {
/** The TaskView callbacks */
interface TaskStackViewCallbacks {
@@ -79,7 +79,6 @@
int mMinScroll;
int mMaxScroll;
int mStashedScroll;
- int mLastInfoPaneStackScroll;
int mFocusedTaskIndex = -1;
OverScroller mScroller;
ObjectAnimator mScrollAnimator;
@@ -114,8 +113,10 @@
requestSynchronizeStackViewsWithModel(0);
}
void requestSynchronizeStackViewsWithModel(int duration) {
- Console.log(Constants.Log.TaskStack.SynchronizeViewsWithModel,
- "[TaskStackView|requestSynchronize]", "" + duration + "ms", Console.AnsiYellow);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.TaskStack.SynchronizeViewsWithModel,
+ "[TaskStackView|requestSynchronize]", "" + duration + "ms", Console.AnsiYellow);
+ }
if (!mStackViewsDirty) {
invalidate();
}
@@ -222,9 +223,11 @@
/** Synchronizes the views with the model */
void synchronizeStackViewsWithModel() {
- Console.log(Constants.Log.TaskStack.SynchronizeViewsWithModel,
- "[TaskStackView|synchronizeViewsWithModel]",
- "mStackViewsDirty: " + mStackViewsDirty, Console.AnsiYellow);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.TaskStack.SynchronizeViewsWithModel,
+ "[TaskStackView|synchronizeViewsWithModel]",
+ "mStackViewsDirty: " + mStackViewsDirty, Console.AnsiYellow);
+ }
if (mStackViewsDirty) {
// XXX: Consider using TaskViewTransform pool to prevent allocations
// XXX: Iterate children views, update transforms and remove all that are not visible
@@ -278,8 +281,10 @@
}
}
- Console.log(Constants.Log.TaskStack.SynchronizeViewsWithModel,
- " [TaskStackView|viewChildren]", "" + getChildCount());
+ if (Console.Enabled) {
+ Console.log(Constants.Log.TaskStack.SynchronizeViewsWithModel,
+ " [TaskStackView|viewChildren]", "" + getChildCount());
+ }
mStackViewsAnimationDuration = 0;
mStackViewsDirty = false;
@@ -290,17 +295,6 @@
public void setStackScroll(int value) {
mStackScroll = value;
requestSynchronizeStackViewsWithModel();
-
- // Close any open info panes if the user has scrolled away from them
- boolean isAnimatingScroll = (mScrollAnimator != null && mScrollAnimator.isRunning());
- if (mLastInfoPaneStackScroll > -1 && !isAnimatingScroll) {
- RecentsConfiguration config = RecentsConfiguration.getInstance();
- if (Math.abs(mStackScroll - mLastInfoPaneStackScroll) >
- config.taskStackScrollDismissInfoPaneDistance) {
- // Close any open info panes
- closeOpenInfoPanes();
- }
- }
}
/** Sets the current stack scroll without synchronizing the stack view with the model */
public void setStackScrollRaw(int value) {
@@ -455,24 +449,11 @@
}
}
- /** Closes any open info panes. */
- boolean closeOpenInfoPanes() {
- if (!Constants.DebugFlags.App.EnableInfoPane) return false;
-
- int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- TaskView tv = (TaskView) getChildAt(i);
- if (tv.isInfoPaneVisible()) {
- tv.hideInfoPane();
- return true;
- }
- }
- return false;
- }
-
/** Focuses the task at the specified index in the stack */
void focusTask(int taskIndex, boolean scrollToNewPosition) {
- Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusTask]", "" + taskIndex);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusTask]", "" + taskIndex);
+ }
if (0 <= taskIndex && taskIndex < mStack.getTaskCount()) {
mFocusedTaskIndex = taskIndex;
@@ -482,7 +463,9 @@
Runnable postScrollRunnable = null;
if (tv != null) {
tv.setFocusedTask();
- Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusTask]", "Requesting focus");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusTask]", "Requesting focus");
+ }
} else {
postScrollRunnable = new Runnable() {
@Override
@@ -491,8 +474,10 @@
TaskView tv = getChildViewForTask(t);
if (tv != null) {
tv.setFocusedTask();
- Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusTask]",
- "Requesting focus after scroll animation");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusTask]",
+ "Requesting focus after scroll animation");
+ }
}
}
};
@@ -514,7 +499,10 @@
/** Focuses the next task in the stack */
void focusNextTask(boolean forward) {
- Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusNextTask]", "" + mFocusedTaskIndex);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusNextTask]", "" +
+ mFocusedTaskIndex);
+ }
// Find the next index to focus
int numTasks = mStack.getTaskCount();
@@ -530,9 +518,11 @@
/** Enables the hw layers and increments the hw layer requirement ref count */
void addHwLayersRefCount(String reason) {
- Console.log(Constants.Log.UI.HwLayers,
- "[TaskStackView|addHwLayersRefCount] refCount: " +
- mHwLayersRefCount + "->" + (mHwLayersRefCount + 1) + " " + reason);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.HwLayers,
+ "[TaskStackView|addHwLayersRefCount] refCount: " +
+ mHwLayersRefCount + "->" + (mHwLayersRefCount + 1) + " " + reason);
+ }
if (mHwLayersRefCount == 0) {
// Enable hw layers on each of the children
int childCount = getChildCount();
@@ -547,9 +537,11 @@
/** Decrements the hw layer requirement ref count and disables the hw layers when we don't
need them anymore. */
void decHwLayersRefCount(String reason) {
- Console.log(Constants.Log.UI.HwLayers,
- "[TaskStackView|decHwLayersRefCount] refCount: " +
- mHwLayersRefCount + "->" + (mHwLayersRefCount - 1) + " " + reason);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.HwLayers,
+ "[TaskStackView|decHwLayersRefCount] refCount: " +
+ mHwLayersRefCount + "->" + (mHwLayersRefCount - 1) + " " + reason);
+ }
mHwLayersRefCount--;
if (mHwLayersRefCount == 0) {
// Disable hw layers on each of the children
@@ -589,8 +581,10 @@
@Override
public void dispatchDraw(Canvas canvas) {
- Console.log(Constants.Log.UI.Draw, "[TaskStackView|dispatchDraw]", "",
- Console.AnsiPurple);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.Draw, "[TaskStackView|dispatchDraw]", "",
+ Console.AnsiPurple);
+ }
synchronizeStackViewsWithModel();
super.dispatchDraw(canvas);
}
@@ -674,9 +668,11 @@
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
- Console.log(Constants.Log.UI.MeasureAndLayout, "[TaskStackView|measure]",
- "width: " + width + " height: " + height +
- " awaitingFirstLayout: " + mAwaitingFirstLayout, Console.AnsiGreen);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.MeasureAndLayout, "[TaskStackView|measure]",
+ "width: " + width + " height: " + height +
+ " awaitingFirstLayout: " + mAwaitingFirstLayout, Console.AnsiGreen);
+ }
// Compute our stack/task rects
RecentsConfiguration config = RecentsConfiguration.getInstance();
@@ -731,8 +727,10 @@
*/
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- Console.log(Constants.Log.UI.MeasureAndLayout, "[TaskStackView|layout]",
- "" + new Rect(left, top, right, bottom), Console.AnsiGreen);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.MeasureAndLayout, "[TaskStackView|layout]",
+ "" + new Rect(left, top, right, bottom), Console.AnsiGreen);
+ }
// Debug logging
if (Constants.Log.UI.MeasureAndLayout) {
@@ -949,9 +947,6 @@
@Override
public void onStackFiltered(TaskStack newStack, final ArrayList<Task> curTasks,
Task filteredTask) {
- // Close any open info panes
- closeOpenInfoPanes();
-
// Stash the scroll and filtered task for us to restore to when we unfilter
mStashedScroll = getStackScroll();
@@ -976,9 +971,6 @@
@Override
public void onStackUnfiltered(TaskStack newStack, final ArrayList<Task> curTasks) {
- // Close any open info panes
- closeOpenInfoPanes();
-
// Calculate the current task transforms
final ArrayList<TaskViewTransform> curTaskTransforms =
getStackTransforms(curTasks, getStackScroll(), null, true);
@@ -1004,7 +996,9 @@
@Override
public TaskView createView(Context context) {
- Console.log(Constants.Log.ViewPool.PoolCallbacks, "[TaskStackView|createPoolView]");
+ if (Console.Enabled) {
+ Console.log(Constants.Log.ViewPool.PoolCallbacks, "[TaskStackView|createPoolView]");
+ }
return (TaskView) mInflater.inflate(R.layout.recents_task_view, this, false);
}
@@ -1012,8 +1006,10 @@
public void prepareViewToEnterPool(TaskView tv) {
Task task = tv.getTask();
tv.resetViewProperties();
- Console.log(Constants.Log.ViewPool.PoolCallbacks, "[TaskStackView|returnToPool]",
- tv.getTask() + " tv: " + tv);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.ViewPool.PoolCallbacks, "[TaskStackView|returnToPool]",
+ tv.getTask() + " tv: " + tv);
+ }
// Report that this tasks's data is no longer being used
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
@@ -1028,8 +1024,10 @@
@Override
public void prepareViewToLeavePool(TaskView tv, Task prepareData, boolean isNewView) {
- Console.log(Constants.Log.ViewPool.PoolCallbacks, "[TaskStackView|leavePool]",
- "isNewView: " + isNewView);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.ViewPool.PoolCallbacks, "[TaskStackView|leavePool]",
+ "isNewView: " + isNewView);
+ }
// Setup and attach the view to the window
Task task = prepareData;
@@ -1051,16 +1049,15 @@
}
// Add/attach the view to the hierarchy
- Console.log(Constants.Log.ViewPool.PoolCallbacks, " [TaskStackView|insertIndex]",
- "" + insertIndex);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.ViewPool.PoolCallbacks, " [TaskStackView|insertIndex]",
+ "" + insertIndex);
+ }
if (isNewView) {
addView(tv, insertIndex);
// Set the callbacks and listeners for this new view
tv.setOnClickListener(this);
- if (Constants.DebugFlags.App.EnableInfoPane) {
- tv.setOnLongClickListener(this);
- }
tv.setCallbacks(this);
} else {
attachViewToParent(tv, insertIndex, tv.getLayoutParams());
@@ -1081,9 +1078,11 @@
@Override
public void onTaskIconClicked(TaskView tv) {
- Console.log(Constants.Log.UI.ClickEvents, "[TaskStack|Clicked|Icon]",
- tv.getTask() + " is currently filtered: " + mStack.hasFilteredTasks(),
- Console.AnsiCyan);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.ClickEvents, "[TaskStack|Clicked|Icon]",
+ tv.getTask() + " is currently filtered: " + mStack.hasFilteredTasks(),
+ Console.AnsiCyan);
+ }
if (Constants.DebugFlags.App.EnableTaskFiltering) {
if (mStack.hasFilteredTasks()) {
mStack.unfilterTasks();
@@ -1094,17 +1093,6 @@
}
@Override
- public void onTaskInfoPanelShown(TaskView tv) {
- // Do nothing
- }
-
- @Override
- public void onTaskInfoPanelHidden(TaskView tv) {
- // Unset the saved scroll
- mLastInfoPaneStackScroll = -1;
- }
-
- @Override
public void onTaskAppInfoClicked(TaskView tv) {
if (mCb != null) {
mCb.onTaskAppInfoLaunched(tv.getTask());
@@ -1126,12 +1114,9 @@
public void onClick(View v) {
TaskView tv = (TaskView) v;
Task task = tv.getTask();
- Console.log(Constants.Log.UI.ClickEvents, "[TaskStack|Clicked|Thumbnail]",
- task + " cb: " + mCb);
-
- // Close any open info panes if the user taps on another task
- if (closeOpenInfoPanes()) {
- return;
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.ClickEvents, "[TaskStack|Clicked|Thumbnail]",
+ task + " cb: " + mCb);
}
if (mCb != null) {
@@ -1139,42 +1124,6 @@
}
}
- @Override
- public boolean onLongClick(View v) {
- if (!Constants.DebugFlags.App.EnableInfoPane) return false;
-
- TaskView tv = (TaskView) v;
-
- // Close any other task info panels if we launch another info pane
- closeOpenInfoPanes();
-
- // Scroll the task view so that it is maximally visible
- float overlapHeight = Constants.Values.TaskStackView.StackOverlapPct * mTaskRect.height();
- int taskIndex = mStack.indexOfTask(tv.getTask());
- int curScroll = getStackScroll();
- int newScroll = (int) Math.max(mMinScroll, Math.min(mMaxScroll, taskIndex * overlapHeight));
- TaskViewTransform transform = getStackTransform(taskIndex, curScroll);
- Rect nonOverlapRect = new Rect(transform.rect);
- if (taskIndex < (mStack.getTaskCount() - 1)) {
- nonOverlapRect.bottom = nonOverlapRect.top + (int) overlapHeight;
- }
-
- // XXX: Use HW Layers
- if (transform.t < 0f) {
- animateScroll(curScroll, newScroll, null);
- } else if (nonOverlapRect.bottom > mStackRectSansPeek.bottom) {
- // Check if we are out of bounds, if so, just scroll it in such that the bottom of the
- // task view is visible
- newScroll = curScroll - (mStackRectSansPeek.bottom - nonOverlapRect.bottom);
- animateScroll(curScroll, newScroll, null);
- }
- mLastInfoPaneStackScroll = newScroll;
-
- // Show the info pane for this task view
- tv.showInfoPane(new Rect(0, 0, 0, (int) overlapHeight));
- return true;
- }
-
/**** RecentsPackageMonitor.PackageCallbacks Implementation ****/
@Override
@@ -1278,9 +1227,11 @@
/** Touch preprocessing for handling below */
public boolean onInterceptTouchEvent(MotionEvent ev) {
- Console.log(Constants.Log.UI.TouchEvents,
- "[TaskStackViewTouchHandler|interceptTouchEvent]",
- Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.TouchEvents,
+ "[TaskStackViewTouchHandler|interceptTouchEvent]",
+ Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+ }
// Return early if we have no children
boolean hasChildren = (mSv.getChildCount() > 0);
@@ -1362,9 +1313,11 @@
/** Handles touch events once we have intercepted them */
public boolean onTouchEvent(MotionEvent ev) {
- Console.log(Constants.Log.UI.TouchEvents,
- "[TaskStackViewTouchHandler|touchEvent]",
- Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.TouchEvents,
+ "[TaskStackViewTouchHandler|touchEvent]",
+ Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+ }
// Short circuit if we have no children
boolean hasChildren = (mSv.getChildCount() > 0);
@@ -1465,12 +1418,14 @@
Math.abs((float) velocity / mMaximumVelocity)) *
Constants.Values.TaskStackView.TaskStackOverscrollRange);
- Console.log(Constants.Log.UI.TouchEvents,
- "[TaskStackViewTouchHandler|fling]",
- "scroll: " + mSv.getStackScroll() + " velocity: " + velocity +
- " maxVelocity: " + mMaximumVelocity +
- " overscrollRange: " + overscrollRange,
- Console.AnsiGreen);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.TouchEvents,
+ "[TaskStackViewTouchHandler|fling]",
+ "scroll: " + mSv.getStackScroll() + " velocity: " + velocity +
+ " maxVelocity: " + mMaximumVelocity +
+ " overscrollRange: " + overscrollRange,
+ Console.AnsiGreen);
+ }
// Fling scroll
mSv.mScroller.fling(0, mSv.getStackScroll(),
@@ -1550,13 +1505,6 @@
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
- // If the info panel is currently showing on this view, then we need to dismiss it
- if (Constants.DebugFlags.App.EnableInfoPane) {
- TaskView tv = (TaskView) v;
- if (tv.isInfoPaneVisible()) {
- tv.hideInfoPane();
- }
- }
}
@Override
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 46af4c1..16a3f45 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -44,8 +44,6 @@
/** The TaskView callbacks */
interface TaskViewCallbacks {
public void onTaskIconClicked(TaskView tv);
- public void onTaskInfoPanelShown(TaskView tv);
- public void onTaskInfoPanelHidden(TaskView tv);
public void onTaskAppInfoClicked(TaskView tv);
public void onTaskDismissed(TaskView tv);
@@ -58,14 +56,12 @@
Task mTask;
boolean mTaskDataLoaded;
- boolean mTaskInfoPaneVisible;
boolean mIsFocused;
Point mLastTouchDown = new Point();
Path mRoundedRectClipPath = new Path();
TaskThumbnailView mThumbnailView;
TaskBarView mBarView;
- TaskInfoView mInfoView;
TaskViewCallbacks mCb;
@@ -94,7 +90,6 @@
// Bind the views
mThumbnailView = (TaskThumbnailView) findViewById(R.id.task_view_thumbnail);
mBarView = (TaskBarView) findViewById(R.id.task_view_bar);
- mInfoView = (TaskInfoView) findViewById(R.id.task_view_info_pane);
if (mTaskDataLoaded) {
onTaskDataLoaded(false);
@@ -280,63 +275,6 @@
return outRect;
}
- /** Returns whether this task has an info pane visible */
- boolean isInfoPaneVisible() {
- return mTaskInfoPaneVisible;
- }
-
- /** Shows the info pane if it is not visible. */
- void showInfoPane(Rect taskVisibleRect) {
- if (mTaskInfoPaneVisible) return;
-
- // Remove the bar view from the visible rect and update the info pane contents
- taskVisibleRect.top += mBarView.getMeasuredHeight();
- mInfoView.updateContents(taskVisibleRect);
-
- // Show the info pane and animate it into view
- mInfoView.setVisibility(View.VISIBLE);
- mInfoView.animateCircularClip(mLastTouchDown, 0f, 1f, null, true);
- mInfoView.setOnClickListener(this);
- mTaskInfoPaneVisible = true;
-
- // Notify any callbacks
- if (mCb != null) {
- mCb.onTaskInfoPanelShown(this);
- }
- }
-
- /** Hides the info pane if it is visible. */
- void hideInfoPane() {
- if (!mTaskInfoPaneVisible) return;
- RecentsConfiguration config = RecentsConfiguration.getInstance();
-
- // Cancel any circular clip animation
- mInfoView.cancelCircularClipAnimation();
-
- // Animate the info pane out
- mInfoView.animate()
- .alpha(0f)
- .setDuration(config.taskViewInfoPaneAnimDuration)
- .setInterpolator(config.defaultBezierInterpolator)
- .withLayer()
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- mInfoView.setVisibility(View.INVISIBLE);
- mInfoView.setOnClickListener(null);
-
- mInfoView.setAlpha(1f);
- }
- })
- .start();
- mTaskInfoPaneVisible = false;
-
- // Notify any callbacks
- if (mCb != null) {
- mCb.onTaskInfoPanelHidden(this);
- }
- }
-
/** Enable the hw layers on this task view */
void enableHwLayers() {
mThumbnailView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
@@ -354,7 +292,6 @@
float dim = (1f - getScaleX()) / scaleRange;
dim = mDimInterpolator.getInterpolation(Math.min(dim, 1f));
mDim = Math.max(0, Math.min(mMaxDim, (int) (dim * 255)));
- invalidate();
}
@Override
@@ -408,11 +345,10 @@
@Override
public void onTaskDataLoaded(boolean reloadingTaskData) {
- if (mThumbnailView != null && mBarView != null && mInfoView != null) {
+ if (mThumbnailView != null && mBarView != null) {
// Bind each of the views to the new task data
mThumbnailView.rebindToTask(mTask, reloadingTaskData);
mBarView.rebindToTask(mTask, reloadingTaskData);
- mInfoView.rebindToTask(mTask, reloadingTaskData);
// Rebind any listeners
mBarView.mApplicationIcon.setOnClickListener(this);
mBarView.mDismissButton.setOnClickListener(this);
@@ -424,16 +360,13 @@
mBarView.mApplicationIcon.setOnLongClickListener(this);
}
}
- if (Constants.DebugFlags.App.EnableInfoPane) {
- mInfoView.mAppInfoButton.setOnClickListener(this);
- }
}
mTaskDataLoaded = true;
}
@Override
public void onTaskDataUnloaded() {
- if (mThumbnailView != null && mBarView != null && mInfoView != null) {
+ if (mThumbnailView != null && mBarView != null) {
// Unbind each of the views from the task data and remove the task callback
mTask.setCallbacks(null);
mThumbnailView.unbindFromTask();
@@ -444,18 +377,13 @@
if (Constants.DebugFlags.App.EnableDevAppInfoOnLongPress) {
mBarView.mApplicationIcon.setOnLongClickListener(null);
}
- if (Constants.DebugFlags.App.EnableInfoPane) {
- mInfoView.mAppInfoButton.setOnClickListener(null);
- }
}
mTaskDataLoaded = false;
}
@Override
public void onClick(View v) {
- if (v == mInfoView) {
- hideInfoPane();
- } else if (v == mBarView.mApplicationIcon) {
+ if (v == mBarView.mApplicationIcon) {
mCb.onTaskIconClicked(this);
} else if (v == mBarView.mDismissButton) {
// Animate out the view and call the callback
@@ -466,8 +394,6 @@
mCb.onTaskDismissed(tv);
}
});
- } else if (v == mInfoView.mAppInfoButton) {
- mCb.onTaskAppInfoClicked(this);
}
}
@@ -479,4 +405,4 @@
}
return false;
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index dc3d92a..ac16164 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -45,7 +45,6 @@
= new PathInterpolator(0.6f, 0, 0.5f, 1);
private static final Interpolator ACTIVATE_INVERSE_ALPHA_INTERPOLATOR
= new PathInterpolator(0, 0, 0.5f, 1);
- private final int mMaxNotificationHeight;
private boolean mDimmed;
@@ -81,8 +80,6 @@
AnimationUtils.loadInterpolator(context, android.R.interpolator.fast_out_slow_in);
mLinearOutSlowInInterpolator =
AnimationUtils.loadInterpolator(context, android.R.interpolator.linear_out_slow_in);
- mMaxNotificationHeight = getResources().getDimensionPixelSize(
- R.dimen.notification_max_height);
setClipChildren(false);
setClipToPadding(false);
}
@@ -92,7 +89,7 @@
super.onFinishInflate();
mBackgroundNormal = (NotificationBackgroundView) findViewById(R.id.backgroundNormal);
mBackgroundDimmed = (NotificationBackgroundView) findViewById(R.id.backgroundDimmed);
- updateBackgroundResource();
+ updateBackgroundResources();
}
private final Runnable mTapTimeoutRunnable = new Runnable() {
@@ -218,9 +215,9 @@
if (mDimmed != dimmed) {
mDimmed = dimmed;
if (fade) {
- fadeBackgroundResource();
+ fadeBackground();
} else {
- updateBackgroundResource();
+ updateBackground();
}
}
}
@@ -236,14 +233,14 @@
mBgTint = bgTint;
mDimmedBgResId = dimmedBgResId;
mDimmedBgTint = dimmedTint;
- updateBackgroundResource();
+ updateBackgroundResources();
}
public void setBackgroundResourceIds(int bgResId, int dimmedBgResId) {
setBackgroundResourceIds(bgResId, 0, dimmedBgResId, 0);
}
- private void fadeBackgroundResource() {
+ private void fadeBackground() {
if (mDimmed) {
mBackgroundDimmed.setVisibility(View.VISIBLE);
} else {
@@ -259,7 +256,7 @@
mBackgroundAnimator.removeAllListeners();
mBackgroundAnimator.cancel();
if (duration <= 0) {
- updateBackgroundResource();
+ updateBackground();
return;
}
}
@@ -282,38 +279,20 @@
mBackgroundAnimator.start();
}
- private void updateBackgroundResource() {
+ private void updateBackground() {
if (mDimmed) {
mBackgroundDimmed.setVisibility(View.VISIBLE);
- mBackgroundDimmed.setCustomBackground(mDimmedBgResId, mDimmedBgTint);
mBackgroundNormal.setVisibility(View.INVISIBLE);
} else {
mBackgroundDimmed.setVisibility(View.INVISIBLE);
mBackgroundNormal.setVisibility(View.VISIBLE);
- mBackgroundNormal.setCustomBackground(mBgResId, mBgTint);
mBackgroundNormal.setAlpha(1f);
}
}
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int newHeightSpec = MeasureSpec.makeMeasureSpec(mMaxNotificationHeight,
- MeasureSpec.AT_MOST);
- int maxChildHeight = 0;
- int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- View child = getChildAt(i);
- if (child != mBackgroundDimmed && child != mBackgroundNormal) {
- child.measure(widthMeasureSpec, newHeightSpec);
- int childHeight = child.getMeasuredHeight();
- maxChildHeight = Math.max(maxChildHeight, childHeight);
- }
- }
- newHeightSpec = MeasureSpec.makeMeasureSpec(maxChildHeight, MeasureSpec.EXACTLY);
- mBackgroundDimmed.measure(widthMeasureSpec, newHeightSpec);
- mBackgroundNormal.measure(widthMeasureSpec, newHeightSpec);
- int width = MeasureSpec.getSize(widthMeasureSpec);
- setMeasuredDimension(width, maxChildHeight);
+ private void updateBackgroundResources() {
+ mBackgroundDimmed.setCustomBackground(mDimmedBgResId, mDimmedBgTint);
+ mBackgroundNormal.setCustomBackground(mBgResId, mBgTint);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index eb4e77a..e699dd9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -619,7 +619,6 @@
protected void hideRecents(boolean triggeredFromAltTab) {
if (mRecents != null) {
- sendCloseSystemWindows(mContext, SYSTEM_DIALOG_REASON_RECENT_APPS);
mRecents.hideRecents(triggeredFromAltTab);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 8f92a4c..84005d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -258,11 +258,4 @@
public void notifyContentUpdated() {
mPrivateLayout.notifyContentUpdated();
}
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- int newHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.EXACTLY);
- mVetoButton.measure(widthMeasureSpec, newHeightSpec);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 5cb1b78..eaaac10 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -21,38 +21,77 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import com.android.systemui.R;
+
+import java.util.ArrayList;
/**
* An abstract view for expandable views.
*/
-public abstract class ExpandableView extends ViewGroup {
+public abstract class ExpandableView extends FrameLayout {
+
+ private final int mMaxNotificationHeight;
private OnHeightChangedListener mOnHeightChangedListener;
protected int mActualHeight;
protected int mClipTopAmount;
private boolean mActualHeightInitialized;
+ private ArrayList<View> mMatchParentViews = new ArrayList<View>();
public ExpandableView(Context context, AttributeSet attrs) {
super(context, attrs);
+ mMaxNotificationHeight = getResources().getDimensionPixelSize(
+ R.dimen.notification_max_height);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int ownMaxHeight = mMaxNotificationHeight;
+ int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+ boolean hasFixedHeight = heightMode == MeasureSpec.EXACTLY;
+ boolean isHeightLimited = heightMode == MeasureSpec.AT_MOST;
+ if (hasFixedHeight || isHeightLimited) {
+ int size = MeasureSpec.getSize(heightMeasureSpec);
+ ownMaxHeight = Math.min(ownMaxHeight, size);
+ }
+ int newHeightSpec = MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.AT_MOST);
+ int maxChildHeight = 0;
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = getChildAt(i);
+ int childHeightSpec = newHeightSpec;
+ ViewGroup.LayoutParams layoutParams = child.getLayoutParams();
+ if (layoutParams.height != ViewGroup.LayoutParams.MATCH_PARENT) {
+ if (layoutParams.height >= 0) {
+ // An actual height is set
+ childHeightSpec = layoutParams.height > ownMaxHeight
+ ? MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.EXACTLY)
+ : MeasureSpec.makeMeasureSpec(layoutParams.height, MeasureSpec.EXACTLY);
+ }
+ child.measure(widthMeasureSpec, childHeightSpec);
+ int childHeight = child.getMeasuredHeight();
+ maxChildHeight = Math.max(maxChildHeight, childHeight);
+ } else {
+ mMatchParentViews.add(child);
+ }
+ }
+ int ownHeight = hasFixedHeight ? ownMaxHeight : maxChildHeight;
+ newHeightSpec = MeasureSpec.makeMeasureSpec(ownHeight, MeasureSpec.EXACTLY);
+ for (View child : mMatchParentViews) {
+ child.measure(widthMeasureSpec, newHeightSpec);
+ }
+ mMatchParentViews.clear();
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ setMeasuredDimension(width, ownHeight);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- for (int i = 0; i < getChildCount(); i++) {
- View child = getChildAt(i);
- int height = child.getMeasuredHeight();
- int width = child.getMeasuredWidth();
- int center = getWidth() / 2;
- int childLeft = center - width / 2;
- child.layout(childLeft,
- 0,
- childLeft + width,
- height);
- }
+ super.onLayout(changed, left, top, right, bottom);
if (!mActualHeightInitialized && mActualHeight == 0) {
- mActualHeight = getInitialHeight();
+ setActualHeight(getInitialHeight());
}
- mActualHeightInitialized = true;
}
protected int getInitialHeight() {
@@ -87,6 +126,7 @@
}
public void setActualHeight(int actualHeight) {
+ mActualHeightInitialized = true;
setActualHeight(actualHeight, true);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
index e49ec64..3c080fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
@@ -31,7 +31,6 @@
private Drawable mBackground;
private int mClipTopAmount;
private int mActualHeight;
- private boolean mActualHeightInitialized;
public NotificationBackgroundView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -39,15 +38,6 @@
}
@Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- if (!mActualHeightInitialized && mActualHeight == 0) {
- mActualHeight = getHeight();
- }
- mActualHeightInitialized = true;
- }
-
- @Override
protected void onDraw(Canvas canvas) {
draw(canvas, mBackground);
}
diff --git a/policy/src/com/android/internal/policy/impl/BarController.java b/policy/src/com/android/internal/policy/impl/BarController.java
index 49e1072..bfbd60d 100644
--- a/policy/src/com/android/internal/policy/impl/BarController.java
+++ b/policy/src/com/android/internal/policy/impl/BarController.java
@@ -121,7 +121,7 @@
}
} else {
vis = (vis & ~mTranslucentFlag) | (oldVis & mTranslucentFlag);
- vis = (vis & View.SYSTEM_UI_TRANSPARENT) | (oldVis & View.SYSTEM_UI_TRANSPARENT);
+ vis = (vis & ~View.SYSTEM_UI_TRANSPARENT) | (oldVis & View.SYSTEM_UI_TRANSPARENT);
}
}
return vis;
diff --git a/policy/src/com/android/internal/policy/impl/ImmersiveModeConfirmation.java b/policy/src/com/android/internal/policy/impl/ImmersiveModeConfirmation.java
index 5602206..a4c2ddd 100644
--- a/policy/src/com/android/internal/policy/impl/ImmersiveModeConfirmation.java
+++ b/policy/src/com/android/internal/policy/impl/ImmersiveModeConfirmation.java
@@ -115,13 +115,14 @@
}
}
- public void immersiveModeChanged(String pkg, boolean isImmersiveMode) {
+ public void immersiveModeChanged(String pkg, boolean isImmersiveMode,
+ boolean userSetupComplete) {
mHandler.removeMessages(H.SHOW);
if (isImmersiveMode) {
final boolean disabled = PolicyControl.disableImmersiveConfirmation(pkg);
if (DEBUG) Slog.d(TAG, String.format("immersiveModeChanged() disabled=%s mConfirmed=%s",
disabled, mConfirmed));
- if (!disabled && (DEBUG_SHOW_EVERY_TIME || !mConfirmed)) {
+ if (!disabled && (DEBUG_SHOW_EVERY_TIME || !mConfirmed) && userSetupComplete) {
mHandler.sendEmptyMessageDelayed(H.SHOW, mShowDelayMs);
}
} else {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 6390a69..d0305e0 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -775,6 +775,11 @@
mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
}
+ boolean isUserSetupComplete() {
+ return Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
+ }
+
private void handleLongPressOnHome() {
if (mLongPressOnHomeBehavior != LONG_PRESS_HOME_NOTHING) {
mHomeConsumed = true;
@@ -4294,6 +4299,10 @@
private void requestTransientBars(WindowState swipeTarget) {
synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
+ if (!isUserSetupComplete()) {
+ // Swipe-up for navigation bar is disabled during setup
+ return;
+ }
boolean sb = mStatusBarController.checkShowTransientBarLw();
boolean nb = mNavigationBarController.checkShowTransientBarLw();
if (sb || nb) {
@@ -5270,7 +5279,8 @@
boolean newImmersiveMode = isImmersiveMode(vis);
if (win != null && oldImmersiveMode != newImmersiveMode) {
final String pkg = win.getOwningPackage();
- mImmersiveModeConfirmation.immersiveModeChanged(pkg, newImmersiveMode);
+ mImmersiveModeConfirmation.immersiveModeChanged(pkg, newImmersiveMode,
+ isUserSetupComplete());
}
vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index a62d1fd..2222d2c 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -73,14 +73,14 @@
* latency over peak performance. This is a hint and may have no effect
* on some implementations.
*/
- public static final long CREATE_FLAG_LOW_LATENCY = 0x0001;
+ public static final long CREATE_FLAG_LOW_LATENCY = 0x0002;
/*
* Context creation flag which specifies a context optimized for long
* battery life over peak performance. This is a hint and may have no effect
* on some implementations.
*/
- public static final long CREATE_FLAG_LOW_POWER = 0x0002;
+ public static final long CREATE_FLAG_LOW_POWER = 0x0004;
static {
sInitialized = false;
@@ -1180,10 +1180,14 @@
return null;
}
+ if ((flags & ~(CREATE_FLAG_LOW_LATENCY | CREATE_FLAG_LOW_POWER)) != 0) {
+ throw new RSIllegalArgumentException("Invalid flags passed.");
+ }
+
RenderScript rs = new RenderScript(ctx);
rs.mDev = rs.nDeviceCreate();
- rs.mContext = rs.nContextCreate(rs.mDev, 0, sdkVersion, ct.mID);
+ rs.mContext = rs.nContextCreate(rs.mDev, (int)flags, sdkVersion, ct.mID);
rs.mContextType = ct;
if (rs.mContext == 0) {
throw new RSDriverException("Failed to create RS context.");
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 168742f..4ab8a01 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -22,7 +22,6 @@
import android.app.IAlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -40,7 +39,6 @@
import android.os.WorkSource;
import android.text.TextUtils;
import android.util.ArrayMap;
-import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
@@ -104,13 +102,21 @@
int mBroadcastRefCount = 0;
PowerManager.WakeLock mWakeLock;
boolean mLastWakeLockUnimportantForLogging;
+ ArrayList<Alarm> mPendingNonWakeupAlarms = new ArrayList<Alarm>();
ArrayList<InFlight> mInFlight = new ArrayList<InFlight>();
final AlarmHandler mHandler = new AlarmHandler();
ClockReceiver mClockReceiver;
+ InteractiveStateReceiver mInteractiveStateReceiver;
private UninstallReceiver mUninstallReceiver;
final ResultReceiver mResultReceiver = new ResultReceiver();
PendingIntent mTimeTickSender;
PendingIntent mDateChangeSender;
+ boolean mInteractive = true;
+ long mNonInteractiveStartTime;
+ long mNonInteractiveTime;
+ long mLastAlarmDeliveryTime;
+ long mStartCurrentDelayTime;
+ long mNextNonWakeupDeliveryTime;
class WakeupEvent {
public long when;
@@ -318,7 +324,11 @@
final Comparator<Alarm> mAlarmDispatchComparator = new Comparator<Alarm>() {
@Override
public int compare(Alarm lhs, Alarm rhs) {
- if (lhs.wakeup != rhs.wakeup) {
+ if ((!lhs.operation.getCreatorPackage().equals(rhs.operation.getCreatorPackage()))
+ && lhs.wakeup != rhs.wakeup) {
+ // We want to put wakeup alarms before non-wakeup alarms, since they are
+ // the things that drive most activity in the alarm manager. However,
+ // alarms from the same package should always be ordered strictly by time.
return lhs.wakeup ? -1 : 1;
}
if (lhs.whenElapsed < rhs.whenElapsed) {
@@ -424,24 +434,21 @@
static final class InFlight extends Intent {
final PendingIntent mPendingIntent;
final WorkSource mWorkSource;
- final Pair<String, ComponentName> mTarget;
+ final String mTag;
final BroadcastStats mBroadcastStats;
final FilterStats mFilterStats;
final int mAlarmType;
InFlight(AlarmManagerService service, PendingIntent pendingIntent, WorkSource workSource,
- int alarmType) {
+ int alarmType, String tag) {
mPendingIntent = pendingIntent;
mWorkSource = workSource;
- Intent intent = pendingIntent.getIntent();
- mTarget = intent != null
- ? new Pair<String, ComponentName>(intent.getAction(), intent.getComponent())
- : null;
+ mTag = tag;
mBroadcastStats = service.getStatsLocked(pendingIntent);
- FilterStats fs = mBroadcastStats.filterStats.get(mTarget);
+ FilterStats fs = mBroadcastStats.filterStats.get(mTag);
if (fs == null) {
- fs = new FilterStats(mBroadcastStats, mTarget);
- mBroadcastStats.filterStats.put(mTarget, fs);
+ fs = new FilterStats(mBroadcastStats, mTag);
+ mBroadcastStats.filterStats.put(mTag, fs);
}
mFilterStats = fs;
mAlarmType = alarmType;
@@ -450,7 +457,7 @@
static final class FilterStats {
final BroadcastStats mBroadcastStats;
- final Pair<String, ComponentName> mTarget;
+ final String mTag;
long aggregateTime;
int count;
@@ -458,9 +465,9 @@
long startTime;
int nesting;
- FilterStats(BroadcastStats broadcastStats, Pair<String, ComponentName> target) {
+ FilterStats(BroadcastStats broadcastStats, String tag) {
mBroadcastStats = broadcastStats;
- mTarget = target;
+ mTag = tag;
}
}
@@ -473,8 +480,7 @@
int numWakeup;
long startTime;
int nesting;
- final ArrayMap<Pair<String, ComponentName>, FilterStats> filterStats
- = new ArrayMap<Pair<String, ComponentName>, FilterStats>();
+ final ArrayMap<String, FilterStats> filterStats = new ArrayMap<String, FilterStats>();
BroadcastStats(int uid, String packageName) {
mUid = uid;
@@ -484,7 +490,11 @@
final SparseArray<ArrayMap<String, BroadcastStats>> mBroadcastStats
= new SparseArray<ArrayMap<String, BroadcastStats>>();
-
+
+ int mNumDelayedAlarms = 0;
+ long mTotalDelayTime = 0;
+ long mMaxDelayTime = 0;
+
@Override
public void onStart() {
mNativeData = init();
@@ -511,6 +521,7 @@
mClockReceiver = new ClockReceiver();
mClockReceiver.scheduleTimeTickEvent();
mClockReceiver.scheduleDateChangedEvent();
+ mInteractiveStateReceiver = new InteractiveStateReceiver();
mUninstallReceiver = new UninstallReceiver();
if (mNativeData != 0) {
@@ -735,13 +746,29 @@
pw.print("nowRTC="); pw.print(nowRTC);
pw.print("="); pw.print(sdf.format(new Date(nowRTC)));
- pw.print(" nowELAPSED="); pw.println(nowELAPSED);
+ pw.print(" nowELAPSED="); TimeUtils.formatDuration(nowELAPSED, pw);
+ pw.println();
+ if (!mInteractive) {
+ pw.print("Time since non-interactive: ");
+ TimeUtils.formatDuration(nowELAPSED - mNonInteractiveStartTime, pw);
+ pw.println();
+ pw.print("Max wakeup delay: ");
+ TimeUtils.formatDuration(currentNonWakeupFuzzLocked(nowELAPSED), pw);
+ pw.println();
+ pw.print("Time since last dispatch: ");
+ TimeUtils.formatDuration(nowELAPSED - mLastAlarmDeliveryTime, pw);
+ pw.println();
+ pw.print("Next non-wakeup delivery time: ");
+ TimeUtils.formatDuration(nowELAPSED - mNextNonWakeupDeliveryTime, pw);
+ pw.println();
+ }
long nextWakeupRTC = mNextWakeup + (nowRTC - nowELAPSED);
long nextNonWakeupRTC = mNextNonWakeup + (nowRTC - nowELAPSED);
- pw.print("Next alarm: "); pw.print(mNextNonWakeup);
+ pw.print("Next non-wakeup alarm: ");
+ TimeUtils.formatDuration(mNextNonWakeup, nowELAPSED, pw);
pw.print(" = "); pw.println(sdf.format(new Date(nextNonWakeupRTC)));
- pw.print("Next wakeup: "); pw.print(mNextWakeup);
+ pw.print("Next wakeup: "); TimeUtils.formatDuration(mNextWakeup, nowELAPSED, pw);
pw.print(" = "); pw.println(sdf.format(new Date(nextWakeupRTC)));
if (mAlarmBatches.size() > 0) {
@@ -750,11 +777,27 @@
pw.println(mAlarmBatches.size());
for (Batch b : mAlarmBatches) {
pw.print(b); pw.println(':');
- dumpAlarmList(pw, b.alarms, " ", nowELAPSED, nowRTC);
+ dumpAlarmList(pw, b.alarms, " ", nowELAPSED, nowRTC, sdf);
}
}
pw.println();
+ pw.print("Past-due non-wakeup alarms: ");
+ if (mPendingNonWakeupAlarms.size() > 0) {
+ pw.println(mPendingNonWakeupAlarms.size());
+ dumpAlarmList(pw, mPendingNonWakeupAlarms, " ", nowELAPSED, nowRTC, sdf);
+ } else {
+ pw.println("(none)");
+ }
+ pw.print(" Number of delayed alarms: "); pw.print(mNumDelayedAlarms);
+ pw.print(", total delay time: "); TimeUtils.formatDuration(mTotalDelayTime, pw);
+ pw.println();
+ pw.print(" Max delay time: "); TimeUtils.formatDuration(mMaxDelayTime, pw);
+ pw.print(", max non-interactive time: ");
+ TimeUtils.formatDuration(mNonInteractiveTime, pw);
+ pw.println();
+
+ pw.println();
pw.print(" Broadcast ref count: "); pw.println(mBroadcastRefCount);
pw.println();
@@ -811,13 +854,7 @@
pw.print(" alarms: "); UserHandle.formatUid(pw, fs.mBroadcastStats.mUid);
pw.print(":"); pw.print(fs.mBroadcastStats.mPackageName);
pw.println();
- pw.print(" ");
- if (fs.mTarget.first != null) {
- pw.print(" act="); pw.print(fs.mTarget.first);
- }
- if (fs.mTarget.second != null) {
- pw.print(" cmp="); pw.print(fs.mTarget.second.toShortString());
- }
+ pw.print(" "); pw.print(fs.mTag);
pw.println();
}
}
@@ -849,13 +886,8 @@
TimeUtils.formatDuration(fs.aggregateTime, pw);
pw.print(" "); pw.print(fs.numWakeup);
pw.print(" wakes " ); pw.print(fs.count);
- pw.print(" alarms:");
- if (fs.mTarget.first != null) {
- pw.print(" act="); pw.print(fs.mTarget.first);
- }
- if (fs.mTarget.second != null) {
- pw.print(" cmp="); pw.print(fs.mTarget.second.toShortString());
- }
+ pw.print(" alarms: ");
+ pw.print(fs.mTag);
pw.println();
}
}
@@ -883,7 +915,7 @@
}
}
- private void logBatchesLocked() {
+ private void logBatchesLocked(SimpleDateFormat sdf) {
ByteArrayOutputStream bs = new ByteArrayOutputStream(2048);
PrintWriter pw = new PrintWriter(bs);
final long nowRTC = System.currentTimeMillis();
@@ -892,7 +924,7 @@
for (int iz = 0; iz < NZ; iz++) {
Batch bz = mAlarmBatches.get(iz);
pw.append("Batch "); pw.print(iz); pw.append(": "); pw.println(bz);
- dumpAlarmList(pw, bz.alarms, " ", nowELAPSED, nowRTC);
+ dumpAlarmList(pw, bz.alarms, " ", nowELAPSED, nowRTC, sdf);
pw.flush();
Slog.v(TAG, bs.toString());
bs.reset();
@@ -910,7 +942,8 @@
lastTime = b.start;
} else {
Slog.e(TAG, "CONSISTENCY FAILURE: Batch " + i + " is out of order");
- logBatchesLocked();
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ logBatchesLocked(sdf);
return false;
}
}
@@ -932,6 +965,7 @@
void rescheduleKernelAlarmsLocked() {
// Schedule the next upcoming wakeup alarm. If there is a deliverable batch
// prior to that which contains no wakeups, we schedule that as well.
+ long nextNonWakeup = 0;
if (mAlarmBatches.size() > 0) {
final Batch firstWakeup = findFirstWakeupBatchLocked();
final Batch firstBatch = mAlarmBatches.get(0);
@@ -939,11 +973,19 @@
mNextWakeup = firstWakeup.start;
setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
}
- if (firstBatch != firstWakeup && mNextNonWakeup != firstBatch.start) {
- mNextNonWakeup = firstBatch.start;
- setLocked(ELAPSED_REALTIME, firstBatch.start);
+ if (firstBatch != firstWakeup) {
+ nextNonWakeup = firstBatch.start;
}
}
+ if (mPendingNonWakeupAlarms.size() > 0) {
+ if (nextNonWakeup == 0 || mNextNonWakeupDeliveryTime < nextNonWakeup) {
+ nextNonWakeup = mNextNonWakeupDeliveryTime;
+ }
+ }
+ if (nextNonWakeup != 0 && mNextNonWakeup != nextNonWakeup) {
+ mNextNonWakeup = nextNonWakeup;
+ setLocked(ELAPSED_REALTIME, nextNonWakeup);
+ }
}
private void removeLocked(PendingIntent operation) {
@@ -1003,6 +1045,32 @@
}
}
+ void interactiveStateChangedLocked(boolean interactive) {
+ if (mInteractive != interactive) {
+ mInteractive = interactive;
+ final long nowELAPSED = SystemClock.elapsedRealtime();
+ if (interactive) {
+ if (mPendingNonWakeupAlarms.size() > 0) {
+ final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
+ mTotalDelayTime += thisDelayTime;
+ if (mMaxDelayTime < thisDelayTime) {
+ mMaxDelayTime = thisDelayTime;
+ }
+ deliverAlarmsLocked(mPendingNonWakeupAlarms, nowELAPSED);
+ mPendingNonWakeupAlarms.clear();
+ }
+ if (mNonInteractiveStartTime > 0) {
+ long dur = nowELAPSED - mNonInteractiveStartTime;
+ if (dur > mNonInteractiveTime) {
+ mNonInteractiveTime = dur;
+ }
+ }
+ } else {
+ mNonInteractiveStartTime = nowELAPSED;
+ }
+ }
+ }
+
boolean lookForPackageLocked(String packageName) {
for (int i = 0; i < mAlarmBatches.size(); i++) {
Batch b = mAlarmBatches.get(i);
@@ -1037,12 +1105,12 @@
}
private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
- String prefix, String label, long now) {
+ String prefix, String label, long nowRTC, long nowELAPSED, SimpleDateFormat sdf) {
for (int i=list.size()-1; i>=0; i--) {
Alarm a = list.get(i);
pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
pw.print(": "); pw.println(a);
- a.dump(pw, prefix + " ", now);
+ a.dump(pw, prefix + " ", nowRTC, nowELAPSED, sdf);
}
}
@@ -1059,14 +1127,13 @@
}
private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
- String prefix, long nowELAPSED, long nowRTC) {
+ String prefix, long nowELAPSED, long nowRTC, SimpleDateFormat sdf) {
for (int i=list.size()-1; i>=0; i--) {
Alarm a = list.get(i);
final String label = labelForType(a.type);
- long now = (a.type <= RTC) ? nowRTC : nowELAPSED;
pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
pw.print(": "); pw.println(a);
- a.dump(pw, prefix + " ", now);
+ a.dump(pw, prefix + " ", nowRTC, nowELAPSED, sdf);
}
}
@@ -1077,8 +1144,9 @@
private native int setKernelTime(long nativeData, long millis);
private native int setKernelTimezone(long nativeData, int minuteswest);
- void triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED,
+ boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED,
final long nowRTC) {
+ boolean hasWakeup = false;
// batches are temporally sorted, so we need only pull from the
// start of the list until we either empty it or hit a batch
// that is not yet deliverable
@@ -1113,8 +1181,14 @@
maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
alarm.repeatInterval, alarm.operation, batch.standalone, true,
alarm.workSource);
- }
+ // For now we count this as a wakeup alarm, meaning it needs to be
+ // delivered immediately. In the future we should change this, but
+ // that required delaying when we reschedule the repeat...!
+ hasWakeup = false;
+ } else if (alarm.wakeup) {
+ hasWakeup = true;
+ }
}
}
@@ -1125,6 +1199,8 @@
Slog.v(TAG, "Triggering alarm #" + i + ": " + triggerList.get(i));
}
}
+
+ return hasWakeup;
}
/**
@@ -1147,15 +1223,16 @@
private static class Alarm {
public final int type;
public final boolean wakeup;
+ public final PendingIntent operation;
+ public final String tag;
+ public final WorkSource workSource;
public int count;
public long when;
public long windowLength;
public long whenElapsed; // 'when' in the elapsed time base
public long maxWhen; // also in the elapsed time base
public long repeatInterval;
- public PendingIntent operation;
- public WorkSource workSource;
-
+
public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
long _interval, PendingIntent _op, WorkSource _ws) {
type = _type;
@@ -1167,12 +1244,17 @@
maxWhen = _maxWhen;
repeatInterval = _interval;
operation = _op;
+ tag = makeTag(_op, _type);
workSource = _ws;
}
+ public static String makeTag(PendingIntent pi, int type) {
+ return pi.getTag(type == ELAPSED_REALTIME_WAKEUP || type == RTC_WAKEUP
+ ? "*walarm*:" : "*alarm*:");
+ }
+
@Override
- public String toString()
- {
+ public String toString() {
StringBuilder sb = new StringBuilder(128);
sb.append("Alarm{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
@@ -1186,11 +1268,20 @@
return sb.toString();
}
- public void dump(PrintWriter pw, String prefix, long now) {
+ public void dump(PrintWriter pw, String prefix, long nowRTC, long nowELAPSED,
+ SimpleDateFormat sdf) {
+ final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
+ pw.print(prefix); pw.print("tag="); pw.println(tag);
pw.print(prefix); pw.print("type="); pw.print(type);
- pw.print(" whenElapsed="); pw.print(whenElapsed);
- pw.print(" when="); TimeUtils.formatDuration(when, now, pw);
- pw.print(" window="); pw.print(windowLength);
+ pw.print(" whenElapsed="); TimeUtils.formatDuration(whenElapsed,
+ nowELAPSED, pw);
+ if (isRtc) {
+ pw.print(" when="); pw.print(sdf.format(new Date(when)));
+ } else {
+ pw.print(" when="); TimeUtils.formatDuration(when, nowELAPSED, pw);
+ }
+ pw.println();
+ pw.print(prefix); pw.print("window="); pw.print(windowLength);
pw.print(" repeatInterval="); pw.print(repeatInterval);
pw.print(" count="); pw.println(count);
pw.print(prefix); pw.print("operation="); pw.println(operation);
@@ -1216,6 +1307,102 @@
}
}
+ long currentNonWakeupFuzzLocked(long nowELAPSED) {
+ long timeSinceOn = nowELAPSED - mNonInteractiveStartTime;
+ if (timeSinceOn < 5*60*1000) {
+ // If the screen has been off for 5 minutes, only delay by at most two minutes.
+ return 2*60*1000;
+ } else if (timeSinceOn < 30*60*1000) {
+ // If the screen has been off for 30 minutes, only delay by at most 15 minutes.
+ return 15*60*1000;
+ } else {
+ // Otherwise, we will delay by at most an hour.
+ return 60*60*1000;
+ }
+ }
+
+ boolean checkAllowNonWakeupDelayLocked(long nowELAPSED) {
+ if (mInteractive) {
+ return false;
+ }
+ if (mLastAlarmDeliveryTime <= 0) {
+ return false;
+ }
+ if (mPendingNonWakeupAlarms.size() > 0 && mNextNonWakeupDeliveryTime > nowELAPSED) {
+ // This is just a little paranoia, if somehow we have pending non-wakeup alarms
+ // and the next delivery time is in the past, then just deliver them all. This
+ // avoids bugs where we get stuck in a loop trying to poll for alarms.
+ return false;
+ }
+ long timeSinceLast = nowELAPSED - mLastAlarmDeliveryTime;
+ return timeSinceLast <= currentNonWakeupFuzzLocked(nowELAPSED);
+ }
+
+ void deliverAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED) {
+ mLastAlarmDeliveryTime = nowELAPSED;
+ for (int i=0; i<triggerList.size(); i++) {
+ Alarm alarm = triggerList.get(i);
+ try {
+ if (localLOGV) Slog.v(TAG, "sending alarm " + alarm);
+ alarm.operation.send(getContext(), 0,
+ mBackgroundIntent.putExtra(
+ Intent.EXTRA_ALARM_COUNT, alarm.count),
+ mResultReceiver, mHandler);
+
+ // we have an active broadcast so stay awake.
+ if (mBroadcastRefCount == 0) {
+ setWakelockWorkSource(alarm.operation, alarm.workSource,
+ alarm.type, alarm.tag, true);
+ mWakeLock.acquire();
+ }
+ final InFlight inflight = new InFlight(AlarmManagerService.this,
+ alarm.operation, alarm.workSource, alarm.type, alarm.tag);
+ mInFlight.add(inflight);
+ mBroadcastRefCount++;
+
+ final BroadcastStats bs = inflight.mBroadcastStats;
+ bs.count++;
+ if (bs.nesting == 0) {
+ bs.nesting = 1;
+ bs.startTime = nowELAPSED;
+ } else {
+ bs.nesting++;
+ }
+ final FilterStats fs = inflight.mFilterStats;
+ fs.count++;
+ if (fs.nesting == 0) {
+ fs.nesting = 1;
+ fs.startTime = nowELAPSED;
+ } else {
+ fs.nesting++;
+ }
+ if (alarm.type == ELAPSED_REALTIME_WAKEUP
+ || alarm.type == RTC_WAKEUP) {
+ bs.numWakeup++;
+ fs.numWakeup++;
+ if (alarm.workSource != null && alarm.workSource.size() > 0) {
+ for (int wi=0; wi<alarm.workSource.size(); wi++) {
+ ActivityManagerNative.noteWakeupAlarm(
+ alarm.operation, alarm.workSource.get(wi),
+ alarm.workSource.getName(wi));
+ }
+ } else {
+ ActivityManagerNative.noteWakeupAlarm(
+ alarm.operation, -1, null);
+ }
+ }
+ } catch (PendingIntent.CanceledException e) {
+ if (alarm.repeatInterval > 0) {
+ // This IntentSender is no longer valid, but this
+ // is a repeating alarm, so toss the hoser.
+ removeImpl(alarm.operation);
+ }
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Failure sending alarm.", e);
+ }
+ }
+ }
+
private class AlarmThread extends Thread
{
public AlarmThread()
@@ -1269,70 +1456,35 @@
}
}
- triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
- rescheduleKernelAlarmsLocked();
-
- // now deliver the alarm intents
- for (int i=0; i<triggerList.size(); i++) {
- Alarm alarm = triggerList.get(i);
- try {
- if (localLOGV) Slog.v(TAG, "sending alarm " + alarm);
- alarm.operation.send(getContext(), 0,
- mBackgroundIntent.putExtra(
- Intent.EXTRA_ALARM_COUNT, alarm.count),
- mResultReceiver, mHandler);
-
- // we have an active broadcast so stay awake.
- if (mBroadcastRefCount == 0) {
- setWakelockWorkSource(alarm.operation, alarm.workSource,
- alarm.type, true);
- mWakeLock.acquire();
- }
- final InFlight inflight = new InFlight(AlarmManagerService.this,
- alarm.operation, alarm.workSource, alarm.type);
- mInFlight.add(inflight);
- mBroadcastRefCount++;
-
- final BroadcastStats bs = inflight.mBroadcastStats;
- bs.count++;
- if (bs.nesting == 0) {
- bs.nesting = 1;
- bs.startTime = nowELAPSED;
- } else {
- bs.nesting++;
- }
- final FilterStats fs = inflight.mFilterStats;
- fs.count++;
- if (fs.nesting == 0) {
- fs.nesting = 1;
- fs.startTime = nowELAPSED;
- } else {
- fs.nesting++;
- }
- if (alarm.type == ELAPSED_REALTIME_WAKEUP
- || alarm.type == RTC_WAKEUP) {
- bs.numWakeup++;
- fs.numWakeup++;
- if (alarm.workSource != null && alarm.workSource.size() > 0) {
- for (int wi=0; wi<alarm.workSource.size(); wi++) {
- ActivityManagerNative.noteWakeupAlarm(
- alarm.operation, alarm.workSource.get(wi),
- alarm.workSource.getName(wi));
- }
- } else {
- ActivityManagerNative.noteWakeupAlarm(
- alarm.operation, -1, null);
- }
- }
- } catch (PendingIntent.CanceledException e) {
- if (alarm.repeatInterval > 0) {
- // This IntentSender is no longer valid, but this
- // is a repeating alarm, so toss the hoser.
- removeImpl(alarm.operation);
- }
- } catch (RuntimeException e) {
- Slog.w(TAG, "Failure sending alarm.", e);
+ boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
+ if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
+ // if there are no wakeup alarms and the screen is off, we can
+ // delay what we have so far until the future.
+ if (mPendingNonWakeupAlarms.size() == 0) {
+ mStartCurrentDelayTime = nowELAPSED;
+ mNextNonWakeupDeliveryTime = nowELAPSED
+ + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2);
}
+ mPendingNonWakeupAlarms.addAll(triggerList);
+ mNumDelayedAlarms += triggerList.size();
+ rescheduleKernelAlarmsLocked();
+ } else {
+ // now deliver the alarm intents; if there are pending non-wakeup
+ // alarms, we need to merge them in to the list. note we don't
+ // just deliver them first because we generally want non-wakeup
+ // alarms delivered after wakeup alarms.
+ rescheduleKernelAlarmsLocked();
+ if (mPendingNonWakeupAlarms.size() > 0) {
+ triggerList.addAll(mPendingNonWakeupAlarms);
+ Collections.sort(triggerList, mAlarmDispatchComparator);
+ final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
+ mTotalDelayTime += thisDelayTime;
+ if (mMaxDelayTime < thisDelayTime) {
+ mMaxDelayTime = thisDelayTime;
+ }
+ mPendingNonWakeupAlarms.clear();
+ }
+ deliverAlarmsLocked(triggerList, nowELAPSED);
}
}
}
@@ -1344,14 +1496,13 @@
* @param pi PendingIntent to attribute blame to if ws is null.
* @param ws WorkSource to attribute blame.
*/
- void setWakelockWorkSource(PendingIntent pi, WorkSource ws, int type, boolean first) {
+ void setWakelockWorkSource(PendingIntent pi, WorkSource ws, int type, String tag,
+ boolean first) {
try {
final boolean unimportant = pi == mTimeTickSender;
mWakeLock.setUnimportantForLogging(unimportant);
if (first || mLastWakeLockUnimportantForLogging) {
- mWakeLock.setHistoryTag(pi.getTag(
- type == ELAPSED_REALTIME_WAKEUP || type == RTC_WAKEUP
- ? "*walarm*:" : "*alarm*:"));
+ mWakeLock.setHistoryTag(tag);
} else {
mWakeLock.setHistoryTag(null);
}
@@ -1462,6 +1613,23 @@
}
}
+ class InteractiveStateReceiver extends BroadcastReceiver {
+ public InteractiveStateReceiver() {
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_SCREEN_OFF);
+ filter.addAction(Intent.ACTION_SCREEN_ON);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+ getContext().registerReceiver(this, filter);
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ synchronized (mLock) {
+ interactiveStateChangedLocked(Intent.ACTION_SCREEN_ON.equals(intent.getAction()));
+ }
+ }
+ }
+
class UninstallReceiver extends BroadcastReceiver {
public UninstallReceiver() {
IntentFilter filter = new IntentFilter();
@@ -1589,7 +1757,7 @@
if (mInFlight.size() > 0) {
InFlight inFlight = mInFlight.get(0);
setWakelockWorkSource(inFlight.mPendingIntent, inFlight.mWorkSource,
- inFlight.mAlarmType, false);
+ inFlight.mAlarmType, inFlight.mTag, false);
} else {
// should never happen
mLog.w("Alarm wakelock still held but sent queue empty");
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index cc132be..af53fef0 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -398,7 +398,7 @@
/**
* used internally when registering NetworkFactories
- * obj = Messenger
+ * obj = NetworkFactoryInfo
*/
private static final int EVENT_REGISTER_NETWORK_FACTORY = 17;
@@ -434,6 +434,13 @@
*/
private static final int EVENT_RELEASE_NETWORK_REQUEST = 22;
+ /**
+ * used internally when registering NetworkFactories
+ * obj = Messenger
+ */
+ private static final int EVENT_UNREGISTER_NETWORK_FACTORY = 23;
+
+
/** Handler used for internal events. */
final private InternalHandler mHandler;
/** Handler used for incoming {@link NetworkStateTracker} events. */
@@ -2889,6 +2896,14 @@
return;
}
+ pw.println("NetworkFactories for:");
+ pw.increaseIndent();
+ for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
+ pw.println(nfi.name);
+ }
+ pw.decreaseIndent();
+ pw.println();
+
NetworkAgentInfo defaultNai = mNetworkForRequestId.get(mDefaultRequest.requestId);
pw.print("Active default network: ");
if (defaultNai == null) {
@@ -2983,6 +2998,7 @@
if (nai == null) {
loge("NetworkAgent not found for EVENT_NETWORK_PROPERTIES_CHANGED");
} else {
+ if (VDBG) log("Update of Linkproperties for " + nai.name());
LinkProperties oldLp = nai.linkProperties;
nai.linkProperties = (LinkProperties)msg.obj;
updateLinkProperties(nai, oldLp);
@@ -3096,18 +3112,19 @@
private void handleAsyncChannelHalfConnect(Message msg) {
AsyncChannel ac = (AsyncChannel) msg.obj;
- if (mNetworkFactories.contains(ac)) {
+ if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
if (VDBG) log("NetworkFactory connected");
// A network factory has connected. Send it all current NetworkRequests.
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
+ if (nri.isRequest == false) continue;
NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
ac.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK,
(nai != null ? nai.currentScore : 0), 0, nri.request);
}
} else {
loge("Error connecting NetworkFactory");
- mNetworkFactories.remove(ac);
+ mNetworkFactoryInfos.remove(msg.obj);
}
} else if (mNetworkAgentInfos.containsKey(msg.replyTo)) {
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
@@ -3214,8 +3231,8 @@
mNetworkRequests.put(nri.request, nri);
if (msg.what == EVENT_REGISTER_NETWORK_REQUEST) {
if (DBG) log("sending new NetworkRequest to factories");
- for (AsyncChannel ac : mNetworkFactories) {
- ac.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, nri.request);
+ for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
+ nfi.asyncChannel.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, nri.request);
}
}
}
@@ -3236,8 +3253,8 @@
}
if (nri.isRequest) {
- for (AsyncChannel factory : mNetworkFactories) {
- factory.sendMessage(NetworkFactoryProtocol.CMD_CANCEL_REQUEST, nri.request);
+ for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
+ nfi.asyncChannel.sendMessage(NetworkFactoryProtocol.CMD_CANCEL_REQUEST, nri.request);
}
if (affectedNetwork != null) {
@@ -3356,7 +3373,11 @@
break;
}
case EVENT_REGISTER_NETWORK_FACTORY: {
- handleRegisterNetworkFactory((Messenger)msg.obj);
+ handleRegisterNetworkFactory((NetworkFactoryInfo)msg.obj);
+ break;
+ }
+ case EVENT_UNREGISTER_NETWORK_FACTORY: {
+ handleUnregisterNetworkFactory((Messenger)msg.obj);
break;
}
case EVENT_REGISTER_NETWORK_AGENT: {
@@ -5222,10 +5243,22 @@
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, wakeupTime, intent);
}
- private final ArrayList<AsyncChannel> mNetworkFactories = new ArrayList<AsyncChannel>();
+ private final HashMap<Messenger, NetworkFactoryInfo> mNetworkFactoryInfos =
+ new HashMap<Messenger, NetworkFactoryInfo>();
private final HashMap<NetworkRequest, NetworkRequestInfo> mNetworkRequests =
new HashMap<NetworkRequest, NetworkRequestInfo>();
+ private static class NetworkFactoryInfo {
+ public final String name;
+ public final Messenger messenger;
+ public final AsyncChannel asyncChannel;
+
+ public NetworkFactoryInfo(String name, Messenger messenger, AsyncChannel asyncChannel) {
+ this.name = name;
+ this.messenger = messenger;
+ this.asyncChannel = asyncChannel;
+ }
+ }
private class NetworkRequestInfo implements IBinder.DeathRecipient {
static final boolean REQUEST = true;
@@ -5263,6 +5296,11 @@
request + ", " + mBinder + ")");
releaseNetworkRequest(request);
}
+
+ public String toString() {
+ return (isRequest ? "Request" : "Listen") + " from uid/pid:" + mUid + "/" +
+ mPid + " for " + request;
+ }
}
@Override
@@ -5326,24 +5364,31 @@
}
@Override
- public void registerNetworkFactory(Messenger messenger) {
+ public void registerNetworkFactory(Messenger messenger, String name) {
enforceConnectivityInternalPermission();
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, messenger));
+ NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel());
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
}
- private void handleRegisterNetworkFactory(Messenger messenger) {
- if (VDBG) log("Got NetworkFactory Messenger");
- AsyncChannel ac = new AsyncChannel();
- mNetworkFactories.add(ac);
- ac.connect(mContext, mTrackerHandler, messenger);
- for (NetworkRequestInfo nri : mNetworkRequests.values()) {
- if (nri.isRequest) {
- int score = 0;
- NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(nri.request.requestId);
- if (currentNetwork != null) score = currentNetwork.currentScore;
- ac.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, nri.request);
- }
+ private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
+ if (VDBG) log("Got NetworkFactory Messenger for " + nfi.name);
+ mNetworkFactoryInfos.put(nfi.messenger, nfi);
+ nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);
+ }
+
+ @Override
+ public void unregisterNetworkFactory(Messenger messenger) {
+ enforceConnectivityInternalPermission();
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_FACTORY, messenger));
+ }
+
+ private void handleUnregisterNetworkFactory(Messenger messenger) {
+ NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(messenger);
+ if (nfi == null) {
+ if (VDBG) log("Failed to find Messenger in unregisterNetworkFactory");
+ return;
}
+ if (VDBG) log("unregisterNetworkFactory for " + nfi.name);
}
/**
@@ -5535,8 +5580,8 @@
private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score) {
if (VDBG) log("sending new Min Network Score(" + score + "): " + networkRequest.toString());
- for (AsyncChannel ac : mNetworkFactories) {
- ac.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, networkRequest);
+ for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
+ nfi.asyncChannel.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, networkRequest);
}
}
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 50553ee..5cb2a8a6f 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -3439,7 +3439,7 @@
+ " mShowExplicitlyRequested=" + mShowExplicitlyRequested
+ " mShowForced=" + mShowForced
+ " mInputShown=" + mInputShown);
- p.println(" mSystemReady=" + mSystemReady + " mScreenOn=" + mScreenOn);
+ p.println(" mSystemReady=" + mSystemReady + " mInteractive=" + mScreenOn);
}
p.println(" ");
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 82c13e0..06dd3ed 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -47,6 +47,7 @@
import com.android.internal.app.IBatteryStats;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;
@@ -136,6 +137,10 @@
}
return true;
}
+
+ public boolean isSystemHapticFeedback() {
+ return (mUid == Process.SYSTEM_UID || mUid == 0) && mRepeat < 0;
+ }
}
VibratorService(Context context) {
@@ -622,20 +627,32 @@
}
}
}
- };
+ }
BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+ @Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
synchronized (mVibrations) {
- doCancelVibrateLocked();
-
- int size = mVibrations.size();
- for(int i = 0; i < size; i++) {
- unlinkVibration(mVibrations.get(i));
+ // When the system is entering a non-interactive state, we want
+ // to cancel vibrations in case a misbehaving app has abandoned
+ // them. However it may happen that the system is currently playing
+ // haptic feedback as part of the transition. So we don't cancel
+ // system vibrations.
+ if (mCurrentVibration != null
+ && !mCurrentVibration.isSystemHapticFeedback()) {
+ doCancelVibrateLocked();
}
- mVibrations.clear();
+ // Clear all remaining vibrations.
+ Iterator<Vibration> it = mVibrations.iterator();
+ while (it.hasNext()) {
+ Vibration vibration = it.next();
+ if (vibration != mCurrentVibration) {
+ unlinkVibration(vibration);
+ it.remove();
+ }
+ }
}
}
}
diff --git a/services/core/java/com/android/server/WiredAccessoryManager.java b/services/core/java/com/android/server/WiredAccessoryManager.java
index c32beda..cd8c13fb 100644
--- a/services/core/java/com/android/server/WiredAccessoryManager.java
+++ b/services/core/java/com/android/server/WiredAccessoryManager.java
@@ -264,7 +264,7 @@
} else if (headset == BIT_USB_HEADSET_DGTL) {
device = AudioManager.DEVICE_OUT_DGTL_DOCK_HEADSET;
} else if (headset == BIT_HDMI_AUDIO) {
- device = AudioManager.DEVICE_OUT_AUX_DIGITAL;
+ device = AudioManager.DEVICE_OUT_HDMI;
} else {
Slog.e(TAG, "setDeviceState() invalid headset type: "+headset);
return;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7abc75f..7cd4ef8 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -13837,7 +13837,7 @@
}
if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
- ProxyInfo proxy = intent.getParcelableExtra("proxy");
+ ProxyInfo proxy = intent.getParcelableExtra(Proxy.EXTRA_PROXY_INFO);
mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG, proxy));
}
diff --git a/services/core/java/com/android/server/hdmi/FeatureAction.java b/services/core/java/com/android/server/hdmi/FeatureAction.java
index d747cd0..1bc278d 100644
--- a/services/core/java/com/android/server/hdmi/FeatureAction.java
+++ b/services/core/java/com/android/server/hdmi/FeatureAction.java
@@ -118,6 +118,11 @@
* @param delayMillis amount of delay for the timer
*/
void sendTimerMessage(int state, long delayMillis);
+
+ /**
+ * Removes any pending timer message.
+ */
+ void clearTimerMessage();
}
private class ActionTimerHandler extends Handler implements ActionTimer {
@@ -132,6 +137,11 @@
}
@Override
+ public void clearTimerMessage() {
+ removeMessages(MSG_TIMEOUT);
+ }
+
+ @Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_TIMEOUT:
@@ -154,15 +164,26 @@
mActionTimer.sendTimerMessage(state, delayMillis);
}
- protected final void sendCommand(HdmiCecMessage cmd) {
- mService.sendCecCommand(cmd);
+ protected final boolean sendCommand(HdmiCecMessage cmd) {
+ return mService.sendCecCommand(cmd);
+ }
+
+ /**
+ * Clean up action's state.
+ *
+ * <p>Declared as package-private. Only {@link HdmiControlService} can access it.
+ */
+ void clear() {
+ mState = STATE_NONE;
+ // Clear all timers.
+ mActionTimer.clearTimerMessage();
}
/**
* Finish up the action. Reset the state, and remove itself from the action queue.
*/
protected void finish() {
- mState = STATE_NONE;
+ clear();
removeAction(this);
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index 986cb9b..f99a01d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -442,9 +442,9 @@
}
- void sendCommand(HdmiCecMessage cecMessage) {
+ boolean sendCommand(HdmiCecMessage cecMessage) {
Message message = mIoHandler.obtainMessage(MSG_SEND_CEC_COMMAND, cecMessage);
- mIoHandler.sendMessage(message);
+ return mIoHandler.sendMessage(message);
}
/**
@@ -465,7 +465,9 @@
* Called by native when a hotplug event issues.
*/
private void handleHotplug(boolean connected) {
- // TODO: Delegate event to main message handler.
+ // TODO: once add port number to cec HAL interface, pass port number
+ // to the service.
+ mService.onHotplug(0, connected);
}
private static native long nativeInit(HdmiCecController handler);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
index 6d2b83b..e47b90d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
@@ -186,6 +186,50 @@
}
/**
+ * Build <Request Arc Initiation>
+ *
+ * @param src source address of command
+ * @param dest destination address of command
+ * @return newly created {@link HdmiCecMessage}
+ */
+ static HdmiCecMessage buildRequestArcInitiation(int src, int dest) {
+ return buildCommand(src, dest, HdmiCec.MESSAGE_REQUEST_ARC_INITIATION);
+ }
+
+ /**
+ * Build <Request Arc Termination>
+ *
+ * @param src source address of command
+ * @param dest destination address of command
+ * @return newly created {@link HdmiCecMessage}
+ */
+ static HdmiCecMessage buildRequestArcTermination(int src, int dest) {
+ return buildCommand(src, dest, HdmiCec.MESSAGE_REQUEST_ARC_TERMINATION);
+ }
+
+ /**
+ * Build <Report Arc Initiated>
+ *
+ * @param src source address of command
+ * @param dest destination address of command
+ * @return newly created {@link HdmiCecMessage}
+ */
+ static HdmiCecMessage buildReportArcInitiated(int src, int dest) {
+ return buildCommand(src, dest, HdmiCec.MESSAGE_REPORT_ARC_INITIATED);
+ }
+
+ /**
+ * Build <Report Arc Terminated>
+ *
+ * @param src source address of command
+ * @param dest destination address of command
+ * @return newly created {@link HdmiCecMessage}
+ */
+ static HdmiCecMessage buildReportArcTerminated(int src, int dest) {
+ return buildCommand(src, dest, HdmiCec.MESSAGE_REPORT_ARC_TERMINATED);
+ }
+
+ /**
* Build a {@link HdmiCecMessage} without extra parameter.
*
* @param src source address of command
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 7c136db..963e818 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -21,12 +21,15 @@
import android.hardware.hdmi.HdmiCec;
import android.hardware.hdmi.HdmiCecDeviceInfo;
import android.hardware.hdmi.HdmiCecMessage;
+import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.util.Slog;
import com.android.server.SystemService;
+import java.util.Iterator;
+import java.util.LinkedList;
import java.util.Locale;
/**
@@ -41,18 +44,30 @@
// and sparse call it shares a thread to handle IO operations.
private final HandlerThread mIoThread = new HandlerThread("Hdmi Control Io Thread");
+ // A collection of FeatureAction.
+ // Note that access to this collection should happen in service thread.
+ private final LinkedList<FeatureAction> mActions = new LinkedList<>();
+
@Nullable
private HdmiCecController mCecController;
@Nullable
private HdmiMhlController mMhlController;
+ // Whether ARC is "enabled" or not.
+ // TODO: it may need to hold lock if it's accessed from others.
+ private boolean mArcStatusEnabled = false;
+
+ // Handler running on service thread. It's used to run a task in service thread.
+ private Handler mHandler = new Handler();
+
public HdmiControlService(Context context) {
super(context);
}
@Override
public void onStart() {
+ mIoThread.start();
mCecController = HdmiCecController.create(this);
if (mCecController != null) {
mCecController.initializeLocalDevices(getContext().getResources()
@@ -83,35 +98,83 @@
* <p>Declared as package-private.
*/
Looper getServiceLooper() {
- return Looper.myLooper();
+ return mHandler.getLooper();
}
/**
- * Add a new {@link FeatureAction} to the action queue.
+ * Add and start a new {@link FeatureAction} to the action queue.
*
- * @param action {@link FeatureAction} to add
+ * @param action {@link FeatureAction} to add and start
*/
- void addAction(FeatureAction action) {
- // TODO: Implement this.
+ void addAndStartAction(final FeatureAction action) {
+ // TODO: may need to check the number of stale actions.
+ runOnServiceThread(new Runnable() {
+ @Override
+ public void run() {
+ mActions.add(action);
+ action.start();
+ }
+ });
}
-
/**
* Remove the given {@link FeatureAction} object from the action queue.
*
- * @param action {@link FeatureAction} to add
+ * @param action {@link FeatureAction} to remove
*/
- void removeAction(FeatureAction action) {
- // TODO: Implement this.
+ void removeAction(final FeatureAction action) {
+ runOnServiceThread(new Runnable() {
+ @Override
+ public void run() {
+ mActions.remove(action);
+ }
+ });
+ }
+
+ // Remove all actions matched with the given Class type.
+ private <T extends FeatureAction> void removeAction(final Class<T> clazz) {
+ runOnServiceThread(new Runnable() {
+ @Override
+ public void run() {
+ Iterator<FeatureAction> iter = mActions.iterator();
+ while (iter.hasNext()) {
+ FeatureAction action = iter.next();
+ if (action.getClass().equals(clazz)) {
+ action.clear();
+ mActions.remove(action);
+ }
+ }
+ }
+ });
+ }
+
+ private void runOnServiceThread(Runnable runnable) {
+ mHandler.post(runnable);
+ }
+
+ /**
+ * Change ARC status into the given {@code enabled} status.
+ *
+ * @return {@code true} if ARC was in "Enabled" status
+ */
+ boolean setArcStatus(boolean enabled) {
+ boolean oldStatus = mArcStatusEnabled;
+ // 1. Enable/disable ARC circuit.
+ // TODO: call set_audio_return_channel of hal interface.
+
+ // 2. Update arc status;
+ mArcStatusEnabled = enabled;
+ return oldStatus;
}
/**
* Transmit a CEC command to CEC bus.
*
* @param command CEC command to send out
+ * @return {@code true} if succeeds to send command
*/
- void sendCecCommand(HdmiCecMessage command) {
- mCecController.sendCommand(command);
+ boolean sendCecCommand(HdmiCecMessage command) {
+ return mCecController.sendCommand(command);
}
/**
@@ -142,6 +205,12 @@
case HdmiCec.MESSAGE_GET_CEC_VERSION:
handleGetCecVersion(message);
return true;
+ case HdmiCec.MESSAGE_INITIATE_ARC:
+ handleInitiateArc(message);
+ return true;
+ case HdmiCec.MESSAGE_TERMINATE_ARC:
+ handleTerminateArc(message);
+ return true;
// TODO: Add remaining system information query such as
// <Give Device Power Status> and <Request Active Source> handler.
default:
@@ -150,6 +219,36 @@
}
}
+ /**
+ * Called when a new hotplug event is issued.
+ *
+ * @param port hdmi port number where hot plug event issued.
+ * @param connected whether to be plugged in or not
+ */
+ void onHotplug(int portNo, boolean connected) {
+ // TODO: Start "RequestArcInitiationAction" if ARC port.
+ }
+
+ private void handleInitiateArc(HdmiCecMessage message){
+ // In case where <Initiate Arc> is started by <Request ARC Initiation>
+ // need to clean up RequestArcInitiationAction.
+ removeAction(RequestArcInitiationAction.class);
+ SetArcTransmissionStateAction action = new SetArcTransmissionStateAction(this,
+ message.getDestination(), message.getSource(), true);
+ addAndStartAction(action);
+ }
+
+ private void handleTerminateArc(HdmiCecMessage message) {
+ // In case where <Terminate Arc> is started by <Request ARC Termination>
+ // need to clean up RequestArcInitiationAction.
+ // TODO: check conditions of power status by calling is_connected api
+ // to be added soon.
+ removeAction(RequestArcTerminationAction.class);
+ SetArcTransmissionStateAction action = new SetArcTransmissionStateAction(this,
+ message.getDestination(), message.getSource(), false);
+ addAndStartAction(action);
+ }
+
private void handleGetCecVersion(HdmiCecMessage message) {
int version = mCecController.getVersion();
HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildCecVersion(message.getDestination(),
diff --git a/services/core/java/com/android/server/hdmi/NewDeviceAction.java b/services/core/java/com/android/server/hdmi/NewDeviceAction.java
index e0bc718..156bbbe 100644
--- a/services/core/java/com/android/server/hdmi/NewDeviceAction.java
+++ b/services/core/java/com/android/server/hdmi/NewDeviceAction.java
@@ -103,7 +103,7 @@
requestVendorId();
return true;
} else if (opcode == HdmiCec.MESSAGE_FEATURE_ABORT) {
- int requestOpcode = params[1];
+ int requestOpcode = params[1] & 0xff;
if (requestOpcode == HdmiCec.MESSAGE_SET_OSD_NAME) {
mState = STATE_WAITING_FOR_DEVICE_VENDOR_ID;
requestVendorId();
@@ -113,7 +113,8 @@
} else if (mState == STATE_WAITING_FOR_DEVICE_VENDOR_ID) {
if (opcode == HdmiCec.MESSAGE_DEVICE_VENDOR_ID) {
if (params.length == 3) {
- mVendorId = (params[0] << 16) + (params[1] << 8) + params[2];
+ mVendorId = ((params[0] & 0xff) << 16) + ((params[1] & 0xff) << 8)
+ + (params[2] & 0xff);
} else {
Slog.e(TAG, "Failed to get device vendor ID: ");
}
@@ -121,7 +122,7 @@
finish();
return true;
} else if (opcode == HdmiCec.MESSAGE_FEATURE_ABORT) {
- int requestOpcode = params[1];
+ int requestOpcode = params[1] & 0xff;
if (requestOpcode == HdmiCec.MESSAGE_DEVICE_VENDOR_ID) {
addDeviceInfo();
finish();
diff --git a/services/core/java/com/android/server/hdmi/RequestArcAction.java b/services/core/java/com/android/server/hdmi/RequestArcAction.java
new file mode 100644
index 0000000..196f28a
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/RequestArcAction.java
@@ -0,0 +1,100 @@
+/*
+ * 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.server.hdmi;
+
+import android.hardware.hdmi.HdmiCec;
+import android.hardware.hdmi.HdmiCecMessage;
+import android.util.Slog;
+
+/**
+ * Base feature action class for <Request ARC Initiation>/<Request ARC Termination>.
+ */
+abstract class RequestArcAction extends FeatureAction {
+ private static final String TAG = "RequestArcAction";
+
+ // State in which waits for ARC response.
+ protected static final int STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE = 1;
+
+ // Logical address of AV Receiver.
+ protected final int mAvrAddress;
+
+ /**
+ * @Constructor
+ *
+ * @param service {@link HdmiControlService} instance
+ * @param sourceAddress logical address to be used as source address. It should
+ * TV type
+ * @param avrAddress address of AV receiver. It should be AUDIO_SYSTEM type
+ * @throw IllegalArugmentException if device type of sourceAddress and avrAddress
+ * is invalid
+ */
+ RequestArcAction(HdmiControlService service, int sourceAddress, int avrAddress) {
+ super(service, sourceAddress);
+ verifyAddressType(sourceAddress, HdmiCec.DEVICE_TV);
+ verifyAddressType(avrAddress, HdmiCec.DEVICE_AUDIO_SYSTEM);
+ mAvrAddress = avrAddress;
+ }
+
+ private static void verifyAddressType(int logicalAddress, int deviceType) {
+ int actualDeviceType = HdmiCec.getTypeFromAddress(logicalAddress);
+ if (actualDeviceType != deviceType) {
+ throw new IllegalArgumentException("Device type missmatch:[Expected:" + deviceType
+ + ", Actual:" + actualDeviceType);
+ }
+ }
+
+ @Override
+ boolean processCommand(HdmiCecMessage cmd) {
+ if (mState != STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE) {
+ return false;
+ }
+
+ int src = cmd.getSource();
+ if (src != mAvrAddress) {
+ Slog.w(TAG, "Invalid source [Expected:" + mAvrAddress + ", Actual:" + src + "]");
+ return false;
+ }
+ int opcode = cmd.getOpcode();
+ switch (opcode) {
+ // Handles only <Feature Abort> here and, both <Initiate ARC> and <Terminate ARC>
+ // are handled in HdmiControlService itself because both can be
+ // received wihtout <Request ARC Initiation> or <Request ARC Termination>.
+ case HdmiCec.MESSAGE_FEATURE_ABORT:
+ disableArcTransmission();
+ finish();
+ return true;
+ default:
+ Slog.w(TAG, "Unsupported opcode:" + cmd.toString());
+ }
+ return false;
+ }
+
+ protected final void disableArcTransmission() {
+ // Start Set ARC Transmission State action.
+ SetArcTransmissionStateAction action = new SetArcTransmissionStateAction(mService,
+ mSourceAddress, mAvrAddress, false);
+ mService.addAndStartAction(action);
+ }
+
+ @Override
+ final void handleTimerEvent(int state) {
+ if (mState != state || state != STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE) {
+ return;
+ }
+ disableArcTransmission();
+ }
+}
diff --git a/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java b/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java
new file mode 100644
index 0000000..0a701f9
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java
@@ -0,0 +1,53 @@
+/*
+ * 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.server.hdmi;
+
+import android.util.Slog;
+
+/**
+ * Feature action that handles ARC action initiated by TV devices.
+ *
+ * <p>This action is created by TV's hot plug event of ARC port.
+ */
+final class RequestArcInitiationAction extends RequestArcAction {
+ private static final String TAG = "RequestArcInitiationAction";
+
+ /**
+ * @Constructor
+ *
+ * For more details look at {@link RequestArcAction#RequestArcAction}.
+ */
+ RequestArcInitiationAction(HdmiControlService service, int sourceAddress, int avrAddress) {
+ super(service, sourceAddress, avrAddress);
+ }
+
+ @Override
+ boolean start() {
+ if (sendCommand(
+ HdmiCecMessageBuilder.buildRequestArcInitiation(mSourceAddress, mAvrAddress))) {
+ mState = STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE;
+ addTimer(mState, TIMEOUT_MS);
+ } else {
+ Slog.w(TAG, "Failed to send <Request ARC Initiation>");
+ // If failed to send <Request ARC Initiation>, start "Disabled" ARC transmission
+ // action.
+ disableArcTransmission();
+ finish();
+ }
+ return true;
+ }
+}
diff --git a/services/core/java/com/android/server/hdmi/RequestArcTerminationAction.java b/services/core/java/com/android/server/hdmi/RequestArcTerminationAction.java
new file mode 100644
index 0000000..db1b992
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/RequestArcTerminationAction.java
@@ -0,0 +1,53 @@
+/*
+ * 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.server.hdmi;
+
+import android.util.Slog;
+
+/**
+ * Feature action to handle <Request ARC Termination>.
+ *
+ * <p>It's initiated by user's manual termination or ARC channel close from TV.
+ */
+final class RequestArcTerminationAction extends RequestArcAction {
+ private static final String TAG = "RequestArcTerminationAction";
+
+ /**
+ * @Constructor
+ *
+ * @see RequestArcAction#RequestArcAction
+ */
+ RequestArcTerminationAction(HdmiControlService service, int sourceAddress, int avrAddress) {
+ super(service, sourceAddress, avrAddress);
+ }
+
+ @Override
+ boolean start() {
+ if (sendCommand(
+ HdmiCecMessageBuilder.buildRequestArcTermination(mSourceAddress, mAvrAddress))) {
+ mState = STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE;
+ addTimer(mState, TIMEOUT_MS);
+ } else {
+ Slog.w(TAG, "Failed to send <Request ARC Initiation>");
+ // If failed to send <Request ARC Termination>, start "Disabled" ARC transmission
+ // action.
+ disableArcTransmission();
+ finish();
+ }
+ return true;
+ }
+}
diff --git a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
new file mode 100644
index 0000000..6bf149b
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
@@ -0,0 +1,128 @@
+/*
+ * 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.server.hdmi;
+
+import android.hardware.hdmi.HdmiCec;
+import android.hardware.hdmi.HdmiCecMessage;
+import android.util.Slog;
+
+/**
+ * Feature action that handles enabling/disabling of ARC transmission channel.
+ * Once TV gets <Initiate ARC>, TV sends <Report ARC Initiated> to AV Receiver.
+ * If it fails or it gets <Terminate ARC>, TV just disables ARC.
+ */
+final class SetArcTransmissionStateAction extends FeatureAction {
+ private static final String TAG = "SetArcTransmissionStateAction";
+
+ // State in which the action sent <Rerpot Arc Initiated> and
+ // is waiting for time out. If it receives <Feature Abort> within timeout
+ // ARC should be disabled.
+ private static final int STATE_WAITING_TIMEOUT = 1;
+
+ private final boolean mEnabled;
+ private final int mAvrAddress;
+
+ /**
+ * @Constructor
+ *
+ * @param service an instance of {@link HdmiControlService}
+ * @param sourceAddress logical address to be used as source address
+ * @param enabled whether to enable ARC Transmission channel
+ */
+ SetArcTransmissionStateAction(HdmiControlService service, int sourceAddress, int avrAddress,
+ boolean enabled) {
+ super(service, sourceAddress);
+ verifyAddressType(sourceAddress, HdmiCec.DEVICE_TV);
+ verifyAddressType(avrAddress, HdmiCec.DEVICE_AUDIO_SYSTEM);
+ mAvrAddress = avrAddress;
+ mEnabled = enabled;
+ }
+
+ // TODO: extract it as separate utility class.
+ private static void verifyAddressType(int logicalAddress, int deviceType) {
+ int actualDeviceType = HdmiCec.getTypeFromAddress(logicalAddress);
+ if (actualDeviceType != deviceType) {
+ throw new IllegalArgumentException("Device type missmatch:[Expected:" + deviceType
+ + ", Actual:" + actualDeviceType);
+ }
+ }
+
+ @Override
+ boolean start() {
+ if (mEnabled) {
+ if (sendCommand(
+ HdmiCecMessageBuilder.buildReportArcInitiated(mSourceAddress, mAvrAddress))) {
+ // Enable ARC status immediately after sending <Report Arc Initiated>.
+ // If AVR responds with <Feature Abort>, disable ARC status again.
+ // This is different from spec that says that turns ARC status to "Enabled"
+ // if <Report ARC Initiated> is acknowledged and no <Feature Abort> is received.
+ // But implemented this way to save the time having to wait for <Feature Abort>.
+ setArcStatus(true);
+ // If succeeds to send <Report ARC Initiated>, wait general timeout
+ // to check whether there is no <Feature Abort> for <Report ARC Initiated>.
+ mState = STATE_WAITING_TIMEOUT;
+ addTimer(mState, TIMEOUT_MS);
+ } else {
+ // If fails to send <Report ARC Initiated>, disable ARC and
+ // send <Report ARC Terminated> directly.
+ Slog.w(TAG, "Failed to send <Report ARC Initiated>:[source:" + mSourceAddress
+ + ", avr Address:" + mAvrAddress + "]");
+ setArcStatus(false);
+ finish();
+ }
+ } else {
+ setArcStatus(false);
+ finish();
+ }
+ return true;
+ }
+
+ private void setArcStatus(boolean enabled) {
+ boolean wasEnabled = mService.setArcStatus(enabled);
+ Slog.i(TAG, "Change arc status [old:" + wasEnabled + " ,new:" + enabled);
+
+ // If enabled before and set to "disabled" and send <Report Arc Terminated> to
+ // av reciever.
+ if (!enabled && wasEnabled) {
+ sendCommand(
+ HdmiCecMessageBuilder.buildReportArcTerminated(mSourceAddress, mAvrAddress));
+ }
+ }
+
+ @Override
+ boolean processCommand(HdmiCecMessage cmd) {
+ if (mState != STATE_WAITING_TIMEOUT) {
+ return false;
+ }
+
+ int opcode = cmd.getOpcode();
+ if (opcode == HdmiCec.MESSAGE_FEATURE_ABORT) {
+ setArcStatus(false);
+ }
+ finish();
+ return true;
+ }
+
+ @Override
+ void handleTimerEvent(int state) {
+ if (mState != state || mState != STATE_WAITING_TIMEOUT) {
+ return;
+ }
+ // Expire timeout for <Feature Abort>.
+ finish();
+ }
+}
diff --git a/services/core/java/com/android/server/net/DelayedDiskWrite.java b/services/core/java/com/android/server/net/DelayedDiskWrite.java
new file mode 100644
index 0000000..6ed277d
--- /dev/null
+++ b/services/core/java/com/android/server/net/DelayedDiskWrite.java
@@ -0,0 +1,92 @@
+/*
+ * 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.server.net;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.io.BufferedOutputStream;
+import java.io.DataOutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+public class DelayedDiskWrite {
+ private HandlerThread mDiskWriteHandlerThread;
+ private Handler mDiskWriteHandler;
+ /* Tracks multiple writes on the same thread */
+ private int mWriteSequence = 0;
+ private final String TAG = "DelayedDiskWrite";
+
+ public interface Writer {
+ public void onWriteCalled(DataOutputStream out) throws IOException;
+ }
+
+ public void write(final String filePath, final Writer w) {
+ if (TextUtils.isEmpty(filePath)) {
+ throw new IllegalArgumentException("empty file path");
+ }
+
+ /* Do a delayed write to disk on a separate handler thread */
+ synchronized (this) {
+ if (++mWriteSequence == 1) {
+ mDiskWriteHandlerThread = new HandlerThread("DelayedDiskWriteThread");
+ mDiskWriteHandlerThread.start();
+ mDiskWriteHandler = new Handler(mDiskWriteHandlerThread.getLooper());
+ }
+ }
+
+ mDiskWriteHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ doWrite(filePath, w);
+ }
+ });
+ }
+
+ private void doWrite(String filePath, Writer w) {
+ DataOutputStream out = null;
+ try {
+ out = new DataOutputStream(new BufferedOutputStream(
+ new FileOutputStream(filePath)));
+ w.onWriteCalled(out);
+ } catch (IOException e) {
+ loge("Error writing data file " + filePath);
+ } finally {
+ if (out != null) {
+ try {
+ out.close();
+ } catch (Exception e) {}
+ }
+
+ // Quit if no more writes sent
+ synchronized (this) {
+ if (--mWriteSequence == 0) {
+ mDiskWriteHandler.getLooper().quit();
+ mDiskWriteHandler = null;
+ mDiskWriteHandlerThread = null;
+ }
+ }
+ }
+ }
+
+ private void loge(String s) {
+ Log.e(TAG, s);
+ }
+}
+
diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java
new file mode 100644
index 0000000..6ccbec0
--- /dev/null
+++ b/services/core/java/com/android/server/net/IpConfigStore.java
@@ -0,0 +1,327 @@
+/*
+ * 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.server.net;
+
+import android.net.IpConfiguration;
+import android.net.IpConfiguration.IpAssignment;
+import android.net.IpConfiguration.ProxySettings;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.NetworkUtils;
+import android.net.ProxyInfo;
+import android.net.RouteInfo;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.server.net.DelayedDiskWrite;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.EOFException;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.util.Map;
+
+public class IpConfigStore {
+ private static final String TAG = "IpConfigStore";
+ private static final boolean DBG = true;
+
+ protected final DelayedDiskWrite mWriter;
+
+ /* IP and proxy configuration keys */
+ protected static final String ID_KEY = "id";
+ protected static final String IP_ASSIGNMENT_KEY = "ipAssignment";
+ protected static final String LINK_ADDRESS_KEY = "linkAddress";
+ protected static final String GATEWAY_KEY = "gateway";
+ protected static final String DNS_KEY = "dns";
+ protected static final String PROXY_SETTINGS_KEY = "proxySettings";
+ protected static final String PROXY_HOST_KEY = "proxyHost";
+ protected static final String PROXY_PORT_KEY = "proxyPort";
+ protected static final String PROXY_PAC_FILE = "proxyPac";
+ protected static final String EXCLUSION_LIST_KEY = "exclusionList";
+ protected static final String EOS = "eos";
+
+ protected static final int IPCONFIG_FILE_VERSION = 2;
+
+ public IpConfigStore() {
+ mWriter = new DelayedDiskWrite();
+ }
+
+ private boolean writeConfig(DataOutputStream out, int configKey,
+ IpConfiguration config) throws IOException {
+ boolean written = false;
+
+ try {
+ LinkProperties linkProperties = config.linkProperties;
+ switch (config.ipAssignment) {
+ case STATIC:
+ out.writeUTF(IP_ASSIGNMENT_KEY);
+ out.writeUTF(config.ipAssignment.toString());
+ for (LinkAddress linkAddr : linkProperties.getLinkAddresses()) {
+ out.writeUTF(LINK_ADDRESS_KEY);
+ out.writeUTF(linkAddr.getAddress().getHostAddress());
+ out.writeInt(linkAddr.getNetworkPrefixLength());
+ }
+ for (RouteInfo route : linkProperties.getRoutes()) {
+ out.writeUTF(GATEWAY_KEY);
+ LinkAddress dest = route.getDestination();
+ if (dest != null) {
+ out.writeInt(1);
+ out.writeUTF(dest.getAddress().getHostAddress());
+ out.writeInt(dest.getNetworkPrefixLength());
+ } else {
+ out.writeInt(0);
+ }
+ if (route.getGateway() != null) {
+ out.writeInt(1);
+ out.writeUTF(route.getGateway().getHostAddress());
+ } else {
+ out.writeInt(0);
+ }
+ }
+ for (InetAddress inetAddr : linkProperties.getDnses()) {
+ out.writeUTF(DNS_KEY);
+ out.writeUTF(inetAddr.getHostAddress());
+ }
+ written = true;
+ break;
+ case DHCP:
+ out.writeUTF(IP_ASSIGNMENT_KEY);
+ out.writeUTF(config.ipAssignment.toString());
+ written = true;
+ break;
+ case UNASSIGNED:
+ /* Ignore */
+ break;
+ default:
+ loge("Ignore invalid ip assignment while writing");
+ break;
+ }
+
+ switch (config.proxySettings) {
+ case STATIC:
+ ProxyInfo proxyProperties = linkProperties.getHttpProxy();
+ String exclusionList = proxyProperties.getExclusionListAsString();
+ out.writeUTF(PROXY_SETTINGS_KEY);
+ out.writeUTF(config.proxySettings.toString());
+ out.writeUTF(PROXY_HOST_KEY);
+ out.writeUTF(proxyProperties.getHost());
+ out.writeUTF(PROXY_PORT_KEY);
+ out.writeInt(proxyProperties.getPort());
+ out.writeUTF(EXCLUSION_LIST_KEY);
+ out.writeUTF(exclusionList);
+ written = true;
+ break;
+ case PAC:
+ ProxyInfo proxyPacProperties = linkProperties.getHttpProxy();
+ out.writeUTF(PROXY_SETTINGS_KEY);
+ out.writeUTF(config.proxySettings.toString());
+ out.writeUTF(PROXY_PAC_FILE);
+ out.writeUTF(proxyPacProperties.getPacFileUrl().toString());
+ written = true;
+ break;
+ case NONE:
+ out.writeUTF(PROXY_SETTINGS_KEY);
+ out.writeUTF(config.proxySettings.toString());
+ written = true;
+ break;
+ case UNASSIGNED:
+ /* Ignore */
+ break;
+ default:
+ loge("Ignore invalid proxy settings while writing");
+ break;
+ }
+
+ if (written) {
+ out.writeUTF(ID_KEY);
+ out.writeInt(configKey);
+ }
+ } catch (NullPointerException e) {
+ loge("Failure in writing " + config.linkProperties + e);
+ }
+ out.writeUTF(EOS);
+
+ return written;
+ }
+
+ public void writeIpAndProxyConfigurations(String filePath,
+ final SparseArray<IpConfiguration> networks) {
+ mWriter.write(filePath, new DelayedDiskWrite.Writer() {
+ public void onWriteCalled(DataOutputStream out) throws IOException{
+ out.writeInt(IPCONFIG_FILE_VERSION);
+ for(int i = 0; i < networks.size(); i++) {
+ writeConfig(out, networks.keyAt(i), networks.valueAt(i));
+ }
+ }
+ });
+ }
+
+ public SparseArray<IpConfiguration> readIpAndProxyConfigurations(String filePath) {
+ SparseArray<IpConfiguration> networks = new SparseArray<IpConfiguration>();
+
+ DataInputStream in = null;
+ try {
+ in = new DataInputStream(new BufferedInputStream(new FileInputStream(filePath)));
+
+ int version = in.readInt();
+ if (version != 2 && version != 1) {
+ loge("Bad version on IP configuration file, ignore read");
+ return null;
+ }
+
+ while (true) {
+ int id = -1;
+ // Default is DHCP with no proxy
+ IpAssignment ipAssignment = IpAssignment.DHCP;
+ ProxySettings proxySettings = ProxySettings.NONE;
+ LinkProperties linkProperties = new LinkProperties();
+ String proxyHost = null;
+ String pacFileUrl = null;
+ int proxyPort = -1;
+ String exclusionList = null;
+ String key;
+
+ do {
+ key = in.readUTF();
+ try {
+ if (key.equals(ID_KEY)) {
+ id = in.readInt();
+ } else if (key.equals(IP_ASSIGNMENT_KEY)) {
+ ipAssignment = IpAssignment.valueOf(in.readUTF());
+ } else if (key.equals(LINK_ADDRESS_KEY)) {
+ LinkAddress linkAddr = new LinkAddress(
+ NetworkUtils.numericToInetAddress(in.readUTF()), in.readInt());
+ linkProperties.addLinkAddress(linkAddr);
+ } else if (key.equals(GATEWAY_KEY)) {
+ LinkAddress dest = null;
+ InetAddress gateway = null;
+ if (version == 1) {
+ // only supported default gateways - leave the dest/prefix empty
+ gateway = NetworkUtils.numericToInetAddress(in.readUTF());
+ } else {
+ if (in.readInt() == 1) {
+ dest = new LinkAddress(
+ NetworkUtils.numericToInetAddress(in.readUTF()),
+ in.readInt());
+ }
+ if (in.readInt() == 1) {
+ gateway = NetworkUtils.numericToInetAddress(in.readUTF());
+ }
+ }
+ linkProperties.addRoute(new RouteInfo(dest, gateway));
+ } else if (key.equals(DNS_KEY)) {
+ linkProperties.addDns(
+ NetworkUtils.numericToInetAddress(in.readUTF()));
+ } else if (key.equals(PROXY_SETTINGS_KEY)) {
+ proxySettings = ProxySettings.valueOf(in.readUTF());
+ } else if (key.equals(PROXY_HOST_KEY)) {
+ proxyHost = in.readUTF();
+ } else if (key.equals(PROXY_PORT_KEY)) {
+ proxyPort = in.readInt();
+ } else if (key.equals(PROXY_PAC_FILE)) {
+ pacFileUrl = in.readUTF();
+ } else if (key.equals(EXCLUSION_LIST_KEY)) {
+ exclusionList = in.readUTF();
+ } else if (key.equals(EOS)) {
+ break;
+ } else {
+ loge("Ignore unknown key " + key + "while reading");
+ }
+ } catch (IllegalArgumentException e) {
+ loge("Ignore invalid address while reading" + e);
+ }
+ } while (true);
+
+ if (id != -1) {
+ IpConfiguration config = new IpConfiguration();
+ networks.put(id, config);
+
+ config.linkProperties = linkProperties;
+ switch (ipAssignment) {
+ case STATIC:
+ case DHCP:
+ config.ipAssignment = ipAssignment;
+ break;
+ case UNASSIGNED:
+ loge("BUG: Found UNASSIGNED IP on file, use DHCP");
+ config.ipAssignment = IpAssignment.DHCP;
+ break;
+ default:
+ loge("Ignore invalid ip assignment while reading.");
+ config.ipAssignment = IpAssignment.UNASSIGNED;
+ break;
+ }
+
+ switch (proxySettings) {
+ case STATIC:
+ config.proxySettings = proxySettings;
+ ProxyInfo ProxyInfo =
+ new ProxyInfo(proxyHost, proxyPort, exclusionList);
+ linkProperties.setHttpProxy(ProxyInfo);
+ break;
+ case PAC:
+ config.proxySettings = proxySettings;
+ ProxyInfo proxyPacProperties =
+ new ProxyInfo(pacFileUrl);
+ linkProperties.setHttpProxy(proxyPacProperties);
+ break;
+ case NONE:
+ config.proxySettings = proxySettings;
+ break;
+ case UNASSIGNED:
+ loge("BUG: Found UNASSIGNED proxy on file, use NONE");
+ config.proxySettings = ProxySettings.NONE;
+ break;
+ default:
+ loge("Ignore invalid proxy settings while reading");
+ config.proxySettings = ProxySettings.UNASSIGNED;
+ break;
+ }
+ } else {
+ if (DBG) log("Missing id while parsing configuration");
+ }
+ }
+ } catch (EOFException ignore) {
+ } catch (IOException e) {
+ loge("Error parsing configuration" + e);
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (Exception e) {}
+ }
+ }
+
+ return networks;
+ }
+
+ protected void loge(String s) {
+ Log.e(TAG, s);
+ }
+
+ protected void log(String s) {
+ Log.d(TAG, s);
+ }
+}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 1734a33..9569c0d1 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -63,7 +63,7 @@
import android.service.notification.IConditionListener;
import android.service.notification.IConditionProvider;
import android.service.notification.NotificationListenerService;
-import android.service.notification.NotificationOrderUpdate;
+import android.service.notification.NotificationRankingUpdate;
import android.service.notification.StatusBarNotification;
import android.service.notification.Condition;
import android.service.notification.ZenModeConfig;
@@ -1744,7 +1744,7 @@
sendAccessibilityEvent(notification, pkg);
}
- mListeners.notifyPostedLocked(r.sbn);
+ mListeners.notifyPostedLocked(r.sbn, cloneNotificationListLocked());
} else {
Slog.e(TAG, "Not posting notification with icon==0: " + notification);
if (old != null && old.statusBarKey != null) {
@@ -1755,7 +1755,7 @@
Binder.restoreCallingIdentity(identity);
}
- mListeners.notifyRemovedLocked(r.sbn);
+ mListeners.notifyRemovedLocked(r.sbn, cloneNotificationListLocked());
}
// ATTENTION: in a future release we will bail out here
// so that we do not play sounds, show lights, etc. for invalid
@@ -2041,16 +2041,19 @@
private void handleSendRankingUpdate() {
synchronized (mNotificationList) {
- final int N = mNotificationList.size();
- ArrayList<StatusBarNotification> sbns =
- new ArrayList<StatusBarNotification>(N);
- for (int i = 0; i < N; i++ ) {
- sbns.add(mNotificationList.get(i).sbn);
- }
- mListeners.notifyOrderUpdateLocked(sbns);
+ mListeners.notifyRankingUpdateLocked(cloneNotificationListLocked());
}
}
+ private ArrayList<StatusBarNotification> cloneNotificationListLocked() {
+ final int N = mNotificationList.size();
+ ArrayList<StatusBarNotification> sbns = new ArrayList<StatusBarNotification>(N);
+ for (int i = 0; i < N; i++) {
+ sbns.add(mNotificationList.get(i).sbn);
+ }
+ return sbns;
+ }
+
private final class WorkerHandler extends Handler
{
@Override
@@ -2136,7 +2139,7 @@
Binder.restoreCallingIdentity(identity);
}
r.statusBarKey = null;
- mListeners.notifyRemovedLocked(r.sbn);
+ mListeners.notifyRemovedLocked(r.sbn, cloneNotificationListLocked());
}
// sound
@@ -2442,6 +2445,33 @@
}
}
+ /**
+ * Generates a NotificationRankingUpdate from 'sbns', considering only
+ * notifications visible to the given listener.
+ */
+ private static NotificationRankingUpdate makeRankingUpdateForListener(ManagedServiceInfo info,
+ ArrayList<StatusBarNotification> sbns) {
+ int speedBumpIndex = -1;
+ ArrayList<String> keys = new ArrayList<String>(sbns.size());
+ ArrayList<String> dndKeys = new ArrayList<String>(sbns.size());
+ for (StatusBarNotification sbn: sbns) {
+ if (!info.enabledAndUserMatches(sbn.getUserId())) {
+ continue;
+ }
+ keys.add(sbn.getKey());
+ if (sbn.getNotification().extras.getBoolean(EXTRA_INTERCEPT)) {
+ dndKeys.add(sbn.getKey());
+ }
+ if (speedBumpIndex == -1 &&
+ sbn.getNotification().priority == Notification.PRIORITY_MIN) {
+ speedBumpIndex = keys.size() - 1;
+ }
+ }
+ String[] keysAr = keys.toArray(new String[keys.size()]);
+ String[] dndKeysAr = dndKeys.toArray(new String[dndKeys.size()]);
+ return new NotificationRankingUpdate(keysAr, dndKeysAr, speedBumpIndex);
+ }
+
public class NotificationListeners extends ManagedServices {
public NotificationListeners() {
@@ -2468,9 +2498,12 @@
@Override
public void onServiceAdded(ManagedServiceInfo info) {
final INotificationListener listener = (INotificationListener) info.service;
- final String[] keys = getActiveNotificationKeys(listener);
+ final ArrayList<StatusBarNotification> sbns;
+ synchronized (mNotificationList) {
+ sbns = cloneNotificationListLocked();
+ }
try {
- listener.onListenerConnected(new NotificationOrderUpdate(keys));
+ listener.onListenerConnected(makeRankingUpdateForListener(info, sbns));
} catch (RemoteException e) {
// we tried
}
@@ -2479,44 +2512,47 @@
/**
* asynchronously notify all listeners about a new notification
*/
- public void notifyPostedLocked(StatusBarNotification sbn) {
+ public void notifyPostedLocked(StatusBarNotification sbn,
+ final ArrayList<StatusBarNotification> sbns) {
// make a copy in case changes are made to the underlying Notification object
final StatusBarNotification sbnClone = sbn.clone();
for (final ManagedServiceInfo info : mServices) {
- if (info.isEnabledForCurrentProfiles()) {
- final INotificationListener listener = (INotificationListener) info.service;
- final String[] keys = getActiveNotificationKeys(listener);
- if (keys.length > 0) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- notifyPostedIfUserMatch(info, sbnClone, keys);
- }
- });
- }
+ if (!info.isEnabledForCurrentProfiles()) {
+ continue;
}
+ final NotificationRankingUpdate update = makeRankingUpdateForListener(info, sbns);
+ if (update.getOrderedKeys().length == 0) {
+ continue;
+ }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ notifyPostedIfUserMatch(info, sbnClone, update);
+ }
+ });
}
}
/**
* asynchronously notify all listeners about a removed notification
*/
- public void notifyRemovedLocked(StatusBarNotification sbn) {
+ public void notifyRemovedLocked(StatusBarNotification sbn,
+ final ArrayList<StatusBarNotification> sbns) {
// make a copy in case changes are made to the underlying Notification object
// NOTE: this copy is lightweight: it doesn't include heavyweight parts of the
// notification
final StatusBarNotification sbnLight = sbn.cloneLight();
for (final ManagedServiceInfo info : mServices) {
- if (info.isEnabledForCurrentProfiles()) {
- final INotificationListener listener = (INotificationListener) info.service;
- final String[] keys = getActiveNotificationKeys(listener);
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- notifyRemovedIfUserMatch(info, sbnLight, keys);
- }
- });
+ if (!info.isEnabledForCurrentProfiles()) {
+ continue;
}
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ notifyRemovedIfUserMatch(info, sbnLight,
+ makeRankingUpdateForListener(info, sbns));
+ }
+ });
}
}
@@ -2526,60 +2562,52 @@
* must not rely on mutable members of these objects, such as the
* {@link Notification}.
*/
- public void notifyOrderUpdateLocked(final ArrayList<StatusBarNotification> sbns) {
+ public void notifyRankingUpdateLocked(final ArrayList<StatusBarNotification> sbns) {
for (final ManagedServiceInfo serviceInfo : mServices) {
+ if (!serviceInfo.isEnabledForCurrentProfiles()) {
+ continue;
+ }
mHandler.post(new Runnable() {
@Override
public void run() {
- notifyOrderUpdateIfUserMatch(serviceInfo, sbns);
+ notifyRankingUpdate(serviceInfo,
+ makeRankingUpdateForListener(serviceInfo, sbns));
}
});
}
}
private void notifyPostedIfUserMatch(final ManagedServiceInfo info,
- final StatusBarNotification sbn, String[] keys) {
+ final StatusBarNotification sbn, NotificationRankingUpdate rankingUpdate) {
if (!info.enabledAndUserMatches(sbn.getUserId())) {
return;
}
final INotificationListener listener = (INotificationListener)info.service;
try {
- listener.onNotificationPosted(sbn, new NotificationOrderUpdate(keys));
+ listener.onNotificationPosted(sbn, rankingUpdate);
} catch (RemoteException ex) {
Log.e(TAG, "unable to notify listener (posted): " + listener, ex);
}
}
private void notifyRemovedIfUserMatch(ManagedServiceInfo info, StatusBarNotification sbn,
- String[] keys) {
+ NotificationRankingUpdate rankingUpdate) {
if (!info.enabledAndUserMatches(sbn.getUserId())) {
return;
}
- final INotificationListener listener = (INotificationListener)info.service;
+ final INotificationListener listener = (INotificationListener) info.service;
try {
- listener.onNotificationRemoved(sbn, new NotificationOrderUpdate(keys));
+ listener.onNotificationRemoved(sbn, rankingUpdate);
} catch (RemoteException ex) {
Log.e(TAG, "unable to notify listener (removed): " + listener, ex);
}
}
- /**
- * @param sbns an array of {@link StatusBarNotification}s to consider. This code
- * must not rely on mutable members of these objects, such as the
- * {@link Notification}.
- */
- public void notifyOrderUpdateIfUserMatch(ManagedServiceInfo info,
- ArrayList<StatusBarNotification> sbns) {
- ArrayList<String> keys = new ArrayList<String>(sbns.size());
- for (StatusBarNotification sbn: sbns) {
- if (info.enabledAndUserMatches(sbn.getUserId())) {
- keys.add(sbn.getKey());
- }
- }
- final INotificationListener listener = (INotificationListener)info.service;
+ private void notifyRankingUpdate(ManagedServiceInfo info,
+ NotificationRankingUpdate rankingUpdate) {
+ final INotificationListener listener = (INotificationListener) info.service;
try {
- listener.onNotificationOrderUpdate(
- new NotificationOrderUpdate(keys.toArray(new String[keys.size()])));
+ listener.onNotificationRankingUpdate(rankingUpdate);
} catch (RemoteException ex) {
Log.e(TAG, "unable to notify listener (ranking update): " + listener, ex);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 61b3a89..dd5e9de 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -5486,6 +5486,20 @@
}
pkg.mScanPath = path;
+ if ((scanMode&SCAN_BOOTING) == 0 && pkgSetting.sharedUser != null) {
+ // We don't do this here during boot because we can do it all
+ // at once after scanning all existing packages.
+ //
+ // We also do this *before* we perform dexopt on this package, so that
+ // we can avoid redundant dexopts, and also to make sure we've got the
+ // code and package path correct.
+ if (!adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages,
+ pkg, forceDex, (scanMode & SCAN_DEFER_DEX) != 0)) {
+ mLastScanError = PackageManager.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE;
+ return null;
+ }
+ }
+
if ((scanMode&SCAN_NO_DEX) == 0) {
if (performDexOptLI(pkg, forceDex, (scanMode&SCAN_DEFER_DEX) != 0, false)
== DEX_OPT_FAILED) {
@@ -5613,16 +5627,6 @@
// writer
synchronized (mPackages) {
- if ((scanMode&SCAN_BOOTING) == 0 && pkgSetting.sharedUser != null) {
- // We don't do this here during boot because we can do it all
- // at once after scanning all existing packages.
- if (!adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages,
- pkg.applicationInfo.cpuAbi,
- forceDex, (scanMode & SCAN_DEFER_DEX) != 0)) {
- mLastScanError = PackageManager.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE;
- return null;
- }
- }
// We don't expect installation to fail beyond this point,
if ((scanMode&SCAN_MONITOR) != 0) {
mAppDirs.put(pkg.mPath, pkg);
@@ -5967,19 +5971,43 @@
return pkg;
}
+ /**
+ * Adjusts ABIs for a set of packages belonging to a shared user so that they all match.
+ * i.e, so that all packages can be run inside a single process if required.
+ *
+ * Optionally, callers can pass in a parsed package via {@code newPackage} in which case
+ * this function will either try and make the ABI for all packages in {@code packagesForUser}
+ * match {@code scannedPackage} or will update the ABI of {@code scannedPackage} to match
+ * the ABI selected for {@code packagesForUser}. This variant is used when installing or
+ * updating a package that belongs to a shared user.
+ */
private boolean adjustCpuAbisForSharedUserLPw(Set<PackageSetting> packagesForUser,
- String requiredInstructionSet, boolean forceDexOpt, boolean deferDexOpt) {
+ PackageParser.Package scannedPackage, boolean forceDexOpt, boolean deferDexOpt) {
+ String requiredInstructionSet = null;
+ if (scannedPackage != null && scannedPackage.applicationInfo.cpuAbi != null) {
+ requiredInstructionSet = VMRuntime.getInstructionSet(
+ scannedPackage.applicationInfo.cpuAbi);
+ }
+
PackageSetting requirer = null;
for (PackageSetting ps : packagesForUser) {
- if (ps.cpuAbiString != null) {
+ // If packagesForUser contains scannedPackage, we skip it. This will happen
+ // when scannedPackage is an update of an existing package. Without this check,
+ // we will never be able to change the ABI of any package belonging to a shared
+ // user, even if it's compatible with other packages.
+ if (scannedPackage == null || ! scannedPackage.packageName.equals(ps.name)) {
+ if (ps.cpuAbiString == null) {
+ continue;
+ }
+
final String instructionSet = VMRuntime.getInstructionSet(ps.cpuAbiString);
if (requiredInstructionSet != null) {
if (!instructionSet.equals(requiredInstructionSet)) {
// We have a mismatch between instruction sets (say arm vs arm64).
// bail out.
String errorMessage = "Instruction set mismatch, "
- + ((requirer == null) ? "[caller]" : requirer.pkg)
- + " requires " + requiredInstructionSet + " whereas " + ps.pkg
+ + ((requirer == null) ? "[caller]" : requirer)
+ + " requires " + requiredInstructionSet + " whereas " + ps
+ " requires " + instructionSet;
Slog.e(TAG, errorMessage);
@@ -5995,20 +6023,37 @@
}
if (requiredInstructionSet != null) {
- for (PackageSetting ps : packagesForUser) {
- if (ps.cpuAbiString == null) {
- ps.cpuAbiString = requirer.cpuAbiString;
- if (ps.pkg != null) {
- ps.pkg.applicationInfo.cpuAbi = requirer.cpuAbiString;
- Slog.i(TAG, "Adjusting ABI for : " + ps.name + " to " + ps.cpuAbiString);
+ String adjustedAbi;
+ if (requirer != null) {
+ // requirer != null implies that either scannedPackage was null or that scannedPackage
+ // did not require an ABI, in which case we have to adjust scannedPackage to match
+ // the ABI of the set (which is the same as requirer's ABI)
+ adjustedAbi = requirer.cpuAbiString;
+ if (scannedPackage != null) {
+ scannedPackage.applicationInfo.cpuAbi = adjustedAbi;
+ }
+ } else {
+ // requirer == null implies that we're updating all ABIs in the set to
+ // match scannedPackage.
+ adjustedAbi = scannedPackage.applicationInfo.cpuAbi;
+ }
- if (performDexOptLI(ps.pkg, forceDexOpt, deferDexOpt, true) == DEX_OPT_FAILED) {
- ps.cpuAbiString = null;
- ps.pkg.applicationInfo.cpuAbi = null;
- return false;
- } else {
- mInstaller.rmdex(ps.codePathString, getPreferredInstructionSet());
- }
+ for (PackageSetting ps : packagesForUser) {
+ if (scannedPackage == null || ! scannedPackage.packageName.equals(ps.name)) {
+ if (ps.cpuAbiString != null) {
+ continue;
+ }
+
+ ps.cpuAbiString = adjustedAbi;
+ ps.pkg.applicationInfo.cpuAbi = adjustedAbi;
+ Slog.i(TAG, "Adjusting ABI for : " + ps.name + " to " + adjustedAbi);
+
+ if (performDexOptLI(ps.pkg, forceDexOpt, deferDexOpt, true) == DEX_OPT_FAILED) {
+ ps.cpuAbiString = null;
+ ps.pkg.applicationInfo.cpuAbi = null;
+ return false;
+ } else {
+ mInstaller.rmdex(ps.codePathString, getPreferredInstructionSet());
}
}
}
@@ -11876,6 +11921,7 @@
pw.println(" cmd may be one of:");
pw.println(" l[ibraries]: list known shared libraries");
pw.println(" f[ibraries]: list device features");
+ pw.println(" k[eysets]: print known keysets");
pw.println(" r[esolvers]: dump intent resolvers");
pw.println(" perm[issions]: dump permissions");
pw.println(" pref[erred]: print preferred package settings");
@@ -11886,8 +11932,8 @@
pw.println(" m[essages]: print collected runtime messages");
pw.println(" v[erifiers]: print package verifier info");
pw.println(" version: print database version info");
+ pw.println(" write: write current settings now");
pw.println(" <package.name>: info about given package");
- pw.println(" k[eysets]: print known keysets");
return;
} else if ("--checkin".equals(opt)) {
checkin = true;
@@ -11938,6 +11984,12 @@
dumpState.setDump(DumpState.DUMP_VERSION);
} else if ("k".equals(cmd) || "keysets".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_KEYSETS);
+ } else if ("write".equals(cmd)) {
+ synchronized (mPackages) {
+ mSettings.writeLPr();
+ pw.println("Settings written.");
+ return;
+ }
}
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index d37b240..3ca658f 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -59,6 +59,7 @@
import android.os.FileUtils;
import android.os.Process;
import android.os.UserHandle;
+import android.os.UserManager;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
@@ -527,8 +528,11 @@
// original default value is true), or we are being
// asked to install for all users, or this is the
// user we are installing for.
+ // In this context all users (USER_ALL) implies an adb install,
+ // so we additionally check whether that is allowed for this user.
final boolean installed = installUser == null
- || installUser.getIdentifier() == UserHandle.USER_ALL
+ || (installUser.getIdentifier() == UserHandle.USER_ALL
+ && (!isUnknownSourcesDisallowed(user.id)))
|| installUser.getIdentifier() == user.id;
p.setUserState(user.id, COMPONENT_ENABLED_STATE_DEFAULT,
installed,
@@ -593,7 +597,10 @@
List<UserInfo> users = getAllUsers();
if (users != null) {
for (UserInfo user : users) {
- if (installUser.getIdentifier() == UserHandle.USER_ALL
+ // Installing for USER_ALL implies an adb install, so we
+ // additionally check whether that is allowed for this user.
+ if ((installUser.getIdentifier() == UserHandle.USER_ALL
+ && (!isUnknownSourcesDisallowed(user.id)))
|| installUser.getIdentifier() == user.id) {
boolean installed = p.getInstalled(user.id);
if (!installed) {
@@ -608,6 +615,12 @@
return p;
}
+ boolean isUnknownSourcesDisallowed(int userId) {
+ UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ return um.getUserRestrictions(new UserHandle(userId)).getBoolean(
+ UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, false);
+ }
+
void insertPackageSettingLPw(PackageSetting p, PackageParser.Package pkg) {
p.pkg = pkg;
// pkg.mSetEnabled = p.getEnabled(userId);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index fd180bf..102b2d4 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -789,6 +789,7 @@
writeBoolean(serializer, restrictions, UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_UNMUTE_MICROPHONE);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_ADJUST_VOLUME);
+ writeBoolean(serializer, restrictions, UserManager.DISALLOW_TELEPHONY);
serializer.endTag(null, TAG_RESTRICTIONS);
}
serializer.endTag(null, TAG_USER);
@@ -941,6 +942,7 @@
UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA);
readBoolean(parser, restrictions, UserManager.DISALLOW_UNMUTE_MICROPHONE);
readBoolean(parser, restrictions, UserManager.DISALLOW_ADJUST_VOLUME);
+ readBoolean(parser, restrictions, UserManager.DISALLOW_TELEPHONY);
}
}
}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index f0b7861..716ee27 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -148,20 +148,9 @@
private static final int USER_ACTIVITY_SCREEN_BRIGHT = 1 << 0;
private static final int USER_ACTIVITY_SCREEN_DIM = 1 << 1;
- // Default and minimum screen off timeout in milliseconds.
+ // Default timeout in milliseconds. This is only used until the settings
+ // provider populates the actual default value (R.integer.def_screen_off_timeout).
private static final int DEFAULT_SCREEN_OFF_TIMEOUT = 15 * 1000;
- private static final int MINIMUM_SCREEN_OFF_TIMEOUT = 10 * 1000;
-
- // The screen dim duration, in milliseconds.
- // This is subtracted from the end of the screen off timeout so the
- // minimum screen off timeout should be longer than this.
- private static final int SCREEN_DIM_DURATION = 7 * 1000;
-
- // The maximum screen dim time expressed as a ratio relative to the screen
- // off timeout. If the screen off timeout is very short then we want the
- // dim timeout to also be quite short so that most of the time is spent on.
- // Otherwise the user won't get much screen on time before dimming occurs.
- private static final float MAXIMUM_SCREEN_DIM_RATIO = 0.2f;
// The name of the boot animation service in init.rc.
private static final String BOOT_ANIMATION_SERVICE = "bootanim";
@@ -342,6 +331,20 @@
// True if dreams should be activated on dock.
private boolean mDreamsActivateOnDockSetting;
+ // The minimum screen off timeout, in milliseconds.
+ private int mMinimumScreenOffTimeoutConfig;
+
+ // The screen dim duration, in milliseconds.
+ // This is subtracted from the end of the screen off timeout so the
+ // minimum screen off timeout should be longer than this.
+ private int mMaximumScreenDimDurationConfig;
+
+ // The maximum screen dim time expressed as a ratio relative to the screen
+ // off timeout. If the screen off timeout is very short then we want the
+ // dim timeout to also be quite short so that most of the time is spent on.
+ // Otherwise the user won't get much screen on time before dimming occurs.
+ private float mMaximumScreenDimRatioConfig;
+
// The screen off timeout setting value in milliseconds.
private int mScreenOffTimeoutSetting;
@@ -583,6 +586,12 @@
com.android.internal.R.integer.config_dreamsBatteryLevelMinimumWhenNotPowered);
mDreamsBatteryLevelDrainCutoffConfig = resources.getInteger(
com.android.internal.R.integer.config_dreamsBatteryLevelDrainCutoff);
+ mMinimumScreenOffTimeoutConfig = resources.getInteger(
+ com.android.internal.R.integer.config_minimumScreenOffTimeout);
+ mMaximumScreenDimDurationConfig = resources.getInteger(
+ com.android.internal.R.integer.config_maximumScreenDimDuration);
+ mMaximumScreenDimRatioConfig = resources.getFraction(
+ com.android.internal.R.fraction.config_maximumScreenDimRatio, 1, 1);
}
private void updateSettingsLocked() {
@@ -1368,12 +1377,12 @@
if (mUserActivityTimeoutOverrideFromWindowManager >= 0) {
timeout = (int)Math.min(timeout, mUserActivityTimeoutOverrideFromWindowManager);
}
- return Math.max(timeout, MINIMUM_SCREEN_OFF_TIMEOUT);
+ return Math.max(timeout, mMinimumScreenOffTimeoutConfig);
}
private int getScreenDimDurationLocked(int screenOffTimeout) {
- return Math.min(SCREEN_DIM_DURATION,
- (int)(screenOffTimeout * MAXIMUM_SCREEN_DIM_RATIO));
+ return Math.min(mMaximumScreenDimDurationConfig,
+ (int)(screenOffTimeout * mMaximumScreenDimRatioConfig));
}
/**
@@ -2158,6 +2167,9 @@
pw.println(" mDreamsEnabledSetting=" + mDreamsEnabledSetting);
pw.println(" mDreamsActivateOnSleepSetting=" + mDreamsActivateOnSleepSetting);
pw.println(" mDreamsActivateOnDockSetting=" + mDreamsActivateOnDockSetting);
+ pw.println(" mMinimumScreenOffTimeoutConfig=" + mMinimumScreenOffTimeoutConfig);
+ pw.println(" mMaximumScreenDimDurationConfig=" + mMaximumScreenDimDurationConfig);
+ pw.println(" mMaximumScreenDimRatioConfig=" + mMaximumScreenDimRatioConfig);
pw.println(" mScreenOffTimeoutSetting=" + mScreenOffTimeoutSetting);
pw.println(" mMaximumScreenOffTimeoutFromDeviceAdmin="
+ mMaximumScreenOffTimeoutFromDeviceAdmin + " (enforced="
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index c20e38c..e2d2ac6 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -26,6 +26,7 @@
import android.os.IRemoteCallback;
import android.os.SystemProperties;
import android.util.Slog;
+import android.view.View;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
@@ -34,7 +35,6 @@
import android.view.animation.ClipRectAnimation;
import android.view.animation.Interpolator;
import android.view.animation.ScaleAnimation;
-
import android.view.animation.TranslateAnimation;
import com.android.internal.util.DumpUtils.Dump;
import com.android.server.AttributeCache;
@@ -500,7 +500,8 @@
*/
Animation createAlternateThumbnailEnterExitAnimationLocked(int thumbTransitState, int appWidth,
int appHeight, int orientation, int transit,
- Rect containingFrame, Rect contentInsets) {
+ Rect containingFrame, Rect contentInsets,
+ boolean isFullScreen) {
Animation a;
final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
@@ -520,6 +521,9 @@
scaledTopDecor = (int) (scale * contentInsets.top);
int unscaledThumbHeight = (int) (thumbHeight / scale);
mTmpFromClipRect.set(containingFrame);
+ if (isFullScreen) {
+ mTmpFromClipRect.top = contentInsets.top;
+ }
mTmpFromClipRect.bottom = (mTmpFromClipRect.top + unscaledThumbHeight);
mTmpToClipRect.set(containingFrame);
} else {
@@ -527,7 +531,12 @@
scale = thumbHeight / (appHeight - contentInsets.top);
scaledTopDecor = (int) (scale * contentInsets.top);
int unscaledThumbWidth = (int) (thumbWidth / scale);
+ int unscaledThumbHeight = (int) (thumbHeight / scale);
mTmpFromClipRect.set(containingFrame);
+ if (isFullScreen) {
+ mTmpFromClipRect.top = contentInsets.top;
+ mTmpFromClipRect.bottom = (mTmpFromClipRect.top + unscaledThumbHeight);
+ }
mTmpFromClipRect.right = (mTmpFromClipRect.left + unscaledThumbWidth);
mTmpToClipRect.set(containingFrame);
}
@@ -575,14 +584,22 @@
int unscaledThumbHeight = (int) (thumbHeight / scale);
mTmpFromClipRect.set(containingFrame);
mTmpToClipRect.set(containingFrame);
+ if (isFullScreen) {
+ mTmpToClipRect.top = contentInsets.top;
+ }
mTmpToClipRect.bottom = (mTmpToClipRect.top + unscaledThumbHeight);
} else {
// In landscape, we scale the height and clip to the top/left square
scale = thumbHeight / (appHeight - contentInsets.top);
scaledTopDecor = (int) (scale * contentInsets.top);
int unscaledThumbWidth = (int) (thumbWidth / scale);
+ int unscaledThumbHeight = (int) (thumbHeight / scale);
mTmpFromClipRect.set(containingFrame);
mTmpToClipRect.set(containingFrame);
+ if (isFullScreen) {
+ mTmpToClipRect.top = contentInsets.top;
+ mTmpToClipRect.bottom = (mTmpToClipRect.top + unscaledThumbHeight);
+ }
mTmpToClipRect.right = (mTmpToClipRect.left + unscaledThumbWidth);
}
@@ -679,7 +696,7 @@
Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
int appWidth, int appHeight, int orientation,
- Rect containingFrame, Rect contentInsets) {
+ Rect containingFrame, Rect contentInsets, boolean isFullScreen) {
Animation a;
if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) {
a = loadAnimation(mNextAppTransitionPackage, enter ?
@@ -702,7 +719,7 @@
(mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP);
a = createAlternateThumbnailEnterExitAnimationLocked(
getThumbnailTransitionState(enter), appWidth, appHeight, orientation,
- transit, containingFrame, contentInsets);
+ transit, containingFrame, contentInsets, isFullScreen);
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
String animName = mNextAppTransitionScaleUp ?
"ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN";
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index c6fffbf..63a4f52 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -289,6 +289,11 @@
private static final int MAX_SCREENSHOT_RETRIES = 3;
+ // The flag describing a full screen app window (where the app takes care of drawing under the
+ // SystemUI bars)
+ private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN =
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+
final private KeyguardDisableHandler mKeyguardDisableHandler;
final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -3193,8 +3198,11 @@
}
}
+ boolean isFullScreen =
+ ((win.mSystemUiVisibility & SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN)
+ == SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN);
Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height,
- mCurConfiguration.orientation, containingFrame, contentInsets);
+ mCurConfiguration.orientation, containingFrame, contentInsets, isFullScreen);
if (a != null) {
if (DEBUG_ANIM) {
RuntimeException e = null;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index e2cd4e2..5d88a57 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2411,6 +2411,9 @@
return;
}
enforceCrossUserPermission(userHandle);
+ if ((flags & DevicePolicyManager.WIPE_EXTERNAL_STORAGE) != 0) {
+ enforceNotManagedProfile(userHandle, "wipe external storage");
+ }
synchronized (this) {
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
@@ -2863,6 +2866,7 @@
return;
}
enforceCrossUserPermission(userHandle);
+ enforceNotManagedProfile(userHandle, "enable/disable cameras");
synchronized (this) {
if (who == null) {
throw new NullPointerException("ComponentName is null");
@@ -2912,6 +2916,7 @@
return;
}
enforceCrossUserPermission(userHandle);
+ enforceNotManagedProfile(userHandle, "disable keyguard features");
synchronized (this) {
if (who == null) {
throw new NullPointerException("ComponentName is null");
@@ -2935,6 +2940,7 @@
return 0;
}
enforceCrossUserPermission(userHandle);
+ enforceNotManagedProfile(userHandle, "list disabled keyguard features");
synchronized (this) {
if (who != null) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
@@ -3384,6 +3390,93 @@
}
@Override
+ public boolean setApplicationBlocked(ComponentName who, String packageName,
+ boolean blocked) {
+ int callingUserId = UserHandle.getCallingUserId();
+ synchronized (this) {
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+ long id = Binder.clearCallingIdentity();
+ try {
+ IPackageManager pm = AppGlobals.getPackageManager();
+ return pm.setApplicationBlockedSettingAsUser(packageName, blocked, callingUserId);
+ } catch (RemoteException re) {
+ // shouldn't happen
+ Slog.e(LOG_TAG, "Failed to setApplicationBlockedSetting", re);
+ } finally {
+ restoreCallingIdentity(id);
+ }
+ return false;
+ }
+ }
+
+ @Override
+ public int setApplicationsBlocked(ComponentName who, Intent intent, boolean blocked) {
+ int callingUserId = UserHandle.getCallingUserId();
+ synchronized (this) {
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+ long id = Binder.clearCallingIdentity();
+ try {
+ IPackageManager pm = AppGlobals.getPackageManager();
+ List<ResolveInfo> activitiesToEnable = pm.queryIntentActivities(intent,
+ intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+ PackageManager.GET_DISABLED_COMPONENTS
+ | PackageManager.GET_UNINSTALLED_PACKAGES,
+ callingUserId);
+
+ if (DBG) Slog.d(LOG_TAG, "Enabling activities: " + activitiesToEnable);
+ int numberOfAppsUnblocked = 0;
+ if (activitiesToEnable != null) {
+ for (ResolveInfo info : activitiesToEnable) {
+ if (info.activityInfo != null) {
+ numberOfAppsUnblocked++;
+ pm.setApplicationBlockedSettingAsUser(info.activityInfo.packageName,
+ blocked, callingUserId);
+ }
+ }
+ }
+ return numberOfAppsUnblocked;
+ } catch (RemoteException re) {
+ // shouldn't happen
+ Slog.e(LOG_TAG, "Failed to setApplicationsBlockedSettingsWithIntent", re);
+ } finally {
+ restoreCallingIdentity(id);
+ }
+ return 0;
+ }
+ }
+
+ @Override
+ public boolean isApplicationBlocked(ComponentName who, String packageName) {
+ int callingUserId = UserHandle.getCallingUserId();
+ synchronized (this) {
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+ long id = Binder.clearCallingIdentity();
+ try {
+ IPackageManager pm = AppGlobals.getPackageManager();
+ return pm.getApplicationBlockedSettingAsUser(packageName, callingUserId);
+ } catch (RemoteException re) {
+ // shouldn't happen
+ Slog.e(LOG_TAG, "Failed to getApplicationBlockedSettingAsUser", re);
+ } finally {
+ restoreCallingIdentity(id);
+ }
+ return false;
+ }
+ }
+
+ @Override
public void enableSystemApp(ComponentName who, String packageName) {
synchronized (this) {
if (who == null) {
@@ -3595,4 +3688,43 @@
}
return false;
}
+
+ @Override
+ public void setGlobalSetting(ComponentName who, String setting, String value) {
+ final ContentResolver contentResolver = mContext.getContentResolver();
+
+ synchronized (this) {
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+
+ long id = Binder.clearCallingIdentity();
+ try {
+ Settings.Global.putString(contentResolver, setting, value);
+ } finally {
+ restoreCallingIdentity(id);
+ }
+ }
+ }
+
+ @Override
+ public void setSecureSetting(ComponentName who, String setting, String value) {
+ int callingUserId = UserHandle.getCallingUserId();
+ final ContentResolver contentResolver = mContext.getContentResolver();
+
+ synchronized (this) {
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+ long id = Binder.clearCallingIdentity();
+ try {
+ Settings.Secure.putStringForUser(contentResolver, setting, value, callingUserId);
+ } finally {
+ restoreCallingIdentity(id);
+ }
+ }
+ }
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 9b3f7ac..55ae9c6 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -125,7 +125,7 @@
private static final String WIFI_SERVICE_CLASS =
"com.android.server.wifi.WifiService";
private static final String WIFI_PASSPOINT_SERVICE_CLASS =
- "com.android.server.wifi.passpoint.WifiPasspointService";
+ "com.android.server.wifi.passpoint.PasspointService";
private static final String WIFI_P2P_SERVICE_CLASS =
"com.android.server.wifi.p2p.WifiP2pService";
private static final String HDMI_CEC_SERVICE_CLASS =
@@ -639,18 +639,18 @@
}
try {
- mSystemServiceManager.startService(WIFI_PASSPOINT_SERVICE_CLASS);
- } catch (Throwable e) {
- reportWtf("starting Wi-Fi PasspointService", e);
- }
-
- try {
mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
} catch (Throwable e) {
reportWtf("starting Wi-Fi Service", e);
}
try {
+ mSystemServiceManager.startService(WIFI_PASSPOINT_SERVICE_CLASS);
+ } catch (Throwable e) {
+ reportWtf("starting Wi-Fi PasspointService", e);
+ }
+
+ try {
Slog.i(TAG, "Wi-Fi Scanning Service");
mSystemServiceManager.startService(
"com.android.server.wifi.WifiScanningService");
diff --git a/tests/RenderThreadTest/Android.mk b/tests/RenderThreadTest/Android.mk
index bdcba2e..e07e943 100644
--- a/tests/RenderThreadTest/Android.mk
+++ b/tests/RenderThreadTest/Android.mk
@@ -1,7 +1,7 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
# Only compile source java files in this apk.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/RenderThreadTest/AndroidManifest.xml b/tests/RenderThreadTest/AndroidManifest.xml
index c76cfce..a7f4f6e 100644
--- a/tests/RenderThreadTest/AndroidManifest.xml
+++ b/tests/RenderThreadTest/AndroidManifest.xml
@@ -4,10 +4,6 @@
android:versionCode="1"
android:versionName="1.0" >
- <uses-sdk
- android:minSdkVersion="18"
- android:targetSdkVersion="18" />
-
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 3e3b6e3..cfd0a51 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -16,8 +16,8 @@
package android.net.wifi;
-import android.net.wifi.passpoint.PasspointInfo;
-import android.net.wifi.passpoint.PasspointManager;
+import android.net.wifi.passpoint.WifiPasspointInfo;
+import android.net.wifi.passpoint.WifiPasspointManager;
import android.os.Parcelable;
import android.os.Parcel;
@@ -80,10 +80,10 @@
/**
* Passpoint ANQP information. This is not fetched automatically.
- * Use {@link PasspointManager#requestAnqpInfo} to request ANQP info.
+ * Use {@link WifiPasspointManager#requestAnqpInfo} to request ANQP info.
* {@hide}
*/
- public PasspointInfo passpoint;
+ public WifiPasspointInfo passpoint;
/**
* {@hide}
@@ -132,7 +132,7 @@
distanceSdCm = source.distanceSdCm;
seen = source.seen;
if (source.passpoint != null)
- passpoint = new PasspointInfo(source.passpoint);
+ passpoint = new WifiPasspointInfo(source.passpoint);
}
}
@@ -219,7 +219,7 @@
in.readInt()
);
if (in.readInt() == 1) {
- sr.passpoint = PasspointInfo.CREATOR.createFromParcel(in);
+ sr.passpoint = WifiPasspointInfo.CREATOR.createFromParcel(in);
}
return sr;
}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index e73cce1..292f844 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -16,9 +16,13 @@
package android.net.wifi;
+import android.net.IpConfiguration;
+import android.net.IpConfiguration.ProxySettings;
+import android.net.IpConfiguration.IpAssignment;
+import android.net.ProxyInfo;
import android.net.LinkProperties;
-import android.os.Parcelable;
import android.os.Parcel;
+import android.os.Parcelable;
import android.text.TextUtils;
import java.util.HashMap;
@@ -286,20 +290,7 @@
/**
* @hide
*/
- public enum IpAssignment {
- /* Use statically configured IP settings. Configuration can be accessed
- * with linkProperties */
- STATIC,
- /* Use dynamically configured IP settigns */
- DHCP,
- /* no IP details are assigned, this is used to indicate
- * that any existing IP settings should be retained */
- UNASSIGNED
- }
- /**
- * @hide
- */
- public IpAssignment ipAssignment;
+ private IpConfiguration mIpConfiguration;
/**
* @hide
@@ -457,32 +448,6 @@
*/
public HashMap<String, Integer> linkedConfigurations;
- /**
- * @hide
- */
- public enum ProxySettings {
- /* No proxy is to be used. Any existing proxy settings
- * should be cleared. */
- NONE,
- /* Use statically configured proxy. Configuration can be accessed
- * with linkProperties */
- STATIC,
- /* no proxy details are assigned, this is used to indicate
- * that any existing proxy settings should be retained */
- UNASSIGNED,
- /* Use a Pac based proxy.
- */
- PAC
- }
- /**
- * @hide
- */
- public ProxySettings proxySettings;
- /**
- * @hide
- */
- public LinkProperties linkProperties;
-
public WifiConfiguration() {
networkId = INVALID_NETWORK_ID;
SSID = null;
@@ -500,12 +465,10 @@
wepKeys[i] = null;
}
enterpriseConfig = new WifiEnterpriseConfig();
- ipAssignment = IpAssignment.UNASSIGNED;
- proxySettings = ProxySettings.UNASSIGNED;
- linkProperties = new LinkProperties();
autoJoinStatus = AUTO_JOIN_ENABLED;
selfAdded = false;
ephemeral = false;
+ mIpConfiguration = new IpConfiguration();
}
/**
@@ -640,12 +603,7 @@
sbuf.append(enterpriseConfig);
sbuf.append('\n');
- sbuf.append("IP assignment: " + ipAssignment.toString());
- sbuf.append("\n");
- sbuf.append("Proxy settings: " + proxySettings.toString());
- sbuf.append("\n");
- sbuf.append(linkProperties.toString());
- sbuf.append("\n");
+ sbuf.append(mIpConfiguration.toString());
return sbuf.toString();
}
@@ -823,6 +781,52 @@
return key;
}
+ /** @hide */
+ public IpConfiguration getIpConfiguration() {
+ return mIpConfiguration;
+ }
+
+ /** @hide */
+ public void setIpConfiguration(IpConfiguration ipConfiguration) {
+ mIpConfiguration = ipConfiguration;
+ }
+
+ /** @hide */
+ public LinkProperties getLinkProperties() {
+ return mIpConfiguration.linkProperties;
+ }
+
+ /** @hide */
+ public void setLinkProperties(LinkProperties linkProperties) {
+ mIpConfiguration.linkProperties = linkProperties;
+ }
+
+ /** @hide */
+ public IpConfiguration.IpAssignment getIpAssignment() {
+ return mIpConfiguration.ipAssignment;
+ }
+
+ /** @hide */
+ public void setIpAssignment(IpConfiguration.IpAssignment ipAssignment) {
+ mIpConfiguration.ipAssignment = ipAssignment;
+ }
+
+ /** @hide */
+ public IpConfiguration.ProxySettings getProxySettings() {
+ return mIpConfiguration.proxySettings;
+ }
+
+ /** @hide */
+ public void setProxySettings(IpConfiguration.ProxySettings proxySettings) {
+ mIpConfiguration.proxySettings = proxySettings;
+ }
+
+ /** @hide */
+ public void setProxy(ProxySettings settings, ProxyInfo proxy) {
+ mIpConfiguration.proxySettings = settings;
+ mIpConfiguration.linkProperties.setHttpProxy(proxy);
+ }
+
/** Implement the Parcelable interface {@hide} */
public int describeContents() {
return 0;
@@ -854,12 +858,10 @@
enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig);
- ipAssignment = source.ipAssignment;
- proxySettings = source.proxySettings;
-
defaultGwMacAddress = source.defaultGwMacAddress;
- linkProperties = new LinkProperties(source.linkProperties);
+ mIpConfiguration = new IpConfiguration(source.mIpConfiguration);
+
if ((source.scanResultCache != null) && (source.scanResultCache.size() > 0)) {
scanResultCache = new HashMap<String, ScanResult>();
scanResultCache.putAll(source.scanResultCache);
@@ -882,10 +884,11 @@
if (source.visibility != null) {
visibility = new Visibility(source.visibility);
}
- }
+ }
}
/** Implement the Parcelable interface {@hide} */
+ @Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(networkId);
dest.writeInt(status);
@@ -908,10 +911,7 @@
dest.writeParcelable(enterpriseConfig, flags);
- dest.writeString(ipAssignment.name());
- dest.writeString(proxySettings.name());
- dest.writeParcelable(linkProperties, flags);
-
+ dest.writeParcelable(mIpConfiguration, flags);
dest.writeString(dhcpServer);
dest.writeString(defaultGwMacAddress);
dest.writeInt(autoJoinStatus);
@@ -943,10 +943,7 @@
config.enterpriseConfig = in.readParcelable(null);
- config.ipAssignment = IpAssignment.valueOf(in.readString());
- config.proxySettings = ProxySettings.valueOf(in.readString());
- config.linkProperties = in.readParcelable(null);
-
+ config.mIpConfiguration = in.readParcelable(null);
config.dhcpServer = in.readString();
config.defaultGwMacAddress = in.readString();
config.autoJoinStatus = in.readInt();
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 69be2cf..1484d49 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -224,8 +224,12 @@
public static final int TTLS = 2;
/** EAP-Password */
public static final int PWD = 3;
+ /** EAP-Subscriber Identity Module */
+ public static final int SIM = 4;
+ /** EAP-Authentication and Key Agreement */
+ public static final int AKA = 5;
/** @hide */
- public static final String[] strings = { "PEAP", "TLS", "TTLS", "PWD" };
+ public static final String[] strings = { "PEAP", "TLS", "TTLS", "PWD", "SIM", "AKA" };
/** Prevent initialization */
private Eap() {}
@@ -271,6 +275,8 @@
case Eap.PWD:
case Eap.TLS:
case Eap.TTLS:
+ case Eap.SIM:
+ case Eap.AKA:
mFields.put(EAP_KEY, Eap.strings[eapMethod]);
mFields.put(OPP_KEY_CACHING, "1");
break;
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 9558d50..c6ce768 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1413,14 +1413,12 @@
/**
* Passed with {@link ActionListener#onFailure}.
* Indicates that the operation failed due to an internal error.
- * @hide
*/
public static final int ERROR = 0;
/**
* Passed with {@link ActionListener#onFailure}.
* Indicates that the operation is already in progress
- * @hide
*/
public static final int IN_PROGRESS = 1;
@@ -1428,30 +1426,28 @@
* Passed with {@link ActionListener#onFailure}.
* Indicates that the operation failed because the framework is busy and
* unable to service the request
- * @hide
*/
public static final int BUSY = 2;
/* WPS specific errors */
- /** WPS overlap detected {@hide} */
+ /** WPS overlap detected */
public static final int WPS_OVERLAP_ERROR = 3;
- /** WEP on WPS is prohibited {@hide} */
+ /** WEP on WPS is prohibited */
public static final int WPS_WEP_PROHIBITED = 4;
- /** TKIP only prohibited {@hide} */
+ /** TKIP only prohibited */
public static final int WPS_TKIP_ONLY_PROHIBITED = 5;
- /** Authentication failure on WPS {@hide} */
+ /** Authentication failure on WPS */
public static final int WPS_AUTH_FAILURE = 6;
- /** WPS timed out {@hide} */
+ /** WPS timed out */
public static final int WPS_TIMED_OUT = 7;
/**
* Passed with {@link ActionListener#onFailure}.
* Indicates that the operation failed due to invalid inputs
- * @hide
*/
public static final int INVALID_ARGS = 8;
- /** Interface for callback invocation on an application action {@hide} */
+ /** Interface for callback invocation on an application action */
public interface ActionListener {
/** The operation succeeded */
public void onSuccess();
@@ -1463,7 +1459,7 @@
public void onFailure(int reason);
}
- /** Interface for callback invocation on a start WPS action {@hide} */
+ /** Interface for callback invocation on a start WPS action */
public interface WpsListener {
/** WPS start succeeded */
public void onStartSuccess(String pin);
@@ -1745,7 +1741,6 @@
* @param listener for callbacks on success or failure. Can be null.
* @throws IllegalStateException if the WifiManager instance needs to be
* initialized again
- * @hide
*/
public void startWps(WpsInfo config, WpsListener listener) {
if (config == null) throw new IllegalArgumentException("config cannot be null");
@@ -1759,7 +1754,6 @@
* @param listener for callbacks on success or failure. Can be null.
* @throws IllegalStateException if the WifiManager instance needs to be
* initialized again
- * @hide
*/
public void cancelWps(ActionListener listener) {
validateChannel();
diff --git a/wifi/java/android/net/wifi/WpsInfo.java b/wifi/java/android/net/wifi/WpsInfo.java
index 2ad4ad0..ae2e771 100644
--- a/wifi/java/android/net/wifi/WpsInfo.java
+++ b/wifi/java/android/net/wifi/WpsInfo.java
@@ -40,7 +40,7 @@
/** Wi-Fi Protected Setup. www.wi-fi.org/wifi-protected-setup has details */
public int setup;
- /** @hide */
+ /** Passed with pin method KEYPAD */
public String BSSID;
/** Passed with pin method configuration */
diff --git a/wifi/java/android/net/wifi/passpoint/IPasspointManager.aidl b/wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl
similarity index 87%
rename from wifi/java/android/net/wifi/passpoint/IPasspointManager.aidl
rename to wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl
index e57db64..8375d09 100644
--- a/wifi/java/android/net/wifi/passpoint/IPasspointManager.aidl
+++ b/wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl
@@ -19,11 +19,11 @@
import android.os.Messenger;
/**
- * Interface that allows controlling and querying Passpoint connectivity.
+ * Interface that allows controlling and querying Wifi Passpoint connectivity.
*
* {@hide}
*/
-interface IPasspointManager
+interface IWifiPasspointManager
{
Messenger getMessenger();
int getPasspointState();
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointCredential.aidl b/wifi/java/android/net/wifi/passpoint/PasspointCredential.aidl
deleted file mode 100644
index 6f75cbe..0000000
--- a/wifi/java/android/net/wifi/passpoint/PasspointCredential.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2014, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.passpoint;
-
-parcelable PasspointCredential;
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointCredential.java b/wifi/java/android/net/wifi/passpoint/PasspointCredential.java
deleted file mode 100644
index 4218f23..0000000
--- a/wifi/java/android/net/wifi/passpoint/PasspointCredential.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.passpoint;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-
-public class PasspointCredential implements Parcelable {
-
- @Override
- public String toString() {
- // TODO
- return null;
- }
-
- /** Implement the Parcelable interface {@hide} */
- @Override
- public int describeContents() {
- return 0;
- }
-
- /** Implement the Parcelable interface {@hide} */
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- // TODO
- }
-
- /** Implement the Parcelable interface {@hide} */
- public static final Creator<PasspointCredential> CREATOR =
- new Creator<PasspointCredential>() {
- @Override
- public PasspointCredential createFromParcel(Parcel in) {
- // TODO
- return null;
- }
-
- @Override
- public PasspointCredential[] newArray(int size) {
- return new PasspointCredential[size];
- }
- };
-}
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointInfo.java b/wifi/java/android/net/wifi/passpoint/PasspointInfo.java
deleted file mode 100644
index d57b0aa..0000000
--- a/wifi/java/android/net/wifi/passpoint/PasspointInfo.java
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.passpoint;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * TODO: doc
- */
-public class PasspointInfo implements Parcelable {
-
- /** TODO doc */
- public static final int ANQP_CAPABILITY = 1 << 0;
-
- /** TODO doc */
- public static final int VENUE_NAME = 1 << 1;
-
- /** TODO doc */
- public static final int NETWORK_AUTH_TYPE = 1 << 2;
-
- /** TODO doc */
- public static final int ROAMING_CONSORTIUM = 1 << 3;
-
- /** TODO doc */
- public static final int IP_ADDR_TYPE_AVAILABILITY = 1 << 4;
-
- /** TODO doc */
- public static final int NAI_REALM = 1 << 5;
-
- /** TODO doc */
- public static final int CELLULAR_NETWORK = 1 << 6;
-
- /** TODO doc */
- public static final int DOMAIN_NAME = 1 << 7;
-
- /** TODO doc */
- public static final int HOTSPOT_CAPABILITY = 1 << 8;
-
- /** TODO doc */
- public static final int OPERATOR_FRIENDLY_NAME = 1 << 9;
-
- /** TODO doc */
- public static final int WAN_METRICS = 1 << 10;
-
- /** TODO doc */
- public static final int CONNECTION_CAPABILITY = 1 << 11;
-
- /** TODO doc */
- public static final int OSU_PROVIDER = 1 << 12;
-
- /** TODO doc */
- public static final int PRESET_CRED_MATCH =
- ANQP_CAPABILITY |
- HOTSPOT_CAPABILITY |
- NAI_REALM |
- CELLULAR_NETWORK |
- DOMAIN_NAME;
-
- /** TODO doc */
- public static final int PRESET_ALL =
- ANQP_CAPABILITY |
- VENUE_NAME |
- NETWORK_AUTH_TYPE |
- ROAMING_CONSORTIUM |
- IP_ADDR_TYPE_AVAILABILITY |
- NAI_REALM |
- CELLULAR_NETWORK |
- DOMAIN_NAME |
- HOTSPOT_CAPABILITY |
- OPERATOR_FRIENDLY_NAME |
- WAN_METRICS |
- CONNECTION_CAPABILITY |
- OSU_PROVIDER;
-
-
- /** TODO doc */
- public String bssid;
-
- /** TODO doc */
- public String venueName;
-
- /** TODO doc */
- public String networkAuthType;
-
- /** TODO doc */
- public String roamingConsortium;
-
- /** TODO doc */
- public String ipAddrTypeAvaibility;
-
- /** TODO doc */
- public String naiRealm;
-
- /** TODO doc */
- public String cellularNetwork;
-
- /** TODO doc */
- public String domainName;
-
- /** TODO doc */
- public String operatorFriendlyName;
-
- /** TODO doc */
- public String wanMetrics;
-
- /** TODO doc */
- public String connectionCapability;
-
- /** TODO doc */
- public List<PasspointOsuProvider> osuProviderList;
-
-
- /** default constructor @hide */
- public PasspointInfo() {
-// osuProviderList = new ArrayList<OsuProvider>();
- }
-
- /** copy constructor @hide */
- public PasspointInfo(PasspointInfo source) {
- // TODO
- bssid = source.bssid;
- venueName = source.venueName;
- networkAuthType = source.networkAuthType;
- roamingConsortium = source.roamingConsortium;
- ipAddrTypeAvaibility = source.ipAddrTypeAvaibility;
- naiRealm = source.naiRealm;
- cellularNetwork = source.cellularNetwork;
- domainName = source.domainName;
- operatorFriendlyName = source.operatorFriendlyName;
- wanMetrics = source.wanMetrics;
- connectionCapability = source.connectionCapability;
- if (source.osuProviderList != null) {
- osuProviderList = new ArrayList<PasspointOsuProvider>();
- for (PasspointOsuProvider osu : source.osuProviderList)
- osuProviderList.add(new PasspointOsuProvider(osu));
- }
- }
-
- /**
- * Convert mask to ANQP subtypes, for supplicant command use.
- *
- * @param mask The ANQP subtypes mask.
- * @return String of ANQP subtypes, good for supplicant command use
- * @hide
- */
- public static String toAnqpSubtypes(int mask) {
- StringBuilder sb = new StringBuilder();
- if ((mask & ANQP_CAPABILITY) != 0) sb.append("257,");
- if ((mask & VENUE_NAME) != 0) sb.append("258,");
- if ((mask & NETWORK_AUTH_TYPE) != 0) sb.append("260,");
- if ((mask & ROAMING_CONSORTIUM) != 0) sb.append("261,");
- if ((mask & IP_ADDR_TYPE_AVAILABILITY) != 0) sb.append("262,");
- if ((mask & NAI_REALM) != 0) sb.append("263,");
- if ((mask & CELLULAR_NETWORK) != 0) sb.append("264,");
- if ((mask & DOMAIN_NAME) != 0) sb.append("268,");
- if ((mask & HOTSPOT_CAPABILITY) != 0) sb.append("hs20:2,");
- if ((mask & OPERATOR_FRIENDLY_NAME) != 0) sb.append("hs20:3,");
- if ((mask & WAN_METRICS) != 0) sb.append("hs20:4,");
- if ((mask & CONNECTION_CAPABILITY) != 0) sb.append("hs20:5,");
- if ((mask & OSU_PROVIDER) != 0) sb.append("hs20:8,");
- if (sb.length() > 0) sb.deleteCharAt(sb.length() - 1);
- return sb.toString();
- }
-
- @Override
- public String toString() {
- StringBuffer sb = new StringBuffer();
- sb.append("BSSID: ").append(bssid);
- if (venueName != null)
- sb.append(" venueName: ").append(venueName);
- if (networkAuthType != null)
- sb.append(" networkAuthType: ").append(networkAuthType);
- if (roamingConsortium != null)
- sb.append(" roamingConsortium: ").append(roamingConsortium);
- if (ipAddrTypeAvaibility != null)
- sb.append(" ipAddrTypeAvaibility: ").append(ipAddrTypeAvaibility);
- if (naiRealm != null)
- sb.append(" naiRealm: ").append(naiRealm);
- if (cellularNetwork != null)
- sb.append(" cellularNetwork: ").append(cellularNetwork);
- if (domainName != null)
- sb.append(" domainName: ").append(domainName);
- if (operatorFriendlyName != null)
- sb.append(" operatorFriendlyName: ").append(operatorFriendlyName);
- if (wanMetrics != null)
- sb.append(" wanMetrics: ").append(wanMetrics);
- if (connectionCapability != null)
- sb.append(" connectionCapability: ").append(connectionCapability);
- if (osuProviderList != null)
- sb.append(" osuProviderList: (size=" + osuProviderList.size() + ")");
- return sb.toString();
- }
-
- /** Implement the Parcelable interface {@hide} */
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeValue(bssid);
- out.writeValue(venueName);
- out.writeValue(networkAuthType);
- out.writeValue(roamingConsortium);
- out.writeValue(ipAddrTypeAvaibility);
- out.writeValue(naiRealm);
- out.writeValue(cellularNetwork);
- out.writeValue(domainName);
- out.writeValue(operatorFriendlyName);
- out.writeValue(wanMetrics);
- out.writeValue(connectionCapability);
- if (osuProviderList == null) {
- out.writeInt(0);
- } else {
- out.writeInt(osuProviderList.size());
- for (PasspointOsuProvider osu : osuProviderList)
- osu.writeToParcel(out, flags);
- }
- }
-
- /** Implement the Parcelable interface {@hide} */
- @Override
- public int describeContents() {
- return 0;
- }
-
- /** Implement the Parcelable interface {@hide} */
- public static final Parcelable.Creator<PasspointInfo> CREATOR =
- new Parcelable.Creator<PasspointInfo>() {
- @Override
- public PasspointInfo createFromParcel(Parcel in) {
- PasspointInfo p = new PasspointInfo();
- p.bssid = (String) in.readValue(String.class.getClassLoader());
- p.venueName = (String) in.readValue(String.class.getClassLoader());
- p.networkAuthType = (String) in.readValue(String.class.getClassLoader());
- p.roamingConsortium = (String) in.readValue(String.class.getClassLoader());
- p.ipAddrTypeAvaibility = (String) in.readValue(String.class.getClassLoader());
- p.naiRealm = (String) in.readValue(String.class.getClassLoader());
- p.cellularNetwork = (String) in.readValue(String.class.getClassLoader());
- p.domainName = (String) in.readValue(String.class.getClassLoader());
- p.operatorFriendlyName = (String) in.readValue(String.class.getClassLoader());
- p.wanMetrics = (String) in.readValue(String.class.getClassLoader());
- p.connectionCapability = (String) in.readValue(String.class.getClassLoader());
- int n = in.readInt();
- if (n > 0) {
- p.osuProviderList = new ArrayList<PasspointOsuProvider>();
- for (int i = 0; i < n; i++) {
- PasspointOsuProvider osu = PasspointOsuProvider.CREATOR.createFromParcel(in);
- p.osuProviderList.add(osu);
- }
- }
- return p;
- }
-
- @Override
- public PasspointInfo[] newArray(int size) {
- return new PasspointInfo[size];
- }
- };
-}
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointPolicy.aidl b/wifi/java/android/net/wifi/passpoint/PasspointPolicy.aidl
deleted file mode 100644
index c2cc731..0000000
--- a/wifi/java/android/net/wifi/passpoint/PasspointPolicy.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2014, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.passpoint;
-
-parcelable PasspointPolicy;
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointPolicy.java b/wifi/java/android/net/wifi/passpoint/PasspointPolicy.java
deleted file mode 100644
index 3a8806b..0000000
--- a/wifi/java/android/net/wifi/passpoint/PasspointPolicy.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.passpoint;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-
-public class PasspointPolicy implements Parcelable {
-
- @Override
- public String toString() {
- // TODO
- return null;
- }
-
- /** Implement the Parcelable interface {@hide} */
- @Override
- public int describeContents() {
- return 0;
- }
-
- /** Implement the Parcelable interface {@hide} */
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- // TODO
- }
-
- /** Implement the Parcelable interface {@hide} */
- public static final Creator<PasspointPolicy> CREATOR =
- new Creator<PasspointPolicy>() {
- @Override
- public PasspointPolicy createFromParcel(Parcel in) {
- return null;
- }
-
- @Override
- public PasspointPolicy[] newArray(int size) {
- return new PasspointPolicy[size];
- }
- };
-}
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointOsuProvider.aidl b/wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.aidl
similarity index 94%
rename from wifi/java/android/net/wifi/passpoint/PasspointOsuProvider.aidl
rename to wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.aidl
index f5ecb7c..cfd3605 100644
--- a/wifi/java/android/net/wifi/passpoint/PasspointOsuProvider.aidl
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.aidl
@@ -16,4 +16,4 @@
package android.net.wifi.passpoint;
-parcelable PasspointOsuProvider;
+parcelable WifiPasspointCredential;
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.java
new file mode 100644
index 0000000..08b430f
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.java
@@ -0,0 +1,711 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.passpoint;
+
+import android.net.wifi.WifiEnterpriseConfig;
+import android.os.Parcelable;
+import android.os.Parcel;
+
+import java.util.Collection;
+import java.util.Set;
+import java.util.Iterator;
+import java.util.Map;
+
+public class WifiPasspointCredential implements Parcelable {
+
+ private final static String TAG = "PasspointCredential";
+ private String mWifiSPFQDN;
+ private String mCredentialName;
+ private String mUpdateIdentifier;
+ private String mSubscriptionUpdateMethod;
+ private String mType;
+ private String mInnerMethod;
+ private String mCertType;
+ private String mCertSha256Fingerprint;
+ private String mUsername;
+ private String mPasswd;
+ private String mImsi;
+ private String mMcc;
+ private String mMnc;
+ private String mCaRootCert;
+ private String mRealm;
+ private int mPriority; //User preferred priority; The smaller, the higher
+ private boolean mUserPreferred = false;
+ private String mHomeSpFqdn;
+ private String mFriendlyName;
+ private String mOtherhomepartnerFqdn;
+ private String mClientCert;
+ private String mCreationDate;
+ private String mExpirationDate;
+
+ private String mSubscriptionDMAccUsername;
+ private String mSubscriptionDMAccPassword;
+ private String mSubscriptionUpdateInterval;
+
+ private String mPolicyUpdateURI;
+ private String mPolicyUpdateInterval;
+ private String mPolicyDMAccUsername;
+ private String mPolicyDMAccPassword;
+ private String mPolicyUpdateRestriction;
+ private String mPolicyUpdateMethod;
+
+ private Collection<WifiPasspointDmTree.PreferredRoamingPartnerList> mPreferredRoamingPartnerList;
+ private Collection<WifiPasspointDmTree.HomeOIList> mHomeOIList;
+ private Collection<WifiPasspointDmTree.MinBackhaulThresholdNetwork> mMinBackhaulThresholdNetwork;
+ private Collection<WifiPasspointDmTree.RequiredProtoPortTuple> mRequiredProtoPortTuple;
+ private Collection<WifiPasspointDmTree.SPExclusionList> mSpExclusionList;
+ private String mMaxBssLoad;
+
+ private boolean mIsMachineRemediation;
+
+ private String mAAACertURL;
+ private String mAAASha256Fingerprint;
+
+ private String mSubscriptionUpdateRestriction;
+ private String mSubscriptionUpdateURI;
+
+ private boolean mCheckAaaServerCertStatus;
+
+ /** @hide */
+ public WifiPasspointCredential() {
+
+ }
+
+ /**
+ * Constructor
+ * @param realm Realm of the passpoint credential
+ * @param config Credential information, must be either EAP-TLS or EAP-TTLS.
+ * @see WifiEnterpriseConfig
+ */
+ public WifiPasspointCredential(String realm, WifiEnterpriseConfig config) {
+ mRealm = realm;
+ switch (config.getEapMethod()) {
+ case WifiEnterpriseConfig.Eap.TLS:
+ // TODO;
+ break;
+ case WifiEnterpriseConfig.Eap.TTLS:
+ // TODO;
+ break;
+ default:
+ // ignore
+ }
+ }
+
+ /** @hide */
+ public WifiPasspointCredential(String type,
+ String caroot,
+ String clientcert,
+ WifiPasspointDmTree.SpFqdn sp,
+ WifiPasspointDmTree.CredentialInfo credinfo) {
+
+ if (credinfo == null) {
+ return;
+ }
+
+ mType = type;
+ mCaRootCert = caroot;
+ mClientCert = clientcert;
+
+ mWifiSPFQDN = sp.nodeName;
+ mUpdateIdentifier = sp.perProviderSubscription.UpdateIdentifier;
+
+ mCredentialName = credinfo.nodeName;
+ Set set = credinfo.homeSP.otherHomePartners.entrySet();
+ Iterator i = set.iterator();
+ if (i.hasNext()) {
+ Map.Entry entry3 = (Map.Entry) i.next();
+ WifiPasspointDmTree.OtherHomePartners ohp = (WifiPasspointDmTree.OtherHomePartners) entry3.getValue();
+ mOtherhomepartnerFqdn = ohp.FQDN;
+ }
+
+ set = credinfo.aAAServerTrustRoot.entrySet();
+ i = set.iterator();
+ if (i.hasNext()) {
+ Map.Entry entry3 = (Map.Entry) i.next();
+ WifiPasspointDmTree.AAAServerTrustRoot aaa = (WifiPasspointDmTree.AAAServerTrustRoot) entry3.getValue();
+ mAAACertURL = aaa.CertURL;
+ mAAASha256Fingerprint = aaa.CertSHA256Fingerprint;
+ }
+
+ mCertType = credinfo.credential.digitalCertificate.CertificateType;
+ mCertSha256Fingerprint = credinfo.credential.digitalCertificate.CertSHA256Fingerprint;
+ mUsername = credinfo.credential.usernamePassword.Username;
+ mPasswd = credinfo.credential.usernamePassword.Password;
+ mIsMachineRemediation = credinfo.credential.usernamePassword.MachineManaged;
+ mInnerMethod = credinfo.credential.usernamePassword.eAPMethod.InnerMethod;
+ mImsi = credinfo.credential.sim.IMSI;
+ mCreationDate = credinfo.credential.CreationDate;
+ mExpirationDate = credinfo.credential.ExpirationDate;
+ mRealm = credinfo.credential.Realm;
+
+ if (credinfo.credentialPriority == null) {
+ credinfo.credentialPriority = "128";
+ }
+ mPriority = Integer.parseInt(credinfo.credentialPriority);
+
+ mHomeSpFqdn = credinfo.homeSP.FQDN;
+
+ mSubscriptionUpdateInterval = credinfo.subscriptionUpdate.UpdateInterval;
+ mSubscriptionUpdateMethod = credinfo.subscriptionUpdate.UpdateMethod;
+ mSubscriptionUpdateRestriction = credinfo.subscriptionUpdate.Restriction;
+ mSubscriptionUpdateURI = credinfo.subscriptionUpdate.URI;
+ mSubscriptionDMAccUsername = credinfo.subscriptionUpdate.usernamePassword.Username;
+ mSubscriptionDMAccPassword = credinfo.subscriptionUpdate.usernamePassword.Password;
+
+ mPolicyUpdateURI = credinfo.policy.policyUpdate.URI;
+ mPolicyUpdateInterval = credinfo.policy.policyUpdate.UpdateInterval;
+ mPolicyDMAccUsername = credinfo.policy.policyUpdate.usernamePassword.Username;
+ mPolicyDMAccPassword = credinfo.policy.policyUpdate.usernamePassword.Password;
+ mPolicyUpdateRestriction = credinfo.policy.policyUpdate.Restriction;
+ mPolicyUpdateMethod = credinfo.policy.policyUpdate.UpdateMethod;
+ mPreferredRoamingPartnerList = credinfo.policy.preferredRoamingPartnerList.values();
+ mMinBackhaulThresholdNetwork = credinfo.policy.minBackhaulThreshold.values();
+ mRequiredProtoPortTuple = credinfo.policy.requiredProtoPortTuple.values();
+ mMaxBssLoad = credinfo.policy.maximumBSSLoadValue;
+ mSpExclusionList = credinfo.policy.sPExclusionList.values();
+
+ mHomeOIList = credinfo.homeSP.homeOIList.values();
+ mFriendlyName = credinfo.homeSP.FriendlyName;
+ mCheckAaaServerCertStatus = credinfo.credential.CheckAAAServerCertStatus;
+ }
+
+ /** @hide */
+ public WifiPasspointCredential(String type,
+ String caroot,
+ String clientcert,
+ String mcc,
+ String mnc,
+ WifiPasspointDmTree.SpFqdn sp,
+ WifiPasspointDmTree.CredentialInfo credinfo) {
+
+ if (credinfo == null) {
+ return;
+ }
+
+ mType = type;
+ mCaRootCert = caroot;
+ mClientCert = clientcert;
+
+ mWifiSPFQDN = sp.nodeName;
+ mUpdateIdentifier = sp.perProviderSubscription.UpdateIdentifier;
+
+ mCredentialName = credinfo.nodeName;
+ Set set = credinfo.homeSP.otherHomePartners.entrySet();
+ Iterator i = set.iterator();
+ if (i.hasNext()) {
+ Map.Entry entry3 = (Map.Entry) i.next();
+ WifiPasspointDmTree.OtherHomePartners ohp = (WifiPasspointDmTree.OtherHomePartners) entry3.getValue();
+ mOtherhomepartnerFqdn = ohp.FQDN;
+ }
+
+ set = credinfo.aAAServerTrustRoot.entrySet();
+ i = set.iterator();
+ if (i.hasNext()) {
+ Map.Entry entry3 = (Map.Entry) i.next();
+ WifiPasspointDmTree.AAAServerTrustRoot aaa = (WifiPasspointDmTree.AAAServerTrustRoot) entry3.getValue();
+ mAAACertURL = aaa.CertURL;
+ mAAASha256Fingerprint = aaa.CertSHA256Fingerprint;
+ }
+
+ mCertType = credinfo.credential.digitalCertificate.CertificateType;
+ mCertSha256Fingerprint = credinfo.credential.digitalCertificate.CertSHA256Fingerprint;
+ mUsername = credinfo.credential.usernamePassword.Username;
+ mPasswd = credinfo.credential.usernamePassword.Password;
+ mIsMachineRemediation = credinfo.credential.usernamePassword.MachineManaged;
+ mInnerMethod = credinfo.credential.usernamePassword.eAPMethod.InnerMethod;
+ mImsi = credinfo.credential.sim.IMSI;
+ mMcc = mcc;
+ mMnc = mnc;
+ mCreationDate = credinfo.credential.CreationDate;
+ mExpirationDate = credinfo.credential.ExpirationDate;
+ mRealm = credinfo.credential.Realm;
+
+ if (credinfo.credentialPriority == null) {
+ credinfo.credentialPriority = "128";
+ }
+ mPriority = Integer.parseInt(credinfo.credentialPriority);
+
+ mHomeSpFqdn = credinfo.homeSP.FQDN;
+
+ mSubscriptionUpdateMethod = credinfo.subscriptionUpdate.UpdateMethod;
+ mSubscriptionUpdateRestriction = credinfo.subscriptionUpdate.Restriction;
+ mSubscriptionUpdateURI = credinfo.subscriptionUpdate.URI;
+ mSubscriptionDMAccUsername = credinfo.subscriptionUpdate.usernamePassword.Username;
+ mSubscriptionDMAccPassword = credinfo.subscriptionUpdate.usernamePassword.Password;
+
+ mPolicyUpdateURI = credinfo.policy.policyUpdate.URI;
+ mPolicyUpdateInterval = credinfo.policy.policyUpdate.UpdateInterval;
+ mPolicyDMAccUsername = credinfo.policy.policyUpdate.usernamePassword.Username;
+ mPolicyDMAccPassword = credinfo.policy.policyUpdate.usernamePassword.Password;
+ mPolicyUpdateRestriction = credinfo.policy.policyUpdate.Restriction;
+ mPolicyUpdateMethod = credinfo.policy.policyUpdate.UpdateMethod;
+ mPreferredRoamingPartnerList = credinfo.policy.preferredRoamingPartnerList.values();
+ mMinBackhaulThresholdNetwork = credinfo.policy.minBackhaulThreshold.values();
+ mRequiredProtoPortTuple = credinfo.policy.requiredProtoPortTuple.values();
+ mMaxBssLoad = credinfo.policy.maximumBSSLoadValue;
+ mSpExclusionList = credinfo.policy.sPExclusionList.values();
+
+ mHomeOIList = credinfo.homeSP.homeOIList.values();
+ mFriendlyName = credinfo.homeSP.FriendlyName;
+ }
+
+ /** @hide */
+ public String getUpdateIdentifier() {
+ return mUpdateIdentifier;
+ }
+
+ /** @hide */
+ public String getUpdateMethod() {
+ return mSubscriptionUpdateMethod;
+ }
+
+ /** @hide */
+ public void setUpdateMethod(String method) {
+ mSubscriptionUpdateMethod = method;
+ }
+
+ /** @hide */
+ public String getWifiSPFQDN() {
+ return mWifiSPFQDN;
+ }
+
+ /** @hide */
+ public String getCredName() {
+ return mCredentialName;
+ }
+
+ /** @hide */
+ public String getEapMethodStr() {
+ return mType;
+ }
+
+ /**
+ * Get EAP method of this Passpoint credential.
+ * @return EAP method, refer to {@link WifiEnterpriseConfig.Eap} for possible return values
+ */
+ public int getEapMethod() {
+ return 0;
+ }
+
+ /** @hide */
+ public String getCertType() {
+ return mCertType;
+ }
+
+ /** @hide */
+ public String getCertSha256Fingerprint() {
+ return mCertSha256Fingerprint;
+ }
+
+ /**
+ * Get the user name of this Passpoint credential, for EAP-TTLS only.
+ * @return user name
+ */
+ public String getUserName() {
+ return mUsername;
+ }
+
+ /** @hide */
+ public String getPassword() {
+ // TODO: guarded by connectivity internal
+ return mPasswd;
+ }
+
+ /**
+ * Get the IMSI of this Passpoint credential, for EAP-SIM / EAP-AKA only.
+ * @return IMSI
+ */
+ public String getImsi() {
+ return mImsi;
+ }
+
+ /** @hide */
+ public String getMcc() {
+ return mMcc;
+ }
+
+ /** @hide */
+ public String getMnc() {
+ return mMnc;
+ }
+
+ /** @hide */
+ public String getCaRootCert() {
+ return mCaRootCert;
+ }
+
+ /**
+ * Get the client certificate path of this Passpoint credential, for EAP-TLS only.
+ * @return client certificate path
+ */
+ public String getClientCertPath() {
+ return mClientCert;
+ }
+
+ /**
+ * Get the realm of this Passpoint credential, for all EAP methods.
+ * @return Realm
+ */
+ public String getRealm() {
+ return mRealm;
+ }
+
+ /** @hide */
+ public int getPriority() {
+ if (mUserPreferred) {
+ return 0;
+ }
+
+ return mPriority;
+ }
+
+ /**
+ * Get the fully qualified domain name (FQDN) of this Passpoint credential,
+ * for all EAP methods.
+ * @return FQDN
+ */
+ public String getFqdn() {
+ return mHomeSpFqdn;
+ }
+
+ /** @hide */
+ public String getOtherhomepartners() {
+ return mOtherhomepartnerFqdn;
+ }
+
+ /** @hide */
+ public String getSubscriptionDMAccUsername() {
+ return mSubscriptionDMAccUsername;
+ }
+
+ /** @hide */
+ public String getSubscriptionDMAccPassword() {
+ return mSubscriptionDMAccPassword;
+ }
+
+ /** @hide */
+ public String getPolicyUpdateURI() {
+ return mPolicyUpdateURI;
+ }
+
+ /** @hide */
+ public String getPolicyUpdateInterval() {
+ return mPolicyUpdateInterval;
+ }
+
+ /** @hide */
+ public String getPolicyDMAccUsername() {
+ return mPolicyDMAccUsername;
+ }
+
+ /** @hide */
+ public String getPolicyDMAccPassword() {
+ return mPolicyDMAccPassword;
+ }
+
+ /** @hide */
+ public String getPolicyUpdateRestriction() {
+ return mPolicyUpdateRestriction;
+ }
+
+ /** @hide */
+ public String getPolicyUpdateMethod() {
+ return mPolicyUpdateMethod;
+ }
+
+ /** @hide */
+ public String getCreationDate() {
+ return mCreationDate;
+ }
+
+ /** @hide */
+ public String getExpirationDate() {
+ return mExpirationDate;
+ }
+
+ /** @hide */
+ public void setExpirationDate(String expirationdate) {
+ mExpirationDate = expirationdate;
+ }
+
+ /** @hide */
+ public Collection<WifiPasspointDmTree.PreferredRoamingPartnerList> getPrpList() {
+ return mPreferredRoamingPartnerList;
+ }
+
+ /** @hide */
+ public Collection<WifiPasspointDmTree.HomeOIList> getHomeOIList() {
+ return mHomeOIList;
+ }
+
+ /** @hide */
+ public Collection<WifiPasspointDmTree.MinBackhaulThresholdNetwork> getBackhaulThresholdList() {
+ return mMinBackhaulThresholdNetwork;
+ }
+
+ /** @hide */
+ public Collection<WifiPasspointDmTree.RequiredProtoPortTuple> getRequiredProtoPortList() {
+ return mRequiredProtoPortTuple;
+ }
+
+ /** @hide */
+ public Collection<WifiPasspointDmTree.SPExclusionList> getSPExclusionList() {
+ return mSpExclusionList;
+ }
+
+ /** @hide */
+ public boolean getIsMachineRemediation() {
+ return mIsMachineRemediation;
+ }
+
+ /** @hide */
+ public String getAAACertURL() {
+ return mAAACertURL;
+ }
+
+ /** @hide */
+ public String getAAASha256Fingerprint() {
+ return mAAASha256Fingerprint;
+ }
+
+ /** @hide */
+ public String getSubscriptionUpdateRestriction() {
+ return mSubscriptionUpdateRestriction;
+ }
+
+ /** @hide */
+ public String getSubscriptionUpdateURI() {
+ return mSubscriptionUpdateURI;
+ }
+
+ /** @hide */
+ public String getSubscriptionUpdateInterval() {
+ return mSubscriptionUpdateInterval;
+ }
+
+ /** @hide */
+ public String getFriendlyName() {
+ return mFriendlyName;
+ }
+
+ /** @hide */
+ public String getMaxBssLoad() {
+ return mMaxBssLoad;
+ }
+
+ /** @hide */
+ public boolean getUserPreference() {
+ return mUserPreferred;
+ }
+
+ /** @hide */
+ public boolean getCheckAaaServerCertStatus() {
+ return mCheckAaaServerCertStatus;
+ }
+
+ /** @hide */
+ public void setUserPreference(boolean value) {
+ mUserPreferred = value;
+ }
+
+ @Override
+ /** @hide */
+ public boolean equals(Object obj) {
+ boolean result = false;
+ if (obj instanceof WifiPasspointCredential) {
+ final WifiPasspointCredential other = (WifiPasspointCredential) obj;
+ if (this.mType.equals(other.mType)) {
+ if (this.mType.equals("TTLS")) {
+ result = this.mUsername.equals(other.mUsername) &&
+ this.mPasswd.equals(other.mPasswd) &&
+ this.mRealm.equals(other.mRealm) &&
+ this.mHomeSpFqdn.equals(other.mHomeSpFqdn);
+ }
+ if (this.mType.equals("TLS")) {
+ result = this.mRealm.equals(other.mRealm) &&
+ this.mHomeSpFqdn.equals(other.mHomeSpFqdn);
+ }
+ if (this.mType.equals("SIM")) {
+ result = this.mMcc.equals(other.mMcc) &&
+ this.mMnc.equals(other.mMnc) &&
+ this.mImsi.equals(other.mImsi) &&
+ this.mHomeSpFqdn.equals(other.mHomeSpFqdn);
+ }
+ }
+ }
+ return result;
+ }
+
+ @Override
+ /** @hide */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ String none = "<none>";
+
+ sb.append(", UpdateIdentifier: ")
+ .append(mUpdateIdentifier == null ? none : mUpdateIdentifier).
+ append(", SubscriptionUpdateMethod: ")
+ .append(mSubscriptionUpdateMethod == null ? none : mSubscriptionUpdateMethod).
+ append(", Type: ").append(mType == null ? none : mType).
+ append(", Username: ").append(mUsername == null ? none : mUsername).
+ append(", Passwd: ").append(mPasswd == null ? none : mPasswd).
+ append(", SubDMAccUsername: ")
+ .append(mSubscriptionDMAccUsername == null ? none : mSubscriptionDMAccUsername).
+ append(", SubDMAccPassword: ")
+ .append(mSubscriptionDMAccPassword == null ? none : mSubscriptionDMAccPassword).
+ append(", PolDMAccUsername: ")
+ .append(mPolicyDMAccUsername == null ? none : mPolicyDMAccUsername).
+ append(", PolDMAccPassword: ")
+ .append(mPolicyDMAccPassword == null ? none : mPolicyDMAccPassword).
+ append(", Imsi: ").append(mImsi == null ? none : mImsi).
+ append(", Mcc: ").append(mMcc == null ? none : mMcc).
+ append(", Mnc: ").append(mMnc == null ? none : mMnc).
+ append(", CaRootCert: ").append(mCaRootCert == null ? none : mCaRootCert).
+ append(", Realm: ").append(mRealm == null ? none : mRealm).
+ append(", Priority: ").append(mPriority).
+ append(", Fqdn: ").append(mHomeSpFqdn == null ? none : mHomeSpFqdn).
+ append(", Otherhomepartners: ")
+ .append(mOtherhomepartnerFqdn == null ? none : mOtherhomepartnerFqdn).
+ append(", ExpirationDate: ")
+ .append(mExpirationDate == null ? none : mExpirationDate).
+ append(", MaxBssLoad: ").append(mMaxBssLoad == null ? none : mMaxBssLoad).
+ append(", SPExclusionList: ").append(mSpExclusionList);
+
+ if (mPreferredRoamingPartnerList != null) {
+ sb.append("PreferredRoamingPartnerList:");
+ for (WifiPasspointDmTree.PreferredRoamingPartnerList prpListItem : mPreferredRoamingPartnerList) {
+ sb.append("[fqdnmatch:").append(prpListItem.FQDN_Match).
+ append(", priority:").append(prpListItem.Priority).
+ append(", country:").append(prpListItem.Country).append("]");
+ }
+ }
+
+ if (mHomeOIList != null) {
+ sb.append("HomeOIList:");
+ for (WifiPasspointDmTree.HomeOIList HomeOIListItem : mHomeOIList) {
+ sb.append("[HomeOI:").append(HomeOIListItem.HomeOI).
+ append(", HomeOIRequired:").append(HomeOIListItem.HomeOIRequired).
+ append("]");
+ }
+ }
+
+ if (mMinBackhaulThresholdNetwork != null) {
+ sb.append("BackHaulThreshold:");
+ for (WifiPasspointDmTree.MinBackhaulThresholdNetwork BhtListItem : mMinBackhaulThresholdNetwork) {
+ sb.append("[networkType:").append(BhtListItem.NetworkType).
+ append(", dlBandwidth:").append(BhtListItem.DLBandwidth).
+ append(", ulBandwidth:").append(BhtListItem.ULBandwidth).
+ append("]");
+ }
+ }
+
+ if (mRequiredProtoPortTuple != null) {
+ sb.append("WifiMORequiredProtoPortTupleList:");
+ for (WifiPasspointDmTree.RequiredProtoPortTuple RpptListItem : mRequiredProtoPortTuple) {
+ sb.append("[IPProtocol:").append(RpptListItem.IPProtocol).
+ append(", PortNumber:").append(RpptListItem.PortNumber).
+ append("]");
+ }
+ }
+
+ return sb.toString();
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(mType);
+ dest.writeString(mUsername);
+ dest.writeString(mPasswd);
+ dest.writeString(mImsi);
+ dest.writeString(mMcc);
+ dest.writeString(mMnc);
+ dest.writeString(mCaRootCert);
+ dest.writeString(mRealm);
+ dest.writeInt(mPriority);
+ dest.writeString(mHomeSpFqdn);
+ dest.writeString(mOtherhomepartnerFqdn);
+ dest.writeString(mClientCert);
+ dest.writeString(mExpirationDate);
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public static final Creator<WifiPasspointCredential> CREATOR =
+ new Creator<WifiPasspointCredential>() {
+ public WifiPasspointCredential createFromParcel(Parcel in) {
+ WifiPasspointCredential pc = new WifiPasspointCredential();
+ pc.mType = in.readString();
+ pc.mUsername = in.readString();
+ pc.mPasswd = in.readString();
+ pc.mImsi = in.readString();
+ pc.mMcc = in.readString();
+ pc.mMnc = in.readString();
+ pc.mCaRootCert = in.readString();
+ pc.mRealm = in.readString();
+ pc.mPriority = in.readInt();
+ pc.mHomeSpFqdn = in.readString();
+ pc.mOtherhomepartnerFqdn = in.readString();
+ pc.mClientCert = in.readString();
+ pc.mExpirationDate = in.readString();
+ return pc;
+ }
+
+ public WifiPasspointCredential[] newArray(int size) {
+ return new WifiPasspointCredential[size];
+ }
+ };
+
+ /** @hide */
+ public int compareTo(WifiPasspointCredential another) {
+
+ //The smaller the higher
+ if (mPriority < another.mPriority) {
+ return -1;
+ } else if (mPriority == another.mPriority) {
+ return this.mType.compareTo(another.mType);
+ } else {
+ return 1;
+ }
+ }
+
+ @Override
+ /** @hide */
+ public int hashCode() {
+ int hash = 208;
+ if (mType != null) {
+ hash += mType.hashCode();
+ }
+ if (mRealm != null) {
+ hash += mRealm.hashCode();
+ }
+ if (mHomeSpFqdn != null) {
+ hash += mHomeSpFqdn.hashCode();
+ }
+ if (mUsername != null) {
+ hash += mUsername.hashCode();
+ }
+ if (mPasswd != null) {
+ hash += mPasswd.hashCode();
+ }
+
+ return hash;
+ }
+}
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointInfo.aidl b/wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.aidl
similarity index 95%
copy from wifi/java/android/net/wifi/passpoint/PasspointInfo.aidl
copy to wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.aidl
index cc11045..6a88b2e 100644
--- a/wifi/java/android/net/wifi/passpoint/PasspointInfo.aidl
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.aidl
@@ -16,4 +16,4 @@
package android.net.wifi.passpoint;
-parcelable PasspointInfo;
+parcelable WifiPasspointDmTree;
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.java
new file mode 100644
index 0000000..9ff1973
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.java
@@ -0,0 +1,1379 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.passpoint;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+import android.util.Log;
+
+import java.util.HashMap;
+
+/**
+ * Required Mobile Device Management Tree Structure
+ *
+ * +----------+
+ * | ./(Root) |
+ * +----+-----+
+ * |
+ * +---------+ | +---------+ +---------+
+ * | DevInfo |-----------+---------| Wi-Fi |---|SP FQDN* |
+ * +---------+ | +---------+ +---------+
+ * +---------+ |
+ * |DevDetail|-----------+
+ * +---------+
+ *
+ * For example,
+ * ./Wi-Fi/wi-fi.org/PerproviderSubscription/Cred01/Policy/PreferredRoamingPartnerList/Roa01/FQDN_Math
+ *
+ * This class contains all nodes start from Wi-Fi
+ * @hide
+ **/
+public class WifiPasspointDmTree implements Parcelable {
+ private final static String TAG = "WifiTree";
+ public int PpsMoId;//plugfest used only
+ public HashMap<String, SpFqdn> spFqdn = new HashMap<String, SpFqdn>();//Maps.newHashMap();
+
+ public SpFqdn createSpFqdn(String name) {
+ SpFqdn obj = new SpFqdn(name);
+ spFqdn.put(name, obj);
+ return obj;
+ }
+
+ public static class SpFqdn implements Parcelable {
+ public String nodeName;
+ public PerProviderSubscription perProviderSubscription = new PerProviderSubscription();
+
+ public SpFqdn(String name) {
+ nodeName = name;
+ }
+
+ public SpFqdn() {
+ }
+
+ public SpFqdn(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(nodeName);
+ out.writeParcelable(perProviderSubscription, flags);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ nodeName = in.readString();
+ perProviderSubscription = in.readParcelable(PerProviderSubscription.class
+ .getClassLoader());
+ }
+ }
+
+ public static final Parcelable.Creator<SpFqdn> CREATOR = new Parcelable.Creator<SpFqdn>() {
+ public SpFqdn createFromParcel(Parcel in) {
+ return new SpFqdn(in);
+ }
+
+ public SpFqdn[] newArray(int size) {
+ return new SpFqdn[size];
+ }
+ };
+ }
+
+ /**
+ * PerProviderSubscription
+ **/
+ public static class PerProviderSubscription implements Parcelable {
+ /**
+ * PerProviderSubscription/UpdateIdentifier
+ **/
+ public String UpdateIdentifier;
+ public HashMap<String, CredentialInfo> credentialInfo = new HashMap<String, CredentialInfo>();
+
+ public CredentialInfo createCredentialInfo(String name) {
+ CredentialInfo obj = new CredentialInfo(name);
+ credentialInfo.put(name, obj);
+ return obj;
+ }
+
+ public PerProviderSubscription() {
+ }
+
+ public PerProviderSubscription(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(UpdateIdentifier);
+ out.writeMap(credentialInfo);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ UpdateIdentifier = in.readString();
+ in.readMap(credentialInfo, CredentialInfo.class.getClassLoader());
+ }
+ }
+
+ public static final Parcelable.Creator<PerProviderSubscription> CREATOR = new Parcelable.Creator<PerProviderSubscription>() {
+ public PerProviderSubscription createFromParcel(Parcel in) {
+ return new PerProviderSubscription(in);
+ }
+
+ public PerProviderSubscription[] newArray(int size) {
+ return new PerProviderSubscription[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>
+ * This interior node contains the Home SP information, subscription policy, management and credential information.
+ **/
+ public static class CredentialInfo implements Parcelable {
+ public String nodeName;
+ public Policy policy = new Policy();
+ public String credentialPriority;
+ public HashMap<String, AAAServerTrustRoot> aAAServerTrustRoot = new HashMap<String, AAAServerTrustRoot>();
+ public SubscriptionUpdate subscriptionUpdate = new SubscriptionUpdate();
+ public HomeSP homeSP = new HomeSP();
+ public SubscriptionParameters subscriptionParameters = new SubscriptionParameters();
+ public Credential credential = new Credential();
+ public Extension extension = new Extension();
+
+ public CredentialInfo(String nn) {
+ nodeName = nn;
+ }
+
+ public AAAServerTrustRoot createAAAServerTrustRoot(String name, String url, String fp) {
+ AAAServerTrustRoot obj = new AAAServerTrustRoot(name, url, fp);
+ aAAServerTrustRoot.put(name, obj);
+ return obj;
+ }
+
+ public CredentialInfo() {
+ }
+
+ public CredentialInfo(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(nodeName);
+ out.writeParcelable(policy, flags);
+ out.writeString(credentialPriority);
+ out.writeMap(aAAServerTrustRoot);
+ out.writeParcelable(subscriptionUpdate, flags);
+ out.writeParcelable(homeSP, flags);
+ out.writeParcelable(subscriptionParameters, flags);
+ out.writeParcelable(credential, flags);
+ //out.writeParcelable(extension, flags);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ nodeName = in.readString();
+ policy = in.readParcelable(Policy.class.getClassLoader());
+ credentialPriority = in.readString();
+ in.readMap(aAAServerTrustRoot, AAAServerTrustRoot.class.getClassLoader());
+ subscriptionUpdate = in.readParcelable(SubscriptionUpdate.class.getClassLoader());
+ homeSP = in.readParcelable(HomeSP.class.getClassLoader());
+ subscriptionParameters = in.readParcelable(SubscriptionParameters.class
+ .getClassLoader());
+ credential = in.readParcelable(Credential.class.getClassLoader());
+ //extension = in.readParcelable(Extension.class.getClassLoader());
+ }
+ }
+
+ public static final Parcelable.Creator<CredentialInfo> CREATOR = new Parcelable.Creator<CredentialInfo>() {
+ public CredentialInfo createFromParcel(Parcel in) {
+ return new CredentialInfo(in);
+ }
+
+ public CredentialInfo[] newArray(int size) {
+ return new CredentialInfo[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Policy
+ **/
+ public static class Policy implements Parcelable {
+ public HashMap<String, PreferredRoamingPartnerList> preferredRoamingPartnerList = new HashMap<String, PreferredRoamingPartnerList>();
+ public HashMap<String, MinBackhaulThresholdNetwork> minBackhaulThreshold = new HashMap<String, MinBackhaulThresholdNetwork>();
+ public PolicyUpdate policyUpdate = new PolicyUpdate();
+ public HashMap<String, SPExclusionList> sPExclusionList = new HashMap<String, SPExclusionList>();
+ public HashMap<String, RequiredProtoPortTuple> requiredProtoPortTuple = new HashMap<String, RequiredProtoPortTuple>();
+ public String maximumBSSLoadValue;
+
+ public PreferredRoamingPartnerList createPreferredRoamingPartnerList(String name,
+ String fqdn, String priority, String country) {
+ PreferredRoamingPartnerList obj = new PreferredRoamingPartnerList(name, fqdn, priority,
+ country);
+ preferredRoamingPartnerList.put(name, obj);
+ return obj;
+ }
+
+ public MinBackhaulThresholdNetwork createMinBackhaulThreshold(String name, String type,
+ String dl, String ul) {
+ MinBackhaulThresholdNetwork obj = new MinBackhaulThresholdNetwork(name, type, dl, ul);
+ minBackhaulThreshold.put(name, obj);
+ return obj;
+ }
+
+ public SPExclusionList createSPExclusionList(String name, String ssid) {
+ SPExclusionList obj = new SPExclusionList(name, ssid);
+ sPExclusionList.put(name, obj);
+ return obj;
+ }
+
+ public RequiredProtoPortTuple createRequiredProtoPortTuple(String name, String proto,
+ String port) {
+ RequiredProtoPortTuple obj = new RequiredProtoPortTuple(name, proto, port);
+ requiredProtoPortTuple.put(name, obj);
+ return obj;
+ }
+
+ public Policy() {
+ }
+
+ public Policy(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeMap(preferredRoamingPartnerList);
+ out.writeMap(minBackhaulThreshold);
+ out.writeParcelable(policyUpdate, flags);
+ out.writeMap(sPExclusionList);
+ out.writeMap(requiredProtoPortTuple);
+ out.writeString(maximumBSSLoadValue);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ in.readMap(preferredRoamingPartnerList,
+ PreferredRoamingPartnerList.class.getClassLoader());
+ in.readMap(minBackhaulThreshold, MinBackhaulThresholdNetwork.class.getClassLoader());
+ policyUpdate = in.readParcelable(PolicyUpdate.class.getClassLoader());
+ in.readMap(sPExclusionList, SPExclusionList.class.getClassLoader());
+ in.readMap(requiredProtoPortTuple, RequiredProtoPortTuple.class.getClassLoader());
+ maximumBSSLoadValue = in.readString();
+
+ }
+ }
+
+ public static final Parcelable.Creator<Policy> CREATOR = new Parcelable.Creator<Policy>() {
+ public Policy createFromParcel(Parcel in) {
+ return new Policy(in);
+ }
+
+ public Policy[] newArray(int size) {
+ return new Policy[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Policy/PreferredRoamingPartnerList/<X+>
+ **/
+ public static class PreferredRoamingPartnerList implements Parcelable {
+ public String nodeName;
+ public String FQDN_Match; //maximum 255 + ",includeSubdomains", equals 273
+ public String Priority;
+ public String Country; // maximum 600 octets
+
+ public PreferredRoamingPartnerList(String nn, String f, String p, String c) {
+ nodeName = nn;
+ FQDN_Match = f;
+ Priority = p;
+ Country = c;
+ }
+
+ public PreferredRoamingPartnerList() {
+ }
+
+ public PreferredRoamingPartnerList(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(nodeName);
+ out.writeString(FQDN_Match);
+ out.writeString(Priority);
+ out.writeString(Country);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ nodeName = in.readString();
+ FQDN_Match = in.readString();
+ Priority = in.readString();
+ Country = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<PreferredRoamingPartnerList> CREATOR = new Parcelable.Creator<PreferredRoamingPartnerList>() {
+ public PreferredRoamingPartnerList createFromParcel(Parcel in) {
+ return new PreferredRoamingPartnerList(in);
+ }
+
+ public PreferredRoamingPartnerList[] newArray(int size) {
+ return new PreferredRoamingPartnerList[size];
+ }
+ };
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Policy/MinBackhaulThreshold
+ **/
+ public static class MinBackhaulThresholdNetwork implements Parcelable {
+ public String nodeName;
+ public String NetworkType;
+ public String DLBandwidth;
+ public String ULBandwidth;
+
+ public MinBackhaulThresholdNetwork(String nn, String nt, String d, String u) {
+ nodeName = nn;
+ NetworkType = nt;
+ DLBandwidth = d;
+ ULBandwidth = u;
+ }
+
+ public MinBackhaulThresholdNetwork() {
+ }
+
+ public MinBackhaulThresholdNetwork(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(nodeName);
+ out.writeString(NetworkType);
+ out.writeString(DLBandwidth);
+ out.writeString(ULBandwidth);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ nodeName = in.readString();
+ NetworkType = in.readString();
+ DLBandwidth = in.readString();
+ ULBandwidth = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<MinBackhaulThresholdNetwork> CREATOR = new Parcelable.Creator<MinBackhaulThresholdNetwork>() {
+ public MinBackhaulThresholdNetwork createFromParcel(Parcel in) {
+ return new MinBackhaulThresholdNetwork(in);
+ }
+
+ public MinBackhaulThresholdNetwork[] newArray(int size) {
+ return new MinBackhaulThresholdNetwork[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Policy/PolicyUpdate
+ **/
+ public static class PolicyUpdate implements Parcelable {
+ public String UpdateInterval;
+ public String UpdateMethod;
+ public String Restriction;
+ public String URI;
+ public UsernamePassword usernamePassword = new UsernamePassword();
+ public String Other;
+ public TrustRoot trustRoot = new TrustRoot();
+
+ public PolicyUpdate() {
+ }
+
+ public PolicyUpdate(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(UpdateInterval);
+ out.writeString(UpdateMethod);
+ out.writeString(Restriction);
+ out.writeString(URI);
+ out.writeParcelable(usernamePassword, flags);
+ out.writeString(Other);
+ out.writeParcelable(trustRoot, flags);
+
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ UpdateInterval = in.readString();
+ UpdateMethod = in.readString();
+ Restriction = in.readString();
+ URI = in.readString();
+ usernamePassword = in.readParcelable(UsernamePassword.class.getClassLoader());
+ Other = in.readString();
+ trustRoot = in.readParcelable(TrustRoot.class.getClassLoader());
+ }
+ }
+
+ public static final Parcelable.Creator<PolicyUpdate> CREATOR = new Parcelable.Creator<PolicyUpdate>() {
+ public PolicyUpdate createFromParcel(Parcel in) {
+ return new PolicyUpdate(in);
+ }
+
+ public PolicyUpdate[] newArray(int size) {
+ return new PolicyUpdate[size];
+ }
+ };
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Policy/SPExclusionList
+ **/
+ public static class SPExclusionList implements Parcelable {
+ public String nodeName;
+ public String SSID;
+
+ public SPExclusionList(String nn, String s) {
+ nodeName = nn;
+ SSID = s;
+ }
+
+ public SPExclusionList() {
+ }
+
+ public SPExclusionList(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(nodeName);
+ out.writeString(SSID);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ nodeName = in.readString();
+ SSID = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<SPExclusionList> CREATOR = new Parcelable.Creator<SPExclusionList>() {
+ public SPExclusionList createFromParcel(Parcel in) {
+ return new SPExclusionList(in);
+ }
+
+ public SPExclusionList[] newArray(int size) {
+ return new SPExclusionList[size];
+ }
+ };
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Policy/RequiredProtoPortTuple
+ **/
+ public static class RequiredProtoPortTuple implements Parcelable {
+ public String nodeName;
+ public String IPProtocol;
+ public String PortNumber;
+
+ public RequiredProtoPortTuple() {
+ }
+
+ public RequiredProtoPortTuple(String nn, String protocol, String port) {
+ nodeName = nn;
+ IPProtocol = protocol;
+ PortNumber = port;
+ }
+
+ public RequiredProtoPortTuple(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(nodeName);
+ out.writeString(IPProtocol);
+ out.writeString(PortNumber);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ nodeName = in.readString();
+ IPProtocol = in.readString();
+ PortNumber = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<RequiredProtoPortTuple> CREATOR = new Parcelable.Creator<RequiredProtoPortTuple>() {
+ public RequiredProtoPortTuple createFromParcel(Parcel in) {
+ return new RequiredProtoPortTuple(in);
+ }
+
+ public RequiredProtoPortTuple[] newArray(int size) {
+ return new RequiredProtoPortTuple[size];
+ }
+ };
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/AAAServerTrustRoot
+ **/
+ public static class AAAServerTrustRoot implements Parcelable {
+ public String nodeName;
+ public String CertURL;
+ public String CertSHA256Fingerprint;
+
+ public AAAServerTrustRoot(String nn, String url, String fp) {
+ nodeName = nn;
+ CertURL = url;
+ CertSHA256Fingerprint = fp;
+ }
+
+ public AAAServerTrustRoot() {
+ }
+
+ public AAAServerTrustRoot(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(nodeName);
+ out.writeString(CertURL);
+ out.writeString(CertSHA256Fingerprint);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ nodeName = in.readString();
+ CertURL = in.readString();
+ CertSHA256Fingerprint = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<AAAServerTrustRoot> CREATOR = new Parcelable.Creator<AAAServerTrustRoot>() {
+ public AAAServerTrustRoot createFromParcel(Parcel in) {
+ return new AAAServerTrustRoot(in);
+ }
+
+ public AAAServerTrustRoot[] newArray(int size) {
+ return new AAAServerTrustRoot[size];
+ }
+ };
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/SubscriptionUpdate
+ **/
+ public static class SubscriptionUpdate implements Parcelable {
+ public String UpdateInterval;
+ public String UpdateMethod;
+ public String Restriction;
+ public String URI;
+ public UsernamePassword usernamePassword = new UsernamePassword();
+ public String Other;
+ public TrustRoot trustRoot = new TrustRoot();
+
+ public SubscriptionUpdate() {
+ }
+
+ public SubscriptionUpdate(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(UpdateInterval);
+ out.writeString(UpdateMethod);
+ out.writeString(Restriction);
+ out.writeString(URI);
+ out.writeParcelable(usernamePassword, flags);
+ out.writeString(Other);
+ out.writeParcelable(trustRoot, flags);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ UpdateInterval = in.readString();
+ UpdateMethod = in.readString();
+ Restriction = in.readString();
+ URI = in.readString();
+ usernamePassword = in.readParcelable(UsernamePassword.class.getClassLoader());
+ Other = in.readString();
+ trustRoot = in.readParcelable(TrustRoot.class.getClassLoader());
+ }
+ }
+
+ public static final Parcelable.Creator<SubscriptionUpdate> CREATOR = new Parcelable.Creator<SubscriptionUpdate>() {
+ public SubscriptionUpdate createFromParcel(Parcel in) {
+ return new SubscriptionUpdate(in);
+ }
+
+ public SubscriptionUpdate[] newArray(int size) {
+ return new SubscriptionUpdate[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Policy/PolicyUpdate/TrustRoot
+ * PerProviderSubscription/<X+>/SubscriptionUpdate/TrustRoot
+ * PerProviderSubscription/<X+>/AAAServerTrustRoot/<X+>
+ **/
+ public static class TrustRoot implements Parcelable {
+ public String CertURL;
+ public String CertSHA256Fingerprint;
+
+ public TrustRoot() {
+ }
+
+ public TrustRoot(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(CertURL);
+ out.writeString(CertSHA256Fingerprint);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ CertURL = in.readString();
+ CertSHA256Fingerprint = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<TrustRoot> CREATOR = new Parcelable.Creator<TrustRoot>() {
+ public TrustRoot createFromParcel(Parcel in) {
+ return new TrustRoot(in);
+ }
+
+ public TrustRoot[] newArray(int size) {
+ return new TrustRoot[size];
+ }
+ };
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Policy/PolicyUpdate/UsernamePassword
+ * PerProviderSubscription/<X+>/SubscriptionUpdate/UsernamePassword
+ * PerProviderSubscription/<X+>/Credential/UsernamePassword
+ **/
+ public static class UsernamePassword implements Parcelable {
+ public String Username;
+ public String Password;
+ //following are Credential node used only
+ public boolean MachineManaged;
+ public String SoftTokenApp;
+ public String AbleToShare;
+ public EAPMethod eAPMethod = new EAPMethod();
+
+ public UsernamePassword() {
+ }
+
+ public UsernamePassword(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(Username);
+ out.writeString(Password);
+ out.writeInt(MachineManaged ? 1 : 0);
+ out.writeString(SoftTokenApp);
+ out.writeString(AbleToShare);
+ out.writeParcelable(eAPMethod, flags);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ Username = in.readString();
+ Password = in.readString();
+ MachineManaged = (in.readInt() == 1) ? true : false;
+ SoftTokenApp = in.readString();
+ AbleToShare = in.readString();
+ eAPMethod = in.readParcelable(EAPMethod.class.getClassLoader());
+ }
+ }
+
+ public static final Parcelable.Creator<UsernamePassword> CREATOR = new Parcelable.Creator<UsernamePassword>() {
+ public UsernamePassword createFromParcel(Parcel in) {
+ return new UsernamePassword(in);
+ }
+
+ public UsernamePassword[] newArray(int size) {
+ return new UsernamePassword[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Credential/UsernamePassword/EAPMethod
+ **/
+ public static class EAPMethod implements Parcelable {
+ public String EAPType;
+ public String VendorId;
+ public String VendorType;
+ public String InnerEAPType;
+ public String InnerVendorId;
+ public String InnerVendorType;
+ public String InnerMethod;
+
+ public EAPMethod() {
+ }
+
+ public EAPMethod(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(EAPType);
+ out.writeString(VendorId);
+ out.writeString(VendorType);
+ out.writeString(InnerEAPType);
+ out.writeString(InnerVendorId);
+ out.writeString(InnerVendorType);
+ out.writeString(InnerMethod);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ EAPType = in.readString();
+ VendorId = in.readString();
+ VendorType = in.readString();
+ InnerEAPType = in.readString();
+ InnerVendorId = in.readString();
+ InnerVendorType = in.readString();
+ InnerMethod = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<EAPMethod> CREATOR = new Parcelable.Creator<EAPMethod>() {
+ public EAPMethod createFromParcel(Parcel in) {
+ return new EAPMethod(in);
+ }
+
+ public EAPMethod[] newArray(int size) {
+ return new EAPMethod[size];
+ }
+ };
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/HomeSP
+ **/
+ public static class HomeSP implements Parcelable {
+ public HashMap<String, NetworkID> networkID = new HashMap<String, NetworkID>();
+ public String FriendlyName;
+ public String IconURL;
+ public String FQDN;
+ public HashMap<String, HomeOIList> homeOIList = new HashMap<String, HomeOIList>();
+ public HashMap<String, OtherHomePartners> otherHomePartners = new HashMap<String, OtherHomePartners>();
+ public String RoamingConsortiumOI;
+
+ public NetworkID createNetworkID(String name, String ssid, String hessid) {
+ NetworkID obj = new NetworkID(name, ssid, hessid);
+ networkID.put(name, obj);
+ return obj;
+ }
+
+ public HomeOIList createHomeOIList(String name, String homeoi, boolean required) {
+ HomeOIList obj = new HomeOIList(name, homeoi, required);
+ homeOIList.put(name, obj);
+ return obj;
+ }
+
+ public OtherHomePartners createOtherHomePartners(String name, String fqdn) {
+ OtherHomePartners obj = new OtherHomePartners(name, fqdn);
+ otherHomePartners.put(name, obj);
+ return obj;
+ }
+
+ public HomeSP() {
+ }
+
+ public HomeSP(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeMap(networkID);
+ out.writeString(FriendlyName);
+ out.writeString(IconURL);
+ out.writeString(FQDN);
+ out.writeMap(homeOIList);
+ out.writeMap(otherHomePartners);
+ out.writeString(RoamingConsortiumOI);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ in.readMap(networkID, NetworkID.class.getClassLoader());
+ FriendlyName = in.readString();
+ IconURL = in.readString();
+ FQDN = in.readString();
+ in.readMap(homeOIList, HomeOIList.class.getClassLoader());
+ in.readMap(otherHomePartners, OtherHomePartners.class.getClassLoader());
+ RoamingConsortiumOI = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<HomeSP> CREATOR = new Parcelable.Creator<HomeSP>() {
+ public HomeSP createFromParcel(Parcel in) {
+ return new HomeSP(in);
+ }
+
+ public HomeSP[] newArray(int size) {
+ return new HomeSP[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/HomeSP/NetworkID
+ **/
+ public static class NetworkID implements Parcelable {
+ public String nodeName;
+ public String SSID;
+ public String HESSID;
+
+ public NetworkID(String nn, String s, String h) {
+ nodeName = nn;
+ SSID = s;
+ HESSID = h;
+ }
+
+ public NetworkID() {
+ }
+
+ public NetworkID(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(nodeName);
+ out.writeString(SSID);
+ out.writeString(HESSID);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ nodeName = in.readString();
+ SSID = in.readString();
+ HESSID = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<NetworkID> CREATOR = new Parcelable.Creator<NetworkID>() {
+ public NetworkID createFromParcel(Parcel in) {
+ return new NetworkID(in);
+ }
+
+ public NetworkID[] newArray(int size) {
+ return new NetworkID[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/HomeSP/HomeOIList
+ **/
+ public static class HomeOIList implements Parcelable {
+ public String nodeName;
+ public String HomeOI;
+ public boolean HomeOIRequired;
+
+ public HomeOIList(String nn, String h, boolean r) {
+ nodeName = nn;
+ HomeOI = h;
+ HomeOIRequired = r;
+ }
+
+ public HomeOIList() {
+ }
+
+ public HomeOIList(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(nodeName);
+ out.writeString(HomeOI);
+ out.writeInt(HomeOIRequired ? 1 : 0);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ nodeName = in.readString();
+ HomeOI = in.readString();
+ HomeOIRequired = (in.readInt() == 1) ? true : false;
+ }
+ }
+
+ public static final Parcelable.Creator<HomeOIList> CREATOR = new Parcelable.Creator<HomeOIList>() {
+ public HomeOIList createFromParcel(Parcel in) {
+ return new HomeOIList(in);
+ }
+
+ public HomeOIList[] newArray(int size) {
+ return new HomeOIList[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/HomeSP/OtherHomePartners
+ **/
+ public static class OtherHomePartners implements Parcelable {
+ public String nodeName;
+ public String FQDN;
+
+ public OtherHomePartners(String nn, String f) {
+ nodeName = nn;
+ FQDN = f;
+ }
+
+ public OtherHomePartners() {
+ }
+
+ public OtherHomePartners(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(nodeName);
+ out.writeString(FQDN);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ nodeName = in.readString();
+ FQDN = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<OtherHomePartners> CREATOR = new Parcelable.Creator<OtherHomePartners>() {
+ public OtherHomePartners createFromParcel(Parcel in) {
+ return new OtherHomePartners(in);
+ }
+
+ public OtherHomePartners[] newArray(int size) {
+ return new OtherHomePartners[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/SubscriptionParameters
+ **/
+ public static class SubscriptionParameters implements Parcelable {
+ public String CreationDate;
+ public String ExpirationDate;
+ public String TypeOfSubscription;
+ public UsageLimits usageLimits = new UsageLimits();
+
+ public SubscriptionParameters() {
+ }
+
+ public SubscriptionParameters(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(CreationDate);
+ out.writeString(ExpirationDate);
+ out.writeString(TypeOfSubscription);
+ out.writeParcelable(usageLimits, flags);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ CreationDate = in.readString();
+ ExpirationDate = in.readString();
+ TypeOfSubscription = in.readString();
+ usageLimits = in.readParcelable(UsageLimits.class.getClassLoader());
+ }
+ }
+
+ public static final Parcelable.Creator<SubscriptionParameters> CREATOR = new Parcelable.Creator<SubscriptionParameters>() {
+ public SubscriptionParameters createFromParcel(Parcel in) {
+ return new SubscriptionParameters(in);
+ }
+
+ public SubscriptionParameters[] newArray(int size) {
+ return new SubscriptionParameters[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/SubscriptionParameters/UsageLimits
+ **/
+ public static class UsageLimits implements Parcelable {
+ public String DataLimit;
+ public String StartDate;
+ public String TimeLimit;
+ public String UsageTimePeriod;
+
+ public UsageLimits() {
+ }
+
+ public UsageLimits(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(DataLimit);
+ out.writeString(StartDate);
+ out.writeString(TimeLimit);
+ out.writeString(UsageTimePeriod);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ DataLimit = in.readString();
+ StartDate = in.readString();
+ TimeLimit = in.readString();
+ UsageTimePeriod = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<UsageLimits> CREATOR = new Parcelable.Creator<UsageLimits>() {
+ public UsageLimits createFromParcel(Parcel in) {
+ return new UsageLimits(in);
+ }
+
+ public UsageLimits[] newArray(int size) {
+ return new UsageLimits[size];
+ }
+ };
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Credential
+ **/
+ public static class Credential implements Parcelable {
+ public String CreationDate;
+ public String ExpirationDate;
+ public UsernamePassword usernamePassword = new UsernamePassword();
+ public DigitalCertificate digitalCertificate = new DigitalCertificate();
+ public String Realm;
+ public boolean CheckAAAServerCertStatus;
+ public SIM sim = new SIM();
+
+ public Credential() {
+ }
+
+ public Credential(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(CreationDate);
+ out.writeString(ExpirationDate);
+ out.writeParcelable(usernamePassword, flags);
+ out.writeParcelable(digitalCertificate, flags);
+ out.writeString(Realm);
+ out.writeInt(CheckAAAServerCertStatus ? 1 : 0);
+ out.writeParcelable(sim, flags);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ CreationDate = in.readString();
+ ExpirationDate = in.readString();
+ usernamePassword = in.readParcelable(UsernamePassword.class.getClassLoader());
+ digitalCertificate = in.readParcelable(DigitalCertificate.class.getClassLoader());
+ Realm = in.readString();
+ CheckAAAServerCertStatus = (in.readInt() == 1) ? true : false;
+ sim = in.readParcelable(SIM.class.getClassLoader());
+ }
+ }
+
+ public static final Parcelable.Creator<Credential> CREATOR = new Parcelable.Creator<Credential>() {
+ public Credential createFromParcel(Parcel in) {
+ return new Credential(in);
+ }
+
+ public Credential[] newArray(int size) {
+ return new Credential[size];
+ }
+ };
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Credential/DigitalCertificate
+ **/
+ public static class DigitalCertificate implements Parcelable {
+ public String CertificateType;
+ public String CertSHA256Fingerprint;
+
+ public DigitalCertificate() {
+ }
+
+ public DigitalCertificate(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(CertificateType);
+ out.writeString(CertSHA256Fingerprint);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ CertificateType = in.readString();
+ CertSHA256Fingerprint = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<DigitalCertificate> CREATOR = new Parcelable.Creator<DigitalCertificate>() {
+ public DigitalCertificate createFromParcel(Parcel in) {
+ return new DigitalCertificate(in);
+ }
+
+ public DigitalCertificate[] newArray(int size) {
+ return new DigitalCertificate[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Credential/SIM
+ **/
+ public static class SIM implements Parcelable {
+ public String IMSI;
+ public String EAPType;
+
+ public SIM() {
+ }
+
+ public SIM(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(IMSI);
+ out.writeString(EAPType);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ IMSI = in.readString();
+ EAPType = in.readString();
+ }
+ }
+
+ public static final Parcelable.Creator<SIM> CREATOR = new Parcelable.Creator<SIM>() {
+ public SIM createFromParcel(Parcel in) {
+ return new SIM(in);
+ }
+
+ public SIM[] newArray(int size) {
+ return new SIM[size];
+ }
+ };
+
+ }
+
+ /**
+ * PerProviderSubscription/<X+>/Extension
+ **/
+ public static class Extension {
+ public String empty;
+ }
+
+ public WifiPasspointDmTree() {
+ }
+
+ public WifiPasspointDmTree(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeMap(spFqdn);
+ }
+
+ public void readFromParcel(Parcel in) {
+ if (in == null) {
+ //log here
+ } else {
+ in.readMap(spFqdn, SpFqdn.class.getClassLoader());
+ }
+ }
+
+ public static final Parcelable.Creator<WifiPasspointDmTree> CREATOR = new Parcelable.Creator<WifiPasspointDmTree>() {
+ public WifiPasspointDmTree createFromParcel(Parcel in) {
+ return new WifiPasspointDmTree(in);
+ }
+
+ public WifiPasspointDmTree[] newArray(int size) {
+ return new WifiPasspointDmTree[size];
+ }
+ };
+
+}
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointInfo.aidl b/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.aidl
similarity index 95%
copy from wifi/java/android/net/wifi/passpoint/PasspointInfo.aidl
copy to wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.aidl
index cc11045..27f23bc 100644
--- a/wifi/java/android/net/wifi/passpoint/PasspointInfo.aidl
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.aidl
@@ -16,4 +16,4 @@
package android.net.wifi.passpoint;
-parcelable PasspointInfo;
+parcelable WifiPasspointInfo;
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.java
new file mode 100644
index 0000000..99bea2f
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.passpoint;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** @hide */
+public class WifiPasspointInfo implements Parcelable {
+
+ /** TODO doc */
+ public static final int ANQP_CAPABILITY = 1 << 0;
+
+ /** TODO doc */
+ public static final int VENUE_NAME = 1 << 1;
+
+ /** TODO doc */
+ public static final int NETWORK_AUTH_TYPE = 1 << 2;
+
+ /** TODO doc */
+ public static final int ROAMING_CONSORTIUM = 1 << 3;
+
+ /** TODO doc */
+ public static final int IP_ADDR_TYPE_AVAILABILITY = 1 << 4;
+
+ /** TODO doc */
+ public static final int NAI_REALM = 1 << 5;
+
+ /** TODO doc */
+ public static final int CELLULAR_NETWORK = 1 << 6;
+
+ /** TODO doc */
+ public static final int DOMAIN_NAME = 1 << 7;
+
+ /** TODO doc */
+ public static final int HOTSPOT_CAPABILITY = 1 << 8;
+
+ /** TODO doc */
+ public static final int OPERATOR_FRIENDLY_NAME = 1 << 9;
+
+ /** TODO doc */
+ public static final int WAN_METRICS = 1 << 10;
+
+ /** TODO doc */
+ public static final int CONNECTION_CAPABILITY = 1 << 11;
+
+ /** TODO doc */
+ public static final int OSU_PROVIDER = 1 << 12;
+
+ /** TODO doc */
+ public static final int PRESET_CRED_MATCH =
+ ANQP_CAPABILITY |
+ HOTSPOT_CAPABILITY |
+ NAI_REALM |
+ CELLULAR_NETWORK |
+ DOMAIN_NAME;
+
+ /** TODO doc */
+ public static final int PRESET_ALL =
+ ANQP_CAPABILITY |
+ VENUE_NAME |
+ NETWORK_AUTH_TYPE |
+ ROAMING_CONSORTIUM |
+ IP_ADDR_TYPE_AVAILABILITY |
+ NAI_REALM |
+ CELLULAR_NETWORK |
+ DOMAIN_NAME |
+ HOTSPOT_CAPABILITY |
+ OPERATOR_FRIENDLY_NAME |
+ WAN_METRICS |
+ CONNECTION_CAPABILITY |
+ OSU_PROVIDER;
+
+ /** TODO doc */
+ public String bssid;
+
+ /** TODO doc */
+ public String venueName;
+
+ /** TODO doc */
+ public String networkAuthType;
+
+ /** TODO doc */
+ public String roamingConsortium;
+
+ /** TODO doc */
+ public String ipAddrTypeAvaibility;
+
+ /** TODO doc */
+ public String naiRealm;
+
+ /** TODO doc */
+ public String cellularNetwork;
+
+ /** TODO doc */
+ public String domainName;
+
+ /** TODO doc */
+ public String operatorFriendlyName;
+
+ /** TODO doc */
+ public String wanMetrics;
+
+ /** TODO doc */
+ public String connectionCapability;
+
+ /** TODO doc */
+ public List<WifiPasspointOsuProvider> osuProviderList;
+
+ /** default constructor @hide */
+ public WifiPasspointInfo() {
+ // osuProviderList = new ArrayList<OsuProvider>();
+ }
+
+ /** copy constructor @hide */
+ public WifiPasspointInfo(WifiPasspointInfo source) {
+ // TODO
+ bssid = source.bssid;
+ venueName = source.venueName;
+ networkAuthType = source.networkAuthType;
+ roamingConsortium = source.roamingConsortium;
+ ipAddrTypeAvaibility = source.ipAddrTypeAvaibility;
+ naiRealm = source.naiRealm;
+ cellularNetwork = source.cellularNetwork;
+ domainName = source.domainName;
+ operatorFriendlyName = source.operatorFriendlyName;
+ wanMetrics = source.wanMetrics;
+ connectionCapability = source.connectionCapability;
+ if (source.osuProviderList != null) {
+ osuProviderList = new ArrayList<WifiPasspointOsuProvider>();
+ for (WifiPasspointOsuProvider osu : source.osuProviderList)
+ osuProviderList.add(new WifiPasspointOsuProvider(osu));
+ }
+ }
+
+ /**
+ * Convert mask to ANQP subtypes, for supplicant command use.
+ *
+ * @param mask The ANQP subtypes mask.
+ * @return String of ANQP subtypes, good for supplicant command use
+ * @hide
+ */
+ public static String toAnqpSubtypes(int mask) {
+ StringBuilder sb = new StringBuilder();
+ if ((mask & ANQP_CAPABILITY) != 0)
+ sb.append("257,");
+ if ((mask & VENUE_NAME) != 0)
+ sb.append("258,");
+ if ((mask & NETWORK_AUTH_TYPE) != 0)
+ sb.append("260,");
+ if ((mask & ROAMING_CONSORTIUM) != 0)
+ sb.append("261,");
+ if ((mask & IP_ADDR_TYPE_AVAILABILITY) != 0)
+ sb.append("262,");
+ if ((mask & NAI_REALM) != 0)
+ sb.append("263,");
+ if ((mask & CELLULAR_NETWORK) != 0)
+ sb.append("264,");
+ if ((mask & DOMAIN_NAME) != 0)
+ sb.append("268,");
+ if ((mask & HOTSPOT_CAPABILITY) != 0)
+ sb.append("hs20:2,");
+ if ((mask & OPERATOR_FRIENDLY_NAME) != 0)
+ sb.append("hs20:3,");
+ if ((mask & WAN_METRICS) != 0)
+ sb.append("hs20:4,");
+ if ((mask & CONNECTION_CAPABILITY) != 0)
+ sb.append("hs20:5,");
+ if ((mask & OSU_PROVIDER) != 0)
+ sb.append("hs20:8,");
+ if (sb.length() > 0)
+ sb.deleteCharAt(sb.length() - 1);
+ return sb.toString();
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("BSSID: ").append(bssid);
+ if (venueName != null)
+ sb.append(" venueName: ").append(venueName);
+ if (networkAuthType != null)
+ sb.append(" networkAuthType: ").append(networkAuthType);
+ if (roamingConsortium != null)
+ sb.append(" roamingConsortium: ").append(roamingConsortium);
+ if (ipAddrTypeAvaibility != null)
+ sb.append(" ipAddrTypeAvaibility: ").append(ipAddrTypeAvaibility);
+ if (naiRealm != null)
+ sb.append(" naiRealm: ").append(naiRealm);
+ if (cellularNetwork != null)
+ sb.append(" cellularNetwork: ").append(cellularNetwork);
+ if (domainName != null)
+ sb.append(" domainName: ").append(domainName);
+ if (operatorFriendlyName != null)
+ sb.append(" operatorFriendlyName: ").append(operatorFriendlyName);
+ if (wanMetrics != null)
+ sb.append(" wanMetrics: ").append(wanMetrics);
+ if (connectionCapability != null)
+ sb.append(" connectionCapability: ").append(connectionCapability);
+ if (osuProviderList != null)
+ sb.append(" osuProviderList: (size=" + osuProviderList.size() + ")");
+ return sb.toString();
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeValue(bssid);
+ out.writeValue(venueName);
+ out.writeValue(networkAuthType);
+ out.writeValue(roamingConsortium);
+ out.writeValue(ipAddrTypeAvaibility);
+ out.writeValue(naiRealm);
+ out.writeValue(cellularNetwork);
+ out.writeValue(domainName);
+ out.writeValue(operatorFriendlyName);
+ out.writeValue(wanMetrics);
+ out.writeValue(connectionCapability);
+ if (osuProviderList == null) {
+ out.writeInt(0);
+ } else {
+ out.writeInt(osuProviderList.size());
+ for (WifiPasspointOsuProvider osu : osuProviderList)
+ osu.writeToParcel(out, flags);
+ }
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public static final Parcelable.Creator<WifiPasspointInfo> CREATOR =
+ new Parcelable.Creator<WifiPasspointInfo>() {
+ @Override
+ public WifiPasspointInfo createFromParcel(Parcel in) {
+ WifiPasspointInfo p = new WifiPasspointInfo();
+ p.bssid = (String) in.readValue(String.class.getClassLoader());
+ p.venueName = (String) in.readValue(String.class.getClassLoader());
+ p.networkAuthType = (String) in.readValue(String.class.getClassLoader());
+ p.roamingConsortium = (String) in.readValue(String.class.getClassLoader());
+ p.ipAddrTypeAvaibility = (String) in.readValue(String.class.getClassLoader());
+ p.naiRealm = (String) in.readValue(String.class.getClassLoader());
+ p.cellularNetwork = (String) in.readValue(String.class.getClassLoader());
+ p.domainName = (String) in.readValue(String.class.getClassLoader());
+ p.operatorFriendlyName = (String) in.readValue(String.class.getClassLoader());
+ p.wanMetrics = (String) in.readValue(String.class.getClassLoader());
+ p.connectionCapability = (String) in.readValue(String.class.getClassLoader());
+ int n = in.readInt();
+ if (n > 0) {
+ p.osuProviderList = new ArrayList<WifiPasspointOsuProvider>();
+ for (int i = 0; i < n; i++) {
+ WifiPasspointOsuProvider osu = WifiPasspointOsuProvider.CREATOR
+ .createFromParcel(in);
+ p.osuProviderList.add(osu);
+ }
+ }
+ return p;
+ }
+
+ @Override
+ public WifiPasspointInfo[] newArray(int size) {
+ return new WifiPasspointInfo[size];
+ }
+ };
+}
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointManager.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointManager.java
similarity index 75%
rename from wifi/java/android/net/wifi/passpoint/PasspointManager.java
rename to wifi/java/android/net/wifi/passpoint/WifiPasspointManager.java
index 234a44c..ee4dc5a 100644
--- a/wifi/java/android/net/wifi/passpoint/PasspointManager.java
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointManager.java
@@ -34,9 +34,9 @@
import java.util.List;
/**
- * TODO: doc
+ * Provides APIs for managing Wifi Passpoint credentials.
*/
-public class PasspointManager {
+public class WifiPasspointManager {
private static final String TAG = "PasspointManager";
@@ -44,37 +44,58 @@
/* Passpoint states values */
- /** Passpoint is in an known state. This should only occur in boot time */
- public static final int PASSPOINT_STATE_UNKNOWN = 0;
+ /** Passpoint is in an known state. This should only occur in boot time @hide */
+ public static final int PASSPOINT_STATE_UNKNOWN = 0;
- /** Passpoint is disabled. This occurs when wifi is disabled. */
- public static final int PASSPOINT_STATE_DISABLED = 1;
+ /** Passpoint is disabled. This occurs when wifi is disabled. @hide */
+ public static final int PASSPOINT_STATE_DISABLED = 1;
- /** Passpoint is enabled and in discovery state. */
- public static final int PASSPOINT_STATE_DISCOVERY = 2;
+ /** Passpoint is enabled and in discovery state. @hide */
+ public static final int PASSPOINT_STATE_DISCOVERY = 2;
- /** Passpoint is enabled and in access state. */
- public static final int PASSPOINT_STATE_ACCESS = 3;
+ /** Passpoint is enabled and in access state. @hide */
+ public static final int PASSPOINT_STATE_ACCESS = 3;
- /** Passpoint is enabled and in provisioning state. */
- public static final int PASSPOINT_STATE_PROVISION = 4;
+ /** Passpoint is enabled and in provisioning state. @hide */
+ public static final int PASSPOINT_STATE_PROVISION = 4;
/* Passpoint callback error codes */
- /** Indicates that the operation failed due to an internal error */
- public static final int ERROR = 0;
+ /** Indicates that the operation failed due to an internal error @hide */
+ public static final int ERROR = 0;
- /** Indicates that the operation failed because wifi is disabled */
- public static final int WIFI_DISABLED = 1;
+ /** Indicates that the operation failed because wifi is disabled @hide */
+ public static final int WIFI_DISABLED = 1;
- /** Indicates that the operation failed because the framework is busy */
- public static final int BUSY = 2;
+ /** Indicates that the operation failed because the framework is busy @hide */
+ public static final int BUSY = 2;
+
+ /**
+ * protocol supported for Passpoint
+ * @hide
+ */
+ public static final String PROTOCOL_DM = "OMA-DM-ClientInitiated";
+
+ /**
+ * protocol supported for Passpoint
+ * @hide
+ */
+ public static final String PROTOCOL_SOAP = "SPP-ClientInitiated";
/* Passpoint broadcasts */
/**
+ * Broadcast intent action indicating that Passpoint online sign up is
+ * avaiable.
+ * @hide
+ */
+ public static final String PASSPOINT_OSU_AVAILABLE =
+ "android.net.wifi.passpoint.OSU_AVAILABLE";
+
+ /**
* Broadcast intent action indicating that the state of Passpoint
* connectivity has changed
+ * @hide
*/
public static final String PASSPOINT_STATE_CHANGED_ACTION =
"android.net.wifi.passpoint.STATE_CHANGE";
@@ -82,6 +103,7 @@
/**
* Broadcast intent action indicating that the saved Passpoint credential
* list has changed
+ * @hide
*/
public static final String PASSPOINT_CRED_CHANGED_ACTION =
"android.net.wifi.passpoint.CRED_CHANGE";
@@ -101,9 +123,9 @@
public static final String PASSPOINT_USER_REM_REQ_ACTION =
"android.net.wifi.passpoint.USER_REM_REQ";
-
/**
* Interface for callback invocation when framework channel is lost
+ * @hide
*/
public interface ChannelListener {
/**
@@ -115,6 +137,7 @@
/**
* Interface for callback invocation on an application action
+ * @hide
*/
public interface ActionListener {
/** The operation succeeded */
@@ -163,6 +186,7 @@
* A channel that connects the application to the wifi passpoint framework.
* Most passpoint operations require a Channel as an argument.
* An instance of Channel is obtained by doing a call on {@link #initialize}
+ * @hide
*/
public static class Channel {
private final static int INVALID_LISTENER_KEY = 0;
@@ -193,7 +217,8 @@
}
private int putListener(Object listener, int count) {
- if (listener == null || count <= 0) return INVALID_LISTENER_KEY;
+ if (listener == null || count <= 0)
+ return INVALID_LISTENER_KEY;
int key;
synchronized (mListenerMapLock) {
do {
@@ -207,13 +232,15 @@
private Object getListener(int key, boolean force) {
Log.d(TAG, "getListener() key=" + key + " force=" + force);
- if (key == INVALID_LISTENER_KEY) return null;
+ if (key == INVALID_LISTENER_KEY)
+ return null;
synchronized (mListenerMapLock) {
if (!force) {
int count = mListenerMapCount.get(key);
Log.d(TAG, "count=" + count);
mListenerMapCount.put(key, --count);
- if (count > 0) return null;
+ if (count > 0)
+ return null;
}
Log.d(TAG, "remove key");
mListenerMapCount.remove(key);
@@ -223,12 +250,14 @@
private void anqpRequestStart(ScanResult sr) {
Log.d(TAG, "anqpRequestStart sr.bssid=" + sr.BSSID);
- synchronized(mAnqpRequestLock) { mAnqpRequest.add(sr); }
+ synchronized (mAnqpRequestLock) {
+ mAnqpRequest.add(sr);
+ }
}
- private void anqpRequestFinish(PasspointInfo result) {
+ private void anqpRequestFinish(WifiPasspointInfo result) {
Log.d(TAG, "anqpRequestFinish pi.bssid=" + result.bssid);
- synchronized(mAnqpRequestLock) {
+ synchronized (mAnqpRequestLock) {
for (ScanResult sr : mAnqpRequest)
if (sr.BSSID.equals(result.bssid)) {
Log.d(TAG, "find hit " + result.bssid);
@@ -242,7 +271,7 @@
private void anqpRequestFinish(ScanResult sr) {
Log.d(TAG, "anqpRequestFinish sr.bssid=" + sr.BSSID);
- synchronized(mAnqpRequestLock) {
+ synchronized (mAnqpRequestLock) {
for (ScanResult sr1 : mAnqpRequest)
if (sr1.BSSID.equals(sr.BSSID)) {
mAnqpRequest.remove(sr1);
@@ -268,7 +297,7 @@
break;
case REQUEST_ANQP_INFO_SUCCEEDED:
- PasspointInfo result = (PasspointInfo) message.obj;
+ WifiPasspointInfo result = (WifiPasspointInfo) message.obj;
anqpRequestFinish(result);
if (listener != null) {
((ActionListener) listener).onSuccess();
@@ -277,7 +306,8 @@
case REQUEST_ANQP_INFO_FAILED:
anqpRequestFinish((ScanResult) message.obj);
- if (listener == null) getListener(message.arg2, true);
+ if (listener == null)
+ getListener(message.arg2, true);
if (listener != null) {
((ActionListener) listener).onFailure(message.arg1);
}
@@ -292,38 +322,36 @@
}
-
private static final int BASE = Protocol.BASE_WIFI_PASSPOINT_MANAGER;
/** @hide */
- public static final int REQUEST_ANQP_INFO = BASE + 1;
+ public static final int REQUEST_ANQP_INFO = BASE + 1;
/** @hide */
- public static final int REQUEST_ANQP_INFO_FAILED = BASE + 2;
+ public static final int REQUEST_ANQP_INFO_FAILED = BASE + 2;
/** @hide */
- public static final int REQUEST_ANQP_INFO_SUCCEEDED = BASE + 3;
+ public static final int REQUEST_ANQP_INFO_SUCCEEDED = BASE + 3;
/** @hide */
- public static final int REQUEST_OSU_INFO = BASE + 4;
+ public static final int REQUEST_OSU_INFO = BASE + 4;
/** @hide */
- public static final int REQUEST_OSU_INFO_FAILED = BASE + 5;
+ public static final int REQUEST_OSU_INFO_FAILED = BASE + 5;
/** @hide */
- public static final int REQUEST_OSU_INFO_SUCCEEDED = BASE + 6;
-
+ public static final int REQUEST_OSU_INFO_SUCCEEDED = BASE + 6;
private Context mContext;
- IPasspointManager mService;
-
+ IWifiPasspointManager mService;
/**
* TODO: doc
* @param context
* @param service
+ * @hide
*/
- public PasspointManager(Context context, IPasspointManager service) {
+ public WifiPasspointManager(Context context, IWifiPasspointManager service) {
mContext = context;
mService = service;
}
@@ -338,10 +366,13 @@
* null.
* @return Channel instance that is necessary for performing any further
* passpoint operations
+ *
+ * @hide
*/
public Channel initialize(Context srcContext, Looper srcLooper, ChannelListener listener) {
Messenger messenger = getMessenger();
- if (messenger == null) return null;
+ if (messenger == null)
+ return null;
Channel c = new Channel(srcContext, srcLooper, listener);
if (c.mAsyncChannel.connectSync(srcContext, c.mHandler, messenger)
@@ -366,49 +397,33 @@
}
}
- /**
- * Get Passpoint state.
- *
- * @return One of {@link #PASSPOINT_STATE_DISABLED},
- * {@link #PASSPOINT_STATE_DISCOVERY},
- * {@link #PASSPOINT_STATE_ACCESS},
- * {@link #PASSPOINT_STATE_PROVISION},
- * {@link #PASSPOINT_STATE_UNKNOWN}
- */
+ /** @hide */
public int getPasspointState() {
- try{
+ try {
return mService.getPasspointState();
- }
- catch (RemoteException e) {
+ } catch (RemoteException e) {
return PASSPOINT_STATE_UNKNOWN;
}
}
- /**
- * TODO: doc
- *
- * @param c
- * @param requested
- * @param mask
- * @param listener
- *
- * @hide
- */
+ /** @hide */
public void requestAnqpInfo(Channel c, List<ScanResult> requested, int mask,
ActionListener listener) {
Log.d(TAG, "requestAnqpInfo start");
Log.d(TAG, "requested.size=" + requested.size());
checkChannel(c);
List<ScanResult> list = new ArrayList<ScanResult>();
- for (ScanResult sr : requested) if (sr.capabilities.contains("[HS20]")) {
- list.add(sr);
- c.anqpRequestStart(sr);
- Log.d(TAG, "adding " + sr.BSSID);
- }
+ for (ScanResult sr : requested)
+ if (sr.capabilities.contains("[HS20]")) {
+ list.add(sr);
+ c.anqpRequestStart(sr);
+ Log.d(TAG, "adding " + sr.BSSID);
+ }
int count = list.size();
Log.d(TAG, "after filter, count=" + count);
if (count == 0) {
- if (DBG) Log.d(TAG, "ANQP info request contains no HS20 APs, skipped");
+ if (DBG)
+ Log.d(TAG, "ANQP info request contains no HS20 APs, skipped");
listener.onSuccess();
return;
}
@@ -418,25 +433,13 @@
Log.d(TAG, "requestAnqpInfo end");
}
- /**
- * TODO: doc
- *
- * @param c
- * @param requested
- * @param resolution
- * @param listener
- */
- public void requestOsuIcons(Channel c, List<PasspointOsuProvider> requested,
+ /** @hide */
+ public void requestOsuIcons(Channel c, List<WifiPasspointOsuProvider> requested,
int resolution, ActionListener listener) {
}
- /**
- * TODO: doc
- *
- * @param requested
- * @return
- */
- public List<PasspointPolicy> requestCredentialMatch(List<ScanResult> requested) {
+ /** @hide */
+ public List<WifiPasspointPolicy> requestCredentialMatch(List<ScanResult> requested) {
return null;
}
@@ -447,7 +450,7 @@
*
* @return The list of credentials
*/
- public List<PasspointCredential> getSavedCredentials() {
+ public List<WifiPasspointCredential> getSavedCredentials() {
return null;
}
@@ -457,32 +460,34 @@
* @param cred The credential to be added
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
- public boolean addCredential(PasspointCredential cred) {
+ public boolean addCredential(WifiPasspointCredential cred) {
return true;
}
/**
- * Update an existing Passpoint credential.
+ * Update an existing Passpoint credential. Only system or the owner of this
+ * credential has the permission to do this.
*
* @param cred The credential to be updated
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
- public boolean updateCredential(PasspointCredential cred) {
+ public boolean updateCredential(WifiPasspointCredential cred) {
return true;
}
/**
- * Remove an existing Passpoint credential.
+ * Remove an existing Passpoint credential. Only system or the owner of this
+ * credential has the permission to do this.
*
* @param cred The credential to be removed
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
- public boolean removeCredential(PasspointCredential cred) {
+ public boolean removeCredential(WifiPasspointCredential cred) {
return true;
}
/** @hide */
- public void startOsu(Channel c, PasspointOsuProvider selected, OsuRemListener listener) {
+ public void startOsu(Channel c, WifiPasspointOsuProvider selected, OsuRemListener listener) {
}
@@ -490,15 +495,12 @@
public void startUserRemediation(Channel c, OsuRemListener listener) {
}
- /**
- * Select and connect to a Passpoint network.
- *
- * @param selected Selected Passpoint network, see {@link PasspointPolicy}
- */
- public void connect(PasspointPolicy selected) {
+ /** @hide */
+ public void connect(WifiPasspointPolicy selected) {
}
private static void checkChannel(Channel c) {
- if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+ if (c == null)
+ throw new IllegalArgumentException("Channel needs to be initialized");
}
}
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointOsuProvider.aidl b/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.aidl
similarity index 94%
copy from wifi/java/android/net/wifi/passpoint/PasspointOsuProvider.aidl
copy to wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.aidl
index f5ecb7c..088136f 100644
--- a/wifi/java/android/net/wifi/passpoint/PasspointOsuProvider.aidl
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.aidl
@@ -16,4 +16,4 @@
package android.net.wifi.passpoint;
-parcelable PasspointOsuProvider;
+parcelable WifiPasspointOsuProvider;
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointOsuProvider.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.java
similarity index 60%
rename from wifi/java/android/net/wifi/passpoint/PasspointOsuProvider.java
rename to wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.java
index 80d5315..18a8f1e 100644
--- a/wifi/java/android/net/wifi/passpoint/PasspointOsuProvider.java
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.java
@@ -19,18 +19,22 @@
import android.os.Parcel;
import android.os.Parcelable;
-/**
- * TODO: doc
- */
-public class PasspointOsuProvider implements Parcelable {
+/** @hide */
+public class WifiPasspointOsuProvider implements Parcelable {
- /** TODO: doc */
+ /** TODO: doc
+ * @hide
+ */
public static final int OSU_METHOD_UNKNOWN = -1;
- /** TODO: doc */
+ /** TODO: doc
+ * @hide
+ */
public static final int OSU_METHOD_OMADM = 0;
- /** TODO: doc */
+ /** TODO: doc
+ * @hide
+ */
public static final int OSU_METHOD_SOAP = 1;
/** TODO: doc */
@@ -39,10 +43,14 @@
/** TODO: doc */
public String friendlyName;
- /** TODO: doc */
+ /** TODO: doc
+ * @hide
+ */
public String serverUri;
- /** TODO: doc */
+ /** TODO: doc
+ * @hide
+ */
public int osuMethod = OSU_METHOD_UNKNOWN;
/** TODO: doc */
@@ -66,14 +74,13 @@
/** TODO: doc */
public String osuService;
-
/** default constructor @hide */
- public PasspointOsuProvider() {
+ public WifiPasspointOsuProvider() {
// TODO
}
/** copy constructor @hide */
- public PasspointOsuProvider(PasspointOsuProvider source) {
+ public WifiPasspointOsuProvider(WifiPasspointOsuProvider source) {
// TODO
}
@@ -88,9 +95,9 @@
sb.append(" osuMethod: ").append(osuMethod);
if (iconFileName != null) {
sb.append(" icon: [").append(iconWidth).append("x")
- .append(iconHeight).append(" ")
- .append(iconType).append(" ")
- .append(iconFileName);
+ .append(iconHeight).append(" ")
+ .append(iconType).append(" ")
+ .append(iconFileName);
}
if (osuNai != null)
sb.append(" osuNai: ").append(osuNai);
@@ -119,27 +126,27 @@
// TODO: icon image?
}
- public static final Parcelable.Creator<PasspointOsuProvider> CREATOR =
- new Parcelable.Creator<PasspointOsuProvider>() {
- @Override
- public PasspointOsuProvider createFromParcel(Parcel in) {
- PasspointOsuProvider osu = new PasspointOsuProvider();
- osu.ssid = (String) in.readValue(String.class.getClassLoader());
- osu.friendlyName = (String) in.readValue(String.class.getClassLoader());
- osu.serverUri = (String) in.readValue(String.class.getClassLoader());
- osu.osuMethod = in.readInt();
- osu.iconWidth = in.readInt();
- osu.iconHeight = in.readInt();
- osu.iconType = (String) in.readValue(String.class.getClassLoader());
- osu.iconFileName = (String) in.readValue(String.class.getClassLoader());
- osu.osuNai = (String) in.readValue(String.class.getClassLoader());
- osu.osuService = (String) in.readValue(String.class.getClassLoader());
- return osu;
- }
+ public static final Parcelable.Creator<WifiPasspointOsuProvider> CREATOR =
+ new Parcelable.Creator<WifiPasspointOsuProvider>() {
+ @Override
+ public WifiPasspointOsuProvider createFromParcel(Parcel in) {
+ WifiPasspointOsuProvider osu = new WifiPasspointOsuProvider();
+ osu.ssid = (String) in.readValue(String.class.getClassLoader());
+ osu.friendlyName = (String) in.readValue(String.class.getClassLoader());
+ osu.serverUri = (String) in.readValue(String.class.getClassLoader());
+ osu.osuMethod = in.readInt();
+ osu.iconWidth = in.readInt();
+ osu.iconHeight = in.readInt();
+ osu.iconType = (String) in.readValue(String.class.getClassLoader());
+ osu.iconFileName = (String) in.readValue(String.class.getClassLoader());
+ osu.osuNai = (String) in.readValue(String.class.getClassLoader());
+ osu.osuService = (String) in.readValue(String.class.getClassLoader());
+ return osu;
+ }
- @Override
- public PasspointOsuProvider[] newArray(int size) {
- return new PasspointOsuProvider[size];
- }
- };
+ @Override
+ public WifiPasspointOsuProvider[] newArray(int size) {
+ return new WifiPasspointOsuProvider[size];
+ }
+ };
}
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointInfo.aidl b/wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.aidl
similarity index 95%
rename from wifi/java/android/net/wifi/passpoint/PasspointInfo.aidl
rename to wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.aidl
index cc11045..1d61da0 100644
--- a/wifi/java/android/net/wifi/passpoint/PasspointInfo.aidl
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.aidl
@@ -16,4 +16,4 @@
package android.net.wifi.passpoint;
-parcelable PasspointInfo;
+parcelable WifiPasspointPolicy;
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.java
new file mode 100644
index 0000000..5f76562
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.passpoint;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+import android.util.Log;
+
+/** @hide */
+public class WifiPasspointPolicy implements Parcelable {
+
+ private final static String TAG = "PasspointPolicy";
+
+ /** @hide */
+ public static final int HOME_SP = 0;
+
+ /** @hide */
+ public static final int ROAMING_PARTNER = 1;
+
+ /** @hide */
+ public static final int UNRESTRICTED = 2;
+
+ private String mName;
+ private int mSubscriptionPriority;
+ private int mRoamingPriority;
+ private String mBssid;
+ private String mSsid;
+ private WifiPasspointCredential mCredential;
+ private int mRestriction;// Permitted values are "HomeSP", "RoamingPartner", or "Unrestricted"
+ private boolean mIsHomeSp;
+
+ /** @hide */
+ public WifiPasspointPolicy(String name, int priority, String ssid,
+ String bssid, WifiPasspointCredential pc,
+ int restriction, boolean ishomesp) {
+ mName = name;
+ mSubscriptionPriority = priority;
+ //PerProviderSubscription/<X+>/Policy/PreferredRoamingPartnerList/<X+>/Priority
+ mRoamingPriority = 128; //default priority value of 128
+ mSsid = ssid;
+ mCredential = pc;
+ mBssid = bssid;
+ mRestriction = restriction;
+ mIsHomeSp = ishomesp;
+ }
+
+ public String getSsid() {
+ return mSsid;
+ }
+
+ /** @hide */
+ public void setBssid(String bssid) {
+ mBssid = bssid;
+ }
+
+ public String getBssid() {
+ return mBssid;
+ }
+
+ /** @hide */
+ public void setRestriction(int r) {
+ mRestriction = r;
+ }
+
+ /** @hide */
+ public int getRestriction() {
+ return mRestriction;
+ }
+
+ /** @hide */
+ public void setHomeSp(boolean b) {
+ mIsHomeSp = b;
+ }
+
+ /** @hide */
+ public boolean getHomeSp() {
+ return mIsHomeSp;
+ }
+
+ /** @hide */
+ public void setCredential(WifiPasspointCredential newCredential) {
+ mCredential = newCredential;
+ }
+
+ public WifiPasspointCredential getCredential() {
+ // TODO: return a copy
+ return mCredential;
+ }
+
+ /** @hide */
+ public void setSubscriptionPriority(int priority) {
+ mSubscriptionPriority = priority;
+ }
+
+ /** @hide */
+ public void setRoamingPriority(int priority) {
+ mRoamingPriority = priority;
+ }
+
+ public int getSubscriptionPriority() {
+ return mSubscriptionPriority;
+ }
+
+ public int getRoamingPriority() {
+ return mRoamingPriority;
+ }
+
+ /** {@inheritDoc} @hide */
+ public int compareTo(WifiPasspointPolicy another) {
+ Log.d(TAG, "this:" + this);
+ Log.d(TAG, "another:" + another);
+
+ if (another == null) {
+ return -1;
+ } else if (this.mIsHomeSp == true && another.getHomeSp() == false) {
+ //home sp priority is higher then roaming
+ Log.d(TAG, "compare HomeSP first, this is HomeSP, another isn't");
+ return -1;
+ } else if ((this.mIsHomeSp == true && another.getHomeSp() == true)) {
+ Log.d(TAG, "both HomeSP");
+ //if both home sp, compare subscription priority
+ if (this.mSubscriptionPriority < another.getSubscriptionPriority()) {
+ Log.d(TAG, "this priority is higher");
+ return -1;
+ } else if (this.mSubscriptionPriority == another.getSubscriptionPriority()) {
+ Log.d(TAG, "both priorities equal");
+ //if priority still the same, compare name(ssid)
+ if (this.mName.compareTo(another.mName) != 0) {
+ Log.d(TAG, "compare mName return:" + this.mName.compareTo(another.mName));
+ return this.mName.compareTo(another.mName);
+ }
+ /**
+ *if name still the same, compare credential
+ *the device may has two more credentials(TLS,SIM..etc)
+ *it can associate to one AP(same ssid). so we should compare by credential
+ */
+ if (this.mCredential != null && another.mCredential != null) {
+ if (this.mCredential.compareTo(another.mCredential) != 0) {
+ Log.d(TAG,
+ "compare mCredential return:" + this.mName.compareTo(another.mName));
+ return this.mCredential.compareTo(another.mCredential);
+ }
+ }
+ } else {
+ return 1;
+ }
+ } else if ((this.mIsHomeSp == false && another.getHomeSp() == false)) {
+ Log.d(TAG, "both RoamingSp");
+ //if both roaming sp, compare roaming priority(preferredRoamingPartnerList/<X+>/priority)
+ if (this.mRoamingPriority < another.getRoamingPriority()) {
+ Log.d(TAG, "this priority is higher");
+ return -1;
+ } else if (this.mRoamingPriority == another.getRoamingPriority()) {//priority equals, compare name
+ Log.d(TAG, "both priorities equal");
+ //if priority still the same, compare name(ssid)
+ if (this.mName.compareTo(another.mName) != 0) {
+ Log.d(TAG, "compare mName return:" + this.mName.compareTo(another.mName));
+ return this.mName.compareTo(another.mName);
+ }
+ //if name still the same, compare credential
+ if (this.mCredential != null && another.mCredential != null) {
+ if (this.mCredential.compareTo(another.mCredential) != 0) {
+ Log.d(TAG,
+ "compare mCredential return:"
+ + this.mCredential.compareTo(another.mCredential));
+ return this.mCredential.compareTo(another.mCredential);
+ }
+ }
+ } else {
+ return 1;
+ }
+ }
+
+ Log.d(TAG, "both policies equal");
+ return 0;
+ }
+
+ @Override
+ /** @hide */
+ public String toString() {
+ return "PasspointPolicy: name=" + mName + " SubscriptionPriority=" + mSubscriptionPriority +
+ " mRoamingPriority" + mRoamingPriority +
+ " ssid=" + mSsid + " restriction=" + mRestriction +
+ " ishomesp=" + mIsHomeSp + " Credential=" + mCredential;
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ // TODO
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public static final Creator<WifiPasspointPolicy> CREATOR =
+ new Creator<WifiPasspointPolicy>() {
+ @Override
+ public WifiPasspointPolicy createFromParcel(Parcel in) {
+ return null;
+ }
+
+ @Override
+ public WifiPasspointPolicy[] newArray(int size) {
+ return new WifiPasspointPolicy[size];
+ }
+ };
+}
diff --git a/wifi/java/android/net/wifi/passpoint/WifiTree.aidl b/wifi/java/android/net/wifi/passpoint/WifiTree.aidl
deleted file mode 100644
index 8e2fab742..0000000
--- a/wifi/java/android/net/wifi/passpoint/WifiTree.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2014, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.passpoint;
-
-parcelable WifiTree;
diff --git a/wifi/java/android/net/wifi/passpoint/WifiTree.java b/wifi/java/android/net/wifi/passpoint/WifiTree.java
deleted file mode 100644
index 8fdb6e1..0000000
--- a/wifi/java/android/net/wifi/passpoint/WifiTree.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.passpoint;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-
-/** @hide */
-public class WifiTree implements Parcelable {
-
- /** Implement the Parcelable interface {@hide} */
- @Override
- public int describeContents() {
- return 0;
- }
-
- /** Implement the Parcelable interface {@hide} */
- @Override
- public void writeToParcel(Parcel out, int flags) {
- // TODO
- }
-
- /** Implement the Parcelable interface {@hide} */
- public static final Parcelable.Creator<WifiTree> CREATOR =
- new Parcelable.Creator<WifiTree>() {
- @Override
- public WifiTree createFromParcel(Parcel in) {
- // TODO
- return null;
- }
-
- @Override
- public WifiTree[] newArray(int size) {
- return new WifiTree[size];
- }
- };
-}