diff options
66 files changed, 1760 insertions, 803 deletions
@@ -197,6 +197,7 @@ LOCAL_SRC_FILES += \ core/java/android/os/IBatteryPropertiesListener.aidl \ core/java/android/os/IBatteryPropertiesRegistrar.aidl \ core/java/android/os/ICancellationSignal.aidl \ + core/java/android/os/IDeviceIdleController.aidl \ core/java/android/os/IMessenger.aidl \ core/java/android/os/INetworkActivityListener.aidl \ core/java/android/os/INetworkManagementService.aidl \ diff --git a/api/current.txt b/api/current.txt index 08dc6f2..f67270e 100644 --- a/api/current.txt +++ b/api/current.txt @@ -2733,7 +2733,6 @@ package android.accounts { } public class AccountManager { - method public boolean accountAuthenticated(android.accounts.Account); method public android.accounts.AccountManagerFuture<android.os.Bundle> addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle); method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean); @@ -2757,6 +2756,7 @@ package android.accounts { method public android.accounts.AccountManagerFuture<java.lang.Boolean> hasFeatures(android.accounts.Account, java.lang.String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler); method public void invalidateAuthToken(java.lang.String, java.lang.String); method public static android.content.Intent newChooseAccountIntent(android.accounts.Account, java.util.ArrayList<android.accounts.Account>, java.lang.String[], boolean, java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle); + method public boolean notifyAccountAuthenticated(android.accounts.Account); method public java.lang.String peekAuthToken(android.accounts.Account, java.lang.String); method public deprecated android.accounts.AccountManagerFuture<java.lang.Boolean> removeAccount(android.accounts.Account, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler); method public android.accounts.AccountManagerFuture<android.os.Bundle> removeAccount(android.accounts.Account, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); @@ -2794,7 +2794,7 @@ package android.accounts { field public static final java.lang.String KEY_ERROR_CODE = "errorCode"; field public static final java.lang.String KEY_ERROR_MESSAGE = "errorMessage"; field public static final java.lang.String KEY_INTENT = "intent"; - field public static final java.lang.String KEY_LAST_AUTHENTICATE_TIME_MILLIS_EPOCH = "lastAuthenticatedTimeMillisEpoch"; + field public static final java.lang.String KEY_LAST_AUTHENTICATED_TIME = "lastAuthenticatedTime"; field public static final java.lang.String KEY_PASSWORD = "password"; field public static final java.lang.String KEY_USERDATA = "userdata"; field public static final java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED"; @@ -14025,6 +14025,7 @@ package android.hardware.usb { method public java.lang.String getProductName(); method public java.lang.String getSerialNumber(); method public int getVendorId(); + method public java.lang.String getVersion(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.hardware.usb.UsbDevice> CREATOR; } @@ -17266,6 +17267,7 @@ package android.media.midi { field public static final java.lang.String PROPERTY_PRODUCT = "product"; field public static final java.lang.String PROPERTY_SERIAL_NUMBER = "serial_number"; field public static final java.lang.String PROPERTY_USB_DEVICE = "usb_device"; + field public static final java.lang.String PROPERTY_VERSION = "version"; field public static final int TYPE_BLUETOOTH = 3; // 0x3 field public static final int TYPE_USB = 1; // 0x1 field public static final int TYPE_VIRTUAL = 2; // 0x2 @@ -30684,11 +30686,34 @@ package android.telephony { method public android.os.Bundle getConfigForSubId(int); method public void reloadCarrierConfigForSubId(int); field public static final java.lang.String ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED"; + field public static final java.lang.String BOOL_ADDITIONAL_CALL_SETTING = "bool_additional_call_setting"; + field public static final java.lang.String BOOL_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG = "bool_allow_emergency_numbers_in_call_log"; + field public static final java.lang.String BOOL_ALLOW_LOCAL_DTMF_TONES = "bool_allow_local_dtmf_tones"; field public static final java.lang.String BOOL_APN_EXPAND = "bool_apn_expand"; + field public static final java.lang.String BOOL_AUTO_RETRY_ENABLED = "bool_auto_retry_enabled"; + field public static final java.lang.String BOOL_CARRIER_SETTINGS_ENABLE = "bool_carrier_settings_enable"; field public static final java.lang.String BOOL_CARRIER_VOLTE_AVAILABLE = "bool_carrier_volte_available"; field public static final java.lang.String BOOL_CARRIER_VOLTE_PROVISIONED = "bool_carrier_volte_provisioned"; field public static final java.lang.String BOOL_CARRIER_VOLTE_TTY_SUPPORTED = "bool_carrier_volte_tty_supported"; + field public static final java.lang.String BOOL_DISABLE_CDMA_ACTIVATION_CODE = "bool_disable_cdma_activation_code"; + field public static final java.lang.String BOOL_DTMF_TYPE_ENABLED = "bool_dtmf_type_enabled"; + field public static final java.lang.String BOOL_ENABLE_DIALER_KEY_VIBRATION = "bool_enable_dialer_key_vibration"; + field public static final java.lang.String BOOL_HAS_IN_CALL_NOISE_SUPPRESSION = "bool_has_in_call_noise_suppression"; + field public static final java.lang.String BOOL_HIDE_CARRIER_NETWORK_SETTINGS = "bool_hide_carrier_network_settings"; + field public static final java.lang.String BOOL_IGNORE_SIM_NETWORK_LOCKED_EVENTS = "bool_ignore_sim_network_locked_events"; + field public static final java.lang.String BOOL_OPERATOR_SELECTION_EXPAND = "bool_operator_selection_expand"; + field public static final java.lang.String BOOL_PREFER_2G = "bool_prefer_2g"; field public static final java.lang.String BOOL_SHOW_APN_SETTING_CDMA = "bool_show_apn_setting_cdma"; + field public static final java.lang.String BOOL_SHOW_CDMA = "bool_show_cdma"; + field public static final java.lang.String BOOL_SHOW_ONSCREEN_DIAL_BUTTON = "bool_show_onscreen_dial_button"; + field public static final java.lang.String BOOL_SIM_NETWORK_UNLOCK_ALLOW_DISMISS = "bool_sim_network_unlock_allow_dismiss"; + field public static final java.lang.String BOOL_SUPPORT_PAUSE_IMS_VIDEO_CALLS = "bool_support_pause_ims_video_calls"; + field public static final java.lang.String BOOL_SUPPORT_SWAP_AFTER_MERGE = "bool_support_swap_after_merge"; + field public static final java.lang.String BOOL_USE_HFA_FOR_PROVISIONING = "bool_use_hfa_for_provisioning"; + field public static final java.lang.String BOOL_USE_OTASP_FOR_PROVISIONING = "bool_use_otasp_for_provisioning"; + field public static final java.lang.String BOOL_VOICEMAIL_NOTIFICATION_PERSISTENT = "bool_voicemail_notification_persistent"; + field public static final java.lang.String BOOL_VOICE_PRIVACY_DISABLE = "bool_voice_privacy_disable"; + field public static final java.lang.String BOOL_WORLD_PHONE = "bool_world_phone"; field public static final java.lang.String INT_VOLTE_REPLACEMENT_RAT = "int_volte_replacement_rat"; } diff --git a/api/system-current.txt b/api/system-current.txt index 92f0a1f..bac38d9 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -2811,7 +2811,6 @@ package android.accounts { } public class AccountManager { - method public boolean accountAuthenticated(android.accounts.Account); method public android.accounts.AccountManagerFuture<android.os.Bundle> addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle); method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean); @@ -2835,6 +2834,7 @@ package android.accounts { method public android.accounts.AccountManagerFuture<java.lang.Boolean> hasFeatures(android.accounts.Account, java.lang.String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler); method public void invalidateAuthToken(java.lang.String, java.lang.String); method public static android.content.Intent newChooseAccountIntent(android.accounts.Account, java.util.ArrayList<android.accounts.Account>, java.lang.String[], boolean, java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle); + method public boolean notifyAccountAuthenticated(android.accounts.Account); method public java.lang.String peekAuthToken(android.accounts.Account, java.lang.String); method public deprecated android.accounts.AccountManagerFuture<java.lang.Boolean> removeAccount(android.accounts.Account, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler); method public android.accounts.AccountManagerFuture<android.os.Bundle> removeAccount(android.accounts.Account, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); @@ -2872,7 +2872,7 @@ package android.accounts { field public static final java.lang.String KEY_ERROR_CODE = "errorCode"; field public static final java.lang.String KEY_ERROR_MESSAGE = "errorMessage"; field public static final java.lang.String KEY_INTENT = "intent"; - field public static final java.lang.String KEY_LAST_AUTHENTICATE_TIME_MILLIS_EPOCH = "lastAuthenticatedTimeMillisEpoch"; + field public static final java.lang.String KEY_LAST_AUTHENTICATED_TIME = "lastAuthenticatedTime"; field public static final java.lang.String KEY_PASSWORD = "password"; field public static final java.lang.String KEY_USERDATA = "userdata"; field public static final java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED"; @@ -3949,6 +3949,7 @@ package android.app { method public void finishOp(java.lang.String, int, java.lang.String); method public int noteOp(java.lang.String, int, java.lang.String); method public int noteOpNoThrow(java.lang.String, int, java.lang.String); + method public static java.lang.String permissionToOp(java.lang.String); method public int startOp(java.lang.String, int, java.lang.String); method public int startOpNoThrow(java.lang.String, int, java.lang.String); method public void startWatchingMode(java.lang.String, java.lang.String, android.app.AppOpsManager.OnOpChangedListener); @@ -14929,6 +14930,7 @@ package android.hardware.usb { method public java.lang.String getProductName(); method public java.lang.String getSerialNumber(); method public int getVendorId(); + method public java.lang.String getVersion(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.hardware.usb.UsbDevice> CREATOR; } @@ -15471,6 +15473,7 @@ package android.location { method public boolean hasPseudorangeUncertaintyInMeters(); method public boolean hasSnrInDb(); method public boolean hasTimeFromLastBitInMs(); + method public boolean isPseudorangeRateCorrected(); method public boolean isUsedInFix(); method public void reset(); method public void resetAzimuthInDeg(); @@ -15536,6 +15539,7 @@ package android.location { field public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0 field public static final short STATE_BIT_SYNC = 2; // 0x2 field public static final short STATE_CODE_LOCK = 1; // 0x1 + field public static final short STATE_MSEC_AMBIGUOUS = 16; // 0x10 field public static final short STATE_SUBFRAME_SYNC = 4; // 0x4 field public static final short STATE_TOW_DECODED = 8; // 0x8 field public static final short STATE_UNKNOWN = 0; // 0x0 @@ -15563,6 +15567,7 @@ package android.location { method public byte[] getData(); method public short getMessageId(); method public byte getPrn(); + method public short getStatus(); method public short getSubmessageId(); method public byte getType(); method public void reset(); @@ -15570,10 +15575,14 @@ package android.location { method public void setData(byte[]); method public void setMessageId(short); method public void setPrn(byte); + method public void setStatus(short); method public void setSubmessageId(short); method public void setType(byte); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessage> CREATOR; + field public static final short STATUS_PARITY_PASSED = 1; // 0x1 + field public static final short STATUS_PARITY_REBUILT = 2; // 0x2 + field public static final short STATUS_UNKNOWN = 0; // 0x0 field public static final byte TYPE_CNAV2 = 4; // 0x4 field public static final byte TYPE_L1CA = 1; // 0x1 field public static final byte TYPE_L2CNAV = 2; // 0x2 @@ -18551,6 +18560,7 @@ package android.media.midi { field public static final java.lang.String PROPERTY_PRODUCT = "product"; field public static final java.lang.String PROPERTY_SERIAL_NUMBER = "serial_number"; field public static final java.lang.String PROPERTY_USB_DEVICE = "usb_device"; + field public static final java.lang.String PROPERTY_VERSION = "version"; field public static final int TYPE_BLUETOOTH = 3; // 0x3 field public static final int TYPE_USB = 1; // 0x1 field public static final int TYPE_VIRTUAL = 2; // 0x2 @@ -32840,11 +32850,34 @@ package android.telephony { method public void reloadCarrierConfigForSubId(int); method public void updateConfigForPhoneId(int, java.lang.String); field public static final java.lang.String ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED"; + field public static final java.lang.String BOOL_ADDITIONAL_CALL_SETTING = "bool_additional_call_setting"; + field public static final java.lang.String BOOL_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG = "bool_allow_emergency_numbers_in_call_log"; + field public static final java.lang.String BOOL_ALLOW_LOCAL_DTMF_TONES = "bool_allow_local_dtmf_tones"; field public static final java.lang.String BOOL_APN_EXPAND = "bool_apn_expand"; + field public static final java.lang.String BOOL_AUTO_RETRY_ENABLED = "bool_auto_retry_enabled"; + field public static final java.lang.String BOOL_CARRIER_SETTINGS_ENABLE = "bool_carrier_settings_enable"; field public static final java.lang.String BOOL_CARRIER_VOLTE_AVAILABLE = "bool_carrier_volte_available"; field public static final java.lang.String BOOL_CARRIER_VOLTE_PROVISIONED = "bool_carrier_volte_provisioned"; field public static final java.lang.String BOOL_CARRIER_VOLTE_TTY_SUPPORTED = "bool_carrier_volte_tty_supported"; + field public static final java.lang.String BOOL_DISABLE_CDMA_ACTIVATION_CODE = "bool_disable_cdma_activation_code"; + field public static final java.lang.String BOOL_DTMF_TYPE_ENABLED = "bool_dtmf_type_enabled"; + field public static final java.lang.String BOOL_ENABLE_DIALER_KEY_VIBRATION = "bool_enable_dialer_key_vibration"; + field public static final java.lang.String BOOL_HAS_IN_CALL_NOISE_SUPPRESSION = "bool_has_in_call_noise_suppression"; + field public static final java.lang.String BOOL_HIDE_CARRIER_NETWORK_SETTINGS = "bool_hide_carrier_network_settings"; + field public static final java.lang.String BOOL_IGNORE_SIM_NETWORK_LOCKED_EVENTS = "bool_ignore_sim_network_locked_events"; + field public static final java.lang.String BOOL_OPERATOR_SELECTION_EXPAND = "bool_operator_selection_expand"; + field public static final java.lang.String BOOL_PREFER_2G = "bool_prefer_2g"; field public static final java.lang.String BOOL_SHOW_APN_SETTING_CDMA = "bool_show_apn_setting_cdma"; + field public static final java.lang.String BOOL_SHOW_CDMA = "bool_show_cdma"; + field public static final java.lang.String BOOL_SHOW_ONSCREEN_DIAL_BUTTON = "bool_show_onscreen_dial_button"; + field public static final java.lang.String BOOL_SIM_NETWORK_UNLOCK_ALLOW_DISMISS = "bool_sim_network_unlock_allow_dismiss"; + field public static final java.lang.String BOOL_SUPPORT_PAUSE_IMS_VIDEO_CALLS = "bool_support_pause_ims_video_calls"; + field public static final java.lang.String BOOL_SUPPORT_SWAP_AFTER_MERGE = "bool_support_swap_after_merge"; + field public static final java.lang.String BOOL_USE_HFA_FOR_PROVISIONING = "bool_use_hfa_for_provisioning"; + field public static final java.lang.String BOOL_USE_OTASP_FOR_PROVISIONING = "bool_use_otasp_for_provisioning"; + field public static final java.lang.String BOOL_VOICEMAIL_NOTIFICATION_PERSISTENT = "bool_voicemail_notification_persistent"; + field public static final java.lang.String BOOL_VOICE_PRIVACY_DISABLE = "bool_voice_privacy_disable"; + field public static final java.lang.String BOOL_WORLD_PHONE = "bool_world_phone"; field public static final java.lang.String INT_VOLTE_REPLACEMENT_RAT = "int_volte_replacement_rat"; } diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index 480d171..ffa36d6 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -207,8 +207,7 @@ public class AccountManager { * were authenticated successfully. Time is specified in milliseconds since * epoch. */ - public static final String KEY_LAST_AUTHENTICATE_TIME_MILLIS_EPOCH = - "lastAuthenticatedTimeMillisEpoch"; + public static final String KEY_LAST_AUTHENTICATED_TIME = "lastAuthenticatedTime"; /** * Authenticators using 'customTokens' option will also get the UID of the @@ -671,8 +670,8 @@ public class AccountManager { } /** - * Informs the system that the account has been authenticated recently. This - * recency may be used by other applications to verify the account. This + * Notifies the system that the account has just been authenticated. This + * information may be used by other applications to verify the account. This * should be called only when the user has entered correct credentials for * the account. * <p> @@ -685,7 +684,7 @@ public class AccountManager { * * @param account The {@link Account} to be updated. */ - public boolean accountAuthenticated(Account account) { + public boolean notifyAccountAuthenticated(Account account) { if (account == null) throw new IllegalArgumentException("account is null"); try { @@ -1587,7 +1586,7 @@ public class AccountManager { * password prompt. * * <p>Also the returning Bundle may contain {@link - * #KEY_LAST_AUTHENTICATE_TIME_MILLIS_EPOCH} indicating the last time the + * #KEY_LAST_AUTHENTICATED_TIME} indicating the last time the * credential was validated/created. * * If an error occurred,{@link AccountManagerFuture#getResult()} throws: diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 223d528..48e380b 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -726,6 +726,16 @@ public class AppOpsManager { false }; + /** + * This is a mapping from a permission name to public app op name. + */ + private static final ArrayMap<String, String> sPermToOp = new ArrayMap<>(); + static { + sPermToOp.put(Manifest.permission.ACCESS_COARSE_LOCATION, OPSTR_COARSE_LOCATION); + sPermToOp.put(Manifest.permission.ACCESS_FINE_LOCATION, OPSTR_FINE_LOCATION); + sPermToOp.put(Manifest.permission.PACKAGE_USAGE_STATS, OPSTR_GET_USAGE_STATS); + } + private static HashMap<String, Integer> sOpStrToOp = new HashMap<String, Integer>(); static { @@ -1066,6 +1076,21 @@ public class AppOpsManager { } /** + * Gets the app op name associated with a given permission. + * The app op name is one of the public constants defined + * in this class such as {@link #OPSTR_COARSE_LOCATION}. + * + * @param permission The permission. + * @return The app op associated with the permission or null. + * + * @hide + */ + @SystemApi + public static String permissionToOp(String permission) { + return sPermToOp.get(permission); + } + + /** * Monitor for changes to the operating mode for the given op in the given app package. * @param op The operation to monitor, one of OPSTR_*. * @param packageName The name of the application to monitor. diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java index ebb3c43..2c12317 100644 --- a/core/java/android/app/KeyguardManager.java +++ b/core/java/android/app/KeyguardManager.java @@ -199,9 +199,12 @@ public class KeyguardManager { } /** - * Return whether the keyguard requires a password to unlock. + * Return whether the keyguard is secured by a PIN, pattern or password or a SIM card + * is currently locked. * - * @return true if keyguard is secure. + * <p>See also {@link #isDeviceSecure()} which ignores SIM locked states. + * + * @return true if a PIN, pattern or password is set or a SIM card is locked. */ public boolean isKeyguardSecure() { try { @@ -240,12 +243,8 @@ public class KeyguardManager { } /** - * Returns whether the device is currently locked and requires a PIN, pattern or - * password to unlock. + * Per-user version of {@link #isDeviceLocked()}. * - * @param userId the user for which the locked state should be reported. - * @return true if unlocking the device currently requires a PIN, pattern or - * password. * @hide */ public boolean isDeviceLocked(int userId) { @@ -260,6 +259,8 @@ public class KeyguardManager { * Returns whether the device is secured with a PIN, pattern or * password. * + * <p>See also {@link #isKeyguardSecure} which treats SIM locked states as secure. + * * @return true if a PIN, pattern or password was set. */ public boolean isDeviceSecure() { @@ -267,11 +268,8 @@ public class KeyguardManager { } /** - * Returns whether the device is secured with a PIN, pattern or - * password. + * Per-user version of {@link #isDeviceSecure()}. * - * @param userId the user for which the secure state should be reported. - * @return true if a PIN, pattern or password was set. * @hide */ public boolean isDeviceSecure(int userId) { diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java index f2e7fc4..4769bd0 100644 --- a/core/java/android/content/ContentProviderNative.java +++ b/core/java/android/content/ContentProviderNative.java @@ -593,7 +593,8 @@ final class ContentProviderProxy implements IContentProvider DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(reply); int has = reply.readInt(); - ParcelFileDescriptor fd = has != 0 ? reply.readFileDescriptor() : null; + ParcelFileDescriptor fd = has != 0 ? ParcelFileDescriptor.CREATOR + .createFromParcel(reply) : null; return fd; } finally { data.recycle(); diff --git a/core/java/android/hardware/usb/UsbDevice.java b/core/java/android/hardware/usb/UsbDevice.java index 1a42319..410d550 100644 --- a/core/java/android/hardware/usb/UsbDevice.java +++ b/core/java/android/hardware/usb/UsbDevice.java @@ -45,6 +45,7 @@ public class UsbDevice implements Parcelable { private final String mName; private final String mManufacturerName; private final String mProductName; + private final String mVersion; private final String mSerialNumber; private final int mVendorId; private final int mProductId; @@ -62,7 +63,7 @@ public class UsbDevice implements Parcelable { */ public UsbDevice(String name, int vendorId, int productId, int Class, int subClass, int protocol, - String manufacturerName, String productName, String serialNumber) { + String manufacturerName, String productName, String version, String serialNumber) { mName = name; mVendorId = vendorId; mProductId = productId; @@ -71,6 +72,7 @@ public class UsbDevice implements Parcelable { mProtocol = protocol; mManufacturerName = manufacturerName; mProductName = productName; + mVersion = version; mSerialNumber = serialNumber; } @@ -104,6 +106,15 @@ public class UsbDevice implements Parcelable { } /** + * Returns the version number of the device. + * + * @return the device version + */ + public String getVersion() { + return mVersion; + } + + /** * Returns the serial number of the device. * * @return the serial number name @@ -263,7 +274,7 @@ public class UsbDevice implements Parcelable { ",mVendorId=" + mVendorId + ",mProductId=" + mProductId + ",mClass=" + mClass + ",mSubclass=" + mSubclass + ",mProtocol=" + mProtocol + ",mManufacturerName=" + mManufacturerName + ",mProductName=" + mProductName + - ",mSerialNumber=" + mSerialNumber + ",mConfigurations=["); + ",mVersion=" + mVersion + ",mSerialNumber=" + mSerialNumber + ",mConfigurations=["); for (int i = 0; i < mConfigurations.length; i++) { builder.append("\n"); builder.append(mConfigurations[i].toString()); @@ -283,10 +294,11 @@ public class UsbDevice implements Parcelable { int protocol = in.readInt(); String manufacturerName = in.readString(); String productName = in.readString(); + String version = in.readString(); String serialNumber = in.readString(); Parcelable[] configurations = in.readParcelableArray(UsbInterface.class.getClassLoader()); UsbDevice device = new UsbDevice(name, vendorId, productId, clasz, subClass, protocol, - manufacturerName, productName, serialNumber); + manufacturerName, productName, version, serialNumber); device.setConfigurations(configurations); return device; } @@ -309,6 +321,7 @@ public class UsbDevice implements Parcelable { parcel.writeInt(mProtocol); parcel.writeString(mManufacturerName); parcel.writeString(mProductName); + parcel.writeString(mVersion); parcel.writeString(mSerialNumber); parcel.writeParcelableArray(mConfigurations, 0); } diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl index c722fbc..7f5f377 100644 --- a/core/java/android/net/INetworkPolicyManager.aidl +++ b/core/java/android/net/INetworkPolicyManager.aidl @@ -38,8 +38,6 @@ interface INetworkPolicyManager { boolean isUidForeground(int uid); - int[] getPowerSaveAppIdWhitelist(); - void registerListener(INetworkPolicyListener listener); void unregisterListener(INetworkPolicyListener listener); diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java index bc03637..ecc3fb4 100644 --- a/core/java/android/net/NetworkPolicyManager.java +++ b/core/java/android/net/NetworkPolicyManager.java @@ -41,6 +41,7 @@ import java.util.HashSet; */ public class NetworkPolicyManager { + /* POLICY_* are masks and can be ORed */ /** No specific network policy, use system default. */ public static final int POLICY_NONE = 0x0; /** Reject network usage on metered networks when application in background. */ @@ -48,10 +49,17 @@ public class NetworkPolicyManager { /** Allow network use (metered or not) in the background in battery save mode. */ public static final int POLICY_ALLOW_BACKGROUND_BATTERY_SAVE = 0x2; + /* RULE_* are not masks and they must be exclusive */ /** All network traffic should be allowed. */ public static final int RULE_ALLOW_ALL = 0x0; /** Reject traffic on metered networks. */ public static final int RULE_REJECT_METERED = 0x1; + /** Reject traffic on all networks. */ + public static final int RULE_REJECT_ALL = 0x2; + + public static final int FIREWALL_RULE_DEFAULT = 0; + public static final int FIREWALL_RULE_ALLOW = 1; + public static final int FIREWALL_RULE_DENY = 2; private static final boolean ALLOW_PLATFORM_APP_POLICY = true; @@ -80,7 +88,7 @@ public class NetworkPolicyManager { * Set policy flags for specific UID. * * @param policy {@link #POLICY_NONE} or combination of flags like - * {@link #POLICY_REJECT_METERED_BACKGROUND}, {@link #POLICY_ALLOW_BACKGROUND_BATTERY_SAVE}. + * {@link #POLICY_REJECT_METERED_BACKGROUND} or {@link #POLICY_ALLOW_BACKGROUND_BATTERY_SAVE}. */ public void setUidPolicy(int uid, int policy) { try { @@ -129,14 +137,6 @@ public class NetworkPolicyManager { } } - public int[] getPowerSaveAppIdWhitelist() { - try { - return mService.getPowerSaveAppIdWhitelist(); - } catch (RemoteException e) { - return new int[0]; - } - } - public void registerListener(INetworkPolicyListener listener) { try { mService.registerListener(listener); @@ -330,6 +330,8 @@ public class NetworkPolicyManager { fout.write("["); if ((rules & RULE_REJECT_METERED) != 0) { fout.write("REJECT_METERED"); + } else if ((rules & RULE_REJECT_ALL) != 0) { + fout.write("REJECT_ALL"); } fout.write("]"); } diff --git a/core/java/android/os/IDeviceIdleController.aidl b/core/java/android/os/IDeviceIdleController.aidl new file mode 100644 index 0000000..3cb29ff --- /dev/null +++ b/core/java/android/os/IDeviceIdleController.aidl @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2015, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +/** @hide */ +interface IDeviceIdleController { + void addPowerSaveWhitelistApp(String name); + void removePowerSaveWhitelistApp(String name); + String[] getSystemPowerWhitelist(); + String[] getFullPowerWhitelist(); + int[] getAppIdWhitelist(); +} diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index f93550a..b29e8d0 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -342,7 +342,7 @@ interface INetworkManagementService void setFirewallInterfaceRule(String iface, boolean allow); void setFirewallEgressSourceRule(String addr, boolean allow); void setFirewallEgressDestRule(String addr, int port, boolean allow); - void setFirewallUidRule(int uid, boolean allow); + void setFirewallUidRule(int uid, int rule); /** * Set all packets from users in ranges to go through VPN specified by netId. diff --git a/core/java/android/os/IPermissionController.aidl b/core/java/android/os/IPermissionController.aidl index 73a68f1..0cc1603 100644 --- a/core/java/android/os/IPermissionController.aidl +++ b/core/java/android/os/IPermissionController.aidl @@ -20,4 +20,5 @@ package android.os; /** @hide */ interface IPermissionController { boolean checkPermission(String permission, int pid, int uid); + String[] getPackagesForUid(int uid); } diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 01c9a21..1d9d7d2 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -920,6 +920,14 @@ public final class PowerManager { = "android.os.action.DEVICE_IDLE_MODE_CHANGED"; /** + * @hide Intent that is broadcast when the set of power save whitelist apps has changed. + * This broadcast is only sent to registered receivers. + */ + @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_POWER_SAVE_WHITELIST_CHANGED + = "android.os.action.POWER_SAVE_WHITELIST_CHANGED"; + + /** * Intent that is broadcast when the state of {@link #isPowerSaveMode()} is about to change. * This broadcast is only sent to registered receivers. * diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index e8fc15e..b5b7f0f 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -15490,12 +15490,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (drawingWithRenderNode) { renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha()); } else if (layerType == LAYER_TYPE_NONE) { - int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG; - if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0) { - layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG; - } canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(), - multipliedAlpha, layerFlags); + multipliedAlpha); } } else { // Alpha is handled by the child directly, clobber the layer's alpha diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java index eff44bd..481ab0e 100644 --- a/core/java/com/android/internal/content/PackageMonitor.java +++ b/core/java/com/android/internal/content/PackageMonitor.java @@ -44,7 +44,6 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver { sPackageFilt.addAction(Intent.ACTION_PACKAGE_CHANGED); sPackageFilt.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); sPackageFilt.addAction(Intent.ACTION_PACKAGE_RESTARTED); - sPackageFilt.addAction(Intent.ACTION_UID_REMOVED); sPackageFilt.addDataScheme("package"); sNonDataFilt.addAction(Intent.ACTION_UID_REMOVED); sNonDataFilt.addAction(Intent.ACTION_USER_STOPPED); diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java index 3a1e0ca..3f7696f 100644 --- a/core/java/com/android/internal/widget/FloatingToolbar.java +++ b/core/java/com/android/internal/widget/FloatingToolbar.java @@ -438,6 +438,9 @@ public final class FloatingToolbar { // Make sure a panel is set as the content. if (mContentContainer.getChildCount() == 0) { setMainPanelAsContent(); + // If we're yet to show the popup, set the container visibility to zero. + // The "show" animation will make this visible. + mContentContainer.setAlpha(0); } preparePopupContent(); mPopupWindow.showAtLocation(mParent, Gravity.NO_GRAVITY, x, y); @@ -478,7 +481,7 @@ public final class FloatingToolbar { * Returns {@code true} if this popup is currently showing. {@code false} otherwise. */ public boolean isShowing() { - return mPopupWindow.isShowing() && !mDismissed && !mHidden; + return !mDismissed && !mHidden; } /** @@ -494,7 +497,7 @@ public final class FloatingToolbar { * This is a no-op if this popup is not showing. */ public void updateCoordinates(int x, int y) { - if (!isShowing()) { + if (!isShowing() || !mPopupWindow.isShowing()) { return; } diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp index c384ef9..6afb226 100644 --- a/core/jni/android_media_AudioRecord.cpp +++ b/core/jni/android_media_AudioRecord.cpp @@ -26,6 +26,8 @@ #include <utils/Log.h> #include <media/AudioRecord.h> +#include <ScopedUtfChars.h> + #include "android_media_AudioFormat.h" #include "android_media_AudioErrors.h" @@ -146,7 +148,7 @@ static sp<AudioRecord> setAudioRecord(JNIEnv* env, jobject thiz, const sp<AudioR static jint android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this, jobject jaa, jint sampleRateInHertz, jint channelMask, jint channelIndexMask, - jint audioFormat, jint buffSizeInBytes, jintArray jSession) + jint audioFormat, jint buffSizeInBytes, jintArray jSession, jstring opPackageName) { //ALOGV(">> Entering android_media_AudioRecord_setup"); //ALOGV("sampleRate=%d, audioFormat=%d, channel mask=%x, buffSizeInBytes=%d", @@ -208,8 +210,10 @@ android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this, env->ReleasePrimitiveArrayCritical(jSession, nSession, 0); nSession = NULL; + ScopedUtfChars opPackageNameStr(env, opPackageName); + // create an uninitialized AudioRecord object - sp<AudioRecord> lpRecorder = new AudioRecord(); + sp<AudioRecord> lpRecorder = new AudioRecord(String16(opPackageNameStr.c_str())); audio_attributes_t *paa = NULL; // read the AudioAttributes values @@ -597,7 +601,7 @@ static JNINativeMethod gMethods[] = { // name, signature, funcPtr {"native_start", "(II)I", (void *)android_media_AudioRecord_start}, {"native_stop", "()V", (void *)android_media_AudioRecord_stop}, - {"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;IIIII[I)I", + {"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;IIIII[ILjava/lang/String;)I", (void *)android_media_AudioRecord_setup}, {"native_finalize", "()V", (void *)android_media_AudioRecord_finalize}, {"native_release", "()V", (void *)android_media_AudioRecord_release}, diff --git a/core/jni/android_media_RemoteDisplay.cpp b/core/jni/android_media_RemoteDisplay.cpp index e2bba30..9bc223b 100644 --- a/core/jni/android_media_RemoteDisplay.cpp +++ b/core/jni/android_media_RemoteDisplay.cpp @@ -134,8 +134,10 @@ private: // ---------------------------------------------------------------------------- -static jlong nativeListen(JNIEnv* env, jobject remoteDisplayObj, jstring ifaceStr) { +static jlong nativeListen(JNIEnv* env, jobject remoteDisplayObj, jstring ifaceStr, + jstring opPackageNameStr) { ScopedUtfChars iface(env, ifaceStr); + ScopedUtfChars opPackageName(env, opPackageNameStr); sp<IServiceManager> sm = defaultServiceManager(); sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>( @@ -146,7 +148,7 @@ static jlong nativeListen(JNIEnv* env, jobject remoteDisplayObj, jstring ifaceSt } sp<NativeRemoteDisplayClient> client(new NativeRemoteDisplayClient(env, remoteDisplayObj)); - sp<IRemoteDisplay> display = service->listenForRemoteDisplay( + sp<IRemoteDisplay> display = service->listenForRemoteDisplay(String16(opPackageName.c_str()), client, String8(iface.c_str())); if (display == NULL) { ALOGE("Media player service rejected request to listen for remote display '%s'.", @@ -176,7 +178,7 @@ static void nativeDispose(JNIEnv* env, jobject remoteDisplayObj, jlong ptr) { // ---------------------------------------------------------------------------- static JNINativeMethod gMethods[] = { - {"nativeListen", "(Ljava/lang/String;)J", + {"nativeListen", "(Ljava/lang/String;Ljava/lang/String;)J", (void*)nativeListen }, {"nativeDispose", "(J)V", (void*)nativeDispose }, diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 45c078d..942e6a6 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -79,6 +79,8 @@ <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED" /> <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGING" /> + <protected-broadcast android:name="android.os.action.DEVICE_IDLE_MODE_CHANGED" /> + <protected-broadcast android:name="android.os.action.POWER_SAVE_WHITELIST_CHANGED" /> <protected-broadcast android:name="android.os.action.SCREEN_BRIGHTNESS_BOOST_CHANGED" /> diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk index a0b26f3..1ea459f 100644 --- a/data/fonts/Android.mk +++ b/data/fonts/Android.mk @@ -50,7 +50,7 @@ extra_font_files := \ # Do not include Motoya on space-constrained devices ifneq ($(SMALLER_FONT_FOOTPRINT),true) # Do not include Motoya if we are including full NotoSans -ifneq ($(FONT_NOTOSANS_FULL),true) +ifneq ($(FONT_NOTOSANS_JP_FULL),true) include $(CLEAR_VARS) LOCAL_MODULE := MTLmr3m.ttf @@ -61,7 +61,7 @@ LOCAL_MODULE_PATH := $(TARGET_OUT)/fonts include $(BUILD_PREBUILT) extra_font_files += MTLmr3m.ttf -endif # !FONT_NOTOSANS_FULL +endif # !FONT_NOTOSANS_JP_FULL endif # !SMALLER_FONT_FOOTPRINT ################################ diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java index c3d8cfa..e5b4612 100644 --- a/graphics/java/android/graphics/drawable/LayerDrawable.java +++ b/graphics/java/android/graphics/drawable/LayerDrawable.java @@ -564,8 +564,6 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { if (drawable != null) { drawable.setCallback(this); - drawable.setLayoutDirection(getLayoutDirection()); - drawable.setLevel(getLevel()); } childDrawable.mDrawable = drawable; diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp index c78971a..dd6af03 100644 --- a/libs/hwui/DeferredDisplayList.cpp +++ b/libs/hwui/DeferredDisplayList.cpp @@ -638,8 +638,7 @@ void DeferredDisplayList::flush(OpenGLRenderer& renderer, Rect& dirty) { DEFER_LOGD("--flushing"); renderer.eventMark("Flush"); - // save and restore (with draw modifiers) so that reordering doesn't affect final state - DrawModifiers restoreDrawModifiers = renderer.getDrawModifiers(); + // save and restore so that reordering doesn't affect final state renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); if (CC_LIKELY(mAvoidOverdraw)) { @@ -654,7 +653,6 @@ void DeferredDisplayList::flush(OpenGLRenderer& renderer, Rect& dirty) { replayBatchList(mBatches, renderer, dirty); renderer.restoreToCount(1); - renderer.setDrawModifiers(restoreDrawModifiers); DEFER_LOGD("--flush complete, returning %x", status); clear(); diff --git a/libs/hwui/DeferredDisplayList.h b/libs/hwui/DeferredDisplayList.h index f535afb..3d0ca6d 100644 --- a/libs/hwui/DeferredDisplayList.h +++ b/libs/hwui/DeferredDisplayList.h @@ -61,7 +61,6 @@ public: int mClipSideFlags; // specifies which sides of the bounds are clipped, unclipped if cleared bool mClipped; mat4 mMatrix; - DrawModifiers mDrawModifiers; float mAlpha; const RoundRectClipState* mRoundRectClipState; }; diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h index 65daf03..c8189b8 100644 --- a/libs/hwui/FrameInfo.h +++ b/libs/hwui/FrameInfo.h @@ -53,6 +53,7 @@ enum class FrameInfoFlags { kWindowLayoutChanged = 1 << 0, kRTAnimation = 1 << 1, kSurfaceCanvas = 1 << 2, + kSkippedFrame = 1 << 3, }; MAKE_FLAGS_ENUM(FrameInfoFlags) @@ -101,6 +102,10 @@ public: set(FrameInfoIndex::kFrameCompleted) = systemTime(CLOCK_MONOTONIC); } + void addFlag(FrameInfoFlags flag) { + set(FrameInfoIndex::kFlags) |= static_cast<uint64_t>(flag); + } + int64_t operator[](FrameInfoIndex index) const { if (index == FrameInfoIndex::kNumIndexes) return 0; return mFrameInfo[static_cast<int>(index)]; diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 30935d5..7fc31b8 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -76,9 +76,6 @@ OpenGLRenderer::OpenGLRenderer(RenderState& renderState) , mLightRadius(FLT_MIN) , mAmbientShadowAlpha(0) , mSpotShadowAlpha(0) { - // *set* draw modifiers to be 0 - memset(&mDrawModifiers, 0, sizeof(mDrawModifiers)); - mDrawModifiers.mOverrideLayerAlpha = 1.0f; } OpenGLRenderer::~OpenGLRenderer() { @@ -1188,10 +1185,9 @@ bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state, int stateDef state.mClip.set(currentClip); } - // Transform, drawModifiers, and alpha always deferred, since they are used by state operations + // Transform and alpha always deferred, since they are used by state operations // (Note: saveLayer/restore use colorFilter and alpha, so we just save restore everything) state.mMatrix.load(*currentMatrix); - state.mDrawModifiers = mDrawModifiers; state.mAlpha = currentSnapshot()->alpha; // always store/restore, since it's just a pointer @@ -1202,7 +1198,6 @@ bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state, int stateDef void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state, bool skipClipRestore) { setMatrix(state.mMatrix); writableSnapshot()->alpha = state.mAlpha; - mDrawModifiers = state.mDrawModifiers; writableSnapshot()->roundRectClipState = state.mRoundRectClipState; if (state.mClipValid && !skipClipRestore) { @@ -1262,7 +1257,7 @@ void OpenGLRenderer::attachStencilBufferToLayer(Layer* layer) { endTiling(); RenderBuffer* buffer = mCaches.renderBufferCache.get( - Stencil::getSmallestStencilFormat(), + Stencil::getLayerStencilFormat(), layer->getWidth(), layer->getHeight()); layer->setStencilRenderBuffer(buffer); @@ -2541,21 +2536,11 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot void OpenGLRenderer::getAlphaAndMode(const SkPaint* paint, int* alpha, SkXfermode::Mode* mode) const { getAlphaAndModeDirect(paint, alpha, mode); - if (mDrawModifiers.mOverrideLayerAlpha < 1.0f) { - // if drawing a layer, ignore the paint's alpha - *alpha = mDrawModifiers.mOverrideLayerAlpha * 255; - } *alpha *= currentSnapshot()->alpha; } float OpenGLRenderer::getLayerAlpha(const Layer* layer) const { - float alpha; - if (mDrawModifiers.mOverrideLayerAlpha < 1.0f) { - alpha = mDrawModifiers.mOverrideLayerAlpha; - } else { - alpha = layer->getAlpha() / 255.0f; - } - return alpha * currentSnapshot()->alpha; + return (layer->getAlpha() / 255.0f) * currentSnapshot()->alpha; } }; // namespace uirenderer diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 5f8960a..c34eb2c 100755 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -68,17 +68,6 @@ class RenderNode; class TextDrawFunctor; class VertexBuffer; -struct DrawModifiers { - DrawModifiers() - : mOverrideLayerAlpha(0.0f) {} - - void reset() { - mOverrideLayerAlpha = 0.0f; - } - - float mOverrideLayerAlpha; -}; - enum StateDeferFlags { kStateDeferFlag_Draw = 0x1, kStateDeferFlag_Clip = 0x2 @@ -236,9 +225,6 @@ public: void setDrawFilter(SkDrawFilter* filter); - // If this value is set to < 1.0, it overrides alpha set on layer (see drawBitmap, drawLayer) - void setOverrideLayerAlpha(float alpha) { mDrawModifiers.mOverrideLayerAlpha = alpha; } - /** * Store the current display state (most importantly, the current clip and transform), and * additionally map the state's bounds from local to window coordinates. @@ -249,9 +235,6 @@ public: void restoreDisplayState(const DeferredDisplayState& state, bool skipClipRestore = false); void setupMergedMultiDraw(const Rect* clipRect); - const DrawModifiers& getDrawModifiers() { return mDrawModifiers; } - void setDrawModifiers(const DrawModifiers& drawModifiers) { mDrawModifiers = drawModifiers; } - bool isCurrentTransformSimple() { return currentTransform()->isSimple(); } @@ -523,8 +506,7 @@ protected: /** * Gets the alpha and xfermode out of a paint object. If the paint is null - * alpha will be 255 and the xfermode will be SRC_OVER. Accounts for both - * snapshot alpha, and overrideLayerAlpha + * alpha will be 255 and the xfermode will be SRC_OVER. Accounts for snapshot alpha. * * @param paint The paint to extract values from * @param alpha Where to store the resulting alpha @@ -533,7 +515,7 @@ protected: inline void getAlphaAndMode(const SkPaint* paint, int* alpha, SkXfermode::Mode* mode) const; /** - * Gets the alpha from a layer, accounting for snapshot alpha and overrideLayerAlpha + * Gets the alpha from a layer, accounting for snapshot alpha * * @param layer The layer from which the alpha is extracted */ @@ -868,10 +850,6 @@ private: // Default UV mapper const UvMapper mUvMapper; - // shader, filters, and shadow - DrawModifiers mDrawModifiers; - SkPaint mFilteredPaint; - // List of rectangles to clear after saveLayer() is invoked std::vector<Rect> mLayers; // List of layers to update at the beginning of a frame diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index ac4c0d0..8f95e0d 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -389,12 +389,9 @@ void RenderNode::setViewProperties(OpenGLRenderer& renderer, T& handler) { if (properties().getAlpha() < 1) { if (isLayer) { clipFlags &= ~CLIP_TO_BOUNDS; // bounds clipping done by layer - - renderer.setOverrideLayerAlpha(properties().getAlpha()); - } else { - LOG_ALWAYS_FATAL_IF(properties().getHasOverlappingRendering()); - renderer.scaleAlpha(properties().getAlpha()); } + LOG_ALWAYS_FATAL_IF(!isLayer && properties().getHasOverlappingRendering()); + renderer.scaleAlpha(properties().getAlpha()); } if (clipFlags) { Rect clipRect; @@ -902,7 +899,6 @@ void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) { DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo); handler(new (alloc) RestoreToCountOp(restoreTo), PROPERTY_SAVECOUNT, properties().getClipToBounds()); - renderer.setOverrideLayerAlpha(1.0f); DISPLAY_LIST_LOGD("%*sDone (%p, %s)", level * 2, "", this, getName()); handler.endMark(); diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp index 0ed3c47..7b75690 100644 --- a/libs/hwui/RenderProperties.cpp +++ b/libs/hwui/RenderProperties.cpp @@ -149,12 +149,10 @@ void RenderProperties::debugOutputProperties(const int level) const { if (mPrimitiveFields.mAlpha < 1) { if (isLayer) { clipFlags &= ~CLIP_TO_BOUNDS; // bounds clipping done by layer - - ALOGD("%*sSetOverrideLayerAlpha %.2f", level * 2, "", mPrimitiveFields.mAlpha); - } else { - LOG_ALWAYS_FATAL_IF(mPrimitiveFields.mHasOverlappingRendering); - ALOGD("%*sScaleAlpha %.2f", level * 2, "", mPrimitiveFields.mAlpha); } + + LOG_ALWAYS_FATAL_IF(!isLayer && mPrimitiveFields.mHasOverlappingRendering); + ALOGD("%*sScaleAlpha %.2f", level * 2, "", mPrimitiveFields.mAlpha); } if (clipFlags) { Rect clipRect; diff --git a/libs/hwui/renderstate/Stencil.cpp b/libs/hwui/renderstate/Stencil.cpp index cedb233..92a057d 100644 --- a/libs/hwui/renderstate/Stencil.cpp +++ b/libs/hwui/renderstate/Stencil.cpp @@ -42,12 +42,17 @@ uint8_t Stencil::getStencilSize() { return STENCIL_BUFFER_SIZE; } -GLenum Stencil::getSmallestStencilFormat() { +/** + * This method will return either GL_STENCIL_INDEX4_OES if supported, + * GL_STENCIL_INDEX8 if not. + * + * Layers can't use a single bit stencil because multi-rect ClipArea needs a high enough + * stencil resolution to represent the summation of multiple intersecting rect geometries. + */ +GLenum Stencil::getLayerStencilFormat() { #if !DEBUG_STENCIL const Extensions& extensions = Caches::getInstance().extensions(); - if (extensions.has1BitStencil()) { - return GL_STENCIL_INDEX1_OES; - } else if (extensions.has4BitStencil()) { + if (extensions.has4BitStencil()) { return GL_STENCIL_INDEX4_OES; } #endif diff --git a/libs/hwui/renderstate/Stencil.h b/libs/hwui/renderstate/Stencil.h index e4f0f3f..3a8f8eb 100644 --- a/libs/hwui/renderstate/Stencil.h +++ b/libs/hwui/renderstate/Stencil.h @@ -42,10 +42,7 @@ public: */ ANDROID_API static uint8_t getStencilSize(); - /** - * Returns the smallest stencil format accepted by render buffers. - */ - static GLenum getSmallestStencilFormat(); + static GLenum getLayerStencilFormat(); /** * Clears the stencil buffer. diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 9237151..3de3086 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -27,12 +27,25 @@ #include "../OpenGLRenderer.h" #include <algorithm> +#include <cutils/properties.h> #include <private/hwui/DrawGlInfo.h> #include <strings.h> #define TRIM_MEMORY_COMPLETE 80 #define TRIM_MEMORY_UI_HIDDEN 20 +#define PROPERTY_SKIP_EMPTY_DAMAGE "debug.hwui.skip_empty_damage" + +static bool sInitialized = false; +static bool sSkipEmptyDamage = true; + +static void initGlobals() { + if (sInitialized) return; + sInitialized = true; + sSkipEmptyDamage = property_get_bool(PROPERTY_SKIP_EMPTY_DAMAGE, + sSkipEmptyDamage); +} + namespace android { namespace uirenderer { namespace renderthread { @@ -45,6 +58,9 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent, , mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord())) , mRootRenderNode(rootRenderNode) , mJankTracker(thread.timeLord().frameIntervalNanos()) { + // Done lazily at first draw instead of at library load to avoid + // running pre-zygote fork + initGlobals(); mRenderThread.renderState().registerCanvasContext(this); mProfiler.setDensity(mRenderThread.mainDisplayInfo().density); } @@ -203,12 +219,17 @@ void CanvasContext::draw() { LOG_ALWAYS_FATAL_IF(!mCanvas || mEglSurface == EGL_NO_SURFACE, "drawRenderNode called on a context with no canvas or surface!"); - profiler().markPlaybackStart(); - mCurrentFrameInfo->markIssueDrawCommandsStart(); - SkRect dirty; mDamageAccumulator.finish(&dirty); + if (dirty.isEmpty() && sSkipEmptyDamage) { + mCurrentFrameInfo->addFlag(FrameInfoFlags::kSkippedFrame); + return; + } + + profiler().markPlaybackStart(); + mCurrentFrameInfo->markIssueDrawCommandsStart(); + EGLint width, height; mEglManager.beginFrame(mEglSurface, &width, &height); if (width != mCanvas->getViewportWidth() || height != mCanvas->getViewportHeight()) { @@ -277,6 +298,8 @@ void CanvasContext::doFrame() { prepareTree(info, frameInfo); if (info.out.canDrawThisFrame) { draw(); + } else { + mCurrentFrameInfo->addFlag(FrameInfoFlags::kSkippedFrame); } } diff --git a/location/java/android/location/GpsMeasurement.java b/location/java/android/location/GpsMeasurement.java index df128c9..f13a440 100644 --- a/location/java/android/location/GpsMeasurement.java +++ b/location/java/android/location/GpsMeasurement.java @@ -140,8 +140,6 @@ public class GpsMeasurement implements Parcelable { /** * The state of the GPS receiver contains millisecond ambiguity. - * - * @hide */ public static final short STATE_MSEC_AMBIGUOUS = (1<<4); @@ -399,8 +397,6 @@ public class GpsMeasurement implements Parcelable { * * @return {@code true} if {@link #getPseudorangeRateInMetersPerSec()} contains a corrected * value, {@code false} if it contains an uncorrected value. - * - * @hide */ public boolean isPseudorangeRateCorrected() { return !isFlagSet(GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE); diff --git a/location/java/android/location/GpsNavigationMessage.java b/location/java/android/location/GpsNavigationMessage.java index 5b12a61..5c3c710 100644 --- a/location/java/android/location/GpsNavigationMessage.java +++ b/location/java/android/location/GpsNavigationMessage.java @@ -62,23 +62,17 @@ public class GpsNavigationMessage implements Parcelable { /** * The Navigation Message Status is 'unknown'. - * - * @hide */ public static final short STATUS_UNKNOWN = 0; /** * The Navigation Message was received without any parity error in its navigation words. - * - * @hide */ public static final short STATUS_PARITY_PASSED = (1<<0); /** * The Navigation Message was received with words that failed parity check, but the receiver was * able to correct those words. - * - * @hide */ public static final short STATUS_PARITY_REBUILT = (1<<1); @@ -220,8 +214,6 @@ public class GpsNavigationMessage implements Parcelable { /** * Gets the Status of the navigation message contained in the object. - * - * @hide */ public short getStatus() { return mStatus; @@ -229,8 +221,6 @@ public class GpsNavigationMessage implements Parcelable { /** * Sets the status of the navigation message. - * - * @hide */ public void setStatus(short value) { mStatus = value; diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java index 201a796..d5e6b3e 100644 --- a/media/java/android/media/AudioRecord.java +++ b/media/java/android/media/AudioRecord.java @@ -26,6 +26,8 @@ import java.util.Iterator; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.SystemApi; +import android.app.ActivityThread; +import android.app.Application; import android.os.Binder; import android.os.Handler; import android.os.IBinder; @@ -378,7 +380,7 @@ public class AudioRecord int initResult = native_setup( new WeakReference<AudioRecord>(this), mAudioAttributes, mSampleRate, mChannelMask, mChannelIndexMask, mAudioFormat, mNativeBufferSizeInBytes, - session); + session, getMyOpPackageName()); if (initResult != SUCCESS) { loge("Error code "+initResult+" when initializing native AudioRecord object."); return; // with mState == STATE_UNINITIALIZED @@ -1321,7 +1323,6 @@ public class AudioRecord return native_set_pos_update_period(periodInFrames); } - //-------------------------------------------------------------------------- // Explicit Routing //-------------------- @@ -1451,7 +1452,7 @@ public class AudioRecord private native final int native_setup(Object audiorecord_this, Object /*AudioAttributes*/ attributes, int sampleRate, int channelMask, int channelIndexMask, int audioFormat, - int buffSizeInBytes, int[] sessionId); + int buffSizeInBytes, int[] sessionId, String opPackageName); // TODO remove: implementation calls directly into implementation of native_release() private native final void native_finalize(); @@ -1500,4 +1501,14 @@ public class AudioRecord Log.e(TAG, msg); } + private static String getMyOpPackageName() { + ActivityThread activityThread = ActivityThread.currentActivityThread(); + if (activityThread != null) { + Application application = activityThread.getApplication(); + if (application != null) { + return application.getOpPackageName(); + } + } + throw new IllegalStateException("Cannot create AudioRecord outside of an app"); + } } diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java index 78fd9f0..1b054cc 100644 --- a/media/java/android/media/MediaRecorder.java +++ b/media/java/android/media/MediaRecorder.java @@ -18,6 +18,7 @@ package android.media; import android.annotation.SystemApi; import android.app.ActivityThread; +import android.app.Application; import android.hardware.Camera; import android.os.Handler; import android.os.Looper; @@ -111,7 +112,7 @@ public class MediaRecorder /* Native setup requires a weak reference to our object. * It's easier to create it here than in C++. */ - native_setup(new WeakReference<MediaRecorder>(this), packageName); + native_setup(new WeakReference<MediaRecorder>(this), packageName, getMyOpPackageName()); } /** @@ -1080,7 +1081,7 @@ public class MediaRecorder private static native final void native_init(); private native final void native_setup(Object mediarecorder_this, - String clientName) throws IllegalStateException; + String clientName, String opPackageName) throws IllegalStateException; private native final void native_finalize(); @@ -1088,4 +1089,15 @@ public class MediaRecorder @Override protected void finalize() { native_finalize(); } + + private static String getMyOpPackageName() { + ActivityThread activityThread = ActivityThread.currentActivityThread(); + if (activityThread != null) { + Application application = activityThread.getApplication(); + if (application != null) { + return application.getOpPackageName(); + } + } + throw new IllegalStateException("Cannot create AudioRecord outside of an app"); + } } diff --git a/media/java/android/media/RemoteDisplay.java b/media/java/android/media/RemoteDisplay.java index 4e937a5..5add65a 100644 --- a/media/java/android/media/RemoteDisplay.java +++ b/media/java/android/media/RemoteDisplay.java @@ -37,17 +37,19 @@ public final class RemoteDisplay { private final CloseGuard mGuard = CloseGuard.get(); private final Listener mListener; private final Handler mHandler; + private final String mOpPackageName; private long mPtr; - private native long nativeListen(String iface); + private native long nativeListen(String iface, String opPackageName); private native void nativeDispose(long ptr); private native void nativePause(long ptr); private native void nativeResume(long ptr); - private RemoteDisplay(Listener listener, Handler handler) { + private RemoteDisplay(Listener listener, Handler handler, String opPackageName) { mListener = listener; mHandler = handler; + mOpPackageName = opPackageName; } @Override @@ -66,7 +68,8 @@ public final class RemoteDisplay { * @param listener The listener to invoke when displays are connected or disconnected. * @param handler The handler on which to invoke the listener. */ - public static RemoteDisplay listen(String iface, Listener listener, Handler handler) { + public static RemoteDisplay listen(String iface, Listener listener, Handler handler, + String opPackageName) { if (iface == null) { throw new IllegalArgumentException("iface must not be null"); } @@ -77,7 +80,7 @@ public final class RemoteDisplay { throw new IllegalArgumentException("handler must not be null"); } - RemoteDisplay display = new RemoteDisplay(listener, handler); + RemoteDisplay display = new RemoteDisplay(listener, handler, opPackageName); display.startListening(iface); return display; } @@ -113,7 +116,7 @@ public final class RemoteDisplay { } private void startListening(String iface) { - mPtr = nativeListen(iface); + mPtr = nativeListen(iface, mOpPackageName); if (mPtr == 0) { throw new IllegalStateException("Could not start listening for " + "remote display connection on \"" + iface + "\""); diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java index a8b9686..9fc90df 100644 --- a/media/java/android/media/audiofx/AudioEffect.java +++ b/media/java/android/media/audiofx/AudioEffect.java @@ -18,6 +18,8 @@ package android.media.audiofx; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.app.ActivityThread; +import android.app.Application; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -395,7 +397,7 @@ public class AudioEffect { // native initialization int initResult = native_setup(new WeakReference<AudioEffect>(this), type.toString(), uuid.toString(), priority, audioSession, id, - desc); + desc, getMyOpPackageName()); if (initResult != SUCCESS && initResult != ALREADY_EXISTS) { Log.e(TAG, "Error code " + initResult + " when initializing AudioEffect."); @@ -1217,7 +1219,8 @@ public class AudioEffect { private static native final void native_init(); private native final int native_setup(Object audioeffect_this, String type, - String uuid, int priority, int audioSession, int[] id, Object[] desc); + String uuid, int priority, int audioSession, int[] id, Object[] desc, + String opPackageName); private native final void native_finalize(); @@ -1356,4 +1359,15 @@ public class AudioEffect { } return b; } + + private static String getMyOpPackageName() { + ActivityThread activityThread = ActivityThread.currentActivityThread(); + if (activityThread != null) { + Application application = activityThread.getApplication(); + if (application != null) { + return application.getOpPackageName(); + } + } + throw new IllegalStateException("Cannot create AudioEffect outside of an app"); + } } diff --git a/media/java/android/media/audiofx/Visualizer.java b/media/java/android/media/audiofx/Visualizer.java index 24c74ac..0c48063 100644 --- a/media/java/android/media/audiofx/Visualizer.java +++ b/media/java/android/media/audiofx/Visualizer.java @@ -16,6 +16,8 @@ package android.media.audiofx; +import android.app.ActivityThread; +import android.app.Application; import android.util.Log; import java.lang.ref.WeakReference; import android.os.Handler; @@ -206,7 +208,8 @@ public class Visualizer { synchronized (mStateLock) { mState = STATE_UNINITIALIZED; // native initialization - int result = native_setup(new WeakReference<Visualizer>(this), audioSession, id); + int result = native_setup(new WeakReference<Visualizer>(this), audioSession, id, + getMyOpPackageName()); if (result != SUCCESS && result != ALREADY_EXISTS) { Log.e(TAG, "Error code "+result+" when initializing Visualizer."); switch (result) { @@ -716,7 +719,8 @@ public class Visualizer { private native final int native_setup(Object audioeffect_this, int audioSession, - int[] id); + int[] id, + String opPackageName); private native final void native_finalize(); @@ -766,5 +770,15 @@ public class Visualizer { } + private static String getMyOpPackageName() { + ActivityThread activityThread = ActivityThread.currentActivityThread(); + if (activityThread != null) { + Application application = activityThread.getApplication(); + if (application != null) { + return application.getOpPackageName(); + } + } + throw new IllegalStateException("Cannot create AudioRecord outside of an app"); + } } diff --git a/media/java/android/media/midi/MidiDeviceInfo.java b/media/java/android/media/midi/MidiDeviceInfo.java index af108eb..35374ed 100644 --- a/media/java/android/media/midi/MidiDeviceInfo.java +++ b/media/java/android/media/midi/MidiDeviceInfo.java @@ -69,6 +69,13 @@ public final class MidiDeviceInfo implements Parcelable { public static final String PROPERTY_PRODUCT = "product"; /** + * Bundle key for the device's version property. + * Used with the {@link android.os.Bundle} returned by {@link #getProperties} + * Matches the USB device version number for USB MIDI devices. + */ + public static final String PROPERTY_VERSION = "version"; + + /** * Bundle key for the device's serial number property. * Used with the {@link android.os.Bundle} returned by {@link #getProperties} * Matches the USB device serial number for USB MIDI devices. diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp index 8b7d40d..02297fc 100644 --- a/media/jni/android_media_MediaRecorder.cpp +++ b/media/jni/android_media_MediaRecorder.cpp @@ -31,6 +31,8 @@ #include <media/mediarecorder.h> #include <utils/threads.h> +#include <ScopedUtfChars.h> + #include "jni.h" #include "JNIHelp.h" #include "android_runtime/AndroidRuntime.h" @@ -444,11 +446,13 @@ android_media_MediaRecorder_native_init(JNIEnv *env) static void android_media_MediaRecorder_native_setup(JNIEnv *env, jobject thiz, jobject weak_this, - jstring packageName) + jstring packageName, jstring opPackageName) { ALOGV("setup"); - sp<MediaRecorder> mr = new MediaRecorder(); + ScopedUtfChars opPackageNameStr(env, opPackageName); + + sp<MediaRecorder> mr = new MediaRecorder(String16(opPackageNameStr.c_str())); if (mr == NULL) { jniThrowException(env, "java/lang/RuntimeException", "Out of memory"); return; @@ -506,7 +510,8 @@ static JNINativeMethod gMethods[] = { {"native_reset", "()V", (void *)android_media_MediaRecorder_native_reset}, {"release", "()V", (void *)android_media_MediaRecorder_release}, {"native_init", "()V", (void *)android_media_MediaRecorder_native_init}, - {"native_setup", "(Ljava/lang/Object;Ljava/lang/String;)V", (void *)android_media_MediaRecorder_native_setup}, + {"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V", + (void *)android_media_MediaRecorder_native_setup}, {"native_finalize", "()V", (void *)android_media_MediaRecorder_native_finalize}, }; diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp index c364d46..96b72a2 100644 --- a/media/jni/audioeffect/android_media_AudioEffect.cpp +++ b/media/jni/audioeffect/android_media_AudioEffect.cpp @@ -25,6 +25,8 @@ #include <android_runtime/AndroidRuntime.h> #include "media/AudioEffect.h" +#include <ScopedUtfChars.h> + using namespace android; #define AUDIOEFFECT_SUCCESS 0 @@ -249,7 +251,8 @@ android_media_AudioEffect_native_init(JNIEnv *env) static jint android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_this, - jstring type, jstring uuid, jint priority, jint sessionId, jintArray jId, jobjectArray javadesc) + jstring type, jstring uuid, jint priority, jint sessionId, jintArray jId, + jobjectArray javadesc, jstring opPackageName) { ALOGV("android_media_AudioEffect_native_setup"); AudioEffectJniStorage* lpJniStorage = NULL; @@ -267,6 +270,8 @@ android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_t jstring jdescName; jstring jdescImplementor; + ScopedUtfChars opPackageNameStr(env, opPackageName); + if (type != NULL) { typeStr = env->GetStringUTFChars(type, NULL); if (typeStr == NULL) { // Out of memory @@ -312,6 +317,7 @@ android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_t // create the native AudioEffect object lpAudioEffect = new AudioEffect(typeStr, + String16(opPackageNameStr.c_str()), uuidStr, priority, effectCallback, @@ -868,7 +874,7 @@ android_media_AudioEffect_native_queryPreProcessings(JNIEnv *env, jclass clazz _ // Dalvik VM type signatures static JNINativeMethod gMethods[] = { {"native_init", "()V", (void *)android_media_AudioEffect_native_init}, - {"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;II[I[Ljava/lang/Object;)I", + {"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;II[I[Ljava/lang/Object;Ljava/lang/String;)I", (void *)android_media_AudioEffect_native_setup}, {"native_finalize", "()V", (void *)android_media_AudioEffect_native_finalize}, {"native_release", "()V", (void *)android_media_AudioEffect_native_release}, diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp index 460277f..abc681e 100644 --- a/media/jni/audioeffect/android_media_Visualizer.cpp +++ b/media/jni/audioeffect/android_media_Visualizer.cpp @@ -26,6 +26,8 @@ #include <utils/threads.h> #include "media/Visualizer.h" +#include <ScopedUtfChars.h> + using namespace android; #define VISUALIZER_SUCCESS 0 @@ -331,7 +333,7 @@ static void android_media_visualizer_effect_callback(int32_t event, static jint android_media_visualizer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this, - jint sessionId, jintArray jId) + jint sessionId, jintArray jId, jstring opPackageName) { ALOGV("android_media_visualizer_native_setup"); visualizerJniStorage* lpJniStorage = NULL; @@ -339,6 +341,8 @@ android_media_visualizer_native_setup(JNIEnv *env, jobject thiz, jobject weak_th Visualizer* lpVisualizer = NULL; jint* nId = NULL; + ScopedUtfChars opPackageNameStr(env, opPackageName); + lpJniStorage = new visualizerJniStorage(); if (lpJniStorage == NULL) { ALOGE("setup: Error creating JNI Storage"); @@ -362,7 +366,8 @@ android_media_visualizer_native_setup(JNIEnv *env, jobject thiz, jobject weak_th } // create the native Visualizer object - lpVisualizer = new Visualizer(0, + lpVisualizer = new Visualizer(String16(opPackageNameStr.c_str()), + 0, android_media_visualizer_effect_callback, lpJniStorage, sessionId); @@ -662,7 +667,7 @@ android_media_setPeriodicCapture(JNIEnv *env, jobject thiz, jint rate, jboolean // Dalvik VM type signatures static JNINativeMethod gMethods[] = { {"native_init", "()V", (void *)android_media_visualizer_native_init}, - {"native_setup", "(Ljava/lang/Object;I[I)I", + {"native_setup", "(Ljava/lang/Object;I[ILjava/lang/String;)I", (void *)android_media_visualizer_native_setup}, {"native_finalize", "()V", (void *)android_media_visualizer_native_finalize}, {"native_release", "()V", (void *)android_media_visualizer_native_release}, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 7b13e4b..a8ecc42 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -2158,7 +2158,7 @@ public class NotificationPanelView extends PanelView implements } @Override - public void onPinnedModeChanged(final boolean inPinnedMode) { + public void onHeadsUpPinnedModeChanged(final boolean inPinnedMode) { if (inPinnedMode) { mHeadsUpExistenceChangedRunnable.run(); updateNotificationTranslucency(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index bf27e84..9a6a80e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -1852,7 +1852,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } @Override - public void onPinnedModeChanged(boolean inPinnedMode) { + public void onHeadsUpPinnedModeChanged(boolean inPinnedMode) { if (inPinnedMode) { mStatusBarWindowManager.setHeadsUpShowing(true); } else { @@ -1874,6 +1874,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, @Override public void onHeadsUpPinned(ExpandableNotificationRow headsUp) { + dismissVolumeDialog(); } @Override @@ -2377,13 +2378,17 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } // manually dismiss the volume panel when interacting with the nav bar if (changing && interacting && barWindow == StatusBarManager.WINDOW_NAVIGATION_BAR) { - if (mVolumeComponent != null) { - mVolumeComponent.dismissNow(); - } + dismissVolumeDialog(); } checkBarModes(); } + private void dismissVolumeDialog() { + if (mVolumeComponent != null) { + mVolumeComponent.dismissNow(); + } + } + private void resumeSuspendedAutohide() { if (mAutohideSuspended) { scheduleAutohide(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index ae98e76..e6edbea 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -347,7 +347,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, } @Override - public void onPinnedModeChanged(boolean inPinnedMode) { + public void onHeadsUpPinnedModeChanged(boolean inPinnedMode) { } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java index 8f83daa..0db9221 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java @@ -208,7 +208,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL } mHasPinnedNotification = hasPinnedNotification; for (OnHeadsUpChangedListener listener : mListeners) { - listener.onPinnedModeChanged(hasPinnedNotification); + listener.onHeadsUpPinnedModeChanged(hasPinnedNotification); } } @@ -539,7 +539,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL * * @param inPinnedMode whether there are any pinned heads-ups */ - void onPinnedModeChanged(boolean inPinnedMode); + void onHeadsUpPinnedModeChanged(boolean inPinnedMode); /** * A notification was just pinned to the top. diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java index 0e3867d..745c190 100644 --- a/services/core/java/com/android/server/AlarmManagerService.java +++ b/services/core/java/com/android/server/AlarmManagerService.java @@ -461,7 +461,7 @@ class AlarmManagerService extends SystemService { // to run during this time are placed in mPendingWhileIdleAlarms Alarm mPendingIdleUntil = null; Alarm mNextWakeFromIdle = null; - final ArrayList<Alarm> mPendingWhileIdleAlarms = new ArrayList<>(); + ArrayList<Alarm> mPendingWhileIdleAlarms = new ArrayList<>(); public AlarmManagerService(Context context) { super(context); @@ -567,10 +567,14 @@ class AlarmManagerService extends SystemService { void restorePendingWhileIdleAlarmsLocked() { // Bring pending alarms back into the main list. - final long nowElapsed = SystemClock.elapsedRealtime(); - for (int i=mPendingWhileIdleAlarms.size() - 1; i >= 0 && mPendingIdleUntil == null; i--) { - Alarm a = mPendingWhileIdleAlarms.remove(i); - reAddAlarmLocked(a, nowElapsed, false); + if (mPendingWhileIdleAlarms.size() > 0) { + ArrayList<Alarm> alarms = mPendingWhileIdleAlarms; + mPendingWhileIdleAlarms = new ArrayList<>(); + final long nowElapsed = SystemClock.elapsedRealtime(); + for (int i=alarms.size() - 1; i >= 0; i--) { + Alarm a = alarms.get(i); + reAddAlarmLocked(a, nowElapsed, false); + } } // Reschedule everything. @@ -1053,11 +1057,16 @@ class AlarmManagerService extends SystemService { dumpAlarmList(pw, b.alarms, " ", nowELAPSED, nowRTC, sdf); } } - if (mPendingIdleUntil != null) { + if (mPendingIdleUntil != null || mPendingWhileIdleAlarms.size() > 0) { pw.println(); pw.println("Idle mode state:"); - pw.print(" Idling until: "); pw.println(mPendingIdleUntil); - mPendingIdleUntil.dump(pw, " ", nowRTC, nowELAPSED, sdf); + pw.print(" Idling until: "); + if (mPendingIdleUntil != null) { + pw.println(mPendingIdleUntil); + mPendingIdleUntil.dump(pw, " ", nowRTC, nowELAPSED, sdf); + } else { + pw.println("null"); + } pw.println(" Pending alarms:"); dumpAlarmList(pw, mPendingWhileIdleAlarms, " ", nowELAPSED, nowRTC, sdf); } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 12a99b0..1a75b8a 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -24,6 +24,7 @@ import static android.net.ConnectivityManager.TYPE_VPN; import static android.net.ConnectivityManager.getNetworkTypeName; import static android.net.ConnectivityManager.isNetworkTypeValid; import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL; +import static android.net.NetworkPolicyManager.RULE_REJECT_ALL; import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; import android.annotation.Nullable; @@ -832,7 +833,8 @@ public class ConnectivityService extends IConnectivityManager.Stub uidRules = mUidRules.get(uid, RULE_ALLOW_ALL); } - if (networkCostly && (uidRules & RULE_REJECT_METERED) != 0) { + if ((uidRules & RULE_REJECT_ALL) != 0 + || (networkCostly && (uidRules & RULE_REJECT_METERED) != 0)) { return true; } @@ -3490,7 +3492,7 @@ public class ConnectivityService extends IConnectivityManager.Stub synchronized(mRulesLock) { uidRules = mUidRules.get(uid, RULE_ALLOW_ALL); } - if ((uidRules & RULE_REJECT_METERED) != 0) { + if ((uidRules & (RULE_REJECT_METERED | RULE_REJECT_ALL)) != 0) { // we could silently fail or we can filter the available nets to only give // them those they have access to. Chose the more useful networkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java new file mode 100644 index 0000000..b7bc0f0 --- /dev/null +++ b/services/core/java/com/android/server/DeviceIdleController.java @@ -0,0 +1,879 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.hardware.Sensor; +import android.hardware.SensorManager; +import android.hardware.TriggerEvent; +import android.hardware.TriggerEventListener; +import android.hardware.display.DisplayManager; +import android.net.INetworkPolicyManager; +import android.os.Binder; +import android.os.Environment; +import android.os.FileUtils; +import android.os.Handler; +import android.os.IDeviceIdleController; +import android.os.Looper; +import android.os.Message; +import android.os.PowerManager; +import android.os.PowerManagerInternal; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.SystemClock; +import android.os.UserHandle; +import android.util.ArrayMap; +import android.util.ArraySet; +import android.util.Slog; +import android.util.SparseBooleanArray; +import android.util.TimeUtils; +import android.util.Xml; +import android.view.Display; +import com.android.internal.app.IBatteryStats; +import com.android.internal.os.AtomicFile; +import com.android.internal.os.BackgroundThread; +import com.android.internal.util.FastXmlSerializer; +import com.android.internal.util.XmlUtils; +import com.android.server.am.BatteryStatsService; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; + +/** + * Keeps track of device idleness and drives low power mode based on that. + */ +public class DeviceIdleController extends SystemService { + private static final String TAG = "DeviceIdleController"; + + public static final String SERVICE_NAME = "deviceidle"; + + private static final String ACTION_STEP_IDLE_STATE = + "com.android.server.device_idle.STEP_IDLE_STATE"; + + // TODO: These need to be moved to system settings. + + /** + * This is the time, after becoming inactive, at which we start looking at the + * motion sensor to determine if the device is being left alone. We don't do this + * immediately after going inactive just because we don't want to be continually running + * the significant motion sensor whenever the screen is off. + */ + private static final long DEFAULT_INACTIVE_TIMEOUT = 30*60*1000L; + /** + * This is the time, after seeing motion, that we wait after becoming inactive from + * that until we start looking for motion again. + */ + private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT = 10*60*1000L; + /** + * This is the time, after the inactive timeout elapses, that we will wait looking + * for significant motion until we truly consider the device to be idle. + */ + private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT = 30*60*1000L; + /** + * This is the initial time, after being idle, that we will allow ourself to be back + * in the IDLE_PENDING state allowing the system to run normally until we return to idle. + */ + private static final long DEFAULT_IDLE_PENDING_TIMEOUT = 5*60*1000L; + /** + * Maximum pending idle timeout (time spent running) we will be allowed to use. + */ + private static final long DEFAULT_MAX_IDLE_PENDING_TIMEOUT = 10*60*1000L; + /** + * Scaling factor to apply to current pending idle timeout each time we cycle through + * that state. + */ + private static final float DEFAULT_IDLE_PENDING_FACTOR = 2f; + /** + * This is the initial time that we want to sit in the idle state before waking up + * again to return to pending idle and allowing normal work to run. + */ + private static final long DEFAULT_IDLE_TIMEOUT = 60*60*1000L; + /** + * Maximum idle duration we will be allowed to use. + */ + private static final long DEFAULT_MAX_IDLE_TIMEOUT = 6*60*60*1000L; + /** + * Scaling factor to apply to current idle timeout each time we cycle through that state. + */ + private static final float DEFAULT_IDLE_FACTOR = 2f; + /** + * This is the minimum time we will allow until the next upcoming alarm for us to + * actually go in to idle mode. + */ + private static final long DEFAULT_MIN_TIME_TO_ALARM = 60*60*1000L; + + private AlarmManager mAlarmManager; + private IBatteryStats mBatteryStats; + private PowerManagerInternal mLocalPowerManager; + private INetworkPolicyManager mNetworkPolicyManager; + private DisplayManager mDisplayManager; + private SensorManager mSensorManager; + private Sensor mSigMotionSensor; + private PendingIntent mAlarmIntent; + private Intent mIdleIntent; + private Display mCurDisplay; + private boolean mScreenOn; + private boolean mCharging; + private boolean mSigMotionActive; + + /** Device is currently active. */ + private static final int STATE_ACTIVE = 0; + /** Device is inactve (screen off, no motion) and we are waiting to for idle. */ + private static final int STATE_INACTIVE = 1; + /** Device is past the initial inactive period, and waiting for the next idle period. */ + private static final int STATE_IDLE_PENDING = 2; + /** Device is in the idle state, trying to stay asleep as much as possible. */ + private static final int STATE_IDLE = 3; + /** Device is in the idle state, but temporarily out of idle to do regular maintenance. */ + private static final int STATE_IDLE_MAINTENANCE = 4; + private static String stateToString(int state) { + switch (state) { + case STATE_ACTIVE: return "ACTIVE"; + case STATE_INACTIVE: return "INACTIVE"; + case STATE_IDLE_PENDING: return "IDLE_PENDING"; + case STATE_IDLE: return "IDLE"; + case STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE"; + default: return Integer.toString(state); + } + } + + private int mState; + + private long mInactiveTimeout; + private long mNextAlarmTime; + private long mNextIdlePendingDelay; + private long mNextIdleDelay; + + public final AtomicFile mConfigFile; + + /** + * Package names the system has white-listed to opt out of power save restrictions. + */ + private final ArrayMap<String, Integer> mPowerSaveWhitelistApps = new ArrayMap<>(); + + /** + * Package names the user has white-listed to opt out of power save restrictions. + */ + private final ArrayMap<String, Integer> mPowerSaveWhitelistUserApps = new ArrayMap<>(); + + /** + * UIDs that have been white-listed to opt out of power save restrictions. + */ + private final SparseBooleanArray mPowerSaveWhitelistAppIds = new SparseBooleanArray(); + + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override public void onReceive(Context context, Intent intent) { + if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) { + int plugged = intent.getIntExtra("plugged", 0); + updateChargingLocked(plugged != 0); + } else if (ACTION_STEP_IDLE_STATE.equals(intent.getAction())) { + synchronized (DeviceIdleController.this) { + stepIdleStateLocked(); + } + } + } + }; + + private final DisplayManager.DisplayListener mDisplayListener + = new DisplayManager.DisplayListener() { + @Override public void onDisplayAdded(int displayId) { + } + + @Override public void onDisplayRemoved(int displayId) { + } + + @Override public void onDisplayChanged(int displayId) { + if (displayId == Display.DEFAULT_DISPLAY) { + synchronized (DeviceIdleController.this) { + updateDisplayLocked(); + } + } + } + }; + + private final TriggerEventListener mSigMotionListener = new TriggerEventListener() { + @Override public void onTrigger(TriggerEvent event) { + synchronized (DeviceIdleController.this) { + significantMotionLocked(); + } + } + }; + + static final int MSG_WRITE_CONFIG = 1; + static final int MSG_REPORT_IDLE_ON = 2; + static final int MSG_REPORT_IDLE_OFF = 3; + static final int MSG_REPORT_ACTIVE = 4; + + final class MyHandler extends Handler { + MyHandler(Looper looper) { + super(looper); + } + + @Override public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_WRITE_CONFIG: { + handleWriteConfigFile(); + } break; + case MSG_REPORT_IDLE_ON: { + mLocalPowerManager.setDeviceIdleMode(true); + try { + mNetworkPolicyManager.setDeviceIdleMode(true); + mBatteryStats.noteDeviceIdleMode(true, false, false); + } catch (RemoteException e) { + } + getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); + } break; + case MSG_REPORT_IDLE_OFF: { + mLocalPowerManager.setDeviceIdleMode(false); + try { + mNetworkPolicyManager.setDeviceIdleMode(false); + mBatteryStats.noteDeviceIdleMode(false, false, false); + } catch (RemoteException e) { + } + getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); + } break; + case MSG_REPORT_ACTIVE: { + boolean fromMotion = msg.arg1 != 0; + boolean needBroadcast = msg.arg2 != 0; + mLocalPowerManager.setDeviceIdleMode(false); + try { + mNetworkPolicyManager.setDeviceIdleMode(false); + mBatteryStats.noteDeviceIdleMode(false, !fromMotion, fromMotion); + } catch (RemoteException e) { + } + if (needBroadcast) { + getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); + } + } break; + } + } + } + + final MyHandler mHandler; + + private final class BinderService extends IDeviceIdleController.Stub { + @Override public void addPowerSaveWhitelistApp(String name) { + getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, + null); + addPowerSaveWhitelistAppInternal(name); + } + + @Override public void removePowerSaveWhitelistApp(String name) { + getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, + null); + removePowerSaveWhitelistAppInternal(name); + } + + @Override public String[] getSystemPowerWhitelist() { + return getSystemPowerWhitelistInternal(); + } + + @Override public String[] getFullPowerWhitelist() { + return getFullPowerWhitelistInternal(); + } + + @Override public int[] getAppIdWhitelist() { + return getAppIdWhitelistInternal(); + } + + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + DeviceIdleController.this.dump(fd, pw, args); + } + } + + public DeviceIdleController(Context context) { + super(context); + mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml")); + mHandler = new MyHandler(BackgroundThread.getHandler().getLooper()); + } + + private static File getSystemDir() { + return new File(Environment.getDataDirectory(), "system"); + } + + @Override + public void onStart() { + final PackageManager pm = getContext().getPackageManager(); + + synchronized (this) { + SystemConfig sysConfig = SystemConfig.getInstance(); + ArraySet<String> allowPower = sysConfig.getAllowInPowerSave(); + for (int i=0; i<allowPower.size(); i++) { + String pkg = allowPower.valueAt(i); + try { + ApplicationInfo ai = pm.getApplicationInfo(pkg, 0); + if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) { + mPowerSaveWhitelistApps.put(ai.packageName, + UserHandle.getAppId(ai.uid)); + } + } catch (PackageManager.NameNotFoundException e) { + } + } + + readConfigFileLocked(); + updateWhitelistAppIdsLocked(); + + mScreenOn = true; + // Start out assuming we are charging. If we aren't, we will at least get + // a battery update the next time the level drops. + mCharging = true; + mState = STATE_ACTIVE; + mInactiveTimeout = DEFAULT_INACTIVE_TIMEOUT; + } + + publishBinderService(SERVICE_NAME, new BinderService()); + } + + @Override + public void onBootPhase(int phase) { + if (phase == PHASE_SYSTEM_SERVICES_READY) { + synchronized (this) { + mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE); + mBatteryStats = BatteryStatsService.getService(); + mLocalPowerManager = getLocalService(PowerManagerInternal.class); + mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface( + ServiceManager.getService(Context.NETWORK_POLICY_SERVICE)); + mDisplayManager = (DisplayManager) getContext().getSystemService( + Context.DISPLAY_SERVICE); + mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE); + mSigMotionSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION); + + Intent intent = new Intent(ACTION_STEP_IDLE_STATE) + .setPackage("android") + .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + mAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0); + + mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); + mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_BATTERY_CHANGED); + filter.addAction(ACTION_STEP_IDLE_STATE); + getContext().registerReceiver(mReceiver, filter); + + mDisplayManager.registerDisplayListener(mDisplayListener, null); + updateDisplayLocked(); + } + } + } + + public boolean addPowerSaveWhitelistAppInternal(String name) { + synchronized (this) { + try { + ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name, 0); + if (mPowerSaveWhitelistUserApps.put(name, UserHandle.getAppId(ai.uid)) == null) { + reportPowerSaveWhitelistChangedLocked(); + updateWhitelistAppIdsLocked(); + writeConfigFileLocked(); + } + return true; + } catch (PackageManager.NameNotFoundException e) { + return false; + } + } + } + + public boolean removePowerSaveWhitelistAppInternal(String name) { + synchronized (this) { + if (mPowerSaveWhitelistUserApps.remove(name) != null) { + reportPowerSaveWhitelistChangedLocked(); + updateWhitelistAppIdsLocked(); + writeConfigFileLocked(); + return true; + } + } + return false; + } + + public String[] getSystemPowerWhitelistInternal() { + synchronized (this) { + int size = mPowerSaveWhitelistApps.size(); + String[] apps = new String[size]; + for (int i = 0; i < mPowerSaveWhitelistApps.size(); i++) { + apps[i] = mPowerSaveWhitelistApps.keyAt(i); + } + return apps; + } + } + + public String[] getFullPowerWhitelistInternal() { + synchronized (this) { + int size = mPowerSaveWhitelistApps.size() + mPowerSaveWhitelistUserApps.size(); + String[] apps = new String[size]; + int cur = 0; + for (int i = 0; i < mPowerSaveWhitelistApps.size(); i++) { + apps[cur] = mPowerSaveWhitelistApps.keyAt(i); + cur++; + } + for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) { + apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i); + cur++; + } + return apps; + } + } + + public int[] getAppIdWhitelistInternal() { + synchronized (this) { + int size = mPowerSaveWhitelistAppIds.size(); + int[] appids = new int[size]; + for (int i = 0; i < size; i++) { + appids[i] = mPowerSaveWhitelistAppIds.keyAt(i); + } + return appids; + } + } + + void updateDisplayLocked() { + mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); + // We consider any situation where the display is showing something to be it on, + // because if there is anything shown we are going to be updating it at some + // frequency so can't be allowed to go into deep sleeps. + boolean screenOn = mCurDisplay.getState() != Display.STATE_OFF;; + if (!screenOn && mScreenOn) { + mScreenOn = false; + becomeInactiveIfAppropriateLocked(); + } else if (screenOn) { + mScreenOn = true; + becomeActiveLocked("screen"); + } + } + + void updateChargingLocked(boolean charging) { + if (!charging && mCharging) { + mCharging = false; + becomeInactiveIfAppropriateLocked(); + } else if (charging) { + mCharging = charging; + becomeActiveLocked("charging"); + } + } + + void scheduleReportActiveLocked(boolean fromMotion) { + Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, fromMotion ? 1 : 0, + mState == STATE_IDLE ? 1 : 0); + mHandler.sendMessage(msg); + } + + void becomeActiveLocked(String reason) { + if (mState != STATE_ACTIVE) { + EventLogTags.writeDeviceIdle(STATE_ACTIVE, reason); + scheduleReportActiveLocked(false); + mState = STATE_ACTIVE; + mInactiveTimeout = DEFAULT_INACTIVE_TIMEOUT; + mNextIdlePendingDelay = 0; + mNextIdleDelay = 0; + cancelAlarmLocked(); + stopMonitoringSignificantMotion(); + } + } + + void becomeInactiveIfAppropriateLocked() { + if (!mScreenOn && !mCharging && mState == STATE_ACTIVE) { + // Screen has turned off; we are now going to become inactive and start + // waiting to see if we will ultimately go idle. + mState = STATE_INACTIVE; + mNextIdlePendingDelay = 0; + mNextIdleDelay = 0; + scheduleAlarmLocked(mInactiveTimeout, false); + EventLogTags.writeDeviceIdle(mState, "no activity"); + } + } + + void stepIdleStateLocked() { + EventLogTags.writeDeviceIdleStep(); + + final long now = SystemClock.elapsedRealtime(); + if ((now+DEFAULT_MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) { + // Whoops, there is an upcoming alarm. We don't actually want to go idle. + if (mState != STATE_ACTIVE) { + becomeActiveLocked("alarm"); + } + return; + } + + switch (mState) { + case STATE_INACTIVE: + // We have now been inactive long enough, it is time to start looking + // for significant motion and sleep some more while doing so. + startMonitoringSignificantMotion(); + scheduleAlarmLocked(DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT, false); + // Reset the upcoming idle delays. + mNextIdlePendingDelay = DEFAULT_IDLE_PENDING_TIMEOUT; + mNextIdleDelay = DEFAULT_IDLE_TIMEOUT; + mState = STATE_IDLE_PENDING; + EventLogTags.writeDeviceIdle(mState, "step"); + break; + case STATE_IDLE_PENDING: + case STATE_IDLE_MAINTENANCE: + // We have been waiting to become idle, and now it is time! This is the + // only case where we want to use a wakeup alarm, because we do want to + // drag the device out of its sleep state in this case to do the next + // scheduled work. + scheduleAlarmLocked(mNextIdleDelay, true); + mNextIdleDelay = (long)(mNextIdleDelay*DEFAULT_IDLE_FACTOR); + if (mNextIdleDelay > DEFAULT_MAX_IDLE_TIMEOUT) { + mNextIdleDelay = DEFAULT_MAX_IDLE_TIMEOUT; + } + mState = STATE_IDLE; + EventLogTags.writeDeviceIdle(mState, "step"); + mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON); + break; + case STATE_IDLE: + // We have been idling long enough, now it is time to do some work. + scheduleAlarmLocked(mNextIdlePendingDelay, false); + mNextIdlePendingDelay = (long)(mNextIdlePendingDelay*DEFAULT_IDLE_PENDING_FACTOR); + if (mNextIdlePendingDelay > DEFAULT_MAX_IDLE_PENDING_TIMEOUT) { + mNextIdlePendingDelay = DEFAULT_MAX_IDLE_PENDING_TIMEOUT; + } + mState = STATE_IDLE_MAINTENANCE; + EventLogTags.writeDeviceIdle(mState, "step"); + mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF); + break; + } + } + + void significantMotionLocked() { + // When the sensor goes off, its trigger is automatically removed. + mSigMotionActive = false; + // The device is not yet active, so we want to go back to the pending idle + // state to wait again for no motion. Note that we only monitor for significant + // motion after moving out of the inactive state, so no need to worry about that. + if (mState != STATE_ACTIVE) { + scheduleReportActiveLocked(true); + mState = STATE_ACTIVE; + mInactiveTimeout = DEFAULT_MOTION_INACTIVE_TIMEOUT; + EventLogTags.writeDeviceIdle(mState, "motion"); + becomeInactiveIfAppropriateLocked(); + } + } + + void startMonitoringSignificantMotion() { + if (mSigMotionSensor != null && !mSigMotionActive) { + mSensorManager.requestTriggerSensor(mSigMotionListener, mSigMotionSensor); + mSigMotionActive = true; + } + } + + void stopMonitoringSignificantMotion() { + if (mSigMotionActive) { + mSensorManager.cancelTriggerSensor(mSigMotionListener, mSigMotionSensor); + mSigMotionActive = false; + } + } + + void cancelAlarmLocked() { + if (mNextAlarmTime != 0) { + mNextAlarmTime = 0; + mAlarmManager.cancel(mAlarmIntent); + } + } + + void scheduleAlarmLocked(long delay, boolean idleUntil) { + if (mSigMotionSensor == null) { + // If there is no significant motion sensor on this device, then we won't schedule + // alarms, because we can't determine if the device is not moving. This effectively + // turns off normal exeuction of device idling, although it is still possible to + // manually poke it by pretending like the alarm is going off. + return; + } + mNextAlarmTime = SystemClock.elapsedRealtime() + delay; + if (idleUntil) { + mAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP, + mNextAlarmTime, mAlarmIntent); + } else { + mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, + mNextAlarmTime, mAlarmIntent); + } + } + + private void updateWhitelistAppIdsLocked() { + mPowerSaveWhitelistAppIds.clear(); + for (int i=0; i<mPowerSaveWhitelistApps.size(); i++) { + mPowerSaveWhitelistAppIds.put(mPowerSaveWhitelistApps.valueAt(i), true); + } + for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) { + mPowerSaveWhitelistAppIds.put(mPowerSaveWhitelistUserApps.valueAt(i), true); + } + } + + private void reportPowerSaveWhitelistChangedLocked() { + Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + getContext().sendBroadcast(intent); + } + + void readConfigFileLocked() { + Slog.d(TAG, "Reading config from " + mConfigFile.getBaseFile()); + mPowerSaveWhitelistUserApps.clear(); + FileInputStream stream; + try { + stream = mConfigFile.openRead(); + } catch (FileNotFoundException e) { + return; + } + try { + XmlPullParser parser = Xml.newPullParser(); + parser.setInput(stream, null); + readConfigFileLocked(parser); + } catch (XmlPullParserException e) { + } finally { + try { + stream.close(); + } catch (IOException e) { + } + } + + } + + private void readConfigFileLocked(XmlPullParser parser) { + final PackageManager pm = getContext().getPackageManager(); + + try { + int type; + while ((type = parser.next()) != XmlPullParser.START_TAG + && type != XmlPullParser.END_DOCUMENT) { + ; + } + + if (type != XmlPullParser.START_TAG) { + throw new IllegalStateException("no start tag found"); + } + + int outerDepth = parser.getDepth(); + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + String tagName = parser.getName(); + if (tagName.equals("wl")) { + String name = parser.getAttributeValue(null, "n"); + if (name != null) { + try { + ApplicationInfo ai = pm.getApplicationInfo(name, 0); + mPowerSaveWhitelistUserApps.put(ai.packageName, + UserHandle.getAppId(ai.uid)); + } catch (PackageManager.NameNotFoundException e) { + } + } + } else { + Slog.w(TAG, "Unknown element under <config>: " + + parser.getName()); + XmlUtils.skipCurrentTag(parser); + } + } + + } catch (IllegalStateException e) { + Slog.w(TAG, "Failed parsing config " + e); + } catch (NullPointerException e) { + Slog.w(TAG, "Failed parsing config " + e); + } catch (NumberFormatException e) { + Slog.w(TAG, "Failed parsing config " + e); + } catch (XmlPullParserException e) { + Slog.w(TAG, "Failed parsing config " + e); + } catch (IOException e) { + Slog.w(TAG, "Failed parsing config " + e); + } catch (IndexOutOfBoundsException e) { + Slog.w(TAG, "Failed parsing config " + e); + } + } + + void writeConfigFileLocked() { + mHandler.removeMessages(MSG_WRITE_CONFIG); + mHandler.sendEmptyMessageDelayed(MSG_WRITE_CONFIG, 5000); + } + + void handleWriteConfigFile() { + final ByteArrayOutputStream memStream = new ByteArrayOutputStream(); + + try { + synchronized (this) { + XmlSerializer out = new FastXmlSerializer(); + out.setOutput(memStream, "utf-8"); + writeConfigFileLocked(out); + } + } catch (IOException e) { + } + + synchronized (mConfigFile) { + FileOutputStream stream = null; + try { + stream = mConfigFile.startWrite(); + memStream.writeTo(stream); + stream.flush(); + FileUtils.sync(stream); + stream.close(); + mConfigFile.finishWrite(stream); + } catch (IOException e) { + Slog.w(TAG, "Error writing config file", e); + mConfigFile.failWrite(stream); + } + } + } + + void writeConfigFileLocked(XmlSerializer out) throws IOException { + out.startDocument(null, true); + out.startTag(null, "config"); + for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) { + String name = mPowerSaveWhitelistUserApps.keyAt(i); + out.startTag(null, "wl"); + out.attribute(null, "n", name); + out.endTag(null, "wl"); + } + out.endTag(null, "config"); + out.endDocument(); + } + + private void dumpHelp(PrintWriter pw) { + pw.println("Device idle controller (deviceidle) dump options:"); + pw.println(" [-h] [CMD]"); + pw.println(" -h: print this help text."); + pw.println("Commands:"); + pw.println(" step"); + pw.println(" Immediately step to next state, without waiting for alarm."); + pw.println(" whitelist"); + pw.println(" Add (prefix with +) or remove (prefix with -) packages."); + } + + void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump DeviceIdleController from from pid=" + + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() + + " without permission " + android.Manifest.permission.DUMP); + return; + } + + if (args != null) { + for (int i=0; i<args.length; i++) { + String arg = args[i]; + if ("-h".equals(arg)) { + dumpHelp(pw); + return; + } else if ("step".equals(arg)) { + synchronized (this) { + stepIdleStateLocked(); + pw.print("Stepped to: "); pw.println(stateToString(mState)); + } + return; + } else if ("whitelist".equals(arg)) { + i++; + while (i < args.length) { + arg = args[i]; + i++; + if (arg.length() < 1 || (arg.charAt(0) != '-' + && arg.charAt(0) != '+')) { + pw.println("Package must be prefixed with + or -: " + arg); + return; + } + char op = arg.charAt(0); + String pkg = arg.substring(1); + if (op == '+') { + if (addPowerSaveWhitelistAppInternal(pkg)) { + pw.println("Added: " + pkg); + } else { + pw.println("Unknown package: " + pkg); + } + } else { + if (removePowerSaveWhitelistAppInternal(pkg)) { + pw.println("Removed: " + pkg); + } + } + } + return; + } else if (arg.length() > 0 && arg.charAt(0) == '-'){ + pw.println("Unknown option: " + arg); + return; + } else { + pw.println("Unknown command: " + arg); + return; + } + } + } + + synchronized (this) { + int size = mPowerSaveWhitelistApps.size(); + if (size > 0) { + pw.println(" Whitelist system apps:"); + for (int i = 0; i < size; i++) { + pw.print(" "); + pw.println(mPowerSaveWhitelistApps.keyAt(i)); + } + } + size = mPowerSaveWhitelistUserApps.size(); + if (size > 0) { + pw.println(" Whitelist user apps:"); + for (int i = 0; i < size; i++) { + pw.print(" "); + pw.println(mPowerSaveWhitelistUserApps.keyAt(i)); + } + } + size = mPowerSaveWhitelistAppIds.size(); + if (size > 0) { + pw.println(" Whitelist app uids:"); + for (int i = 0; i < size; i++) { + pw.print(" UID="); + pw.print(mPowerSaveWhitelistAppIds.keyAt(i)); + pw.print(": "); + pw.print(mPowerSaveWhitelistAppIds.valueAt(i)); + pw.println(); + } + } + pw.print(" mSigMotionSensor="); pw.println(mSigMotionSensor); + pw.print(" mCurDisplay="); pw.println(mCurDisplay); + pw.print(" mScreenOn="); pw.println(mScreenOn); + pw.print(" mCharging="); pw.println(mCharging); + pw.print(" mSigMotionActive="); pw.println(mSigMotionActive); + pw.print(" mState="); pw.println(stateToString(mState)); + pw.print(" mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw); + pw.println(); + if (mNextAlarmTime != 0) { + pw.print(" mNextAlarmTime="); + TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw); + pw.println(); + } + if (mNextIdlePendingDelay != 0) { + pw.print(" mNextIdlePendingDelay="); + TimeUtils.formatDuration(mNextIdlePendingDelay, pw); + pw.println(); + } + if (mNextIdleDelay != 0) { + pw.print(" mNextIdleDelay="); + TimeUtils.formatDuration(mNextIdleDelay, pw); + pw.println(); + } + } + } +} diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index b5b62b4..f6998ca 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -43,6 +43,7 @@ import android.net.InterfaceConfiguration; import android.net.IpPrefix; import android.net.LinkAddress; import android.net.Network; +import android.net.NetworkPolicyManager; import android.net.NetworkStats; import android.net.NetworkUtils; import android.net.RouteInfo; @@ -107,8 +108,8 @@ import java.util.concurrent.CountDownLatch; */ public class NetworkManagementService extends INetworkManagementService.Stub implements Watchdog.Monitor { - private static final String TAG = "NetworkManagementService"; - private static final boolean DBG = false; + private static final String TAG = "NetworkManagement"; + private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); private static final String NETD_TAG = "NetdConnector"; private static final String NETD_SOCKET_NAME = "netd"; @@ -188,6 +189,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub /** Set of UIDs with cleartext penalties. */ @GuardedBy("mQuotaLock") private SparseIntArray mUidCleartextPolicy = new SparseIntArray(); + /** Set of UIDs that are to be blocked/allowed by firewall controller. */ + @GuardedBy("mQuotaLock") + private SparseIntArray mUidFirewallRules = new SparseIntArray(); private Object mIdleTimerLock = new Object(); /** Set of interfaces with active idle timers. */ @@ -563,10 +567,19 @@ public class NetworkManagementService extends INetworkManagementService.Stub setUidCleartextNetworkPolicy(local.keyAt(i), local.valueAt(i)); } } - } - // TODO: Push any existing firewall state - setFirewallEnabled(mFirewallEnabled || LockdownVpnTracker.isEnabled()); + setFirewallEnabled(mFirewallEnabled || LockdownVpnTracker.isEnabled()); + + size = mUidFirewallRules.size(); + if (size > 0) { + Slog.d(TAG, "Pushing " + size + " active firewall UID rules"); + final SparseIntArray uidFirewallRules = mUidFirewallRules; + mUidFirewallRules = new SparseIntArray(); + for (int i = 0; i < uidFirewallRules.size(); i++) { + setFirewallUidRule(uidFirewallRules.keyAt(i), uidFirewallRules.valueAt(i)); + } + } + } } /** @@ -1899,7 +1912,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub public void setFirewallEnabled(boolean enabled) { enforceSystemUid(); try { - mConnector.execute("firewall", enabled ? "enable" : "disable"); + mConnector.execute("firewall", "enable", enabled ? "whitelist" : "blacklist"); mFirewallEnabled = enabled; } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); @@ -1949,14 +1962,48 @@ public class NetworkManagementService extends INetworkManagementService.Stub } @Override - public void setFirewallUidRule(int uid, boolean allow) { + public void setFirewallUidRule(int uid, int rule) { enforceSystemUid(); - Preconditions.checkState(mFirewallEnabled); - final String rule = allow ? "allow" : "deny"; - try { - mConnector.execute("firewall", "set_uid_rule", uid, rule); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); + if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) { + Preconditions.checkState(mFirewallEnabled); + } + synchronized (mQuotaLock) { + final int oldUidFirewallRule = mUidFirewallRules.get(uid); + if (DBG) { + Slog.d(TAG, "oldRule = " + oldUidFirewallRule + + ", newRule=" + rule + " for uid=" + uid); + } + if (oldUidFirewallRule == rule) { + if (DBG) Slog.d(TAG, "!!!!! Skipping change"); + // TODO: eventually consider throwing + return; + } + + try { + String ruleName; + if (isFirewallEnabled()) { // Whitelist mode + if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) { + ruleName = "allow"; + } else { + ruleName = "deny"; + } + } else { // Blacklist mode + if (rule == NetworkPolicyManager.FIREWALL_RULE_DENY) { + ruleName = "deny"; + } else { + ruleName = "allow"; + } + } + + if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) { + mUidFirewallRules.delete(uid); + } else { + mUidFirewallRules.put(uid, rule); + } + mConnector.execute("firewall", "set_uid_rule", uid, ruleName); + } catch (NativeDaemonConnectorException e) { + throw e.rethrowAsParcelableException(); + } } } @@ -2072,6 +2119,18 @@ public class NetworkManagementService extends INetworkManagementService.Stub pw.println("]"); } + synchronized (mUidFirewallRules) { + pw.print("UID firewall rule: ["); + final int size = mUidFirewallRules.size(); + for (int i = 0; i < size; i++) { + pw.print(mUidFirewallRules.keyAt(i)); + pw.print(":"); + pw.print(mUidFirewallRules.valueAt(i)); + if (i < size - 1) pw.print(","); + } + pw.println("]"); + } + synchronized (mIdleTimerLock) { pw.println("Idle timers:"); for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) { diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index ac2f5b0..62f168d 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -2771,26 +2771,10 @@ public class AccountManagerService mAccountName, mAccountType }); } - result.putLong(AccountManager.KEY_LAST_AUTHENTICATE_TIME_MILLIS_EPOCH, + result.putLong(AccountManager.KEY_LAST_AUTHENTICATED_TIME, lastAuthenticatedTime); } } - if (mAuthDetailsRequired) { - long lastAuthenticatedTime = -1; - if (isAccountPresentForCaller(mAccountName, mAccountType)) { - lastAuthenticatedTime = DatabaseUtils.longForQuery( - mAccounts.openHelper.getReadableDatabase(), - "select " + ACCOUNTS_LAST_AUTHENTICATE_TIME_EPOCH_MILLIS + " from " - + - TABLE_ACCOUNTS + " WHERE " + ACCOUNTS_NAME + "=? AND " - + ACCOUNTS_TYPE + "=?", - new String[] { - mAccountName, mAccountType - }); - } - result.putLong(AccountManager.KEY_LAST_AUTHENTICATE_TIME_MILLIS_EPOCH, - lastAuthenticatedTime); - } } if (result != null && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 15d7367..25a98c0 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -699,12 +699,10 @@ public final class ActivityManagerService extends ActivityManagerNative private final StringBuilder mStrictModeBuffer = new StringBuilder(); /** - * Keeps track of all IIntentReceivers that have been registered for - * broadcasts. Hash keys are the receiver IBinder, hash value is - * a ReceiverList. + * Keeps track of all IIntentReceivers that have been registered for broadcasts. + * Hash keys are the receiver IBinder, hash value is a ReceiverList. */ - final HashMap<IBinder, ReceiverList> mRegisteredReceivers = - new HashMap<IBinder, ReceiverList>(); + final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>(); /** * Resolver for broadcast intents to registered receivers. @@ -716,7 +714,7 @@ public final class ActivityManagerService extends ActivityManagerNative protected boolean allowFilterResult( BroadcastFilter filter, List<BroadcastFilter> dest) { IBinder target = filter.receiverList.receiver.asBinder(); - for (int i=dest.size()-1; i>=0; i--) { + for (int i = dest.size() - 1; i >= 0; i--) { if (dest.get(i).receiverList.receiver.asBinder() == target) { return false; } @@ -6603,6 +6601,12 @@ public final class ActivityManagerService extends ActivityManagerNative return mActivityManagerService.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_GRANTED; } + + @Override + public String[] getPackagesForUid(int uid) { + return mActivityManagerService.mContext.getPackageManager() + .getPackagesForUid(uid); + } } class IntentFirewallInterface implements IntentFirewall.AMSInterface { @@ -15656,8 +15660,7 @@ public final class ActivityManagerService extends ActivityManagerNative // Original caller already died return null; } - ReceiverList rl - = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder()); + ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder()); if (rl == null) { rl = new ReceiverList(this, callerApp, callingPid, callingUid, userId, receiver); @@ -15689,7 +15692,7 @@ public final class ActivityManagerService extends ActivityManagerNative permission, callingUid, userId); rl.add(bf); if (!bf.debugCheck()) { - Slog.w(TAG, "==> For Dynamic broadast"); + Slog.w(TAG, "==> For Dynamic broadcast"); } mReceiverResolver.addFilter(bf); @@ -15699,9 +15702,9 @@ public final class ActivityManagerService extends ActivityManagerNative ArrayList receivers = new ArrayList(); receivers.add(bf); - int N = allSticky.size(); - for (int i=0; i<N; i++) { - Intent intent = (Intent)allSticky.get(i); + final int stickyCount = allSticky.size(); + for (int i = 0; i < stickyCount; i++) { + Intent intent = allSticky.get(i); BroadcastQueue queue = broadcastQueueForIntent(intent); BroadcastRecord r = new BroadcastRecord(queue, intent, null, null, -1, -1, null, null, AppOpsManager.OP_NONE, receivers, null, 0, @@ -15761,8 +15764,7 @@ public final class ActivityManagerService extends ActivityManagerNative void removeReceiverLocked(ReceiverList rl) { mRegisteredReceivers.remove(rl.receiver.asBinder()); - int N = rl.size(); - for (int i=0; i<N; i++) { + for (int i = rl.size() - 1; i >= 0; i--) { mReceiverResolver.removeFilter(rl.get(i)); } } @@ -16133,24 +16135,24 @@ public final class ActivityManagerService extends ActivityManagerNative } ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId); if (stickies == null) { - stickies = new ArrayMap<String, ArrayList<Intent>>(); + stickies = new ArrayMap<>(); mStickyBroadcasts.put(userId, stickies); } ArrayList<Intent> list = stickies.get(intent.getAction()); if (list == null) { - list = new ArrayList<Intent>(); + list = new ArrayList<>(); stickies.put(intent.getAction(), list); } - int N = list.size(); + final int stickiesCount = list.size(); int i; - for (i=0; i<N; i++) { + for (i = 0; i < stickiesCount; i++) { if (intent.filterEquals(list.get(i))) { // This sticky already exists, replace it. list.set(i, new Intent(intent)); break; } } - if (i >= N) { + if (i >= stickiesCount) { list.add(new Intent(intent)); } } diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index a91a7ca..e5c5dff 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -309,7 +309,6 @@ public final class BroadcastQueue { } public void skipCurrentReceiverLocked(ProcessRecord app) { - boolean reschedule = false; BroadcastRecord r = app.curReceiver; if (r != null && r.queue == this) { // The current broadcast is waiting for this app's receiver @@ -318,7 +317,6 @@ public final class BroadcastQueue { logBroadcastReceiverDiscardLocked(r); finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, false); - reschedule = true; } if (r == null && mPendingBroadcast != null && mPendingBroadcast.curApp == app) { if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, diff --git a/services/core/java/com/android/server/display/WifiDisplayController.java b/services/core/java/com/android/server/display/WifiDisplayController.java index 31c1eea..8932ca0 100644 --- a/services/core/java/com/android/server/display/WifiDisplayController.java +++ b/services/core/java/com/android/server/display/WifiDisplayController.java @@ -775,7 +775,7 @@ final class WifiDisplayController implements DumpUtils.Dump { handleConnectionFailure(false); } } - }, mHandler); + }, mHandler, mContext.getOpPackageName()); // Use extended timeout value for certification, as some tests require user inputs int rtspTimeout = mWifiDisplayCertMode ? diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java index d3240ec..6bd646d 100644 --- a/services/core/java/com/android/server/location/GpsLocationProvider.java +++ b/services/core/java/com/android/server/location/GpsLocationProvider.java @@ -952,13 +952,18 @@ public class GpsLocationProvider implements LocationProviderInterface { return GPS_POSITION_MODE_STANDALONE; } } + // MS-Based is the preferred mode for Assisted-GPS position computation, so we favor + // such mode when it is available + if (hasCapability(GPS_CAPABILITY_MSB) && (suplMode & AGPS_SUPL_MODE_MSB) != 0) { + return GPS_POSITION_MODE_MS_BASED; + } + // for now, just as the legacy code did, we fallback to MS-Assisted if it is available, + // do fallback only for single-shot requests, because it is too expensive to do for + // periodic requests as well if (singleShot && hasCapability(GPS_CAPABILITY_MSA) && (suplMode & AGPS_SUPL_MODE_MSA) != 0) { return GPS_POSITION_MODE_MS_ASSISTED; - } else if (hasCapability(GPS_CAPABILITY_MSB) - && (suplMode & AGPS_SUPL_MODE_MSB) != 0) { - return GPS_POSITION_MODE_MS_BASED; } } return GPS_POSITION_MODE_STANDALONE; diff --git a/services/core/java/com/android/server/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java index 6ffe6ac..0f88883 100644 --- a/services/core/java/com/android/server/net/LockdownVpnTracker.java +++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java @@ -17,6 +17,8 @@ package com.android.server.net; import static android.Manifest.permission.CONNECTIVITY_INTERNAL; +import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW; +import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT; import android.app.Notification; import android.app.NotificationManager; @@ -31,6 +33,7 @@ import android.net.LinkAddress; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.NetworkInfo.State; +import android.net.NetworkPolicyManager; import android.os.INetworkManagementService; import android.os.RemoteException; import android.security.Credentials; @@ -198,8 +201,8 @@ public class LockdownVpnTracker { setFirewallEgressSourceRule(addr, true); } - mNetService.setFirewallUidRule(ROOT_UID, true); - mNetService.setFirewallUidRule(Os.getuid(), true); + mNetService.setFirewallUidRule(ROOT_UID, FIREWALL_RULE_ALLOW); + mNetService.setFirewallUidRule(Os.getuid(), FIREWALL_RULE_ALLOW); mErrorCount = 0; mAcceptedIface = iface; @@ -288,8 +291,8 @@ public class LockdownVpnTracker { setFirewallEgressSourceRule(addr, false); } - mNetService.setFirewallUidRule(ROOT_UID, false); - mNetService.setFirewallUidRule(Os.getuid(), false); + mNetService.setFirewallUidRule(ROOT_UID, FIREWALL_RULE_DEFAULT); + mNetService.setFirewallUidRule(Os.getuid(), FIREWALL_RULE_DEFAULT); mAcceptedSourceAddr = null; } diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index 818f0aa..57df1c3 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -36,11 +36,14 @@ import static android.net.NetworkPolicy.LIMIT_DISABLED; import static android.net.NetworkPolicy.SNOOZE_NEVER; import static android.net.NetworkPolicy.WARNING_DISABLED; import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE; +import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY; +import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT; import static android.net.NetworkPolicyManager.POLICY_ALLOW_BACKGROUND_BATTERY_SAVE; import static android.net.NetworkPolicyManager.POLICY_NONE; import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL; import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; +import static android.net.NetworkPolicyManager.RULE_REJECT_ALL; import static android.net.NetworkPolicyManager.computeLastCycleBoundary; import static android.net.NetworkPolicyManager.dumpPolicy; import static android.net.NetworkPolicyManager.dumpRules; @@ -80,6 +83,8 @@ import android.app.INotificationManager; import android.app.IProcessObserver; import android.app.Notification; import android.app.PendingIntent; +import android.app.usage.UsageStatsManagerInternal; +import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; @@ -88,6 +93,7 @@ import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.UserInfo; import android.content.res.Resources; import android.net.ConnectivityManager; @@ -110,13 +116,16 @@ import android.os.Binder; import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; +import android.os.IDeviceIdleController; import android.os.INetworkManagementService; import android.os.IPowerManager; import android.os.Message; import android.os.MessageQueue.IdleHandler; +import android.os.PowerManager; import android.os.PowerManagerInternal; import android.os.RemoteCallbackList; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; @@ -137,7 +146,6 @@ import android.util.SparseIntArray; import android.util.TrustedTime; import android.util.Xml; -import com.android.server.AppOpsService; import libcore.io.IoUtils; import com.android.internal.R; @@ -145,6 +153,8 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.IndentingPrintWriter; +import com.android.server.AppOpsService; +import com.android.server.DeviceIdleController; import com.android.server.LocalServices; import com.android.server.SystemConfig; import com.google.android.collect.Lists; @@ -172,7 +182,8 @@ import java.util.List; * and delivers to listeners, such as {@link ConnectivityManager}, for * enforcement. */ -public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { +public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub + implements AppIdleStateChangeListener { private static final String TAG = "NetworkPolicy"; private static final boolean LOGD = false; private static final boolean LOGV = false; @@ -240,11 +251,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private final IPowerManager mPowerManager; private final INetworkStatsService mNetworkStats; private final INetworkManagementService mNetworkManager; + private UsageStatsManagerInternal mUsageStats; private final TrustedTime mTime; private IConnectivityManager mConnManager; private INotificationManager mNotifManager; private PowerManagerInternal mPowerManagerInternal; + private IDeviceIdleController mDeviceIdleController; final Object mRulesLock = new Object(); @@ -321,6 +334,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mPowerManager = checkNotNull(powerManager, "missing powerManager"); mNetworkStats = checkNotNull(networkStats, "missing networkStats"); mNetworkManager = checkNotNull(networkManagement, "missing networkManagement"); + mDeviceIdleController = IDeviceIdleController.Stub.asInterface(ServiceManager.getService( + DeviceIdleController.SERVICE_NAME)); mTime = checkNotNull(time, "missing TrustedTime"); HandlerThread thread = new HandlerThread(TAG); @@ -342,28 +357,31 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mNotifManager = checkNotNull(notifManager, "missing INotificationManager"); } + void updatePowerSaveWhitelistLocked() { + try { + final int[] whitelist = mDeviceIdleController.getAppIdWhitelist(); + mPowerSaveWhitelistAppIds.clear(); + if (whitelist != null) { + for (int uid : whitelist) { + mPowerSaveWhitelistAppIds.put(uid, true); + } + } + } catch (RemoteException e) { + } + } + public void systemReady() { if (!isBandwidthControlEnabled()) { Slog.w(TAG, "bandwidth controls disabled, unable to enforce policy"); return; } + mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class); + final PackageManager pm = mContext.getPackageManager(); synchronized (mRulesLock) { - SystemConfig sysConfig = SystemConfig.getInstance(); - ArraySet<String> allowPower = sysConfig.getAllowInPowerSave(); - for (int i=0; i<allowPower.size(); i++) { - String pkg = allowPower.valueAt(i); - try { - ApplicationInfo ai = pm.getApplicationInfo(pkg, 0); - if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) { - mPowerSaveWhitelistAppIds.put(UserHandle.getAppId(ai.uid), true); - } - } catch (PackageManager.NameNotFoundException e) { - } - } - + updatePowerSaveWhitelistLocked(); mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); mPowerManagerInternal.registerLowPowerModeObserver( new PowerManagerInternal.LowPowerModeListener() { @@ -406,6 +424,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { screenFilter.addAction(Intent.ACTION_SCREEN_OFF); mContext.registerReceiver(mScreenReceiver, screenFilter); + // listen for changes to power save whitelist + final IntentFilter whitelistFilter = new IntentFilter( + PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED); + mContext.registerReceiver(mPowerSaveWhitelistReceiver, whitelistFilter, null, mHandler); + // watch for network interfaces to be claimed final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION); mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler); @@ -449,6 +472,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { WifiManager.NETWORK_STATE_CHANGED_ACTION); mContext.registerReceiver(mWifiStateReceiver, wifiStateFilter, null, mHandler); + mUsageStats.addAppIdleStateChangeListener(this); + } private IProcessObserver mProcessObserver = new IProcessObserver.Stub() { @@ -489,6 +514,17 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } }; + private BroadcastReceiver mPowerSaveWhitelistReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + // on background handler thread, and POWER_SAVE_WHITELIST_CHANGED is protected + synchronized (mRulesLock) { + updatePowerSaveWhitelistLocked(); + updateRulesForGlobalChangeLocked(false); + } + } + }; + private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -546,12 +582,17 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); if (userId == -1) return; - synchronized (mRulesLock) { - // Remove any policies for given user; both cleaning up after a - // USER_REMOVED, and one last sanity check during USER_ADDED - removePoliciesForUserLocked(userId); - // Update global restrict for new user - updateRulesForGlobalChangeLocked(true); + switch (action) { + case ACTION_USER_REMOVED: + case ACTION_USER_ADDED: + synchronized (mRulesLock) { + // Remove any policies for given user; both cleaning up after a + // USER_REMOVED, and one last sanity check during USER_ADDED + removePoliciesForUserLocked(userId); + // Update global restrict for new user + updateRulesForGlobalChangeLocked(true); + } + break; } } }; @@ -1528,20 +1569,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { return uids; } - @Override - public int[] getPowerSaveAppIdWhitelist() { - mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); - - synchronized (mRulesLock) { - int size = mPowerSaveWhitelistAppIds.size(); - int[] appids = new int[size]; - for (int i = 0; i < size; i++) { - appids[i] = mPowerSaveWhitelistAppIds.keyAt(i); - } - return appids; - } - } - /** * Remove any policies associated with given {@link UserHandle}, persisting * if any changes are made. @@ -2032,6 +2059,22 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { return false; } + private boolean isUidIdle(int uid) { + final String[] packages = mContext.getPackageManager().getPackagesForUid(uid); + final int userId = UserHandle.getUserId(uid); + + for (String packageName : packages) { + if (!mUsageStats.isAppIdle(packageName, userId)) { + return false; + } + } + return true; + } + + /** + * Applies network rules to bandwidth and firewall controllers based on uid policy. + * @param uid The uid for which to apply the latest policy + */ void updateRulesForUidLocked(int uid) { if (!isUidValidForRules(uid)) return; @@ -2048,10 +2091,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE); final boolean uidForeground = isUidForegroundLocked(uid); + final boolean uidIdle = isUidIdle(uid); // derive active rules based on policy and active state + int uidRules = RULE_ALLOW_ALL; - if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) { + if (uidIdle && !mPowerSaveWhitelistAppIds.get(UserHandle.getAppId(uid))) { + uidRules = RULE_REJECT_ALL; + } else if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) { // uid in background, and policy says to block metered data uidRules = RULE_REJECT_METERED; } else if (mRestrictBackground) { @@ -2070,7 +2117,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } - // TODO: only dispatch when rules actually change + final int oldRules = mUidRules.get(uid); if (uidRules == RULE_ALLOW_ALL) { mUidRules.delete(uid); @@ -2078,11 +2125,24 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mUidRules.put(uid, uidRules); } + // Update bandwidth rules if necessary + final boolean oldRejectMetered = (oldRules & RULE_REJECT_METERED) != 0; final boolean rejectMetered = (uidRules & RULE_REJECT_METERED) != 0; - setUidNetworkRules(uid, rejectMetered); + if (oldRejectMetered != rejectMetered) { + setUidNetworkRules(uid, rejectMetered); + } + + // Update firewall rules if necessary + final boolean oldFirewallReject = (oldRules & RULE_REJECT_ALL) != 0; + final boolean firewallReject = (uidRules & RULE_REJECT_ALL) != 0; + if (oldFirewallReject != firewallReject) { + setUidFirewallRules(uid, firewallReject); + } // dispatch changed rule to existing listeners - mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget(); + if (oldRules != uidRules) { + mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget(); + } try { // adjust stats accounting based on foreground status @@ -2092,6 +2152,18 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + @Override + public void onAppIdleStateChanged(String packageName, int userId, boolean idle) { + try { + int uid = mContext.getPackageManager().getPackageUid(packageName, userId); + synchronized (mRulesLock) { + updateRulesForUidLocked(uid); + } + } catch (NameNotFoundException nnfe) { + return; + } + } + private Handler.Callback mHandlerCallback = new Handler.Callback() { @Override public boolean handleMessage(Message msg) { @@ -2215,6 +2287,22 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + /** + * Add or remove a uid to the firewall blacklist for all network ifaces. + * @param uid + * @param rejectOnAll + */ + private void setUidFirewallRules(int uid, boolean rejectOnAll) { + try { + mNetworkManager.setFirewallUidRule(uid, + rejectOnAll ? FIREWALL_RULE_DENY : FIREWALL_RULE_DEFAULT); + } catch (IllegalStateException e) { + Log.wtf(TAG, "problem setting firewall uid rules", e); + } catch (RemoteException e) { + // ignored; service lives in system_server + } + } + private long getTotalBytes(NetworkTemplate template, long start, long end) { try { return mNetworkStats.getNetworkTotalBytes(template, start, end); diff --git a/services/core/java/com/android/server/power/DeviceIdleController.java b/services/core/java/com/android/server/power/DeviceIdleController.java deleted file mode 100644 index 6b29b9a..0000000 --- a/services/core/java/com/android/server/power/DeviceIdleController.java +++ /dev/null @@ -1,489 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.power; - -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.hardware.Sensor; -import android.hardware.SensorManager; -import android.hardware.TriggerEvent; -import android.hardware.TriggerEventListener; -import android.hardware.display.DisplayManager; -import android.net.INetworkPolicyManager; -import android.os.Binder; -import android.os.PowerManager; -import android.os.PowerManagerInternal; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.SystemClock; -import android.os.UserHandle; -import android.util.TimeUtils; -import android.view.Display; -import com.android.internal.app.IBatteryStats; -import com.android.server.SystemService; -import com.android.server.am.BatteryStatsService; -import com.android.server.EventLogTags; - -import java.io.FileDescriptor; -import java.io.PrintWriter; - -/** - * Keeps track of device idleness and drives low power mode based on that. - */ -public class DeviceIdleController extends SystemService { - private static final String TAG = "DeviceIdleController"; - - private static final String ACTION_STEP_IDLE_STATE = - "com.android.server.device_idle.STEP_IDLE_STATE"; - - // TODO: These need to be moved to system settings. - - /** - * This is the time, after becoming inactive, at which we start looking at the - * motion sensor to determine if the device is being left alone. We don't do this - * immediately after going inactive just because we don't want to be continually running - * the significant motion sensor whenever the screen is off. - */ - private static final long DEFAULT_INACTIVE_TIMEOUT = 30*60*1000L; - /** - * This is the time, after seeing motion, that we wait after becoming inactive from - * that until we start looking for motion again. - */ - private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT = 10*60*1000L; - /** - * This is the time, after the inactive timeout elapses, that we will wait looking - * for significant motion until we truly consider the device to be idle. - */ - private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT = 30*60*1000L; - /** - * This is the initial time, after being idle, that we will allow ourself to be back - * in the IDLE_PENDING state allowing the system to run normally until we return to idle. - */ - private static final long DEFAULT_IDLE_PENDING_TIMEOUT = 5*60*1000L; - /** - * Maximum pending idle timeout (time spent running) we will be allowed to use. - */ - private static final long DEFAULT_MAX_IDLE_PENDING_TIMEOUT = 10*60*1000L; - /** - * Scaling factor to apply to current pending idle timeout each time we cycle through - * that state. - */ - private static final float DEFAULT_IDLE_PENDING_FACTOR = 2f; - /** - * This is the initial time that we want to sit in the idle state before waking up - * again to return to pending idle and allowing normal work to run. - */ - private static final long DEFAULT_IDLE_TIMEOUT = 60*60*1000L; - /** - * Maximum idle duration we will be allowed to use. - */ - private static final long DEFAULT_MAX_IDLE_TIMEOUT = 6*60*60*1000L; - /** - * Scaling factor to apply to current idle timeout each time we cycle through that state. - */ - private static final float DEFAULT_IDLE_FACTOR = 2f; - /** - * This is the minimum time we will allow until the next upcoming alarm for us to - * actually go in to idle mode. - */ - private static final long DEFAULT_MIN_TIME_TO_ALARM = 60*60*1000L; - - private AlarmManager mAlarmManager; - private IBatteryStats mBatteryStats; - private PowerManagerInternal mLocalPowerManager; - private INetworkPolicyManager mNetworkPolicyManager; - private DisplayManager mDisplayManager; - private SensorManager mSensorManager; - private Sensor mSigMotionSensor; - private PendingIntent mAlarmIntent; - private Intent mIdleIntent; - private Display mCurDisplay; - private boolean mScreenOn; - private boolean mCharging; - private boolean mSigMotionActive; - - /** Device is currently active. */ - private static final int STATE_ACTIVE = 0; - /** Device is inactve (screen off, no motion) and we are waiting to for idle. */ - private static final int STATE_INACTIVE = 1; - /** Device is past the initial inactive period, and waiting for the next idle period. */ - private static final int STATE_IDLE_PENDING = 2; - /** Device is in the idle state, trying to stay asleep as much as possible. */ - private static final int STATE_IDLE = 3; - private static String stateToString(int state) { - switch (state) { - case STATE_ACTIVE: return "ACTIVE"; - case STATE_INACTIVE: return "INACTIVE"; - case STATE_IDLE_PENDING: return "IDLE_PENDING"; - case STATE_IDLE: return "IDLE"; - default: return Integer.toString(state); - } - } - - private int mState; - - private long mInactiveTimeout; - private long mNextAlarmTime; - private long mNextIdlePendingDelay; - private long mNextIdleDelay; - - private final Binder mBinder = new Binder() { - @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - DeviceIdleController.this.dump(fd, pw, args); - } - }; - - private final BroadcastReceiver mReceiver = new BroadcastReceiver() { - @Override public void onReceive(Context context, Intent intent) { - if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) { - int plugged = intent.getIntExtra("plugged", 0); - updateChargingLocked(plugged != 0); - } else if (ACTION_STEP_IDLE_STATE.equals(intent.getAction())) { - synchronized (DeviceIdleController.this) { - stepIdleStateLocked(); - } - } - } - }; - - private final DisplayManager.DisplayListener mDisplayListener - = new DisplayManager.DisplayListener() { - @Override public void onDisplayAdded(int displayId) { - } - - @Override public void onDisplayRemoved(int displayId) { - } - - @Override public void onDisplayChanged(int displayId) { - if (displayId == Display.DEFAULT_DISPLAY) { - synchronized (DeviceIdleController.this) { - updateDisplayLocked(); - } - } - } - }; - - private final TriggerEventListener mSigMotionListener = new TriggerEventListener() { - @Override public void onTrigger(TriggerEvent event) { - synchronized (DeviceIdleController.this) { - significantMotionLocked(); - } - } - }; - - public DeviceIdleController(Context context) { - super(context); - } - - @Override - public void onStart() { - synchronized (this) { - mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE); - mBatteryStats = BatteryStatsService.getService(); - mLocalPowerManager = getLocalService(PowerManagerInternal.class); - mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface( - ServiceManager.getService(Context.NETWORK_POLICY_SERVICE)); - mDisplayManager = (DisplayManager) getContext().getSystemService( - Context.DISPLAY_SERVICE); - mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE); - mSigMotionSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION); - - Intent intent = new Intent(ACTION_STEP_IDLE_STATE) - .setPackage("android") - .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - mAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0); - - mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); - mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - - IntentFilter filter = new IntentFilter(); - filter.addAction(Intent.ACTION_BATTERY_CHANGED); - filter.addAction(ACTION_STEP_IDLE_STATE); - getContext().registerReceiver(mReceiver, filter); - - mDisplayManager.registerDisplayListener(mDisplayListener, null); - - mScreenOn = true; - // Start out assuming we are charging. If we aren't, we will at least get - // a battery update the next time the level drops. - mCharging = true; - mState = STATE_ACTIVE; - mInactiveTimeout = DEFAULT_INACTIVE_TIMEOUT; - updateDisplayLocked(); - } - - publishBinderService("deviceidle", mBinder); - } - - void updateDisplayLocked() { - mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); - // We consider any situation where the display is showing something to be it on, - // because if there is anything shown we are going to be updating it at some - // frequency so can't be allowed to go into deep sleeps. - boolean screenOn = mCurDisplay.getState() != Display.STATE_OFF;; - if (!screenOn && mScreenOn) { - mScreenOn = false; - becomeInactiveIfAppropriateLocked(); - } else if (screenOn) { - mScreenOn = true; - becomeActiveLocked("screen"); - } - } - - void updateChargingLocked(boolean charging) { - if (!charging && mCharging) { - mCharging = false; - becomeInactiveIfAppropriateLocked(); - } else if (charging) { - mCharging = charging; - becomeActiveLocked("charging"); - } - } - - void becomeActiveLocked(String reason) { - if (mState != STATE_ACTIVE) { - EventLogTags.writeDeviceIdle(STATE_ACTIVE, reason); - mLocalPowerManager.setDeviceIdleMode(false); - try { - mNetworkPolicyManager.setDeviceIdleMode(false); - mBatteryStats.noteDeviceIdleMode(false, true, false); - } catch (RemoteException e) { - } - if (mState == STATE_IDLE) { - getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); - } - mState = STATE_ACTIVE; - mInactiveTimeout = DEFAULT_INACTIVE_TIMEOUT; - mNextIdlePendingDelay = 0; - mNextIdleDelay = 0; - cancelAlarmLocked(); - stopMonitoringSignificantMotion(); - } - } - - void becomeInactiveIfAppropriateLocked() { - if (!mScreenOn && !mCharging && mState == STATE_ACTIVE) { - // Screen has turned off; we are now going to become inactive and start - // waiting to see if we will ultimately go idle. - mState = STATE_INACTIVE; - mNextIdlePendingDelay = 0; - mNextIdleDelay = 0; - scheduleAlarmLocked(mInactiveTimeout, false); - EventLogTags.writeDeviceIdle(mState, "no activity"); - } - } - - void stepIdleStateLocked() { - EventLogTags.writeDeviceIdleStep(); - - final long now = SystemClock.elapsedRealtime(); - if ((now+DEFAULT_MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) { - // Whoops, there is an upcoming alarm. We don't actually want to go idle. - if (mState != STATE_ACTIVE) { - becomeActiveLocked("alarm"); - } - return; - } - - switch (mState) { - case STATE_INACTIVE: - // We have now been inactive long enough, it is time to start looking - // for significant motion and sleep some more while doing so. - startMonitoringSignificantMotion(); - scheduleAlarmLocked(DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT, false); - // Reset the upcoming idle delays. - mNextIdlePendingDelay = DEFAULT_IDLE_PENDING_TIMEOUT; - mNextIdleDelay = DEFAULT_IDLE_TIMEOUT; - mState = STATE_IDLE_PENDING; - EventLogTags.writeDeviceIdle(mState, "step"); - break; - case STATE_IDLE_PENDING: - // We have been waiting to become idle, and now it is time! This is the - // only case where we want to use a wakeup alarm, because we do want to - // drag the device out of its sleep state in this case to do the next - // scheduled work. - scheduleAlarmLocked(mNextIdleDelay, true); - mNextIdleDelay = (long)(mNextIdleDelay*DEFAULT_IDLE_FACTOR); - if (mNextIdleDelay > DEFAULT_MAX_IDLE_TIMEOUT) { - mNextIdleDelay = DEFAULT_MAX_IDLE_TIMEOUT; - } - mState = STATE_IDLE; - EventLogTags.writeDeviceIdle(mState, "step"); - mLocalPowerManager.setDeviceIdleMode(true); - try { - mNetworkPolicyManager.setDeviceIdleMode(true); - mBatteryStats.noteDeviceIdleMode(true, false, false); - } catch (RemoteException e) { - } - getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); - break; - case STATE_IDLE: - // We have been idling long enough, now it is time to do some work. - scheduleAlarmLocked(mNextIdlePendingDelay, false); - mNextIdlePendingDelay = (long)(mNextIdlePendingDelay*DEFAULT_IDLE_PENDING_FACTOR); - if (mNextIdlePendingDelay > DEFAULT_MAX_IDLE_PENDING_TIMEOUT) { - mNextIdlePendingDelay = DEFAULT_MAX_IDLE_PENDING_TIMEOUT; - } - mState = STATE_IDLE_PENDING; - EventLogTags.writeDeviceIdle(mState, "step"); - mLocalPowerManager.setDeviceIdleMode(false); - try { - mNetworkPolicyManager.setDeviceIdleMode(false); - mBatteryStats.noteDeviceIdleMode(false, false, false); - } catch (RemoteException e) { - } - getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); - break; - } - } - - void significantMotionLocked() { - // When the sensor goes off, its trigger is automatically removed. - mSigMotionActive = false; - // The device is not yet active, so we want to go back to the pending idle - // state to wait again for no motion. Note that we only monitor for significant - // motion after moving out of the inactive state, so no need to worry about that. - if (mState != STATE_ACTIVE) { - mLocalPowerManager.setDeviceIdleMode(false); - try { - mNetworkPolicyManager.setDeviceIdleMode(false); - mBatteryStats.noteDeviceIdleMode(false, false, true); - } catch (RemoteException e) { - } - if (mState == STATE_IDLE) { - getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); - } - mState = STATE_ACTIVE; - mInactiveTimeout = DEFAULT_MOTION_INACTIVE_TIMEOUT; - EventLogTags.writeDeviceIdle(mState, "motion"); - becomeInactiveIfAppropriateLocked(); - } - } - - void startMonitoringSignificantMotion() { - if (mSigMotionSensor != null && !mSigMotionActive) { - mSensorManager.requestTriggerSensor(mSigMotionListener, mSigMotionSensor); - mSigMotionActive = true; - } - } - - void stopMonitoringSignificantMotion() { - if (mSigMotionActive) { - mSensorManager.cancelTriggerSensor(mSigMotionListener, mSigMotionSensor); - mSigMotionActive = false; - } - } - - void cancelAlarmLocked() { - if (mNextAlarmTime != 0) { - mNextAlarmTime = 0; - mAlarmManager.cancel(mAlarmIntent); - } - } - - void scheduleAlarmLocked(long delay, boolean idleUntil) { - if (mSigMotionSensor == null) { - // If there is no significant motion sensor on this device, then we won't schedule - // alarms, because we can't determine if the device is not moving. This effectively - // turns off normal exeuction of device idling, although it is still possible to - // manually poke it by pretending like the alarm is going off. - return; - } - mNextAlarmTime = SystemClock.elapsedRealtime() + delay; - if (idleUntil) { - mAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP, - mNextAlarmTime, mAlarmIntent); - } else { - mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, - mNextAlarmTime, mAlarmIntent); - } - } - - private void dumpHelp(PrintWriter pw) { - pw.println("Device idle controller (deviceidle) dump options:"); - pw.println(" [-h] [CMD]"); - pw.println(" -h: print this help text."); - pw.println("Commands:"); - pw.println(" step"); - pw.println(" Immediately step to next state, without waiting for alarm."); - } - - void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) - != PackageManager.PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump DeviceIdleController from from pid=" - + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() - + " without permission " + android.Manifest.permission.DUMP); - return; - } - - if (args != null) { - for (int i=0; i<args.length; i++) { - String arg = args[i]; - if ("-h".equals(arg)) { - dumpHelp(pw); - return; - } else if ("step".equals(arg)) { - synchronized (this) { - stepIdleStateLocked(); - pw.print("Stepped to: "); pw.println(stateToString(mState)); - } - return; - } else if (arg.length() > 0 && arg.charAt(0) == '-'){ - pw.println("Unknown option: " + arg); - dumpHelp(pw); - return; - } else { - pw.println("Unknown command: " + arg); - dumpHelp(pw); - return; - } - } - } - - synchronized (this) { - pw.print(" mSigMotionSensor="); pw.println(mSigMotionSensor); - pw.print(" mCurDisplay="); pw.println(mCurDisplay); - pw.print(" mScreenOn="); pw.println(mScreenOn); - pw.print(" mCharging="); pw.println(mCharging); - pw.print(" mSigMotionActive="); pw.println(mSigMotionActive); - pw.print(" mState="); pw.println(stateToString(mState)); - pw.print(" mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw); - pw.println(); - if (mNextAlarmTime != 0) { - pw.print(" mNextAlarmTime="); - TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw); - pw.println(); - } - if (mNextIdlePendingDelay != 0) { - pw.print(" mNextIdlePendingDelay="); - TimeUtils.formatDuration(mNextIdlePendingDelay, pw); - pw.println(); - } - if (mNextIdleDelay != 0) { - pw.print(" mNextIdleDelay="); - TimeUtils.formatDuration(mNextIdleDelay, pw); - pw.println(); - } - } - } -} diff --git a/services/core/jni/com_android_server_UsbHostManager.cpp b/services/core/jni/com_android_server_UsbHostManager.cpp index ee50ff9..d8c172f 100644 --- a/services/core/jni/com_android_server_UsbHostManager.cpp +++ b/services/core/jni/com_android_server_UsbHostManager.cpp @@ -71,6 +71,7 @@ static int usb_device_added(const char *devname, void* client_data) { char *manufacturer = usb_device_get_manufacturer_name(device); char *product = usb_device_get_product_name(device); + int version = usb_device_get_version(device); char *serial = usb_device_get_serial(device); jstring deviceName = env->NewStringUTF(devname); @@ -81,7 +82,7 @@ static int usb_device_added(const char *devname, void* client_data) { jboolean result = env->CallBooleanMethod(thiz, method_beginUsbDeviceAdded, deviceName, usb_device_get_vendor_id(device), usb_device_get_product_id(device), deviceDesc->bDeviceClass, deviceDesc->bDeviceSubClass, deviceDesc->bDeviceProtocol, - manufacturerName, productName, serialNumber); + manufacturerName, productName, version, serialNumber); env->DeleteLocalRef(serialNumber); env->DeleteLocalRef(productName); @@ -199,7 +200,7 @@ int register_android_server_UsbHostManager(JNIEnv *env) return -1; } method_beginUsbDeviceAdded = env->GetMethodID(clazz, "beginUsbDeviceAdded", - "(Ljava/lang/String;IIIIILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z"); + "(Ljava/lang/String;IIIIILjava/lang/String;Ljava/lang/String;ILjava/lang/String;)Z"); if (method_beginUsbDeviceAdded == NULL) { ALOGE("Can't find beginUsbDeviceAdded"); return -1; diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 593853c..2922130 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -76,7 +76,6 @@ import com.android.server.pm.Installer; import com.android.server.pm.LauncherAppsService; import com.android.server.pm.PackageManagerService; import com.android.server.pm.UserManagerService; -import com.android.server.power.DeviceIdleController; import com.android.server.power.PowerManagerService; import com.android.server.power.ShutdownThread; import com.android.server.restrictions.RestrictionsManagerService; @@ -599,6 +598,8 @@ public final class SystemServer { mSystemServiceManager.startService(PersistentDataBlockService.class); } + mSystemServiceManager.startService(DeviceIdleController.class); + // Always start the Device Policy Manager, so that the API is compatible with // API8. mSystemServiceManager.startService(DevicePolicyManagerService.Lifecycle.class); @@ -965,7 +966,6 @@ public final class SystemServer { if (!disableNonCoreServices) { mSystemServiceManager.startService(MediaProjectionManagerService.class); - mSystemServiceManager.startService(DeviceIdleController.class); } // Before things start rolling, be sure we have decided whether diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index 04984d3..c2e61c6 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -28,7 +28,6 @@ import android.app.usage.UsageEvents.Event; import android.app.usage.UsageStats; import android.app.usage.UsageStatsManagerInternal; import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener; -import android.appwidget.AppWidgetManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; @@ -41,6 +40,7 @@ import android.content.pm.UserInfo; import android.content.res.Configuration; import android.database.ContentObserver; import android.net.Uri; +import android.os.BatteryManager; import android.os.Binder; import android.os.Environment; import android.os.Handler; @@ -81,6 +81,8 @@ public class UsageStatsService extends SystemService implements private static final long TWENTY_MINUTES = 20 * 60 * 1000; private static final long FLUSH_INTERVAL = DEBUG ? TEN_SECONDS : TWENTY_MINUTES; private static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds. + static final long DEFAULT_APP_IDLE_THRESHOLD_MILLIS = 2L * 24 * 60 * 60 * 1000; // 1 day + static final long DEFAULT_CHECK_IDLE_INTERVAL = 8 * 3600 * 1000; // 8 hours // Handler message types. static final int MSG_REPORT_EVENT = 0; @@ -88,6 +90,7 @@ public class UsageStatsService extends SystemService implements static final int MSG_REMOVE_USER = 2; static final int MSG_INFORM_LISTENERS = 3; static final int MSG_RESET_LAST_TIMESTAMP = 4; + static final int MSG_CHECK_IDLE_STATES = 5; private final Object mLock = new Object(); Handler mHandler; @@ -98,9 +101,11 @@ public class UsageStatsService extends SystemService implements private File mUsageStatsDir; long mRealTimeSnapshot; long mSystemTimeSnapshot; + boolean mAppIdleParoled; - private static final long DEFAULT_APP_IDLE_THRESHOLD_MILLIS = 1L * 24 * 60 * 60 * 1000; // 1 day - private long mAppIdleDurationMillis; + long mAppIdleDurationMillis; + + long mCheckIdleIntervalMillis = DEFAULT_CHECK_IDLE_INTERVAL; private ArrayList<UsageStatsManagerInternal.AppIdleStateChangeListener> mPackageAccessListeners = new ArrayList<>(); @@ -113,6 +118,7 @@ public class UsageStatsService extends SystemService implements public void onStart() { mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE); mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); + mHandler = new H(BackgroundThread.get().getLooper()); File systemDataDir = new File(Environment.getDataDirectory(), "system"); @@ -123,9 +129,14 @@ public class UsageStatsService extends SystemService implements + mUsageStatsDir.getAbsolutePath()); } - getContext().registerReceiver(new UserRemovedReceiver(), - new IntentFilter(Intent.ACTION_USER_REMOVED)); + IntentFilter userActions = new IntentFilter(Intent.ACTION_USER_REMOVED); + userActions.addAction(Intent.ACTION_USER_STARTED); + getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, userActions, + null, null); + IntentFilter deviceStates = new IntentFilter(BatteryManager.ACTION_CHARGING); + deviceStates.addAction(BatteryManager.ACTION_DISCHARGING); + getContext().registerReceiver(new DeviceStateReceiver(), deviceStates); synchronized (mLock) { cleanUpRemovedUsersLocked(); } @@ -147,18 +158,35 @@ public class UsageStatsService extends SystemService implements if (phase == PHASE_SYSTEM_SERVICES_READY) { // Observe changes to the threshold new SettingsObserver(mHandler).registerObserver(); + } else if (phase == PHASE_BOOT_COMPLETED) { + setAppIdleParoled(getContext().getSystemService(BatteryManager.class).isCharging()); } } - private class UserRemovedReceiver extends BroadcastReceiver { + private class UserActionsReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - if (intent != null && intent.getAction().equals(Intent.ACTION_USER_REMOVED)) { - final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); + final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); + if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) { if (userId >= 0) { mHandler.obtainMessage(MSG_REMOVE_USER, userId, 0).sendToTarget(); } + } else if (Intent.ACTION_USER_STARTED.equals(intent.getAction())) { + if (userId >=0) { + postCheckIdleStates(); + } + } + } + } + + private class DeviceStateReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + if (BatteryManager.ACTION_CHARGING.equals(action) + || BatteryManager.ACTION_DISCHARGING.equals(action)) { + setAppIdleParoled(BatteryManager.ACTION_CHARGING.equals(action)); } } } @@ -195,6 +223,49 @@ public class UsageStatsService extends SystemService implements } } + void setAppIdleParoled(boolean paroled) { + synchronized (mLock) { + if (mAppIdleParoled != paroled) { + mAppIdleParoled = paroled; + postCheckIdleStates(); + } + } + } + + void postCheckIdleStates() { + mHandler.removeMessages(MSG_CHECK_IDLE_STATES); + mHandler.sendEmptyMessage(MSG_CHECK_IDLE_STATES); + } + + /** Check all running users' apps to see if they enter an idle state. */ + void checkIdleStates() { + final int[] runningUsers; + try { + runningUsers = ActivityManagerNative.getDefault().getRunningUserIds(); + } catch (RemoteException re) { + return; + } + + for (int i = 0; i < runningUsers.length; i++) { + final int userId = runningUsers[i]; + List<PackageInfo> packages = + getContext().getPackageManager().getInstalledPackages( + PackageManager.GET_DISABLED_COMPONENTS + | PackageManager.GET_UNINSTALLED_PACKAGES, + userId); + synchronized (mLock) { + final int packageCount = packages.size(); + for (int p = 0; p < packageCount; p++) { + final String packageName = packages.get(p).packageName; + final boolean isIdle = isAppIdle(packageName, userId); + mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, + userId, isIdle ? 1 : 0, packageName)); + } + } + } + mHandler.sendEmptyMessageDelayed(MSG_CHECK_IDLE_STATES, mCheckIdleIntervalMillis); + } + private static void deleteRecursively(File f) { File[] files = f.listFiles(); if (files != null) { @@ -291,7 +362,7 @@ public class UsageStatsService extends SystemService implements void resetLastTimestamp(String packageName, int userId, boolean idle) { synchronized (mLock) { final long timeNow = checkAndGetTimeLocked(); - final long lastTimestamp = timeNow - (idle ? mAppIdleDurationMillis : 0); + final long lastTimestamp = timeNow - (idle ? mAppIdleDurationMillis : 0) - 5000; final UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId, timeNow); @@ -409,14 +480,22 @@ public class UsageStatsService extends SystemService implements private boolean hasPassedIdleDuration(long lastUsed) { final long now = System.currentTimeMillis(); - return lastUsed < now - mAppIdleDurationMillis; + return lastUsed <= now - mAppIdleDurationMillis; } boolean isAppIdle(String packageName, int userId) { if (packageName == null) return false; + synchronized (mLock) { + // Temporary exemption, probably due to device charging or occasional allowance to + // be allowed to sync, etc. + if (mAppIdleParoled) { + return false; + } + } if (SystemConfig.getInstance().getAllowInPowerSave().contains(packageName)) { return false; } + // TODO: Optimize this check if (isActiveDeviceAdmin(packageName, userId)) { return false; } @@ -518,6 +597,9 @@ public class UsageStatsService extends SystemService implements resetLastTimestamp((String) msg.obj, msg.arg1, msg.arg2 == 1); break; + case MSG_CHECK_IDLE_STATES: + checkIdleStates(); + break; default: super.handleMessage(msg); break; @@ -544,7 +626,9 @@ public class UsageStatsService extends SystemService implements mAppIdleDurationMillis = Settings.Secure.getLongForUser(getContext().getContentResolver(), Settings.Secure.APP_IDLE_DURATION, DEFAULT_APP_IDLE_THRESHOLD_MILLIS, UserHandle.USER_OWNER); - // TODO: Check if we need to update idle states of all the apps + mCheckIdleIntervalMillis = Math.min(DEFAULT_CHECK_IDLE_INTERVAL, + mAppIdleDurationMillis / 4); + postCheckIdleStates(); } } diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java index daccf95..27c97d0 100644 --- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java +++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java @@ -401,6 +401,7 @@ public final class UsbAlsaManager { Bundle properties = new Bundle(); String manufacturer = usbDevice.getManufacturerName(); String product = usbDevice.getProductName(); + String version = usbDevice.getVersion(); String name; if (manufacturer == null || manufacturer.isEmpty()) { name = product; @@ -412,6 +413,7 @@ public final class UsbAlsaManager { properties.putString(MidiDeviceInfo.PROPERTY_NAME, name); properties.putString(MidiDeviceInfo.PROPERTY_MANUFACTURER, manufacturer); properties.putString(MidiDeviceInfo.PROPERTY_PRODUCT, product); + properties.putString(MidiDeviceInfo.PROPERTY_VERSION, version); properties.putString(MidiDeviceInfo.PROPERTY_SERIAL_NUMBER, usbDevice.getSerialNumber()); properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_CARD, alsaDevice.mCard); diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java index 5b58051..f5f2b07 100644 --- a/services/usb/java/com/android/server/usb/UsbHostManager.java +++ b/services/usb/java/com/android/server/usb/UsbHostManager.java @@ -112,7 +112,7 @@ public class UsbHostManager { */ private boolean beginUsbDeviceAdded(String deviceName, int vendorID, int productID, int deviceClass, int deviceSubclass, int deviceProtocol, - String manufacturerName, String productName, String serialNumber) { + String manufacturerName, String productName, int version, String serialNumber) { if (DEBUG) { Slog.d(TAG, "usb:UsbHostManager.beginUsbDeviceAdded(" + deviceName + ")"); @@ -149,9 +149,12 @@ public class UsbHostManager { return false; } + // Create version string in "%.%" format + String versionString = Integer.toString(version >> 8) + "." + (version & 0xFF); + mNewDevice = new UsbDevice(deviceName, vendorID, productID, deviceClass, deviceSubclass, deviceProtocol, - manufacturerName, productName, serialNumber); + manufacturerName, productName, versionString, serialNumber); mNewConfigurations = new ArrayList<UsbConfiguration>(); mNewInterfaces = new ArrayList<UsbInterface>(); diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 831a194..299c7c4 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -48,33 +48,147 @@ public class CarrierConfigManager { ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED"; /** - * Flag specifying whether VoLTE should be available for carrier, independent of carrier - * provisioning. If false: hard disabled. If true: then depends on carrier provisioning, - * availability, etc. + * Flag indicating whether the Phone app should ignore EVENT_SIM_NETWORK_LOCKED + * events from the Sim. + * If true, this will prevent the IccNetworkDepersonalizationPanel from being shown, and + * effectively disable the "Sim network lock" feature. */ - public static final String BOOL_CARRIER_VOLTE_AVAILABLE = "bool_carrier_volte_available"; + public static final String + BOOL_IGNORE_SIM_NETWORK_LOCKED_EVENTS = "bool_ignore_sim_network_locked_events"; /** - * Flag specifying whether VoLTE availability is based on provisioning. + * Flag indicating whether the Phone app should provide a "Dismiss" button on the SIM network + * unlock screen. The default value is true. If set to false, there will be *no way* to dismiss + * the SIM network unlock screen if you don't enter the correct unlock code. (One important + * consequence: there will be no way to make an Emergency Call if your SIM is network-locked and + * you don't know the PIN.) */ - public static final String BOOL_CARRIER_VOLTE_PROVISIONED = "bool_carrier_volte_provisioned"; + public static final String + BOOL_SIM_NETWORK_UNLOCK_ALLOW_DISMISS = "bool_sim_network_unlock_allow_dismiss"; + + /** Flag indicating if the phone is a world phone */ + public static final String BOOL_WORLD_PHONE = "bool_world_phone"; /** - * Flag specifying whether VoLTE TTY is supported. + * If true, enable vibration (haptic feedback) for key presses in the EmergencyDialer activity. + * The pattern is set on a per-platform basis using config_virtualKeyVibePattern. To be + * consistent with the regular Dialer, this value should agree with the corresponding values + * from config.xml under apps/Contacts. */ - public static final String BOOL_CARRIER_VOLTE_TTY_SUPPORTED - = "bool_carrier_volte_tty_supported"; + public static final String + BOOL_ENABLE_DIALER_KEY_VIBRATION = "bool_enable_dialer_key_vibration"; + + /** Flag indicating if dtmf tone type is enabled */ + public static final String BOOL_DTMF_TYPE_ENABLED = "bool_dtmf_type_enabled"; + + /** Flag indicating if auto retry is enabled */ + public static final String BOOL_AUTO_RETRY_ENABLED = "bool_auto_retry_enabled"; /** - * Show APN Settings for some CDMA carriers. + * Determine whether we want to play local DTMF tones in a call, or just let the radio/BP handle + * playing of the tones. */ - public static final String BOOL_SHOW_APN_SETTING_CDMA = "bool_show_apn_setting_cdma"; + public static final String BOOL_ALLOW_LOCAL_DTMF_TONES = "bool_allow_local_dtmf_tones"; + + /** + * If true, show an onscreen "Dial" button in the dialer. In practice this is used on all + * platforms, even the ones with hard SEND/END keys, but for maximum flexibility it's controlled + * by a flag here (which can be overridden on a per-product basis.) + */ + public static final String BOOL_SHOW_ONSCREEN_DIAL_BUTTON = "bool_show_onscreen_dial_button"; + + /** Determines if device implements a noise suppression device for in call audio. */ + public static final String + BOOL_HAS_IN_CALL_NOISE_SUPPRESSION = "bool_has_in_call_noise_suppression"; /** - * Control whether users can edit APNs in Settings. + * Determines if the current device should allow emergency numbers to be logged in the Call Log. + * (Some carriers require that emergency calls *not* be logged, presumably to avoid the risk of + * accidental redialing from the call log UI. This is a good idea, so the default here is + * false.) + * <p> + * TODO: on the other hand, it might still be useful to have some record of the emergency calls + * you've made, or to be able to look up the exact date/time of an emergency call. So perhaps we + * <b>should</b> log those calls, but instead fix the call log to disable the "call" button for + * emergency numbers. */ + public static final String + BOOL_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG = "bool_allow_emergency_numbers_in_call_log"; + + /** If true, removes the Voice Privacy option from Call Settings */ + public static final String BOOL_VOICE_PRIVACY_DISABLE = "bool_voice_privacy_disable"; + + /** Control whether users can reach the carrier portions of Cellular Network Settings. */ + public static final String + BOOL_HIDE_CARRIER_NETWORK_SETTINGS = "bool_hide_carrier_network_settings"; + + /** Control whether users can edit APNs in Settings. */ public static final String BOOL_APN_EXPAND = "bool_apn_expand"; + /** Control whether users can choose a network operator. */ + public static final String BOOL_OPERATOR_SELECTION_EXPAND = "bool_operator_selection_expand"; + + /** Used in Cellular Network Settings for preferred network type. */ + public static final String BOOL_PREFER_2G = "bool_prefer_2g"; + + /** Show cdma auto network mode in (glabal) roaming */ + public static final String BOOL_SHOW_CDMA = "bool_show_cdma"; + + /** CDMA activation goes through HFA */ + public static final String BOOL_USE_HFA_FOR_PROVISIONING = "bool_use_hfa_for_provisioning"; + + /** + * CDMA activation goes through OTASP. + * <p> + * TODO: This should be combined with config_use_hfa_for_provisioning and implemented as an enum + * (NONE, HFA, OTASP). + */ + public static final String BOOL_USE_OTASP_FOR_PROVISIONING = "bool_use_otasp_for_provisioning"; + + /** Display carrier settings menu if true */ + public static final String BOOL_CARRIER_SETTINGS_ENABLE = "bool_carrier_settings_enable"; + + /** Does not display additional call seting for IMS phone based on GSM Phone */ + public static final String BOOL_ADDITIONAL_CALL_SETTING = "bool_additional_call_setting"; + + /** Show APN Settings for some CDMA carriers */ + public static final String BOOL_SHOW_APN_SETTING_CDMA = "bool_show_apn_setting_cdma"; + + /** After a CDMA conference call is merged, the swap button should be displayed. */ + public static final String BOOL_SUPPORT_SWAP_AFTER_MERGE = "bool_support_swap_after_merge"; + + /** + * Determine whether the voicemail notification is persistent in the notification bar. If true, + * the voicemail notifications cannot be dismissed from the notification bar. + */ + public static final String + BOOL_VOICEMAIL_NOTIFICATION_PERSISTENT = "bool_voicemail_notification_persistent"; + + /** For IMS video over LTE calls, determines whether video pause signalling is supported. */ + public static final String + BOOL_SUPPORT_PAUSE_IMS_VIDEO_CALLS = "bool_support_pause_ims_video_calls"; + + /** + * Disables dialing "*228" (OTASP provisioning) on CDMA carriers where it is not supported or is + * potentially harmful by locking the SIM to 3G. + */ + public static final String + BOOL_DISABLE_CDMA_ACTIVATION_CODE = "bool_disable_cdma_activation_code"; + + /** + * Flag specifying whether VoLTE should be available for carrier, independent of carrier + * provisioning. If false: hard disabled. If true: then depends on carrier provisioning, + * availability, etc. + */ + public static final String BOOL_CARRIER_VOLTE_AVAILABLE = "bool_carrier_volte_available"; + + /** Flag specifying whether VoLTE availability is based on provisioning. */ + public static final String BOOL_CARRIER_VOLTE_PROVISIONED = "bool_carrier_volte_provisioned"; + + /** Flag specifying whether VoLTE TTY is supported. */ + public static final String BOOL_CARRIER_VOLTE_TTY_SUPPORTED + = "bool_carrier_volte_tty_supported"; + /** * If Voice Radio Technology is RIL_RADIO_TECHNOLOGY_LTE:14 or RIL_RADIO_TECHNOLOGY_UNKNOWN:0 * this is the value that should be used instead. A configuration value of @@ -86,9 +200,9 @@ public class CarrierConfigManager { /* The following 3 fields are related to carrier visual voicemail. */ /** - * The carrier number MO sms messages are sent to. + * The carrier number MO sms messages are sent to. * - * @hide + * @hide */ public static final String STRING_VVM_DESTINATION_NUMBER = "string_vvm_destination_number"; @@ -122,17 +236,38 @@ public class CarrierConfigManager { static { sDefaults = new Bundle(); + sDefaults.putBoolean(BOOL_ADDITIONAL_CALL_SETTING, true); + sDefaults.putBoolean(BOOL_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG, false); + sDefaults.putBoolean(BOOL_ALLOW_LOCAL_DTMF_TONES, true); + sDefaults.putBoolean(BOOL_APN_EXPAND, true); + sDefaults.putBoolean(BOOL_AUTO_RETRY_ENABLED, false); + sDefaults.putBoolean(BOOL_CARRIER_SETTINGS_ENABLE, false); sDefaults.putBoolean(BOOL_CARRIER_VOLTE_AVAILABLE, false); sDefaults.putBoolean(BOOL_CARRIER_VOLTE_PROVISIONED, false); sDefaults.putBoolean(BOOL_CARRIER_VOLTE_TTY_SUPPORTED, true); + sDefaults.putBoolean(BOOL_DISABLE_CDMA_ACTIVATION_CODE, false); + sDefaults.putBoolean(BOOL_DTMF_TYPE_ENABLED, false); + sDefaults.putBoolean(BOOL_ENABLE_DIALER_KEY_VIBRATION, true); + sDefaults.putBoolean(BOOL_HAS_IN_CALL_NOISE_SUPPRESSION, false); + sDefaults.putBoolean(BOOL_HIDE_CARRIER_NETWORK_SETTINGS, false); + sDefaults.putBoolean(BOOL_IGNORE_SIM_NETWORK_LOCKED_EVENTS, false); + sDefaults.putBoolean(BOOL_OPERATOR_SELECTION_EXPAND, true); + sDefaults.putBoolean(BOOL_PREFER_2G, true); sDefaults.putBoolean(BOOL_SHOW_APN_SETTING_CDMA, false); - sDefaults.putBoolean(BOOL_APN_EXPAND, true); - + sDefaults.putBoolean(BOOL_SHOW_CDMA, false); + sDefaults.putBoolean(BOOL_SHOW_ONSCREEN_DIAL_BUTTON, true); + sDefaults.putBoolean(BOOL_SIM_NETWORK_UNLOCK_ALLOW_DISMISS, true); + sDefaults.putBoolean(BOOL_SUPPORT_PAUSE_IMS_VIDEO_CALLS, true); + sDefaults.putBoolean(BOOL_SUPPORT_SWAP_AFTER_MERGE, true); + sDefaults.putBoolean(BOOL_USE_HFA_FOR_PROVISIONING, false); + sDefaults.putBoolean(BOOL_USE_OTASP_FOR_PROVISIONING, false); + sDefaults.putBoolean(BOOL_VOICEMAIL_NOTIFICATION_PERSISTENT, false); + sDefaults.putBoolean(BOOL_VOICE_PRIVACY_DISABLE, false); + sDefaults.putBoolean(BOOL_WORLD_PHONE, false); sDefaults.putInt(INT_VOLTE_REPLACEMENT_RAT, 0); - + sDefaults.putInt(INT_VVM_PORT_NUMBER, 0); sDefaults.putString(STRING_VVM_DESTINATION_NUMBER, ""); sDefaults.putString(STRING_VVM_TYPE, ""); - sDefaults.putInt(INT_VVM_PORT_NUMBER, 0); } /** @@ -190,10 +325,11 @@ public class CarrierConfigManager { /** * Request the carrier config loader to update the cofig for phoneId. - * - * Depending on simState, the config may be cleared or loaded from config app. - * This is only used by SubscriptionInfoUpdater. - * + * <p> + * Depending on simState, the config may be cleared or loaded from config app. This is only used + * by SubscriptionInfoUpdater. + * </p> + * * @hide */ @SystemApi diff --git a/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java index 322b853..30d204f 100644 --- a/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java +++ b/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java @@ -52,6 +52,11 @@ public class ServiceManagerPermissionTests extends TestCase { public boolean checkPermission(java.lang.String permission, int pid, int uid) { return true; } + + @Override + public String[] getPackagesForUid(int uid) { + return new String[0]; + } }; ServiceManagerNative.asInterface(BinderInternal.getContextObject()) .setPermissionController(pc); |
