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 \
}
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);
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);
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";
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;
}
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
method public android.security.KeyPairGeneratorSpec.Builder setUserAuthenticationValidityDurationSeconds(int);
}
+ public class KeyPermanentlyInvalidatedException extends java.security.InvalidKeyException {
+ ctor public KeyPermanentlyInvalidatedException();
+ ctor public KeyPermanentlyInvalidatedException(java.lang.String);
+ ctor public KeyPermanentlyInvalidatedException(java.lang.String, java.lang.Throwable);
+ }
+
public abstract class KeyStoreKeyProperties {
}
method public boolean isCleartextTrafficPermitted();
}
- public class NewFingerprintEnrolledException extends java.security.InvalidKeyException {
- ctor public NewFingerprintEnrolledException();
- ctor public NewFingerprintEnrolledException(java.lang.String);
- }
-
public class UserNotAuthenticatedException extends java.security.InvalidKeyException {
ctor public UserNotAuthenticatedException();
ctor public UserNotAuthenticatedException(java.lang.String);
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";
}
}
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);
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);
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";
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);
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;
}
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
method public android.security.KeyPairGeneratorSpec.Builder setUserAuthenticationValidityDurationSeconds(int);
}
+ public class KeyPermanentlyInvalidatedException extends java.security.InvalidKeyException {
+ ctor public KeyPermanentlyInvalidatedException();
+ ctor public KeyPermanentlyInvalidatedException(java.lang.String);
+ ctor public KeyPermanentlyInvalidatedException(java.lang.String, java.lang.Throwable);
+ }
+
public abstract class KeyStoreKeyProperties {
}
method public boolean isCleartextTrafficPermitted();
}
- public class NewFingerprintEnrolledException extends java.security.InvalidKeyException {
- ctor public NewFingerprintEnrolledException();
- ctor public NewFingerprintEnrolledException(java.lang.String);
- }
-
public class UserNotAuthenticatedException extends java.security.InvalidKeyException {
ctor public UserNotAuthenticatedException();
ctor public UserNotAuthenticatedException(java.lang.String);
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";
}
* 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
}
/**
- * 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>
*
* @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 {
* 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:
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 {
}
/**
+ * 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.
}
/**
- * 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 {
}
/**
- * 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) {
* 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() {
}
/**
- * 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) {
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();
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;
*/
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;
mProtocol = protocol;
mManufacturerName = manufacturerName;
mProductName = productName;
+ mVersion = version;
mSerialNumber = serialNumber;
}
}
/**
+ * 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
",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());
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;
}
parcel.writeInt(mProtocol);
parcel.writeString(mManufacturerName);
parcel.writeString(mProductName);
+ parcel.writeString(mVersion);
parcel.writeString(mSerialNumber);
parcel.writeParcelableArray(mConfigurations, 0);
}
boolean isUidForeground(int uid);
- int[] getPowerSaveAppIdWhitelist();
-
void registerListener(INetworkPolicyListener listener);
void unregisterListener(INetworkPolicyListener listener);
*/
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. */
/** 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;
* 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 {
}
}
- public int[] getPowerSaveAppIdWhitelist() {
- try {
- return mService.getPowerSaveAppIdWhitelist();
- } catch (RemoteException e) {
- return new int[0];
- }
- }
-
public void registerListener(INetworkPolicyListener listener) {
try {
mService.registerListener(listener);
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("]");
}
--- /dev/null
+/**
+ * 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();
+}
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.
/** @hide */
interface IPermissionController {
boolean checkPermission(String permission, int pid, int uid);
+ String[] getPackagesForUid(int uid);
}
= "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.
*
return result;
}
+ public Long getLong(int tag) {
+ if (hwEnforced.containsTag(tag)) {
+ return hwEnforced.getLong(tag, -1);
+ } else if (swEnforced.containsTag(tag)) {
+ return swEnforced.getLong(tag, -1);
+ } else {
+ return null;
+ }
+ }
+
+ public long getLong(int tag, long defaultValue) {
+ Long result = getLong(tag);
+ return (result != null) ? result : defaultValue;
+ }
+
+ public List<Long> getLongs(int tag) {
+ List<Long> result = new ArrayList<Long>();
+ result.addAll(hwEnforced.getLongs(tag));
+ result.addAll(swEnforced.getLongs(tag));
+ return result;
+ }
+
public Date getDate(int tag) {
Date result = hwEnforced.getDate(tag, null);
if (result == null) {
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
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);
// 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);
* Returns {@code true} if this popup is currently showing. {@code false} otherwise.
*/
public boolean isShowing() {
- return mPopupWindow.isShowing() && !mDismissed && !mHidden;
+ return !mDismissed && !mHidden;
}
/**
* 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;
}
$(call include-path-for, libhardware)/hardware \
$(call include-path-for, libhardware_legacy)/hardware_legacy \
$(TOP)/frameworks/av/include \
+ $(TOP)/frameworks/base/media/jni \
$(TOP)/system/media/camera/include \
$(TOP)/system/netd/include \
external/pdfium/core/include/fpdfapi \
#include <utils/Log.h>
#include <media/AudioRecord.h>
+#include <ScopedUtfChars.h>
+
#include "android_media_AudioFormat.h"
#include "android_media_AudioErrors.h"
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",
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
// 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},
#include "android_media_AudioFormat.h"
#include "android_media_AudioErrors.h"
+#include "android_media_PlaybackSettings.h"
// ----------------------------------------------------------------------------
};
static audio_track_fields_t javaAudioTrackFields;
static audio_attributes_fields_t javaAudioAttrFields;
+static PlaybackSettings::fields_t gPlaybackSettingsFields;
struct audiotrack_callback_cookie {
jclass audioTrack_class;
// ----------------------------------------------------------------------------
static void android_media_AudioTrack_set_playback_settings(JNIEnv *env, jobject thiz,
- jfloatArray floatArray, jintArray intArray) {
+ jobject settings) {
sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
if (lpTrack == NULL) {
jniThrowException(env, "java/lang/IllegalStateException",
return;
}
- // NOTE: Get<Primitive>ArrayRegion throws ArrayIndexOutOfBoundsException if not valid.
- // TODO: consider the actual occupancy.
- float farray[2];
- int iarray[2];
- if ((env->GetFloatArrayRegion(floatArray, 0, 2, farray), env->ExceptionCheck()) == JNI_FALSE
- &&
- (env->GetIntArrayRegion(intArray, 0, 2, iarray), env->ExceptionCheck()) == JNI_FALSE) {
- // arrays retrieved OK
- AudioPlaybackRate playbackRate;
- playbackRate.mSpeed = farray[0];
- playbackRate.mPitch = farray[1];
- playbackRate.mFallbackMode = (AudioTimestretchFallbackMode)iarray[0];
- playbackRate.mStretchMode = (AudioTimestretchStretchMode)iarray[1];
- if (lpTrack->setPlaybackRate(playbackRate) != OK) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "arguments out of range");
- }
+ PlaybackSettings pbs;
+ pbs.fillFromJobject(env, gPlaybackSettingsFields, settings);
+
+ ALOGV("setPlaybackSettings: %d:%f %d:%f %d:%u %d:%u",
+ pbs.speedSet, pbs.audioRate.mSpeed,
+ pbs.pitchSet, pbs.audioRate.mPitch,
+ pbs.audioFallbackModeSet, pbs.audioRate.mFallbackMode,
+ pbs.audioStretchModeSet, pbs.audioRate.mStretchMode);
+
+ if (lpTrack->setPlaybackRate(pbs.audioRate) != OK) {
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ "arguments out of range");
}
}
// ----------------------------------------------------------------------------
-static void android_media_AudioTrack_get_playback_settings(JNIEnv *env, jobject thiz,
- jfloatArray floatArray, jintArray intArray) {
+static jobject android_media_AudioTrack_get_playback_settings(JNIEnv *env, jobject thiz,
+ jobject settings) {
sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
if (lpTrack == NULL) {
jniThrowException(env, "java/lang/IllegalStateException",
"AudioTrack not initialized");
- return;
+ return NULL;
}
- AudioPlaybackRate playbackRate = lpTrack->getPlaybackRate();
-
- float farray[2] = {
- playbackRate.mSpeed,
- playbackRate.mPitch,
- };
- int iarray[2] = {
- playbackRate.mFallbackMode,
- playbackRate.mStretchMode,
- };
- // NOTE: Set<Primitive>ArrayRegion throws ArrayIndexOutOfBoundsException if not valid.
- env->SetFloatArrayRegion(floatArray, 0, 2, farray);
- env->SetIntArrayRegion(intArray, 0, 2, iarray);
+ PlaybackSettings pbs;
+ pbs.audioRate = lpTrack->getPlaybackRate();
+ pbs.speedSet = true;
+ pbs.pitchSet = true;
+ pbs.audioFallbackModeSet = true;
+ pbs.audioStretchModeSet = true;
+ return pbs.asJobject(env, gPlaybackSettingsFields);
}
{"native_get_playback_rate",
"()I", (void *)android_media_AudioTrack_get_playback_rate},
{"native_set_playback_settings",
- "([F[I)V", (void *)android_media_AudioTrack_set_playback_settings},
+ "(Landroid/media/PlaybackSettings;)V",
+ (void *)android_media_AudioTrack_set_playback_settings},
{"native_get_playback_settings",
- "([F[I)V", (void *)android_media_AudioTrack_get_playback_settings},
+ "()Landroid/media/PlaybackSettings;",
+ (void *)android_media_AudioTrack_get_playback_settings},
{"native_set_marker_pos","(I)I", (void *)android_media_AudioTrack_set_marker_pos},
{"native_get_marker_pos","()I", (void *)android_media_AudioTrack_get_marker_pos},
{"native_set_pos_update_period",
javaAudioTrackFields.fieldStreamType = GetFieldIDOrDie(env,
audioTrackClass, JAVA_STREAMTYPE_FIELD_NAME, "I");
+ env->DeleteLocalRef(audioTrackClass);
+
// Get the AudioAttributes class and fields
jclass audioAttrClass = FindClassOrDie(env, kAudioAttributesClassPathName);
javaAudioAttrFields.fieldUsage = GetFieldIDOrDie(env, audioAttrClass, "mUsage", "I");
javaAudioAttrFields.fieldFormattedTags = GetFieldIDOrDie(env,
audioAttrClass, "mFormattedTags", "Ljava/lang/String;");
+ env->DeleteLocalRef(audioAttrClass);
+
+ // initialize PlaybackSettings field info
+ gPlaybackSettingsFields.init(env);
+
return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
}
// ----------------------------------------------------------------------------
-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>(
}
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'.",
// ----------------------------------------------------------------------------
static JNINativeMethod gMethods[] = {
- {"nativeListen", "(Ljava/lang/String;)J",
+ {"nativeListen", "(Ljava/lang/String;Ljava/lang/String;)J",
(void*)nativeListen },
{"nativeDispose", "(J)V",
(void*)nativeDispose },
<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" />
# 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
include $(BUILD_PREBUILT)
extra_font_files += MTLmr3m.ttf
-endif # !FONT_NOTOSANS_FULL
+endif # !FONT_NOTOSANS_JP_FULL
endif # !SMALLER_FONT_FOOTPRINT
################################
if (drawable != null) {
drawable.setCallback(this);
- drawable.setLayoutDirection(getLayoutDirection());
- drawable.setLevel(getLevel());
}
childDrawable.mDrawable = drawable;
private GateKeeper() {}
public static IGateKeeperService getService() {
- return IGateKeeperService.Stub.asInterface(
+ IGateKeeperService service = IGateKeeperService.Stub.asInterface(
ServiceManager.getService("android.service.gatekeeper.IGateKeeperService"));
+ if (service == null) {
+ throw new IllegalStateException("Gatekeeper service not available");
+ }
+ return service;
}
public static long getSecureUserId() throws IllegalStateException {
try {
- return GateKeeper.getService().getSecureUserId(UserHandle.myUserId());
+ return getService().getSecureUserId(UserHandle.myUserId());
} catch (RemoteException e) {
throw new IllegalStateException(
"Failed to obtain secure user ID from gatekeeper", e);
--- /dev/null
+/*
+ * 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.security;
+
+import java.security.InvalidKeyException;
+
+/**
+ * Indicates that the key can no longer be used because it has been permanently invalidated.
+ *
+ * <p>This can currently occur only for keys that require user authentication. Such keys are
+ * permanently invalidated once the secure lock screen is disabled (i.e., reconfigured to None,
+ * Swipe or other mode which does not authenticate the user) or when the secure lock screen is
+ * forcibly reset (e.g., by Device Admin). Additionally, keys configured to require user
+ * authentication for every use of the key are also permanently invalidated once a new fingerprint
+ * is enrolled or once no more fingerprints are enrolled.
+ */
+public class KeyPermanentlyInvalidatedException extends InvalidKeyException {
+
+ /**
+ * Constructs a new {@code KeyPermanentlyInvalidatedException} without detail message and cause.
+ */
+ public KeyPermanentlyInvalidatedException() {
+ super("Key permanently invalidated");
+ }
+
+ /**
+ * Constructs a new {@code KeyPermanentlyInvalidatedException} with the provided detail message
+ * and no cause.
+ */
+ public KeyPermanentlyInvalidatedException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new {@code KeyPermanentlyInvalidatedException} with the provided detail message
+ * and cause.
+ */
+ public KeyPermanentlyInvalidatedException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
import com.android.org.conscrypt.NativeConstants;
+import android.content.Context;
+import android.hardware.fingerprint.IFingerprintService;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import java.security.InvalidKeyException;
+import java.util.List;
import java.util.Locale;
/**
/**
* Check if the operation referenced by {@code token} is currently authorized.
*
- * @param token An operation token returned by a call to {@link KeyStore.begin}.
+ * @param token An operation token returned by a call to
+ * {@link #begin(String, int, boolean, KeymasterArguments, byte[], KeymasterArguments) begin}.
*/
public boolean isOperationAuthorized(IBinder token) {
try {
* Returns an {@link InvalidKeyException} corresponding to the provided
* {@link KeyStoreException}.
*/
- static InvalidKeyException getInvalidKeyException(KeyStoreException e) {
+ InvalidKeyException getInvalidKeyException(String keystoreKeyAlias, KeyStoreException e) {
switch (e.getErrorCode()) {
case KeymasterDefs.KM_ERROR_KEY_EXPIRED:
return new KeyExpiredException();
case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID:
return new KeyNotYetValidException();
case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED:
- return new UserNotAuthenticatedException();
- // TODO: Handle TBD Keymaster error code "invalid key: new fingerprint enrolled"
- // case KeymasterDefs.KM_ERROR_TBD
- // return new NewFingerprintEnrolledException();
+ {
+ // We now need to determine whether the key/operation can become usable if user
+ // authentication is performed, or whether it can never become usable again.
+ // User authentication requirements are contained in the key's characteristics. We
+ // need to check whether these requirements can be be satisfied by asking the user
+ // to authenticate.
+ KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
+ int getKeyCharacteristicsErrorCode =
+ getKeyCharacteristics(keystoreKeyAlias, null, null, keyCharacteristics);
+ if (getKeyCharacteristicsErrorCode != NO_ERROR) {
+ return new InvalidKeyException(
+ "Failed to obtained key characteristics",
+ getKeyStoreException(getKeyCharacteristicsErrorCode));
+ }
+ List<Long> keySids =
+ keyCharacteristics.getLongs(KeymasterDefs.KM_TAG_USER_SECURE_ID);
+ if (keySids.isEmpty()) {
+ // Key is not bound to any SIDs -- no amount of authentication will help here.
+ return new KeyPermanentlyInvalidatedException();
+ }
+ long rootSid = GateKeeper.getSecureUserId();
+ if ((rootSid != 0) && (keySids.contains(Long.valueOf(rootSid)))) {
+ // One of the key's SIDs is the current root SID -- user can be authenticated
+ // against that SID.
+ return new UserNotAuthenticatedException();
+ }
+
+ long fingerprintOnlySid = getFingerprintOnlySid();
+ if ((fingerprintOnlySid != 0)
+ && (keySids.contains(Long.valueOf(fingerprintOnlySid)))) {
+ // One of the key's SIDs is the current fingerprint SID -- user can be
+ // authenticated against that SID.
+ return new UserNotAuthenticatedException();
+ }
+
+ // None of the key's SIDs can ever be authenticated
+ return new KeyPermanentlyInvalidatedException();
+ }
default:
return new InvalidKeyException("Keystore operation failed", e);
}
}
+ private static long getFingerprintOnlySid() {
+ IFingerprintService service = IFingerprintService.Stub.asInterface(
+ ServiceManager.getService(Context.FINGERPRINT_SERVICE));
+ if (service == null) {
+ return 0;
+ }
+
+ try {
+ long deviceId = 0; // TODO: plumb hardware id to FPMS
+ if (!service.isHardwareDetected(deviceId)) {
+ return 0;
+ }
+
+ return service.getAuthenticatorId();
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Failed to communicate with fingerprint service", e);
+ }
+ }
+
/**
* Returns an {@link InvalidKeyException} corresponding to the provided keystore/keymaster error
* code.
*/
- static InvalidKeyException getInvalidKeyException(int errorCode) {
- return getInvalidKeyException(getKeyStoreException(errorCode));
+ InvalidKeyException getInvalidKeyException(String keystoreKeyAlias, int errorCode) {
+ return getInvalidKeyException(keystoreKeyAlias, getKeyStoreException(errorCode));
}
}
case KeymasterDefs.KM_ERROR_INVALID_NONCE:
throw new InvalidAlgorithmParameterException("Invalid IV");
}
- throw KeyStore.getInvalidKeyException(opResult.resultCode);
+ throw mKeyStore.getInvalidKeyException(mKey.getAlias(), opResult.resultCode);
}
if (opResult.token == null) {
if (opResult == null) {
throw new KeyStoreConnectException();
} else if (opResult.resultCode != KeyStore.NO_ERROR) {
- throw KeyStore.getInvalidKeyException(opResult.resultCode);
+ throw mKeyStore.getInvalidKeyException(mKey.getAlias(), opResult.resultCode);
}
if (opResult.token == null) {
throw new IllegalStateException("Keystore returned null operation token");
import android.content.Context;
import android.hardware.fingerprint.FingerprintManager;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.UserHandle;
import android.security.keymaster.KeymasterArguments;
import android.security.keymaster.KeymasterDefs;
-import android.service.gatekeeper.IGateKeeperService;
import libcore.util.EmptyArray;
return result;
}
- private static long getRootSid() {
- IGateKeeperService gatekeeperService = IGateKeeperService.Stub.asInterface(
- ServiceManager.getService("android.service.gatekeeper.IGateKeeperService"));
- if (gatekeeperService == null) {
- throw new IllegalStateException("Gatekeeper service not available");
- }
-
- try {
- return gatekeeperService.getSecureUserId(UserHandle.myUserId());
- } catch (RemoteException e) {
- throw new IllegalStateException("Failed to obtain root SID");
- }
- }
-
/**
* Adds keymaster arguments to express the key's authorization policy supported by user
* authentication.
} else {
// The key is authorized for use for the specified amount of time after the user has
// authenticated. Whatever unlocks the secure lock screen should authorize this key.
- long rootSid = getRootSid();
+ long rootSid = GateKeeper.getSecureUserId();
if (rootSid == 0) {
throw new IllegalStateException("Secure lock screen must be enabled"
+ " to create keys requiring user authentication");
+++ /dev/null
-/*
- * 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.security;
-
-import java.security.InvalidKeyException;
-
-/**
- * Indicates that a cryptographic operation could not be performed because the key used by the
- * operation is permanently invalid because a new fingerprint was enrolled.
- */
-public class NewFingerprintEnrolledException extends InvalidKeyException {
-
- /**
- * Constructs a new {@code NewFingerprintEnrolledException} without detail message and cause.
- */
- public NewFingerprintEnrolledException() {
- super("Invalid key: new fingerprint enrolled");
- }
-
- /**
- * Constructs a new {@code NewFingerprintEnrolledException} with the provided detail message and
- * no cause.
- */
- public NewFingerprintEnrolledException(String message) {
- super(message);
- }
-}
/**
* Indicates that a cryptographic operation could not be performed because the user has not been
- * authenticated recently enough.
+ * authenticated recently enough. Authenticating the user will resolve this issue.
*/
public class UserNotAuthenticatedException extends InvalidKeyException {
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)) {
replayBatchList(mBatches, renderer, dirty);
renderer.restoreToCount(1);
- renderer.setDrawModifiers(restoreDrawModifiers);
DEFER_LOGD("--flush complete, returning %x", status);
clear();
int mClipSideFlags; // specifies which sides of the bounds are clipped, unclipped if cleared
bool mClipped;
mat4 mMatrix;
- DrawModifiers mDrawModifiers;
float mAlpha;
const RoundRectClipState* mRoundRectClipState;
};
kWindowLayoutChanged = 1 << 0,
kRTAnimation = 1 << 1,
kSurfaceCanvas = 1 << 2,
+ kSkippedFrame = 1 << 3,
};
MAKE_FLAGS_ENUM(FrameInfoFlags)
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)];
, mLightRadius(FLT_MIN)
, mAmbientShadowAlpha(0)
, mSpotShadowAlpha(0) {
- // *set* draw modifiers to be 0
- memset(&mDrawModifiers, 0, sizeof(mDrawModifiers));
- mDrawModifiers.mOverrideLayerAlpha = 1.0f;
}
OpenGLRenderer::~OpenGLRenderer() {
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
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) {
endTiling();
RenderBuffer* buffer = mCaches.renderBufferCache.get(
- Stencil::getSmallestStencilFormat(),
+ Stencil::getLayerStencilFormat(),
layer->getWidth(), layer->getHeight());
layer->setStencilRenderBuffer(buffer);
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
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
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.
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();
}
/**
* 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
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
*/
// 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
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;
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();
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;
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
*/
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.
#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 {
, 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);
}
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()) {
prepareTree(info, frameInfo);
if (info.out.canDrawThisFrame) {
draw();
+ } else {
+ mCurrentFrameInfo->addFlag(FrameInfoFlags::kSkippedFrame);
}
}
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;
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
return native_set_pos_update_period(periodInFrames);
}
-
//--------------------------------------------------------------------------
// Explicit Routing
//--------------------
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();
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");
+ }
}
* @throws IllegalStateException if track is not initialized.
*/
public @NonNull PlaybackSettings getPlaybackSettings() {
- float[] floatArray = new float[2];
- int[] intArray = new int[2];
- native_get_playback_settings(floatArray, intArray);
- return new PlaybackSettings()
- .setSpeed(floatArray[0])
- .setPitch(floatArray[1])
- .setAudioFallbackMode(intArray[0]);
+ return native_get_playback_settings();
}
/**
if (settings == null) {
throw new IllegalArgumentException("settings is null");
}
- float[] floatArray;
- int[] intArray;
- try {
- floatArray = new float[] {
- settings.getSpeed(),
- settings.getPitch(),
- };
- intArray = new int[] {
- settings.getAudioFallbackMode(),
- PlaybackSettings.AUDIO_STRETCH_MODE_DEFAULT,
- };
- } catch (IllegalStateException e) {
- throw new IllegalArgumentException(e);
- }
- native_set_playback_settings(floatArray, intArray);
+ native_set_playback_settings(settings);
}
private native final int native_set_playback_rate(int sampleRateInHz);
private native final int native_get_playback_rate();
- // floatArray must be a non-null array of length >= 2
- // [0] is speed
- // [1] is pitch
- // intArray must be a non-null array of length >= 2
- // [0] is audio fallback mode
- // [1] is audio stretch mode
- private native final void native_set_playback_settings(float[] floatArray, int[] intArray);
- private native final void native_get_playback_settings(float[] floatArray, int[] intArray);
+ private native final void native_set_playback_settings(@NonNull PlaybackSettings settings);
+ private native final @NonNull PlaybackSettings native_get_playback_settings();
private native final int native_set_marker_pos(int marker);
private native final int native_get_marker_pos();
import android.annotation.SystemApi;
import android.app.ActivityThread;
+import android.app.Application;
import android.hardware.Camera;
import android.os.Handler;
import android.os.Looper;
/* 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());
}
/**
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();
@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");
+ }
}
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
* @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");
}
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;
}
}
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 + "\"");
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;
// 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.");
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();
}
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");
+ }
}
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;
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) {
private native final int native_setup(Object audioeffect_this,
int audioSession,
- int[] id);
+ int[] id,
+ String opPackageName);
private native final void 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");
+ }
}
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.
#include <media/mediarecorder.h>
#include <utils/threads.h>
+#include <ScopedUtfChars.h>
+
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
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;
{"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},
};
#include <android_runtime/AndroidRuntime.h>
#include "media/AudioEffect.h"
+#include <ScopedUtfChars.h>
+
using namespace android;
#define AUDIOEFFECT_SUCCESS 0
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;
jstring jdescName;
jstring jdescImplementor;
+ ScopedUtfChars opPackageNameStr(env, opPackageName);
+
if (type != NULL) {
typeStr = env->GetStringUTFChars(type, NULL);
if (typeStr == NULL) { // Out of memory
// create the native AudioEffect object
lpAudioEffect = new AudioEffect(typeStr,
+ String16(opPackageNameStr.c_str()),
uuidStr,
priority,
effectCallback,
// 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},
#include <utils/threads.h>
#include "media/Visualizer.h"
+#include <ScopedUtfChars.h>
+
using namespace android;
#define VISUALIZER_SUCCESS 0
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;
Visualizer* lpVisualizer = NULL;
jint* nId = NULL;
+ ScopedUtfChars opPackageNameStr(env, opPackageName);
+
lpJniStorage = new visualizerJniStorage();
if (lpJniStorage == NULL) {
ALOGE("setup: Error creating JNI Storage");
}
// create the native Visualizer object
- lpVisualizer = new Visualizer(0,
+ lpVisualizer = new Visualizer(String16(opPackageNameStr.c_str()),
+ 0,
android_media_visualizer_effect_callback,
lpJniStorage,
sessionId);
// 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},
}
@Override
- public void onPinnedModeChanged(final boolean inPinnedMode) {
+ public void onHeadsUpPinnedModeChanged(final boolean inPinnedMode) {
if (inPinnedMode) {
mHeadsUpExistenceChangedRunnable.run();
updateNotificationTranslucency();
}
@Override
- public void onPinnedModeChanged(boolean inPinnedMode) {
+ public void onHeadsUpPinnedModeChanged(boolean inPinnedMode) {
if (inPinnedMode) {
mStatusBarWindowManager.setHeadsUpShowing(true);
} else {
@Override
public void onHeadsUpPinned(ExpandableNotificationRow headsUp) {
+ dismissVolumeDialog();
}
@Override
}
// 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();
}
@Override
- public void onPinnedModeChanged(boolean inPinnedMode) {
+ public void onHeadsUpPinnedModeChanged(boolean inPinnedMode) {
}
@Override
}
mHasPinnedNotification = hasPinnedNotification;
for (OnHeadsUpChangedListener listener : mListeners) {
- listener.onPinnedModeChanged(hasPinnedNotification);
+ listener.onHeadsUpPinnedModeChanged(hasPinnedNotification);
}
}
*
* @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.
// 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);
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.
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);
}
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;
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;
}
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);
--- /dev/null
+/*
+ * 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();
+ }
+ }
+ }
+}
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;
*/
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";
/** 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. */
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));
+ }
+ }
+ }
}
/**
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();
}
@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();
+ }
}
}
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()) {
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) {
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.
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;
}
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 {
// 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);
permission, callingUid, userId);
rl.add(bf);
if (!bf.debugCheck()) {
- Slog.w(TAG, "==> For Dynamic broadast");
+ Slog.w(TAG, "==> For Dynamic broadcast");
}
mReceiverResolver.addFilter(bf);
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,
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));
}
}
}
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));
}
}
}
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
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,
handleConnectionFailure(false);
}
}
- }, mHandler);
+ }, mHandler, mContext.getOpPackageName());
// Use extended timeout value for certification, as some tests require user inputs
int rtspTimeout = mWifiDisplayCertMode ?
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;
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;
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;
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;
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;
}
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;
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;
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;
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;
import android.util.TrustedTime;
import android.util.Xml;
-import com.android.server.AppOpsService;
import libcore.io.IoUtils;
import com.android.internal.R;
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;
* 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;
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();
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);
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() {
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);
WifiManager.NETWORK_STATE_CHANGED_ACTION);
mContext.registerReceiver(mWifiStateReceiver, wifiStateFilter, null, mHandler);
+ mUsageStats.addAppIdleStateChangeListener(this);
+
}
private IProcessObserver mProcessObserver = new IProcessObserver.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) {
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;
}
}
};
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.
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;
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) {
}
}
- // TODO: only dispatch when rules actually change
+ final int oldRules = mUidRules.get(uid);
if (uidRules == RULE_ALLOW_ALL) {
mUidRules.delete(uid);
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
}
}
+ @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) {
}
}
+ /**
+ * 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);
+++ /dev/null
-/*
- * 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();
- }
- }
- }
-}
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);
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);
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;
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;
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);
if (!disableNonCoreServices) {
mSystemServiceManager.startService(MediaProjectionManagerService.class);
- mSystemServiceManager.startService(DeviceIdleController.class);
}
// Before things start rolling, be sure we have decided whether
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;
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;
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;
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;
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<>();
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");
+ 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();
}
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));
}
}
}
}
}
+ 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) {
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);
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;
}
resetLastTimestamp((String) msg.obj, msg.arg1, msg.arg2 == 1);
break;
+ case MSG_CHECK_IDLE_STATES:
+ checkIdleStates();
+ break;
default:
super.handleMessage(msg);
break;
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();
}
}
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;
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);
*/
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 + ")");
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>();
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
/* 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";
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);
}
/**
/**
* 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
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);