Merge "UsbMidiDevice: Only keep ALSA devices open when device is in use" into mnc-dev
diff --git a/Android.mk b/Android.mk
index 68f471a..1752caf 100644
--- a/Android.mk
+++ b/Android.mk
@@ -451,6 +451,7 @@
frameworks/base/telephony/java/android/telephony/SignalStrength.aidl \
frameworks/base/telephony/java/android/telephony/IccOpenLogicalChannelResponse.aidl \
frameworks/base/telephony/java/android/telephony/NeighboringCellInfo.aidl \
+ frameworks/base/telephony/java/android/telephony/ModemActivityInfo.aidl \
frameworks/base/location/java/android/location/Location.aidl \
frameworks/base/location/java/android/location/Address.aidl \
frameworks/base/location/java/android/location/Criteria.aidl \
diff --git a/api/current.txt b/api/current.txt
index 6b261d8..58ecc39 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5790,7 +5790,6 @@
method public void setPermissionPolicy(android.content.ComponentName, int);
method public boolean setPermittedAccessibilityServices(android.content.ComponentName, java.util.List<java.lang.String>);
method public boolean setPermittedInputMethods(android.content.ComponentName, java.util.List<java.lang.String>);
- method public void setPreferredSetupActivity(android.content.ComponentName, android.content.ComponentName);
method public void setProfileEnabled(android.content.ComponentName);
method public void setProfileName(android.content.ComponentName, java.lang.String);
method public void setRecommendedGlobalProxy(android.content.ComponentName, android.net.ProxyInfo);
@@ -13942,16 +13941,8 @@
package android.hardware.fingerprint {
- public final class Fingerprint implements android.os.Parcelable {
- ctor public Fingerprint(java.lang.CharSequence, int, int, long);
- method public int describeContents();
- method public java.lang.CharSequence getName();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.hardware.fingerprint.Fingerprint> CREATOR;
- }
-
public class FingerprintManager {
- method public void authenticate(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.CancellationSignal, android.hardware.fingerprint.FingerprintManager.AuthenticationCallback, int);
+ method public void authenticate(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.CancellationSignal, int, android.hardware.fingerprint.FingerprintManager.AuthenticationCallback, android.os.Handler);
method public boolean hasEnrolledFingerprints();
method public boolean isHardwareDetected();
field public static final int FINGERPRINT_ACQUIRED_GOOD = 0; // 0x0
@@ -13960,14 +13951,12 @@
field public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1; // 0x1
field public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 5; // 0x5
field public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 4; // 0x4
- field public static final int FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000; // 0x3e8
field public static final int FINGERPRINT_ERROR_CANCELED = 5; // 0x5
field public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; // 0x1
field public static final int FINGERPRINT_ERROR_LOCKOUT = 7; // 0x7
field public static final int FINGERPRINT_ERROR_NO_SPACE = 4; // 0x4
field public static final int FINGERPRINT_ERROR_TIMEOUT = 3; // 0x3
field public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2; // 0x2
- field public static final int FINGERPRINT_ERROR_VENDOR_BASE = 1000; // 0x3e8
}
public static abstract class FingerprintManager.AuthenticationCallback {
@@ -13979,11 +13968,10 @@
}
public static final class FingerprintManager.AuthenticationResult {
- ctor public FingerprintManager.AuthenticationResult(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.hardware.fingerprint.Fingerprint);
method public android.hardware.fingerprint.FingerprintManager.CryptoObject getCryptoObject();
}
- public static class FingerprintManager.CryptoObject {
+ public static final class FingerprintManager.CryptoObject {
ctor public FingerprintManager.CryptoObject(java.security.Signature);
ctor public FingerprintManager.CryptoObject(javax.crypto.Cipher);
ctor public FingerprintManager.CryptoObject(javax.crypto.Mac);
@@ -18340,6 +18328,7 @@
public class Network implements android.os.Parcelable {
method public void bindSocket(java.net.DatagramSocket) throws java.io.IOException;
method public void bindSocket(java.net.Socket) throws java.io.IOException;
+ method public void bindSocket(java.io.FileDescriptor) throws java.io.IOException;
method public int describeContents();
method public java.net.InetAddress[] getAllByName(java.lang.String) throws java.net.UnknownHostException;
method public java.net.InetAddress getByName(java.lang.String) throws java.net.UnknownHostException;
@@ -22910,6 +22899,8 @@
public static class Debug.MemoryInfo implements android.os.Parcelable {
ctor public Debug.MemoryInfo();
method public int describeContents();
+ method public java.lang.String getMemoryStat(java.lang.String);
+ method public java.util.Map<java.lang.String, java.lang.String> getMemoryStats();
method public int getTotalPrivateClean();
method public int getTotalPrivateDirty();
method public int getTotalPss();
@@ -28395,7 +28386,7 @@
method public static android.content.Intent createInstallIntent();
method public static java.security.cert.X509Certificate[] getCertificateChain(android.content.Context, java.lang.String) throws java.lang.InterruptedException, android.security.KeyChainException;
method public static java.security.PrivateKey getPrivateKey(android.content.Context, java.lang.String) throws java.lang.InterruptedException, android.security.KeyChainException;
- method public static boolean isBoundKeyAlgorithm(java.lang.String);
+ method public static deprecated boolean isBoundKeyAlgorithm(java.lang.String);
method public static boolean isKeyAlgorithmSupported(java.lang.String);
field public static final java.lang.String ACTION_STORAGE_CHANGED = "android.security.STORAGE_CHANGED";
field public static final java.lang.String EXTRA_CERTIFICATE = "CERT";
@@ -30670,7 +30661,7 @@
public class CarrierConfigManager {
method public android.os.PersistableBundle getConfig();
method public android.os.PersistableBundle getConfigForSubId(int);
- method public void reloadCarrierConfigForSubId(int);
+ method public void notifyConfigChangedForSubId(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 KEY_ADDITIONAL_CALL_SETTING_BOOL = "additional_call_setting_bool";
field public static final java.lang.String KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL = "allow_emergency_numbers_in_call_log_bool";
diff --git a/api/system-current.txt b/api/system-current.txt
index 1c524c1..e3e1787 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5900,7 +5900,6 @@
method public void setPermissionPolicy(android.content.ComponentName, int);
method public boolean setPermittedAccessibilityServices(android.content.ComponentName, java.util.List<java.lang.String>);
method public boolean setPermittedInputMethods(android.content.ComponentName, java.util.List<java.lang.String>);
- method public void setPreferredSetupActivity(android.content.ComponentName, android.content.ComponentName);
method public void setProfileEnabled(android.content.ComponentName);
method public void setProfileName(android.content.ComponentName, java.lang.String);
method public void setRecommendedGlobalProxy(android.content.ComponentName, android.net.ProxyInfo);
@@ -14260,16 +14259,8 @@
package android.hardware.fingerprint {
- public final class Fingerprint implements android.os.Parcelable {
- ctor public Fingerprint(java.lang.CharSequence, int, int, long);
- method public int describeContents();
- method public java.lang.CharSequence getName();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.hardware.fingerprint.Fingerprint> CREATOR;
- }
-
public class FingerprintManager {
- method public void authenticate(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.CancellationSignal, android.hardware.fingerprint.FingerprintManager.AuthenticationCallback, int);
+ method public void authenticate(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.CancellationSignal, int, android.hardware.fingerprint.FingerprintManager.AuthenticationCallback, android.os.Handler);
method public boolean hasEnrolledFingerprints();
method public boolean isHardwareDetected();
field public static final int FINGERPRINT_ACQUIRED_GOOD = 0; // 0x0
@@ -14278,14 +14269,12 @@
field public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1; // 0x1
field public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 5; // 0x5
field public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 4; // 0x4
- field public static final int FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000; // 0x3e8
field public static final int FINGERPRINT_ERROR_CANCELED = 5; // 0x5
field public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; // 0x1
field public static final int FINGERPRINT_ERROR_LOCKOUT = 7; // 0x7
field public static final int FINGERPRINT_ERROR_NO_SPACE = 4; // 0x4
field public static final int FINGERPRINT_ERROR_TIMEOUT = 3; // 0x3
field public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2; // 0x2
- field public static final int FINGERPRINT_ERROR_VENDOR_BASE = 1000; // 0x3e8
}
public static abstract class FingerprintManager.AuthenticationCallback {
@@ -14297,11 +14286,10 @@
}
public static final class FingerprintManager.AuthenticationResult {
- ctor public FingerprintManager.AuthenticationResult(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.hardware.fingerprint.Fingerprint);
method public android.hardware.fingerprint.FingerprintManager.CryptoObject getCryptoObject();
}
- public static class FingerprintManager.CryptoObject {
+ public static final class FingerprintManager.CryptoObject {
ctor public FingerprintManager.CryptoObject(java.security.Signature);
ctor public FingerprintManager.CryptoObject(javax.crypto.Cipher);
ctor public FingerprintManager.CryptoObject(javax.crypto.Mac);
@@ -19826,6 +19814,7 @@
public class Network implements android.os.Parcelable {
method public void bindSocket(java.net.DatagramSocket) throws java.io.IOException;
method public void bindSocket(java.net.Socket) throws java.io.IOException;
+ method public void bindSocket(java.io.FileDescriptor) throws java.io.IOException;
method public int describeContents();
method public java.net.InetAddress[] getAllByName(java.lang.String) throws java.net.UnknownHostException;
method public java.net.InetAddress getByName(java.lang.String) throws java.net.UnknownHostException;
@@ -24828,6 +24817,8 @@
public static class Debug.MemoryInfo implements android.os.Parcelable {
ctor public Debug.MemoryInfo();
method public int describeContents();
+ method public java.lang.String getMemoryStat(java.lang.String);
+ method public java.util.Map<java.lang.String, java.lang.String> getMemoryStats();
method public int getTotalPrivateClean();
method public int getTotalPrivateDirty();
method public int getTotalPss();
@@ -30428,7 +30419,7 @@
method public static android.content.Intent createInstallIntent();
method public static java.security.cert.X509Certificate[] getCertificateChain(android.content.Context, java.lang.String) throws java.lang.InterruptedException, android.security.KeyChainException;
method public static java.security.PrivateKey getPrivateKey(android.content.Context, java.lang.String) throws java.lang.InterruptedException, android.security.KeyChainException;
- method public static boolean isBoundKeyAlgorithm(java.lang.String);
+ method public static deprecated boolean isBoundKeyAlgorithm(java.lang.String);
method public static boolean isKeyAlgorithmSupported(java.lang.String);
field public static final java.lang.String ACTION_STORAGE_CHANGED = "android.security.STORAGE_CHANGED";
field public static final java.lang.String EXTRA_CERTIFICATE = "CERT";
@@ -32885,7 +32876,7 @@
method public android.os.PersistableBundle getConfig();
method public android.os.PersistableBundle getConfigForSubId(int);
method public static android.os.PersistableBundle getDefaultConfig();
- method public void reloadCarrierConfigForSubId(int);
+ method public void notifyConfigChangedForSubId(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 KEY_ADDITIONAL_CALL_SETTING_BOOL = "additional_call_setting_bool";
@@ -33422,6 +33413,7 @@
method public void call(java.lang.String, java.lang.String);
method public boolean canChangeDtmfToneLength();
method public int checkCarrierPrivilegesForPackage(java.lang.String);
+ method public int checkCarrierPrivilegesForPackageAnyPhone(java.lang.String);
method public void dial(java.lang.String);
method public boolean disableDataConnectivity();
method public boolean enableDataConnectivity();
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index bb553e4..dabcc50c 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2534,15 +2534,6 @@
return true;
}
- case UPDATE_PREFERRED_SETUP_ACTIVITY_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- ComponentName preferredActivity = ComponentName.readFromParcel(data);
- int userId = data.readInt();
- updatePreferredSetupActivity(preferredActivity, userId);
- reply.writeNoException();
- return true;
- }
-
case GET_PACKAGE_PROCESS_STATE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
String pkg = data.readString();
@@ -5868,20 +5859,6 @@
}
@Override
- public void updatePreferredSetupActivity(ComponentName preferredActivity, int userId)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- ComponentName.writeToParcel(preferredActivity, data);
- data.writeInt(userId);
- mRemote.transact(UPDATE_PREFERRED_SETUP_ACTIVITY_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
-
- @Override
public int getPackageProcessState(String packageName) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index e87eabe..0d5e1c7 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -502,8 +502,6 @@
throws RemoteException;
public void updateLockTaskPackages(int userId, String[] packages) throws RemoteException;
public void updateDeviceOwner(String packageName) throws RemoteException;
- public void updatePreferredSetupActivity(ComponentName preferredActivity, int userId)
- throws RemoteException;
public int getPackageProcessState(String packageName) throws RemoteException;
@@ -850,8 +848,7 @@
int GET_PACKAGE_PROCESS_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+293;
int SHOW_LOCK_TASK_ESCAPE_MESSAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+294;
int UPDATE_DEVICE_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+295;
- int UPDATE_PREFERRED_SETUP_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+296;
- int KEYGUARD_GOING_AWAY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+297;
- int REGISTER_UID_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+298;
- int UNREGISTER_UID_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+299;
+ int KEYGUARD_GOING_AWAY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+296;
+ int REGISTER_UID_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+297;
+ int UNREGISTER_UID_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+298;
}
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index 9ba6a8e..39cd3bc 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -239,9 +239,10 @@
public void run() {
InputStream in = null;
OutputStream out = null;
+ java.lang.Process process = null;
try {
- java.lang.Process process = Runtime.getRuntime().exec(command);
+ process = Runtime.getRuntime().exec(command);
in = process.getInputStream();
out = new FileOutputStream(sink.getFileDescriptor());
@@ -257,7 +258,9 @@
} catch (IOException ioe) {
throw new RuntimeException("Error running shell command", ioe);
} finally {
- IoUtils.closeQuietly(in);
+ if (process != null) {
+ process.destroy();
+ }
IoUtils.closeQuietly(out);
IoUtils.closeQuietly(sink);
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 55eaf27..3ab0e01 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -4404,24 +4404,6 @@
}
/**
- * Called by a device initializer to set the activity to be launched on device boot or after a
- * user switch during user setup. This activity will be started regardless of the priority of
- * other 'home' activities. Once user setup is complete, the preferred setup activity will be
- * ignored.
- *
- * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @param activity The Activity to be started by default during user setup.
- */
- public void setPreferredSetupActivity(@NonNull ComponentName admin,
- @NonNull ComponentName activity) {
- try {
- mService.setPreferredSetupActivity(admin, activity);
- } catch (RemoteException re) {
- Log.w(TAG, "Failed talking with device policy service", re);
- }
- }
-
- /**
* Called by profile or device owners to set the default response for future runtime permission
* requests by applications. The policy can allow for normal operation which prompts the
* user to grant a permission, or can allow automatic granting or denying of runtime
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 477a338..8c7b20a 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -218,8 +218,6 @@
String getDeviceInitializer();
ComponentName getDeviceInitializerComponent();
- void setPreferredSetupActivity(in ComponentName admin, in ComponentName activity);
-
void setUserIcon(in ComponentName admin, in Bitmap icon);
void sendDeviceInitializerStatus(int statusCode, String description);
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index caf21d5..e61813c 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -18,32 +18,30 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.app.ActivityManagerNative;
-import android.content.ContentResolver;
import android.content.Context;
import android.os.Binder;
import android.os.CancellationSignal;
import android.os.CancellationSignal.OnCancelListener;
import android.os.Handler;
import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
+import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.provider.Settings;
-import android.hardware.fingerprint.FingerprintManager.EnrollmentCallback;
import android.security.keystore.AndroidKeyStoreProvider;
import android.util.Log;
import android.util.Slog;
import java.security.Signature;
-import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
import javax.crypto.Cipher;
import javax.crypto.Mac;
+import static android.Manifest.permission.USE_FINGERPRINT;
+import static android.Manifest.permission.MANAGE_FINGERPRINT;
+
/**
* A class that coordinates access to the fingerprint hardware.
* <p>
@@ -57,9 +55,10 @@
private static final boolean DEBUG = true;
private static final int MSG_ENROLL_RESULT = 100;
private static final int MSG_ACQUIRED = 101;
- private static final int MSG_AUTHENTICATED = 102;
- private static final int MSG_ERROR = 103;
- private static final int MSG_REMOVED = 104;
+ private static final int MSG_AUTHENTICATION_SUCCEEDED = 102;
+ private static final int MSG_AUTHENTICATION_FAILED = 103;
+ private static final int MSG_ERROR = 104;
+ private static final int MSG_REMOVED = 105;
//
// Error messages from fingerprint hardware during initilization, enrollment, authentication or
@@ -112,6 +111,7 @@
/**
* Hardware vendors may extend this list if there are conditions that do not fall under one of
* the above categories. Vendors are responsible for providing error strings for these errors.
+ * @hide
*/
public static final int FINGERPRINT_ERROR_VENDOR_BASE = 1000;
@@ -162,6 +162,7 @@
/**
* Hardware vendors may extend this list if there are conditions that do not fall under one of
* the above categories. Vendors are responsible for providing error strings for these errors.
+ * @hide
*/
public static final int FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000;
@@ -173,6 +174,7 @@
private RemovalCallback mRemovalCallback;
private CryptoObject mCryptoObject;
private Fingerprint mRemovalFingerprint;
+ private Handler mHandler;
private class OnEnrollCancelListener implements OnCancelListener {
@Override
@@ -198,72 +200,71 @@
* A wrapper class for the crypto objects supported by FingerprintManager. Currently the
* framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects.
*/
- public static class CryptoObject {
+ public static final class CryptoObject {
public CryptoObject(@NonNull Signature signature) {
- mSignature = signature;
- mCipher = null;
- mMac = null;
+ mCrypto = signature;
}
public CryptoObject(@NonNull Cipher cipher) {
- mCipher = cipher;
- mSignature = null;
- mMac = null;
+ mCrypto = cipher;
}
public CryptoObject(@NonNull Mac mac) {
- mMac = mac;
- mCipher = null;
- mSignature = null;
+ mCrypto = mac;
}
/**
* Get {@link Signature} object.
* @return {@link Signature} object or null if this doesn't contain one.
*/
- public Signature getSignature() { return mSignature; }
+ public Signature getSignature() {
+ return mCrypto instanceof Signature ? (Signature) mCrypto : null;
+ }
/**
* Get {@link Cipher} object.
* @return {@link Cipher} object or null if this doesn't contain one.
*/
- public Cipher getCipher() { return mCipher; }
+ public Cipher getCipher() {
+ return mCrypto instanceof Cipher ? (Cipher) mCrypto : null;
+ }
/**
* Get {@link Mac} object.
* @return {@link Mac} object or null if this doesn't contain one.
*/
- public Mac getMac() { return mMac; }
+ public Mac getMac() {
+ return mCrypto instanceof Mac ? (Mac) mCrypto : null;
+ }
/**
* @hide
* @return the opId associated with this object or 0 if none
*/
public long getOpId() {
- if (mSignature != null) {
- return AndroidKeyStoreProvider.getKeyStoreOperationHandle(mSignature);
- } else if (mCipher != null) {
- return AndroidKeyStoreProvider.getKeyStoreOperationHandle(mCipher);
- } else if (mMac != null) {
- return AndroidKeyStoreProvider.getKeyStoreOperationHandle(mMac);
- }
- return 0;
+ return mCrypto != null ?
+ AndroidKeyStoreProvider.getKeyStoreOperationHandle(mCrypto) : 0;
}
- private final Signature mSignature;
- private final Cipher mCipher;
- private final Mac mMac;
+ private final Object mCrypto;
};
/**
* Container for callback data from {@link FingerprintManager#authenticate(CryptoObject,
- * CancellationSignal, AuthenticationCallback, int)}.
+ * CancellationSignal, int, AuthenticationCallback, Handler)}.
*/
public static final class AuthenticationResult {
private Fingerprint mFingerprint;
private CryptoObject mCryptoObject;
+ /**
+ * Authentication result
+ *
+ * @param crypto the crypto object
+ * @param fingerprint the recognized fingerprint data, if allowed.
+ * @hide
+ */
public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint) {
mCryptoObject = crypto;
mFingerprint = fingerprint;
@@ -272,7 +273,7 @@
/**
* Obtain the crypto object associated with this transaction
* @return crypto object provided to {@link FingerprintManager#authenticate(CryptoObject,
- * CancellationSignal, AuthenticationCallback, int)}.
+ * CancellationSignal, int, AuthenticationCallback, Handler)}.
*/
public CryptoObject getCryptoObject() { return mCryptoObject; }
@@ -287,28 +288,28 @@
/**
* Callback structure provided to {@link FingerprintManager#authenticate(CryptoObject,
- * CancellationSignal, AuthenticationCallback, int)}. Users of {@link
+ * CancellationSignal, int, AuthenticationCallback, Handler)}. Users of {@link
* FingerprintManager#authenticate(CryptoObject, CancellationSignal,
- * AuthenticationCallback, int) } must provide an implementation of this for listening to
+ * int, AuthenticationCallback, Handler) } must provide an implementation of this for listening to
* fingerprint events.
*/
public static abstract class AuthenticationCallback {
/**
* Called when an unrecoverable error has been encountered and the operation is complete.
* No further callbacks will be made on this object.
- * @param errMsgId An integer identifying the error message
+ * @param errorCode An integer identifying the error message
* @param errString A human-readable error string that can be shown in UI
*/
- public void onAuthenticationError(int errMsgId, CharSequence errString) { }
+ public void onAuthenticationError(int errorCode, CharSequence errString) { }
/**
* Called when a recoverable error has been encountered during authentication. The help
* string is provided to give the user guidance for what went wrong, such as
* "Sensor dirty, please clean it."
- * @param helpMsgId An integer identifying the error message
+ * @param helpCode An integer identifying the error message
* @param helpString A human-readable string that can be shown in UI
*/
- public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { }
+ public void onAuthenticationHelp(int helpCode, CharSequence helpString) { }
/**
* Called when a fingerprint is recognized.
@@ -326,7 +327,7 @@
* Callback structure provided to {@link FingerprintManager#enroll(long, EnrollmentCallback,
* CancellationSignal, int). Users of {@link #FingerprintManager()}
* must provide an implementation of this to {@link FingerprintManager#enroll(long,
- * CancellationSignal, EnrollmentCallback, int) for listening to fingerprint events.
+ * CancellationSignal, int, EnrollmentCallback) for listening to fingerprint events.
*
* @hide
*/
@@ -392,31 +393,35 @@
*
* @param crypto object associated with the call or null if none required.
* @param cancel an object that can be used to cancel authentication
- * @param callback an object to receive authentication events
* @param flags optional flags; should be 0
+ * @param callback an object to receive authentication events
+ * @param handler an optional handler to handle callback events
*/
+ @RequiresPermission(USE_FINGERPRINT)
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
- @NonNull AuthenticationCallback callback, int flags) {
- authenticate(crypto, cancel, callback, flags, UserHandle.myUserId());
+ int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler) {
+ authenticate(crypto, cancel, flags, callback, handler, UserHandle.myUserId());
}
/**
- * Request authentication of a crypto object. This call warms up the fingerprint hardware
- * and starts scanning for a fingerprint. It terminates when
- * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or
- * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult) is called, at
- * which point the object is no longer valid. The operation can be canceled by using the
- * provided cancel object.
- *
- * @param crypto object associated with the call or null if none required.
- * @param cancel an object that can be used to cancel authentication
- * @param callback an object to receive authentication events
- * @param flags optional flags; should be 0
- * @param userId the userId the fingerprint belongs to
+ * Use the provided handler thread for events.
+ * @param handler
+ */
+ private void useHandler(Handler handler) {
+ if (handler != null) {
+ mHandler = new MyHandler(handler.getLooper());
+ } else if (mHandler.getLooper() != mContext.getMainLooper()){
+ mHandler = new MyHandler(mContext.getMainLooper());
+ }
+ }
+
+ /**
+ * Per-user version
* @hide
*/
+ @RequiresPermission(USE_FINGERPRINT)
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
- @NonNull AuthenticationCallback callback, int flags, int userId) {
+ int flags, @NonNull AuthenticationCallback callback, Handler handler, int userId) {
if (callback == null) {
throw new IllegalArgumentException("Must supply an authentication callback");
}
@@ -431,6 +436,7 @@
}
if (mService != null) try {
+ useHandler(handler);
mAuthenticationCallback = callback;
mCryptoObject = crypto;
long sessionId = crypto != null ? crypto.getOpId() : 0;
@@ -458,12 +464,13 @@
* @param token a unique token provided by a recent creation or verification of device
* credentials (e.g. pin, pattern or password).
* @param cancel an object that can be used to cancel enrollment
- * @param callback an object to receive enrollment events
* @param flags optional flags
+ * @param callback an object to receive enrollment events
* @hide
*/
- public void enroll(byte [] token, CancellationSignal cancel, EnrollmentCallback callback,
- int flags) {
+ @RequiresPermission(MANAGE_FINGERPRINT)
+ public void enroll(byte [] token, CancellationSignal cancel, int flags,
+ EnrollmentCallback callback) {
if (callback == null) {
throw new IllegalArgumentException("Must supply an enrollment callback");
}
@@ -496,6 +503,7 @@
* existing device credentials (e.g. pin/pattern/password).
* @hide
*/
+ @RequiresPermission(MANAGE_FINGERPRINT)
public long preEnroll() {
long result = 0;
if (mService != null) try {
@@ -514,6 +522,7 @@
*
* @hide
*/
+ @RequiresPermission(MANAGE_FINGERPRINT)
public void remove(Fingerprint fp, RemovalCallback callback) {
if (mService != null) try {
mRemovalCallback = callback;
@@ -535,6 +544,7 @@
*
* @hide
*/
+ @RequiresPermission(MANAGE_FINGERPRINT)
public void rename(int fpId, String newName) {
// Renames the given fpId
if (mService != null) {
@@ -554,6 +564,7 @@
*
* @hide
*/
+ @RequiresPermission(USE_FINGERPRINT)
public List<Fingerprint> getEnrolledFingerprints(int userId) {
if (mService != null) try {
return mService.getEnrolledFingerprints(userId, mContext.getOpPackageName());
@@ -569,6 +580,7 @@
*
* @hide
*/
+ @RequiresPermission(USE_FINGERPRINT)
public List<Fingerprint> getEnrolledFingerprints() {
return getEnrolledFingerprints(UserHandle.myUserId());
}
@@ -578,6 +590,7 @@
*
* @return true if at least one fingerprint is enrolled, false otherwise
*/
+ @RequiresPermission(USE_FINGERPRINT)
public boolean hasEnrolledFingerprints() {
if (mService != null) try {
return mService.hasEnrolledFingerprints(UserHandle.myUserId(),
@@ -593,6 +606,7 @@
*
* @return true if hardware is present and functional, false otherwise.
*/
+ @RequiresPermission(USE_FINGERPRINT)
public boolean isHardwareDetected() {
if (mService != null) {
try {
@@ -626,13 +640,15 @@
return 0;
}
- private Handler mHandler;
-
private class MyHandler extends Handler {
private MyHandler(Context context) {
super(context.getMainLooper());
}
+ private MyHandler(Looper looper) {
+ super(looper);
+ }
+
public void handleMessage(android.os.Message msg) {
switch(msg.what) {
case MSG_ENROLL_RESULT:
@@ -641,8 +657,11 @@
case MSG_ACQUIRED:
sendAcquiredResult((Long) msg.obj /* deviceId */, msg.arg1 /* acquire info */);
break;
- case MSG_AUTHENTICATED:
- sendAuthenticatedResult((Fingerprint) msg.obj);
+ case MSG_AUTHENTICATION_SUCCEEDED:
+ sendAuthenticatedSucceeded((Fingerprint) msg.obj);
+ break;
+ case MSG_AUTHENTICATION_FAILED:
+ sendAuthenticatedFailed();
break;
case MSG_ERROR:
sendErrorResult((Long) msg.obj /* deviceId */, msg.arg1 /* errMsgId */);
@@ -684,15 +703,16 @@
}
}
- private void sendAuthenticatedResult(Fingerprint fp) {
+ private void sendAuthenticatedSucceeded(Fingerprint fp) {
if (mAuthenticationCallback != null) {
- if (fp.getFingerId() == 0) {
- // Fingerprint template valid but doesn't match one in database
- mAuthenticationCallback.onAuthenticationFailed();
- } else {
- final AuthenticationResult result = new AuthenticationResult(mCryptoObject, fp);
- mAuthenticationCallback.onAuthenticationSucceeded(result);
- }
+ final AuthenticationResult result = new AuthenticationResult(mCryptoObject, fp);
+ mAuthenticationCallback.onAuthenticationSucceeded(result);
+ }
+ }
+
+ private void sendAuthenticatedFailed() {
+ if (mAuthenticationCallback != null) {
+ mAuthenticationCallback.onAuthenticationFailed();
}
}
@@ -809,24 +829,33 @@
private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {
+ @Override // binder call
public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0,
new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
}
+ @Override // binder call
public void onAcquired(long deviceId, int acquireInfo) {
mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, 0, deviceId).sendToTarget();
}
- public void onAuthenticated(long deviceId, int fingerId, int groupId) {
- mHandler.obtainMessage(MSG_AUTHENTICATED,
- new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
+ @Override // binder call
+ public void onAuthenticationSucceeded(long deviceId, Fingerprint fp) {
+ mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, fp).sendToTarget();
}
+ @Override // binder call
+ public void onAuthenticationFailed(long deviceId) {
+ mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();;
+ }
+
+ @Override // binder call
public void onError(long deviceId, int error) {
mHandler.obtainMessage(MSG_ERROR, error, 0, deviceId).sendToTarget();
}
+ @Override // binder call
public void onRemoved(long deviceId, int fingerId, int groupId) {
mHandler.obtainMessage(MSG_REMOVED, fingerId, groupId, deviceId).sendToTarget();
}
diff --git a/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl b/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl
index a2d74b8..57a429f 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl
@@ -15,6 +15,7 @@
*/
package android.hardware.fingerprint;
+import android.hardware.fingerprint.Fingerprint;
import android.os.Bundle;
import android.os.UserHandle;
@@ -25,7 +26,8 @@
oneway interface IFingerprintServiceReceiver {
void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining);
void onAcquired(long deviceId, int acquiredInfo);
- void onAuthenticated(long deviceId, int fingerId, int groupId);
+ void onAuthenticationSucceeded(long deviceId, in Fingerprint fp);
+ void onAuthenticationFailed(long deviceId);
void onError(long deviceId, int error);
void onRemoved(long deviceId, int fingerId, int groupId);
}
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index 754c6b3..9628bae 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -19,6 +19,8 @@
import android.os.Parcelable;
import android.os.Parcel;
import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -64,7 +66,7 @@
// maybeInitHttpClient() must be called prior to reading either variable.
private volatile ConnectionPool mConnectionPool = null;
private volatile com.android.okhttp.internal.Network mNetwork = null;
- private Object mLock = new Object();
+ private final Object mLock = new Object();
// Default connection pool values. These are evaluated at startup, just
// like the OkHttp code. Also like the OkHttp code, we will throw parse
@@ -300,14 +302,10 @@
* connected.
*/
public void bindSocket(DatagramSocket socket) throws IOException {
- // Apparently, the kernel doesn't update a connected UDP socket's routing upon mark changes.
- if (socket.isConnected()) {
- throw new SocketException("Socket is connected");
- }
// Query a property of the underlying socket to ensure that the socket's file descriptor
// exists, is available to bind to a network and is not closed.
socket.getReuseAddress();
- bindSocketFd(socket.getFileDescriptor$());
+ bindSocket(socket.getFileDescriptor$());
}
/**
@@ -316,18 +314,38 @@
* {@link ConnectivityManager#bindProcessToNetwork}. The socket must not be connected.
*/
public void bindSocket(Socket socket) throws IOException {
- // Apparently, the kernel doesn't update a connected TCP socket's routing upon mark changes.
- if (socket.isConnected()) {
- throw new SocketException("Socket is connected");
- }
// Query a property of the underlying socket to ensure that the socket's file descriptor
// exists, is available to bind to a network and is not closed.
socket.getReuseAddress();
- bindSocketFd(socket.getFileDescriptor$());
+ bindSocket(socket.getFileDescriptor$());
}
- private void bindSocketFd(FileDescriptor fd) throws IOException {
- int err = NetworkUtils.bindSocketToNetwork(fd.getInt$(), netId);
+ /**
+ * Binds the specified {@link FileDescriptor} to this {@code Network}. All data traffic on the
+ * socket represented by this file descriptor will be sent on this {@code Network},
+ * irrespective of any process-wide network binding set by
+ * {@link ConnectivityManager#bindProcessToNetwork}. The socket must not be connected.
+ */
+ public void bindSocket(FileDescriptor fd) throws IOException {
+ try {
+ final SocketAddress peer = Os.getpeername(fd);
+ final InetAddress inetPeer = ((InetSocketAddress) peer).getAddress();
+ if (!inetPeer.isAnyLocalAddress()) {
+ // Apparently, the kernel doesn't update a connected UDP socket's
+ // routing upon mark changes.
+ throw new SocketException("Socket is connected");
+ }
+ } catch (ErrnoException e) {
+ // getpeername() failed.
+ if (e.errno != OsConstants.ENOTCONN) {
+ throw e.rethrowAsSocketException();
+ }
+ } catch (ClassCastException e) {
+ // Wasn't an InetSocketAddress.
+ throw new SocketException("Only AF_INET/AF_INET6 sockets supported");
+ }
+
+ final int err = NetworkUtils.bindSocketToNetwork(fd.getInt$(), netId);
if (err != 0) {
// bindSocketToNetwork returns negative errno.
throw new ErrnoException("Binding socket to network " + netId, -err)
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 19c8fa9..87e8c5e 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -34,6 +34,7 @@
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
import java.util.Map;
import org.apache.harmony.dalvik.ddmc.Chunk;
@@ -389,6 +390,132 @@
}
}
+ /**
+ * Returns the value of a particular memory statistic or {@code null} if no
+ * such memory statistic exists.
+ *
+ * <p>The following table lists the memory statistics that are supported.
+ * Note that memory statistics may be added or removed in a future API level.</p>
+ *
+ * <table>
+ * <thead>
+ * <tr>
+ * <th>Memory statistic name</th>
+ * <th>Meaning</th>
+ * <th>Example</th>
+ * <th>Supported (API Levels)</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td>summary.java-heap</td>
+ * <td>The private Java Heap usage in kB. This corresponds to the Java Heap field
+ * in the App Summary section output by dumpsys meminfo.</td>
+ * <td>{@code 1442}</td>
+ * <td>23</td>
+ * </tr>
+ * <tr>
+ * <td>summary.native-heap</td>
+ * <td>The private Native Heap usage in kB. This corresponds to the Native Heap
+ * field in the App Summary section output by dumpsys meminfo.</td>
+ * <td>{@code 1442}</td>
+ * <td>23</td>
+ * </tr>
+ * <tr>
+ * <td>summary.code</td>
+ * <td>The memory usage for static code and resources in kB. This corresponds to
+ * the Code field in the App Summary section output by dumpsys meminfo.</td>
+ * <td>{@code 1442}</td>
+ * <td>23</td>
+ * </tr>
+ * <tr>
+ * <td>summary.stack</td>
+ * <td>The stack usage in kB. This corresponds to the Stack field in the
+ * App Summary section output by dumpsys meminfo.</td>
+ * <td>{@code 1442}</td>
+ * <td>23</td>
+ * </tr>
+ * <tr>
+ * <td>summary.graphics</td>
+ * <td>The graphics usage in kB. This corresponds to the Graphics field in the
+ * App Summary section output by dumpsys meminfo.</td>
+ * <td>{@code 1442}</td>
+ * <td>23</td>
+ * </tr>
+ * <tr>
+ * <td>summary.private-other</td>
+ * <td>Other private memory usage in kB. This corresponds to the Private Other
+ * field output in the App Summary section by dumpsys meminfo.</td>
+ * <td>{@code 1442}</td>
+ * <td>23</td>
+ * </tr>
+ * <tr>
+ * <td>summary.system</td>
+ * <td>Shared and system memory usage in kB. This corresponds to the System
+ * field output in the App Summary section by dumpsys meminfo.</td>
+ * <td>{@code 1442}</td>
+ * <td>23</td>
+ * </tr>
+ * <tr>
+ * <td>summary.total-pss</td>
+ * <td>Total PPS memory usage in kB.</td>
+ * <td>{@code 1442}</td>
+ * <td>23</td>
+ * </tr>
+ * <tr>
+ * <td>summary.total-swap</td>
+ * <td>Total swap usage in kB.</td>
+ * <td>{@code 1442}</td>
+ * <td>23</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ */
+ public String getMemoryStat(String statName) {
+ switch(statName) {
+ case "summary.java-heap":
+ return Integer.toString(getSummaryJavaHeap());
+ case "summary.native-heap":
+ return Integer.toString(getSummaryNativeHeap());
+ case "summary.code":
+ return Integer.toString(getSummaryCode());
+ case "summary.stack":
+ return Integer.toString(getSummaryStack());
+ case "summary.graphics":
+ return Integer.toString(getSummaryGraphics());
+ case "summary.private-other":
+ return Integer.toString(getSummaryPrivateOther());
+ case "summary.system":
+ return Integer.toString(getSummarySystem());
+ case "summary.total-pss":
+ return Integer.toString(getSummaryTotalPss());
+ case "summary.total-swap":
+ return Integer.toString(getSummaryTotalSwap());
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Returns a map of the names/values of the memory statistics
+ * that {@link #getMemoryStat(String)} supports.
+ *
+ * @return a map of the names/values of the supported memory statistics.
+ */
+ public Map<String, String> getMemoryStats() {
+ Map<String, String> stats = new HashMap<String, String>();
+ stats.put("summary.java-heap", Integer.toString(getSummaryJavaHeap()));
+ stats.put("summary.native-heap", Integer.toString(getSummaryNativeHeap()));
+ stats.put("summary.code", Integer.toString(getSummaryCode()));
+ stats.put("summary.stack", Integer.toString(getSummaryStack()));
+ stats.put("summary.graphics", Integer.toString(getSummaryGraphics()));
+ stats.put("summary.private-other", Integer.toString(getSummaryPrivateOther()));
+ stats.put("summary.system", Integer.toString(getSummarySystem()));
+ stats.put("summary.total-pss", Integer.toString(getSummaryTotalPss()));
+ stats.put("summary.total-swap", Integer.toString(getSummaryTotalSwap()));
+ return stats;
+ }
+
/**
* Pss of Java Heap bytes in KB due to the application.
* Notes:
diff --git a/core/java/android/service/carrier/CarrierService.java b/core/java/android/service/carrier/CarrierService.java
index 4a4a375..5f83452 100644
--- a/core/java/android/service/carrier/CarrierService.java
+++ b/core/java/android/service/carrier/CarrierService.java
@@ -59,16 +59,16 @@
* <ol>
* <li>The carrier app package is updated, or</li>
* <li>The carrier app requests a reload with
- * {@link android.telephony.CarrierConfigManager#reloadCarrierConfigForSubId
- * reloadCarrierConfigForSubId}.</li>
+ * {@link android.telephony.CarrierConfigManager#notifyConfigChangedForSubId
+ * notifyConfigChangedForSubId}.</li>
* </ol>
* This method can be called after a SIM card loads, which may be before or after boot.
* </p>
* <p>
* This method should not block for a long time. If expensive operations (e.g. network access)
* are required, this method can schedule the work and return null. Then, use
- * {@link android.telephony.CarrierConfigManager#reloadCarrierConfigForSubId
- * reloadCarrierConfigForSubId} to trigger a reload when the config is ready.
+ * {@link android.telephony.CarrierConfigManager#notifyConfigChangedForSubId
+ * notifyConfigChangedForSubId} to trigger a reload when the config is ready.
* </p>
* <p>
* Implementations should use the keys defined in {@link android.telephony.CarrierConfigManager
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
index 644adb6..a2bd700 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -97,6 +97,11 @@
void showSessionForActiveService(IVoiceInteractionSessionShowCallback showCallback);
/**
+ * Hides the session from the active service, if it is showing.
+ */
+ void hideCurrentSession();
+
+ /**
* Notifies the active service that a launch was requested from the Keyguard. This will only
* be called if {@link #activeServiceSupportsLaunchFromKeyguard()} returns true.
*/
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 25228d0..ee7ed0b 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -105,7 +105,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 126 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 127 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index c010dfe..294e4ba 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -2741,7 +2741,14 @@
try {
mode = getCallback().onWindowStartingActionMode(wrappedCallback, type);
} catch (AbstractMethodError ame) {
- // Older apps might not implement this callback method.
+ // Older apps might not implement the typed version of this method.
+ if (type == ActionMode.TYPE_PRIMARY) {
+ try {
+ mode = getCallback().onWindowStartingActionMode(wrappedCallback);
+ } catch (AbstractMethodError ame2) {
+ // Older apps might not implement this callback method at all.
+ }
+ }
}
}
if (mode != null) {
diff --git a/core/tests/coretests/src/android/net/NetworkTest.java b/core/tests/coretests/src/android/net/NetworkTest.java
new file mode 100644
index 0000000..b0ecb04
--- /dev/null
+++ b/core/tests/coretests/src/android/net/NetworkTest.java
@@ -0,0 +1,96 @@
+/*
+ * 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.net;
+
+import android.net.LocalServerSocket;
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
+import android.net.Network;
+import android.test.suitebuilder.annotation.SmallTest;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.Inet6Address;
+import java.net.SocketException;
+import junit.framework.TestCase;
+
+public class NetworkTest extends TestCase {
+ final Network mNetwork = new Network(99);
+
+ @SmallTest
+ public void testBindSocketOfInvalidFdThrows() throws Exception {
+
+ final FileDescriptor fd = new FileDescriptor();
+ assertFalse(fd.valid());
+
+ try {
+ mNetwork.bindSocket(fd);
+ fail("SocketException not thrown");
+ } catch (SocketException expected) {}
+ }
+
+ @SmallTest
+ public void testBindSocketOfNonSocketFdThrows() throws Exception {
+ final File devNull = new File("/dev/null");
+ assertTrue(devNull.canRead());
+
+ final FileInputStream fis = new FileInputStream(devNull);
+ assertTrue(null != fis.getFD());
+ assertTrue(fis.getFD().valid());
+
+ try {
+ mNetwork.bindSocket(fis.getFD());
+ fail("SocketException not thrown");
+ } catch (SocketException expected) {}
+ }
+
+ @SmallTest
+ public void testBindSocketOfConnectedDatagramSocketThrows() throws Exception {
+ final DatagramSocket mDgramSocket = new DatagramSocket(0, (InetAddress) Inet6Address.ANY);
+ mDgramSocket.connect((InetAddress) Inet6Address.LOOPBACK, 53);
+ assertTrue(mDgramSocket.isConnected());
+
+ try {
+ mNetwork.bindSocket(mDgramSocket);
+ fail("SocketException not thrown");
+ } catch (SocketException expected) {}
+ }
+
+ @SmallTest
+ public void testBindSocketOfLocalSocketThrows() throws Exception {
+ final LocalSocket mLocalClient = new LocalSocket();
+ mLocalClient.bind(new LocalSocketAddress("testClient"));
+ assertTrue(mLocalClient.getFileDescriptor().valid());
+
+ try {
+ mNetwork.bindSocket(mLocalClient.getFileDescriptor());
+ fail("SocketException not thrown");
+ } catch (SocketException expected) {}
+
+ final LocalServerSocket mLocalServer = new LocalServerSocket("testServer");
+ mLocalClient.connect(mLocalServer.getLocalSocketAddress());
+ assertTrue(mLocalClient.isConnected());
+
+ try {
+ mNetwork.bindSocket(mLocalClient.getFileDescriptor());
+ fail("SocketException not thrown");
+ } catch (SocketException expected) {}
+ }
+}
diff --git a/docs/html/training/articles/keystore.jd b/docs/html/training/articles/keystore.jd
index 20963f5..fca958e 100644
--- a/docs/html/training/articles/keystore.jd
+++ b/docs/html/training/articles/keystore.jd
@@ -197,7 +197,7 @@
reset (e.g. by a Device Admin).</li>
<li>User authentication is required for every use of the key. In this mode, a specific operation
involving a specific key is authorized by the user. Currently, the only means of such
- authorization is fingerprint authentication: {@link android.hardware.fingerprint.FingerprintManager#authenticate(CryptoObject, CancellationSignal, AuthenticationCallback, int) FingerprintManager.authenticate}.
+ authorization is fingerprint authentication: {@link android.hardware.fingerprint.FingerprintManager#authenticate(CryptoObject, CancellationSignal, int, AuthenticationCallback, Handler) FingerprintManager.authenticate}.
Such keys can only be generated or imported if at least one fingerprint is enrolled (see {@link android.hardware.fingerprint.FingerprintManager#hasEnrolledFingerprints() FingerprintManager.hasEnrolledFingerprints}).
These keys become permanently invalidated once all fingerprints are unenrolled.</li>
</ul>
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 817b7c9..059d8e6 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -29,11 +29,13 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.security.keystore.KeyInfo;
import android.security.keystore.KeyProperties;
import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.security.InvalidKeyException;
+import java.security.KeyFactory;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.cert.Certificate;
@@ -442,7 +444,20 @@
* imported or generated. This can be used to tell if there is special
* hardware support that can be used to bind keys to the device in a way
* that makes it non-exportable.
+ *
+ * @deprecated Whether the key is bound to the secure hardware is known only
+ * once the key has been imported. To find out, use:
+ * <pre>{@code
+ * PrivateKey key = ...; // private key from KeyChain
+ *
+ * KeyFactory keyFactory =
+ * KeyFactory.getInstance(key.getAlgorithm(), "AndroidKeyStore");
+ * KeyInfo keyInfo = keyFactory.getKeySpec(key, KeyInfo.class);
+ * if (keyInfo.isInsideSecureHardware()) {
+ * // The key is bound to the secure hardware of this Android
+ * }}</pre>
*/
+ @Deprecated
public static boolean isBoundKeyAlgorithm(
@NonNull @KeyProperties.KeyAlgorithmEnum String algorithm) {
if (!isKeyAlgorithmSupported(algorithm)) {
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 367257a..ad348f8 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -383,7 +383,7 @@
}
}
- // TODO remove this when it's removed from Settings
+ // TODO: remove this when it's removed from Settings
public boolean isHardwareBacked() {
return isHardwareBacked("RSA");
}
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index e59688c..5147e98 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -215,16 +215,6 @@
return texture;
}
-Texture* TextureCache::getTransient(const SkBitmap* bitmap) {
- Texture* texture = new Texture(Caches::getInstance());
- texture->bitmapSize = bitmap->rowBytes() * bitmap->height();
- texture->cleanup = true;
-
- generateTexture(bitmap, texture, false);
-
- return texture;
-}
-
void TextureCache::releaseTexture(uint32_t pixelRefStableID) {
Mutex::Autolock _l(mLock);
mGarbage.push(pixelRefStableID);
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index a2c6380..e7fc990 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -80,11 +80,6 @@
* cannot be found in the cache, a new texture is generated.
*/
Texture* get(const SkBitmap* bitmap);
- /**
- * Returns the texture associated with the specified bitmap. The generated
- * texture is not kept in the cache. The caller must destroy the texture.
- */
- Texture* getTransient(const SkBitmap* bitmap);
/**
* Removes the texture associated with the specified pixelRef. This is meant
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 4b1fa13..c537dd6 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -549,8 +549,9 @@
private static final String generateInputIdForHdmiDevice(
ComponentName name, HdmiDeviceInfo deviceInfo) {
// Example of the format : "/HDMI%04X%02X"
- String format = String.format("%s%s%%0%sX%%0%sX", DELIMITER_INFO_IN_ID, PREFIX_HDMI_DEVICE,
- LENGTH_HDMI_PHYSICAL_ADDRESS, LENGTH_HDMI_DEVICE_ID);
+ String format = DELIMITER_INFO_IN_ID + PREFIX_HDMI_DEVICE
+ + "%0" + LENGTH_HDMI_PHYSICAL_ADDRESS + "X"
+ + "%0" + LENGTH_HDMI_DEVICE_ID + "X";
return name.flattenToShortString() + String.format(format,
deviceInfo.getPhysicalAddress(), deviceInfo.getId());
}
@@ -564,8 +565,8 @@
*/
private static final String generateInputIdForHardware(
ComponentName name, TvInputHardwareInfo hardwareInfo) {
- return name.flattenToShortString() + String.format("%s%s%d",
- DELIMITER_INFO_IN_ID, PREFIX_HARDWARE_DEVICE, hardwareInfo.getDeviceId());
+ return name.flattenToShortString() + DELIMITER_INFO_IN_ID + PREFIX_HARDWARE_DEVICE
+ + hardwareInfo.getDeviceId();
}
public static final Parcelable.Creator<TvInputInfo> CREATOR =
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index 96b72a2..fdc586b 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -92,6 +92,7 @@
}
}
+static Mutex sLock;
// ----------------------------------------------------------------------------
static void effectCallback(int event, void* user, void *info) {
@@ -182,6 +183,32 @@
}
// ----------------------------------------------------------------------------
+
+static sp<AudioEffect> getAudioEffect(JNIEnv* env, jobject thiz)
+{
+ Mutex::Autolock l(sLock);
+ AudioEffect* const ae =
+ (AudioEffect*)env->GetLongField(thiz, fields.fidNativeAudioEffect);
+ return sp<AudioEffect>(ae);
+}
+
+static sp<AudioEffect> setAudioEffect(JNIEnv* env, jobject thiz,
+ const sp<AudioEffect>& ae)
+{
+ Mutex::Autolock l(sLock);
+ sp<AudioEffect> old =
+ (AudioEffect*)env->GetLongField(thiz, fields.fidNativeAudioEffect);
+ if (ae.get()) {
+ ae->incStrong((void*)setAudioEffect);
+ }
+ if (old != 0) {
+ old->decStrong((void*)setAudioEffect);
+ }
+ env->SetLongField(thiz, fields.fidNativeAudioEffect, (jlong)ae.get());
+ return old;
+}
+
+// ----------------------------------------------------------------------------
// This function gets some field IDs, which in turn causes class initialization.
// It is called from a static block in AudioEffect, which won't run until the
// first time an instance of this class is used.
@@ -257,7 +284,7 @@
ALOGV("android_media_AudioEffect_native_setup");
AudioEffectJniStorage* lpJniStorage = NULL;
int lStatus = AUDIOEFFECT_ERROR_NO_MEMORY;
- AudioEffect* lpAudioEffect = NULL;
+ sp<AudioEffect> lpAudioEffect;
jint* nId = NULL;
const char *typeStr = NULL;
const char *uuidStr = NULL;
@@ -272,6 +299,8 @@
ScopedUtfChars opPackageNameStr(env, opPackageName);
+ setAudioEffect(env, thiz, 0);
+
if (type != NULL) {
typeStr = env->GetStringUTFChars(type, NULL);
if (typeStr == NULL) { // Out of memory
@@ -324,7 +353,7 @@
&lpJniStorage->mCallbackData,
sessionId,
0);
- if (lpAudioEffect == NULL) {
+ if (lpAudioEffect == 0) {
ALOGE("Error creating AudioEffect");
goto setup_failure;
}
@@ -394,7 +423,7 @@
env->SetObjectArrayElement(javadesc, 0, jdesc);
- env->SetLongField(thiz, fields.fidNativeAudioEffect, (jlong)lpAudioEffect);
+ setAudioEffect(env, thiz, lpAudioEffect);
env->SetLongField(thiz, fields.fidJniData, (jlong)lpJniStorage);
@@ -407,12 +436,9 @@
env->ReleasePrimitiveArrayCritical(jId, nId, 0);
}
- if (lpAudioEffect) {
- delete lpAudioEffect;
- }
- env->SetLongField(thiz, fields.fidNativeAudioEffect, 0);
-
if (lpJniStorage) {
+ env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioEffect_class);
+ env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioEffect_ref);
delete lpJniStorage;
}
env->SetLongField(thiz, fields.fidJniData, 0);
@@ -430,20 +456,20 @@
// ----------------------------------------------------------------------------
-static void android_media_AudioEffect_native_finalize(JNIEnv *env, jobject thiz) {
- ALOGV("android_media_AudioEffect_native_finalize jobject: %p\n", thiz);
-
- // delete the AudioEffect object
- AudioEffect* lpAudioEffect = (AudioEffect *)env->GetLongField(
- thiz, fields.fidNativeAudioEffect);
- if (lpAudioEffect) {
- ALOGV("deleting AudioEffect: %p\n", lpAudioEffect);
- delete lpAudioEffect;
+static void android_media_AudioEffect_native_release(JNIEnv *env, jobject thiz) {
+ sp<AudioEffect> lpAudioEffect = setAudioEffect(env, thiz, 0);
+ if (lpAudioEffect == 0) {
+ return;
}
// delete the JNI data
- AudioEffectJniStorage* lpJniStorage = (AudioEffectJniStorage *)env->GetLongField(
- thiz, fields.fidJniData);
+ AudioEffectJniStorage* lpJniStorage =
+ (AudioEffectJniStorage *)env->GetLongField(thiz, fields.fidJniData);
+
+ // reset the native resources in the Java object so any attempt to access
+ // them after a call to release fails.
+ env->SetLongField(thiz, fields.fidJniData, 0);
+
if (lpJniStorage) {
ALOGV("deleting pJniStorage: %p\n", lpJniStorage);
delete lpJniStorage;
@@ -451,24 +477,16 @@
}
// ----------------------------------------------------------------------------
-static void android_media_AudioEffect_native_release(JNIEnv *env, jobject thiz) {
-
- // do everything a call to finalize would
- android_media_AudioEffect_native_finalize(env, thiz);
- // + reset the native resources in the Java object so any attempt to access
- // them after a call to release fails.
- env->SetLongField(thiz, fields.fidNativeAudioEffect, 0);
- env->SetLongField(thiz, fields.fidJniData, 0);
+static void android_media_AudioEffect_native_finalize(JNIEnv *env, jobject thiz) {
+ ALOGV("android_media_AudioEffect_native_finalize jobject: %p\n", thiz);
+ android_media_AudioEffect_native_release(env, thiz);
}
static jint
android_media_AudioEffect_native_setEnabled(JNIEnv *env, jobject thiz, jboolean enabled)
{
- // retrieve the AudioEffect object
- AudioEffect* lpAudioEffect = (AudioEffect *)env->GetLongField(
- thiz, fields.fidNativeAudioEffect);
-
- if (lpAudioEffect == NULL) {
+ sp<AudioEffect> lpAudioEffect = getAudioEffect(env, thiz);
+ if (lpAudioEffect == 0) {
jniThrowException(env, "java/lang/IllegalStateException",
"Unable to retrieve AudioEffect pointer for enable()");
return AUDIOEFFECT_ERROR_NO_INIT;
@@ -480,11 +498,8 @@
static jboolean
android_media_AudioEffect_native_getEnabled(JNIEnv *env, jobject thiz)
{
- // retrieve the AudioEffect object
- AudioEffect* lpAudioEffect = (AudioEffect *)env->GetLongField(
- thiz, fields.fidNativeAudioEffect);
-
- if (lpAudioEffect == NULL) {
+ sp<AudioEffect> lpAudioEffect = getAudioEffect(env, thiz);
+ if (lpAudioEffect == 0) {
jniThrowException(env, "java/lang/IllegalStateException",
"Unable to retrieve AudioEffect pointer for getEnabled()");
return JNI_FALSE;
@@ -501,11 +516,8 @@
static jboolean
android_media_AudioEffect_native_hasControl(JNIEnv *env, jobject thiz)
{
- // retrieve the AudioEffect object
- AudioEffect* lpAudioEffect = (AudioEffect *)env->GetLongField(
- thiz, fields.fidNativeAudioEffect);
-
- if (lpAudioEffect == NULL) {
+ sp<AudioEffect> lpAudioEffect = getAudioEffect(env, thiz);
+ if (lpAudioEffect == 0) {
jniThrowException(env, "java/lang/IllegalStateException",
"Unable to retrieve AudioEffect pointer for hasControl()");
return JNI_FALSE;
@@ -528,10 +540,8 @@
effect_param_t *p;
int voffset;
- AudioEffect* lpAudioEffect = (AudioEffect *) env->GetLongField(thiz,
- fields.fidNativeAudioEffect);
-
- if (lpAudioEffect == NULL) {
+ sp<AudioEffect> lpAudioEffect = getAudioEffect(env, thiz);
+ if (lpAudioEffect == 0) {
jniThrowException(env, "java/lang/IllegalStateException",
"Unable to retrieve AudioEffect pointer for setParameter()");
return AUDIOEFFECT_ERROR_NO_INIT;
@@ -591,10 +601,8 @@
effect_param_t *p;
int voffset;
- AudioEffect* lpAudioEffect = (AudioEffect *) env->GetLongField(thiz,
- fields.fidNativeAudioEffect);
-
- if (lpAudioEffect == NULL) {
+ sp<AudioEffect> lpAudioEffect = getAudioEffect(env, thiz);
+ if (lpAudioEffect == 0) {
jniThrowException(env, "java/lang/IllegalStateException",
"Unable to retrieve AudioEffect pointer for getParameter()");
return AUDIOEFFECT_ERROR_NO_INIT;
@@ -657,11 +665,8 @@
jbyte* pReplyData = NULL;
jint lStatus = AUDIOEFFECT_ERROR_BAD_VALUE;
- // retrieve the AudioEffect object
- AudioEffect* lpAudioEffect = (AudioEffect *) env->GetLongField(thiz,
- fields.fidNativeAudioEffect);
-
- if (lpAudioEffect == NULL) {
+ sp<AudioEffect> lpAudioEffect = getAudioEffect(env, thiz);
+ if (lpAudioEffect == 0) {
jniThrowException(env, "java/lang/IllegalStateException",
"Unable to retrieve AudioEffect pointer for setParameter()");
return AUDIOEFFECT_ERROR_NO_INIT;
diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp
index abc681e..6098b4a 100644
--- a/media/jni/audioeffect/android_media_Visualizer.cpp
+++ b/media/jni/audioeffect/android_media_Visualizer.cpp
@@ -102,14 +102,14 @@
};
// ----------------------------------------------------------------------------
-class visualizerJniStorage {
+class VisualizerJniStorage {
public:
visualizer_callback_cookie mCallbackData;
- visualizerJniStorage() {
+ VisualizerJniStorage() {
}
- ~visualizerJniStorage() {
+ ~VisualizerJniStorage() {
}
};
@@ -135,6 +135,7 @@
}
}
+static Mutex sLock;
// ----------------------------------------------------------------------------
static void ensureArraySize(JNIEnv *env, jbyteArray *array, uint32_t size) {
@@ -227,15 +228,30 @@
}
}
-static Visualizer *getVisualizer(JNIEnv* env, jobject thiz)
+// ----------------------------------------------------------------------------
+
+static sp<Visualizer> getVisualizer(JNIEnv* env, jobject thiz)
{
- Visualizer *v = (Visualizer *)env->GetLongField(
- thiz, fields.fidNativeVisualizer);
- if (v == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException",
- "Unable to retrieve Visualizer pointer");
+ Mutex::Autolock l(sLock);
+ Visualizer* const v =
+ (Visualizer*)env->GetLongField(thiz, fields.fidNativeVisualizer);
+ return sp<Visualizer>(v);
+}
+
+static sp<Visualizer> setVisualizer(JNIEnv* env, jobject thiz,
+ const sp<Visualizer>& v)
+{
+ Mutex::Autolock l(sLock);
+ sp<Visualizer> old =
+ (Visualizer*)env->GetLongField(thiz, fields.fidNativeVisualizer);
+ if (v.get()) {
+ v->incStrong((void*)setVisualizer);
}
- return v;
+ if (old != 0) {
+ old->decStrong((void*)setVisualizer);
+ }
+ env->SetLongField(thiz, fields.fidNativeVisualizer, (jlong)v.get());
+ return old;
}
// ----------------------------------------------------------------------------
@@ -318,7 +334,7 @@
void *info) {
if ((event == AudioEffect::EVENT_ERROR) &&
(*((status_t*)info) == DEAD_OBJECT)) {
- visualizerJniStorage* lpJniStorage = (visualizerJniStorage*)user;
+ VisualizerJniStorage* lpJniStorage = (VisualizerJniStorage*)user;
visualizer_callback_cookie* callbackInfo = &lpJniStorage->mCallbackData;
JNIEnv *env = AndroidRuntime::getJNIEnv();
@@ -336,14 +352,16 @@
jint sessionId, jintArray jId, jstring opPackageName)
{
ALOGV("android_media_visualizer_native_setup");
- visualizerJniStorage* lpJniStorage = NULL;
+ VisualizerJniStorage* lpJniStorage = NULL;
int lStatus = VISUALIZER_ERROR_NO_MEMORY;
- Visualizer* lpVisualizer = NULL;
+ sp<Visualizer> lpVisualizer;
jint* nId = NULL;
ScopedUtfChars opPackageNameStr(env, opPackageName);
- lpJniStorage = new visualizerJniStorage();
+ setVisualizer(env, thiz, 0);
+
+ lpJniStorage = new VisualizerJniStorage();
if (lpJniStorage == NULL) {
ALOGE("setup: Error creating JNI Storage");
goto setup_failure;
@@ -371,7 +389,7 @@
android_media_visualizer_effect_callback,
lpJniStorage,
sessionId);
- if (lpVisualizer == NULL) {
+ if (lpVisualizer == 0) {
ALOGE("Error creating Visualizer");
goto setup_failure;
}
@@ -392,7 +410,7 @@
env->ReleasePrimitiveArrayCritical(jId, nId, 0);
nId = NULL;
- env->SetLongField(thiz, fields.fidNativeVisualizer, (jlong)lpVisualizer);
+ setVisualizer(env, thiz, lpVisualizer);
env->SetLongField(thiz, fields.fidJniData, (jlong)lpJniStorage);
@@ -405,12 +423,9 @@
env->ReleasePrimitiveArrayCritical(jId, nId, 0);
}
- if (lpVisualizer) {
- delete lpVisualizer;
- }
- env->SetLongField(thiz, fields.fidNativeVisualizer, 0);
-
if (lpJniStorage) {
+ env->DeleteGlobalRef(lpJniStorage->mCallbackData.visualizer_class);
+ env->DeleteGlobalRef(lpJniStorage->mCallbackData.visualizer_ref);
delete lpJniStorage;
}
env->SetLongField(thiz, fields.fidJniData, 0);
@@ -419,49 +434,44 @@
}
// ----------------------------------------------------------------------------
-static void android_media_visualizer_native_finalize(JNIEnv *env, jobject thiz) {
- ALOGV("android_media_visualizer_native_finalize jobject: %p\n", thiz);
-
- // delete the Visualizer object
- Visualizer* lpVisualizer = (Visualizer *)env->GetLongField(
- thiz, fields.fidNativeVisualizer);
- if (lpVisualizer) {
- ALOGV("deleting Visualizer: %p\n", lpVisualizer);
- delete lpVisualizer;
+static void android_media_visualizer_native_release(JNIEnv *env, jobject thiz) {
+ sp<Visualizer> lpVisualizer = setVisualizer(env, thiz, 0);
+ if (lpVisualizer == 0) {
+ return;
}
// delete the JNI data
- visualizerJniStorage* lpJniStorage = (visualizerJniStorage *)env->GetLongField(
- thiz, fields.fidJniData);
+ VisualizerJniStorage* lpJniStorage =
+ (VisualizerJniStorage *)env->GetLongField(thiz, fields.fidJniData);
+
+ // reset the native resources in the Java object so any attempt to access
+ // them after a call to release fails.
+ env->SetLongField(thiz, fields.fidJniData, 0);
+
if (lpJniStorage) {
ALOGV("deleting pJniStorage: %p\n", lpJniStorage);
delete lpJniStorage;
}
}
-// ----------------------------------------------------------------------------
-static void android_media_visualizer_native_release(JNIEnv *env, jobject thiz) {
-
- // do everything a call to finalize would
- android_media_visualizer_native_finalize(env, thiz);
- // + reset the native resources in the Java object so any attempt to access
- // them after a call to release fails.
- env->SetLongField(thiz, fields.fidNativeVisualizer, 0);
- env->SetLongField(thiz, fields.fidJniData, 0);
+static void android_media_visualizer_native_finalize(JNIEnv *env, jobject thiz) {
+ ALOGV("android_media_visualizer_native_finalize jobject: %p\n", thiz);
+ android_media_visualizer_native_release(env, thiz);
}
+// ----------------------------------------------------------------------------
static jint
android_media_visualizer_native_setEnabled(JNIEnv *env, jobject thiz, jboolean enabled)
{
- Visualizer* lpVisualizer = getVisualizer(env, thiz);
- if (lpVisualizer == NULL) {
+ sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
+ if (lpVisualizer == 0) {
return VISUALIZER_ERROR_NO_INIT;
}
jint retVal = translateError(lpVisualizer->setEnabled(enabled));
if (!enabled) {
- visualizerJniStorage* lpJniStorage = (visualizerJniStorage *)env->GetLongField(
+ VisualizerJniStorage* lpJniStorage = (VisualizerJniStorage *)env->GetLongField(
thiz, fields.fidJniData);
if (NULL != lpJniStorage)
@@ -474,8 +484,8 @@
static jboolean
android_media_visualizer_native_getEnabled(JNIEnv *env, jobject thiz)
{
- Visualizer* lpVisualizer = getVisualizer(env, thiz);
- if (lpVisualizer == NULL) {
+ sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
+ if (lpVisualizer == 0) {
return JNI_FALSE;
}
@@ -507,8 +517,8 @@
static jint
android_media_visualizer_native_setCaptureSize(JNIEnv *env, jobject thiz, jint size)
{
- Visualizer* lpVisualizer = getVisualizer(env, thiz);
- if (lpVisualizer == NULL) {
+ sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
+ if (lpVisualizer == 0) {
return VISUALIZER_ERROR_NO_INIT;
}
@@ -518,8 +528,8 @@
static jint
android_media_visualizer_native_getCaptureSize(JNIEnv *env, jobject thiz)
{
- Visualizer* lpVisualizer = getVisualizer(env, thiz);
- if (lpVisualizer == NULL) {
+ sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
+ if (lpVisualizer == 0) {
return -1;
}
return (jint) lpVisualizer->getCaptureSize();
@@ -528,8 +538,8 @@
static jint
android_media_visualizer_native_setScalingMode(JNIEnv *env, jobject thiz, jint mode)
{
- Visualizer* lpVisualizer = getVisualizer(env, thiz);
- if (lpVisualizer == NULL) {
+ sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
+ if (lpVisualizer == 0) {
return VISUALIZER_ERROR_NO_INIT;
}
@@ -539,8 +549,8 @@
static jint
android_media_visualizer_native_getScalingMode(JNIEnv *env, jobject thiz)
{
- Visualizer* lpVisualizer = getVisualizer(env, thiz);
- if (lpVisualizer == NULL) {
+ sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
+ if (lpVisualizer == 0) {
return -1;
}
return (jint)lpVisualizer->getScalingMode();
@@ -549,8 +559,8 @@
static jint
android_media_visualizer_native_setMeasurementMode(JNIEnv *env, jobject thiz, jint mode)
{
- Visualizer* lpVisualizer = getVisualizer(env, thiz);
- if (lpVisualizer == NULL) {
+ sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
+ if (lpVisualizer == 0) {
return VISUALIZER_ERROR_NO_INIT;
}
return translateError(lpVisualizer->setMeasurementMode(mode));
@@ -559,8 +569,8 @@
static jint
android_media_visualizer_native_getMeasurementMode(JNIEnv *env, jobject thiz)
{
- Visualizer* lpVisualizer = getVisualizer(env, thiz);
- if (lpVisualizer == NULL) {
+ sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
+ if (lpVisualizer == 0) {
return MEASUREMENT_MODE_NONE;
}
return lpVisualizer->getMeasurementMode();
@@ -569,8 +579,8 @@
static jint
android_media_visualizer_native_getSamplingRate(JNIEnv *env, jobject thiz)
{
- Visualizer* lpVisualizer = getVisualizer(env, thiz);
- if (lpVisualizer == NULL) {
+ sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
+ if (lpVisualizer == 0) {
return -1;
}
return (jint) lpVisualizer->getSamplingRate();
@@ -579,8 +589,8 @@
static jint
android_media_visualizer_native_getWaveForm(JNIEnv *env, jobject thiz, jbyteArray jWaveform)
{
- Visualizer* lpVisualizer = getVisualizer(env, thiz);
- if (lpVisualizer == NULL) {
+ sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
+ if (lpVisualizer == 0) {
return VISUALIZER_ERROR_NO_INIT;
}
@@ -597,8 +607,8 @@
static jint
android_media_visualizer_native_getFft(JNIEnv *env, jobject thiz, jbyteArray jFft)
{
- Visualizer* lpVisualizer = getVisualizer(env, thiz);
- if (lpVisualizer == NULL) {
+ sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
+ if (lpVisualizer == 0) {
return VISUALIZER_ERROR_NO_INIT;
}
@@ -616,8 +626,8 @@
static jint
android_media_visualizer_native_getPeakRms(JNIEnv *env, jobject thiz, jobject jPeakRmsObj)
{
- Visualizer* lpVisualizer = getVisualizer(env, thiz);
- if (lpVisualizer == NULL) {
+ sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
+ if (lpVisualizer == 0) {
return VISUALIZER_ERROR_NO_INIT;
}
int32_t measurements[2];
@@ -635,11 +645,11 @@
static jint
android_media_setPeriodicCapture(JNIEnv *env, jobject thiz, jint rate, jboolean jWaveform, jboolean jFft)
{
- Visualizer* lpVisualizer = getVisualizer(env, thiz);
- if (lpVisualizer == NULL) {
+ sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
+ if (lpVisualizer == 0) {
return VISUALIZER_ERROR_NO_INIT;
}
- visualizerJniStorage* lpJniStorage = (visualizerJniStorage *)env->GetLongField(thiz,
+ VisualizerJniStorage* lpJniStorage = (VisualizerJniStorage *)env->GetLongField(thiz,
fields.fidJniData);
if (lpJniStorage == NULL) {
return VISUALIZER_ERROR_NO_INIT;
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index 3c76115..359a7a9 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -32,6 +32,7 @@
import android.content.Context;
import android.content.pm.ConfigurationInfo;
import android.os.SystemProperties;
+import android.os.Trace;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
@@ -1497,7 +1498,12 @@
}
GLSurfaceView view = mGLSurfaceViewWeakRef.get();
if (view != null) {
- view.mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);
+ try {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "onSurfaceCreated");
+ view.mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
}
createEglContext = false;
}
@@ -1508,7 +1514,12 @@
}
GLSurfaceView view = mGLSurfaceViewWeakRef.get();
if (view != null) {
- view.mRenderer.onSurfaceChanged(gl, w, h);
+ try {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "onSurfaceChanged");
+ view.mRenderer.onSurfaceChanged(gl, w, h);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
}
sizeChanged = false;
}
@@ -1519,7 +1530,12 @@
{
GLSurfaceView view = mGLSurfaceViewWeakRef.get();
if (view != null) {
- view.mRenderer.onDrawFrame(gl);
+ try {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "onDrawFrame");
+ view.mRenderer.onDrawFrame(gl);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
}
}
int swapError = mEglHelper.swap();
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index d876264..ddbcd78 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -336,12 +336,24 @@
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
- Log.w(TAG, "SSL error; displaying SSL warning.");
+ Log.w(TAG, "SSL error (error: " + error.getPrimaryError() + " host: " +
+ // Only show host to avoid leaking private info.
+ Uri.parse(error.getUrl()).getHost() + " certificate: " +
+ error.getCertificate() + "); displaying SSL warning.");
final String html = String.format(SSL_ERROR_HTML, getString(R.string.ssl_error_warning),
getString(R.string.ssl_error_example), mBrowserBailOutToken,
getString(R.string.ssl_error_continue));
view.loadDataWithBaseURL(INTERNAL_ASSETS, html, "text/HTML", "UTF-8", null);
}
+
+ @Override
+ public boolean shouldOverrideUrlLoading (WebView view, String url) {
+ if (url.startsWith("tel:")) {
+ startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse(url)));
+ return true;
+ }
+ return false;
+ }
}
private class MyWebChromeClient extends WebChromeClient {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 3c30d8c..e6a89f1 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -205,7 +205,7 @@
handleScreenTurnedOn();
break;
case MSG_FINGERPRINT_AUTHENTICATED:
- handleFingerprintAuthenticated(msg.arg1, msg.arg2);
+ handleFingerprintAuthenticated();
break;
case MSG_FINGERPRINT_HELP:
handleFingerprintHelp(msg.arg1 /* msgId */, (String) msg.obj /* errString */);
@@ -348,7 +348,7 @@
handleFingerprintHelp(-1, mContext.getString(R.string.fingerprint_not_recognized));
}
- private void handleFingerprintAuthenticated(int fingerId, int groupId) {
+ private void handleFingerprintAuthenticated() {
try {
final int userId;
try {
@@ -524,9 +524,7 @@
@Override
public void onAuthenticationSucceeded(AuthenticationResult result) {
- mHandler.obtainMessage(MSG_FINGERPRINT_AUTHENTICATED,
- result.getFingerprint().getFingerId(),
- result.getFingerprint().getGroupId()).sendToTarget();
+ mHandler.obtainMessage(MSG_FINGERPRINT_AUTHENTICATED).sendToTarget();
}
@Override
@@ -796,7 +794,7 @@
mFingerprintCancelSignal.cancel();
}
mFingerprintCancelSignal = new CancellationSignal();
- mFpm.authenticate(null, mFingerprintCancelSignal, mAuthenticationCallback, 0, userId);
+ mFpm.authenticate(null, mFingerprintCancelSignal, 0, mAuthenticationCallback, null, userId);
setFingerprintRunningDetectionRunning(true);
}
}
diff --git a/packages/SettingsLib/AndroidManifest.xml b/packages/SettingsLib/AndroidManifest.xml
index eacafd5..3873593 100644
--- a/packages/SettingsLib/AndroidManifest.xml
+++ b/packages/SettingsLib/AndroidManifest.xml
@@ -16,5 +16,9 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.settingslib">
+ package="com.android.settingslib">
+
+ <uses-sdk
+ android:minSdkVersion="21" />
+
</manifest>
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
new file mode 100644
index 0000000..d20ee61
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -0,0 +1,1339 @@
+/*
+ * 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.settingslib.applications;
+
+import android.app.ActivityManager;
+import android.app.AppGlobals;
+import android.app.Application;
+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.IPackageManager;
+import android.content.pm.IPackageStatsObserver;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageStats;
+import android.content.pm.ParceledListSlice;
+import android.content.pm.ResolveInfo;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.text.format.Formatter;
+import android.util.Log;
+import android.util.SparseArray;
+
+import java.io.File;
+import java.text.Collator;
+import java.text.Normalizer;
+import java.text.Normalizer.Form;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Objects;
+import java.util.regex.Pattern;
+
+/**
+ * Keeps track of information about all installed applications, lazy-loading
+ * as needed.
+ */
+public class ApplicationsState {
+ static final String TAG = "ApplicationsState";
+ static final boolean DEBUG = false;
+ static final boolean DEBUG_LOCKING = false;
+
+ public static final int SIZE_UNKNOWN = -1;
+ public static final int SIZE_INVALID = -2;
+
+ static final Pattern REMOVE_DIACRITICALS_PATTERN
+ = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
+
+ static final Object sLock = new Object();
+ static ApplicationsState sInstance;
+
+ public static ApplicationsState getInstance(Application app) {
+ synchronized (sLock) {
+ if (sInstance == null) {
+ sInstance = new ApplicationsState(app);
+ }
+ return sInstance;
+ }
+ }
+
+ final Context mContext;
+ final PackageManager mPm;
+ final IPackageManager mIpm;
+ final UserManager mUm;
+ final int mOwnerRetrieveFlags;
+ final int mRetrieveFlags;
+ PackageIntentReceiver mPackageIntentReceiver;
+
+ boolean mResumed;
+ boolean mHaveDisabledApps;
+
+ // Information about all applications. Synchronize on mEntriesMap
+ // to protect access to these.
+ final ArrayList<Session> mSessions = new ArrayList<Session>();
+ final ArrayList<Session> mRebuildingSessions = new ArrayList<Session>();
+ final InterestingConfigChanges mInterestingConfigChanges = new InterestingConfigChanges();
+ // Map: userid => (Map: package name => AppEntry)
+ final SparseArray<HashMap<String, AppEntry>> mEntriesMap =
+ new SparseArray<HashMap<String, AppEntry>>();
+ final ArrayList<AppEntry> mAppEntries = new ArrayList<AppEntry>();
+ List<ApplicationInfo> mApplications = new ArrayList<ApplicationInfo>();
+ long mCurId = 1;
+ String mCurComputingSizePkg;
+ int mCurComputingSizeUserId;
+ boolean mSessionsChanged;
+
+ // Temporary for dispatching session callbacks. Only touched by main thread.
+ final ArrayList<Session> mActiveSessions = new ArrayList<Session>();
+
+ final HandlerThread mThread;
+ final BackgroundHandler mBackgroundHandler;
+ final MainHandler mMainHandler = new MainHandler();
+
+ private ApplicationsState(Application app) {
+ mContext = app;
+ mPm = mContext.getPackageManager();
+ mIpm = AppGlobals.getPackageManager();
+ mUm = (UserManager) app.getSystemService(Context.USER_SERVICE);
+ for (UserHandle user : mUm.getUserProfiles()) {
+ mEntriesMap.put(user.getIdentifier(), new HashMap<String, AppEntry>());
+ }
+ mThread = new HandlerThread("ApplicationsState.Loader",
+ Process.THREAD_PRIORITY_BACKGROUND);
+ mThread.start();
+ mBackgroundHandler = new BackgroundHandler(mThread.getLooper());
+
+ // Only the owner can see all apps.
+ mOwnerRetrieveFlags = PackageManager.GET_UNINSTALLED_PACKAGES |
+ PackageManager.GET_DISABLED_COMPONENTS |
+ PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS;
+ mRetrieveFlags = PackageManager.GET_DISABLED_COMPONENTS |
+ PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS;
+
+ /**
+ * This is a trick to prevent the foreground thread from being delayed.
+ * The problem is that Dalvik monitors are initially spin locks, to keep
+ * them lightweight. This leads to unfair contention -- Even though the
+ * background thread only holds the lock for a short amount of time, if
+ * it keeps running and locking again it can prevent the main thread from
+ * acquiring its lock for a long time... sometimes even > 5 seconds
+ * (leading to an ANR).
+ *
+ * Dalvik will promote a monitor to a "real" lock if it detects enough
+ * contention on it. It doesn't figure this out fast enough for us
+ * here, though, so this little trick will force it to turn into a real
+ * lock immediately.
+ */
+ synchronized (mEntriesMap) {
+ try {
+ mEntriesMap.wait(1);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ public Looper getBackgroundLooper() {
+ return mThread.getLooper();
+ }
+
+ public Session newSession(Callbacks callbacks) {
+ Session s = new Session(callbacks);
+ synchronized (mEntriesMap) {
+ mSessions.add(s);
+ }
+ return s;
+ }
+
+ void doResumeIfNeededLocked() {
+ if (mResumed) {
+ return;
+ }
+ mResumed = true;
+ if (mPackageIntentReceiver == null) {
+ mPackageIntentReceiver = new PackageIntentReceiver();
+ mPackageIntentReceiver.registerReceiver();
+ }
+ mApplications = new ArrayList<ApplicationInfo>();
+ for (UserHandle user : mUm.getUserProfiles()) {
+ try {
+ // If this user is new, it needs a map created.
+ if (mEntriesMap.indexOfKey(user.getIdentifier()) < 0) {
+ mEntriesMap.put(user.getIdentifier(), new HashMap<String, AppEntry>());
+ }
+ @SuppressWarnings("unchecked")
+ ParceledListSlice<ApplicationInfo> list =
+ mIpm.getInstalledApplications(
+ user.isOwner() ? mOwnerRetrieveFlags : mRetrieveFlags,
+ user.getIdentifier());
+ mApplications.addAll(list.getList());
+ } catch (RemoteException e) {
+ }
+ }
+
+ if (mInterestingConfigChanges.applyNewConfig(mContext.getResources())) {
+ // If an interesting part of the configuration has changed, we
+ // should completely reload the app entries.
+ clearEntries();
+ } else {
+ for (int i=0; i<mAppEntries.size(); i++) {
+ mAppEntries.get(i).sizeStale = true;
+ }
+ }
+
+ mHaveDisabledApps = false;
+ for (int i=0; i<mApplications.size(); i++) {
+ final ApplicationInfo info = mApplications.get(i);
+ // Need to trim out any applications that are disabled by
+ // something different than the user.
+ if (!info.enabled) {
+ if (info.enabledSetting != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
+ mApplications.remove(i);
+ i--;
+ continue;
+ }
+ mHaveDisabledApps = true;
+ }
+ int userId = UserHandle.getUserId(info.uid);
+ final AppEntry entry = mEntriesMap.get(userId).get(info.packageName);
+ if (entry != null) {
+ entry.info = info;
+ }
+ }
+ if (mAppEntries.size() > mApplications.size()) {
+ // There are less apps now, some must have been uninstalled.
+ clearEntries();
+ }
+ mCurComputingSizePkg = null;
+ if (!mBackgroundHandler.hasMessages(BackgroundHandler.MSG_LOAD_ENTRIES)) {
+ mBackgroundHandler.sendEmptyMessage(BackgroundHandler.MSG_LOAD_ENTRIES);
+ }
+ }
+
+ private void clearEntries() {
+ for (int i = 0; i < mEntriesMap.size(); i++) {
+ mEntriesMap.valueAt(i).clear();
+ }
+ mAppEntries.clear();
+ }
+
+ public boolean haveDisabledApps() {
+ return mHaveDisabledApps;
+ }
+
+ void doPauseIfNeededLocked() {
+ if (!mResumed) {
+ return;
+ }
+ for (int i=0; i<mSessions.size(); i++) {
+ if (mSessions.get(i).mResumed) {
+ return;
+ }
+ }
+ doPauseLocked();
+ }
+
+ void doPauseLocked() {
+ mResumed = false;
+ if (mPackageIntentReceiver != null) {
+ mPackageIntentReceiver.unregisterReceiver();
+ mPackageIntentReceiver = null;
+ }
+ }
+
+ public AppEntry getEntry(String packageName, int userId) {
+ if (DEBUG_LOCKING) Log.v(TAG, "getEntry about to acquire lock...");
+ synchronized (mEntriesMap) {
+ AppEntry entry = mEntriesMap.get(userId).get(packageName);
+ if (entry == null) {
+ ApplicationInfo info = getAppInfoLocked(packageName, userId);
+ if (info == null) {
+ try {
+ info = mIpm.getApplicationInfo(packageName, 0, userId);
+ } catch (RemoteException e) {
+ Log.w(TAG, "getEntry couldn't reach PackageManager", e);
+ return null;
+ }
+ }
+ entry = getEntryLocked(info);
+ }
+ if (DEBUG_LOCKING) Log.v(TAG, "...getEntry releasing lock");
+ return entry;
+ }
+ }
+
+ private ApplicationInfo getAppInfoLocked(String pkg, int userId) {
+ for (int i = 0; i < mApplications.size(); i++) {
+ ApplicationInfo info = mApplications.get(i);
+ if (pkg.equals(info.packageName)
+ && userId == UserHandle.getUserId(info.uid)) {
+ return info;
+ }
+ }
+ return null;
+ }
+
+ public void ensureIcon(AppEntry entry) {
+ if (entry.icon != null) {
+ return;
+ }
+ synchronized (entry) {
+ entry.ensureIconLocked(mContext, mPm);
+ }
+ }
+
+ public void requestSize(String packageName, int userId) {
+ if (DEBUG_LOCKING) Log.v(TAG, "requestSize about to acquire lock...");
+ synchronized (mEntriesMap) {
+ AppEntry entry = mEntriesMap.get(userId).get(packageName);
+ if (entry != null) {
+ mPm.getPackageSizeInfo(packageName, userId, mBackgroundHandler.mStatsObserver);
+ }
+ if (DEBUG_LOCKING) Log.v(TAG, "...requestSize releasing lock");
+ }
+ }
+
+ long sumCacheSizes() {
+ long sum = 0;
+ if (DEBUG_LOCKING) Log.v(TAG, "sumCacheSizes about to acquire lock...");
+ synchronized (mEntriesMap) {
+ if (DEBUG_LOCKING) Log.v(TAG, "-> sumCacheSizes now has lock");
+ for (int i=mAppEntries.size()-1; i>=0; i--) {
+ sum += mAppEntries.get(i).cacheSize;
+ }
+ if (DEBUG_LOCKING) Log.v(TAG, "...sumCacheSizes releasing lock");
+ }
+ return sum;
+ }
+
+ int indexOfApplicationInfoLocked(String pkgName, int userId) {
+ for (int i=mApplications.size()-1; i>=0; i--) {
+ ApplicationInfo appInfo = mApplications.get(i);
+ if (appInfo.packageName.equals(pkgName)
+ && UserHandle.getUserId(appInfo.uid) == userId) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ void addPackage(String pkgName, int userId) {
+ try {
+ synchronized (mEntriesMap) {
+ if (DEBUG_LOCKING) Log.v(TAG, "addPackage acquired lock");
+ if (DEBUG) Log.i(TAG, "Adding package " + pkgName);
+ if (!mResumed) {
+ // If we are not resumed, we will do a full query the
+ // next time we resume, so there is no reason to do work
+ // here.
+ if (DEBUG_LOCKING) Log.v(TAG, "addPackage release lock: not resumed");
+ return;
+ }
+ if (indexOfApplicationInfoLocked(pkgName, userId) >= 0) {
+ if (DEBUG) Log.i(TAG, "Package already exists!");
+ if (DEBUG_LOCKING) Log.v(TAG, "addPackage release lock: already exists");
+ return;
+ }
+ ApplicationInfo info = mIpm.getApplicationInfo(pkgName,
+ userId == UserHandle.USER_OWNER ? mOwnerRetrieveFlags : mRetrieveFlags,
+ userId);
+ if (info == null) {
+ return;
+ }
+ if (!info.enabled) {
+ if (info.enabledSetting
+ != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
+ return;
+ }
+ mHaveDisabledApps = true;
+ }
+ mApplications.add(info);
+ if (!mBackgroundHandler.hasMessages(BackgroundHandler.MSG_LOAD_ENTRIES)) {
+ mBackgroundHandler.sendEmptyMessage(BackgroundHandler.MSG_LOAD_ENTRIES);
+ }
+ if (!mMainHandler.hasMessages(MainHandler.MSG_PACKAGE_LIST_CHANGED)) {
+ mMainHandler.sendEmptyMessage(MainHandler.MSG_PACKAGE_LIST_CHANGED);
+ }
+ if (DEBUG_LOCKING) Log.v(TAG, "addPackage releasing lock");
+ }
+ } catch (RemoteException e) {
+ }
+ }
+
+ void removePackage(String pkgName, int userId) {
+ synchronized (mEntriesMap) {
+ if (DEBUG_LOCKING) Log.v(TAG, "removePackage acquired lock");
+ int idx = indexOfApplicationInfoLocked(pkgName, userId);
+ if (DEBUG) Log.i(TAG, "removePackage: " + pkgName + " @ " + idx);
+ if (idx >= 0) {
+ AppEntry entry = mEntriesMap.get(userId).get(pkgName);
+ if (DEBUG) Log.i(TAG, "removePackage: " + entry);
+ if (entry != null) {
+ mEntriesMap.get(userId).remove(pkgName);
+ mAppEntries.remove(entry);
+ }
+ ApplicationInfo info = mApplications.get(idx);
+ mApplications.remove(idx);
+ if (!info.enabled) {
+ mHaveDisabledApps = false;
+ for (int i=0; i<mApplications.size(); i++) {
+ if (!mApplications.get(i).enabled) {
+ mHaveDisabledApps = true;
+ break;
+ }
+ }
+ }
+ if (!mMainHandler.hasMessages(MainHandler.MSG_PACKAGE_LIST_CHANGED)) {
+ mMainHandler.sendEmptyMessage(MainHandler.MSG_PACKAGE_LIST_CHANGED);
+ }
+ }
+ if (DEBUG_LOCKING) Log.v(TAG, "removePackage releasing lock");
+ }
+ }
+
+ public void invalidatePackage(String pkgName, int userId) {
+ removePackage(pkgName, userId);
+ addPackage(pkgName, userId);
+ }
+
+ private void addUser(int userId) {
+ if (mUm.getUserProfiles().contains(new UserHandle(userId))) {
+ synchronized (mEntriesMap) {
+ mEntriesMap.put(userId, new HashMap<String, AppEntry>());
+ if (mResumed) {
+ // If resumed, Manually pause, then cause a resume to repopulate the app list.
+ // This is the simplest way to reload the packages so that the new user
+ // is included. Otherwise the list will be repopulated on next resume.
+ doPauseLocked();
+ doResumeIfNeededLocked();
+ }
+ if (!mMainHandler.hasMessages(MainHandler.MSG_PACKAGE_LIST_CHANGED)) {
+ mMainHandler.sendEmptyMessage(MainHandler.MSG_PACKAGE_LIST_CHANGED);
+ }
+ }
+ }
+ }
+
+ private void removeUser(int userId) {
+ synchronized (mEntriesMap) {
+ HashMap<String, AppEntry> userMap = mEntriesMap.get(userId);
+ if (userMap != null) {
+ for (AppEntry appEntry : userMap.values()) {
+ mAppEntries.remove(appEntry);
+ mApplications.remove(appEntry.info);
+ }
+ mEntriesMap.remove(userId);
+ if (!mMainHandler.hasMessages(MainHandler.MSG_PACKAGE_LIST_CHANGED)) {
+ mMainHandler.sendEmptyMessage(MainHandler.MSG_PACKAGE_LIST_CHANGED);
+ }
+ }
+ }
+ }
+
+ private AppEntry getEntryLocked(ApplicationInfo info) {
+ int userId = UserHandle.getUserId(info.uid);
+ AppEntry entry = mEntriesMap.get(userId).get(info.packageName);
+ if (DEBUG) Log.i(TAG, "Looking up entry of pkg " + info.packageName + ": " + entry);
+ if (entry == null) {
+ if (DEBUG) Log.i(TAG, "Creating AppEntry for " + info.packageName);
+ entry = new AppEntry(mContext, info, mCurId++);
+ mEntriesMap.get(userId).put(info.packageName, entry);
+ mAppEntries.add(entry);
+ } else if (entry.info != info) {
+ entry.info = info;
+ }
+ return entry;
+ }
+
+ // --------------------------------------------------------------
+
+ private long getTotalInternalSize(PackageStats ps) {
+ if (ps != null) {
+ return ps.codeSize + ps.dataSize;
+ }
+ return SIZE_INVALID;
+ }
+
+ private long getTotalExternalSize(PackageStats ps) {
+ if (ps != null) {
+ // We also include the cache size here because for non-emulated
+ // we don't automtically clean cache files.
+ return ps.externalCodeSize + ps.externalDataSize
+ + ps.externalCacheSize
+ + ps.externalMediaSize + ps.externalObbSize;
+ }
+ return SIZE_INVALID;
+ }
+
+ private String getSizeStr(long size) {
+ if (size >= 0) {
+ return Formatter.formatFileSize(mContext, size);
+ }
+ return null;
+ }
+
+ void rebuildActiveSessions() {
+ synchronized (mEntriesMap) {
+ if (!mSessionsChanged) {
+ return;
+ }
+ mActiveSessions.clear();
+ for (int i=0; i<mSessions.size(); i++) {
+ Session s = mSessions.get(i);
+ if (s.mResumed) {
+ mActiveSessions.add(s);
+ }
+ }
+ }
+ }
+
+ public class Session {
+ final Callbacks mCallbacks;
+ boolean mResumed;
+
+ // Rebuilding of app list. Synchronized on mRebuildSync.
+ final Object mRebuildSync = new Object();
+ boolean mRebuildRequested;
+ boolean mRebuildAsync;
+ AppFilter mRebuildFilter;
+ Comparator<AppEntry> mRebuildComparator;
+ ArrayList<AppEntry> mRebuildResult;
+ ArrayList<AppEntry> mLastAppList;
+
+ Session(Callbacks callbacks) {
+ mCallbacks = callbacks;
+ }
+
+ public void resume() {
+ if (DEBUG_LOCKING) Log.v(TAG, "resume about to acquire lock...");
+ synchronized (mEntriesMap) {
+ if (!mResumed) {
+ mResumed = true;
+ mSessionsChanged = true;
+ doResumeIfNeededLocked();
+ }
+ }
+ if (DEBUG_LOCKING) Log.v(TAG, "...resume releasing lock");
+ }
+
+ public void pause() {
+ if (DEBUG_LOCKING) Log.v(TAG, "pause about to acquire lock...");
+ synchronized (mEntriesMap) {
+ if (mResumed) {
+ mResumed = false;
+ mSessionsChanged = true;
+ mBackgroundHandler.removeMessages(BackgroundHandler.MSG_REBUILD_LIST, this);
+ doPauseIfNeededLocked();
+ }
+ if (DEBUG_LOCKING) Log.v(TAG, "...pause releasing lock");
+ }
+ }
+
+ public ArrayList<AppEntry> getAllApps() {
+ synchronized (mEntriesMap) {
+ return new ArrayList<>(mAppEntries);
+ }
+ }
+
+ // Creates a new list of app entries with the given filter and comparator.
+ public ArrayList<AppEntry> rebuild(AppFilter filter, Comparator<AppEntry> comparator) {
+ synchronized (mRebuildSync) {
+ synchronized (mEntriesMap) {
+ mRebuildingSessions.add(this);
+ mRebuildRequested = true;
+ mRebuildAsync = false;
+ mRebuildFilter = filter;
+ mRebuildComparator = comparator;
+ mRebuildResult = null;
+ if (!mBackgroundHandler.hasMessages(BackgroundHandler.MSG_REBUILD_LIST)) {
+ Message msg = mBackgroundHandler.obtainMessage(
+ BackgroundHandler.MSG_REBUILD_LIST);
+ mBackgroundHandler.sendMessage(msg);
+ }
+ }
+
+ // We will wait for .25s for the list to be built.
+ long waitend = SystemClock.uptimeMillis()+250;
+
+ while (mRebuildResult == null) {
+ long now = SystemClock.uptimeMillis();
+ if (now >= waitend) {
+ break;
+ }
+ try {
+ mRebuildSync.wait(waitend - now);
+ } catch (InterruptedException e) {
+ }
+ }
+
+ mRebuildAsync = true;
+
+ return mRebuildResult;
+ }
+ }
+
+ void handleRebuildList() {
+ AppFilter filter;
+ Comparator<AppEntry> comparator;
+ synchronized (mRebuildSync) {
+ if (!mRebuildRequested) {
+ return;
+ }
+
+ filter = mRebuildFilter;
+ comparator = mRebuildComparator;
+ mRebuildRequested = false;
+ mRebuildFilter = null;
+ mRebuildComparator = null;
+ }
+
+ Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
+
+ if (filter != null) {
+ filter.init();
+ }
+
+ List<AppEntry> apps;
+ synchronized (mEntriesMap) {
+ apps = new ArrayList<>(mAppEntries);
+ }
+
+ ArrayList<AppEntry> filteredApps = new ArrayList<AppEntry>();
+ if (DEBUG) Log.i(TAG, "Rebuilding...");
+ for (int i=0; i<apps.size(); i++) {
+ AppEntry entry = apps.get(i);
+ if (filter == null || filter.filterApp(entry)) {
+ synchronized (mEntriesMap) {
+ if (DEBUG_LOCKING) Log.v(TAG, "rebuild acquired lock");
+ entry.ensureLabel(mContext);
+ if (DEBUG) Log.i(TAG, "Using " + entry.info.packageName + ": " + entry);
+ filteredApps.add(entry);
+ if (DEBUG_LOCKING) Log.v(TAG, "rebuild releasing lock");
+ }
+ }
+ }
+
+ Collections.sort(filteredApps, comparator);
+
+ synchronized (mRebuildSync) {
+ if (!mRebuildRequested) {
+ mLastAppList = filteredApps;
+ if (!mRebuildAsync) {
+ mRebuildResult = filteredApps;
+ mRebuildSync.notifyAll();
+ } else {
+ if (!mMainHandler.hasMessages(MainHandler.MSG_REBUILD_COMPLETE, this)) {
+ Message msg = mMainHandler.obtainMessage(
+ MainHandler.MSG_REBUILD_COMPLETE, this);
+ mMainHandler.sendMessage(msg);
+ }
+ }
+ }
+ }
+
+ Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+ }
+
+ public void release() {
+ pause();
+ synchronized (mEntriesMap) {
+ mSessions.remove(this);
+ }
+ }
+ }
+
+ class MainHandler extends Handler {
+ static final int MSG_REBUILD_COMPLETE = 1;
+ static final int MSG_PACKAGE_LIST_CHANGED = 2;
+ static final int MSG_PACKAGE_ICON_CHANGED = 3;
+ static final int MSG_PACKAGE_SIZE_CHANGED = 4;
+ static final int MSG_ALL_SIZES_COMPUTED = 5;
+ static final int MSG_RUNNING_STATE_CHANGED = 6;
+ static final int MSG_LAUNCHER_INFO_CHANGED = 7;
+ static final int MSG_LOAD_ENTRIES_COMPLETE = 8;
+
+ @Override
+ public void handleMessage(Message msg) {
+ rebuildActiveSessions();
+ switch (msg.what) {
+ case MSG_REBUILD_COMPLETE: {
+ Session s = (Session)msg.obj;
+ if (mActiveSessions.contains(s)) {
+ s.mCallbacks.onRebuildComplete(s.mLastAppList);
+ }
+ } break;
+ case MSG_PACKAGE_LIST_CHANGED: {
+ for (int i=0; i<mActiveSessions.size(); i++) {
+ mActiveSessions.get(i).mCallbacks.onPackageListChanged();
+ }
+ } break;
+ case MSG_PACKAGE_ICON_CHANGED: {
+ for (int i=0; i<mActiveSessions.size(); i++) {
+ mActiveSessions.get(i).mCallbacks.onPackageIconChanged();
+ }
+ } break;
+ case MSG_PACKAGE_SIZE_CHANGED: {
+ for (int i=0; i<mActiveSessions.size(); i++) {
+ mActiveSessions.get(i).mCallbacks.onPackageSizeChanged(
+ (String)msg.obj);
+ }
+ } break;
+ case MSG_ALL_SIZES_COMPUTED: {
+ for (int i=0; i<mActiveSessions.size(); i++) {
+ mActiveSessions.get(i).mCallbacks.onAllSizesComputed();
+ }
+ } break;
+ case MSG_RUNNING_STATE_CHANGED: {
+ for (int i=0; i<mActiveSessions.size(); i++) {
+ mActiveSessions.get(i).mCallbacks.onRunningStateChanged(
+ msg.arg1 != 0);
+ }
+ } break;
+ case MSG_LAUNCHER_INFO_CHANGED: {
+ for (int i=0; i<mActiveSessions.size(); i++) {
+ mActiveSessions.get(i).mCallbacks.onLauncherInfoChanged();
+ }
+ } break;
+ case MSG_LOAD_ENTRIES_COMPLETE: {
+ for (int i=0; i<mActiveSessions.size(); i++) {
+ mActiveSessions.get(i).mCallbacks.onLoadEntriesCompleted();
+ }
+ } break;
+ }
+ }
+ }
+
+ private class BackgroundHandler extends Handler {
+ static final int MSG_REBUILD_LIST = 1;
+ static final int MSG_LOAD_ENTRIES = 2;
+ static final int MSG_LOAD_ICONS = 3;
+ static final int MSG_LOAD_SIZES = 4;
+ static final int MSG_LOAD_LAUNCHER = 5;
+
+ boolean mRunning;
+
+ BackgroundHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ // Always try rebuilding list first thing, if needed.
+ ArrayList<Session> rebuildingSessions = null;
+ synchronized (mEntriesMap) {
+ if (mRebuildingSessions.size() > 0) {
+ rebuildingSessions = new ArrayList<Session>(mRebuildingSessions);
+ mRebuildingSessions.clear();
+ }
+ }
+ if (rebuildingSessions != null) {
+ for (int i=0; i<rebuildingSessions.size(); i++) {
+ rebuildingSessions.get(i).handleRebuildList();
+ }
+ }
+
+ switch (msg.what) {
+ case MSG_REBUILD_LIST: {
+ } break;
+ case MSG_LOAD_ENTRIES: {
+ int numDone = 0;
+ synchronized (mEntriesMap) {
+ if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_ENTRIES acquired lock");
+ for (int i = 0; i < mApplications.size() && numDone < 6; i++) {
+ if (!mRunning) {
+ mRunning = true;
+ Message m = mMainHandler.obtainMessage(
+ MainHandler.MSG_RUNNING_STATE_CHANGED, 1);
+ mMainHandler.sendMessage(m);
+ }
+ ApplicationInfo info = mApplications.get(i);
+ int userId = UserHandle.getUserId(info.uid);
+ if (mEntriesMap.get(userId).get(info.packageName) == null) {
+ numDone++;
+ getEntryLocked(info);
+ }
+ }
+ if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_ENTRIES releasing lock");
+ }
+
+ if (numDone >= 6) {
+ sendEmptyMessage(MSG_LOAD_ENTRIES);
+ } else {
+ if (!mMainHandler.hasMessages(MainHandler.MSG_LOAD_ENTRIES_COMPLETE)) {
+ mMainHandler.sendEmptyMessage(MainHandler.MSG_LOAD_ENTRIES_COMPLETE);
+ }
+ sendEmptyMessage(MSG_LOAD_LAUNCHER);
+ }
+ } break;
+ case MSG_LOAD_LAUNCHER: {
+ Intent launchIntent = new Intent(Intent.ACTION_MAIN, null)
+ .addCategory(Intent.CATEGORY_LAUNCHER);
+
+ for (int i = 0; i < mEntriesMap.size(); i++) {
+ int userId = mEntriesMap.keyAt(i);
+ List<ResolveInfo> intents = mPm.queryIntentActivitiesAsUser(launchIntent,
+ PackageManager.GET_DISABLED_COMPONENTS, userId);
+ synchronized (mEntriesMap) {
+ if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_LAUNCHER acquired lock");
+ HashMap<String, AppEntry> userEntries = mEntriesMap.valueAt(i);
+ final int N = intents.size();
+ for (int j = 0; j < N; j++) {
+ String packageName = intents.get(j).activityInfo.packageName;
+ AppEntry entry = userEntries.get(packageName);
+ if (entry != null) {
+ entry.hasLauncherEntry = true;
+ } else {
+ Log.w(TAG, "Cannot find pkg: " + packageName
+ + " on user " + userId);
+ }
+ }
+ if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_LAUNCHER releasing lock");
+ }
+ }
+
+ if (!mMainHandler.hasMessages(MainHandler.MSG_LAUNCHER_INFO_CHANGED)) {
+ mMainHandler.sendEmptyMessage(MainHandler.MSG_LAUNCHER_INFO_CHANGED);
+ }
+ sendEmptyMessage(MSG_LOAD_ICONS);
+ } break;
+ case MSG_LOAD_ICONS: {
+ int numDone = 0;
+ synchronized (mEntriesMap) {
+ if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_ICONS acquired lock");
+ for (int i=0; i<mAppEntries.size() && numDone<2; i++) {
+ AppEntry entry = mAppEntries.get(i);
+ if (entry.icon == null || !entry.mounted) {
+ synchronized (entry) {
+ if (entry.ensureIconLocked(mContext, mPm)) {
+ if (!mRunning) {
+ mRunning = true;
+ Message m = mMainHandler.obtainMessage(
+ MainHandler.MSG_RUNNING_STATE_CHANGED, 1);
+ mMainHandler.sendMessage(m);
+ }
+ numDone++;
+ }
+ }
+ }
+ }
+ if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_ICONS releasing lock");
+ }
+ if (numDone > 0) {
+ if (!mMainHandler.hasMessages(MainHandler.MSG_PACKAGE_ICON_CHANGED)) {
+ mMainHandler.sendEmptyMessage(MainHandler.MSG_PACKAGE_ICON_CHANGED);
+ }
+ }
+ if (numDone >= 2) {
+ sendEmptyMessage(MSG_LOAD_ICONS);
+ } else {
+ sendEmptyMessage(MSG_LOAD_SIZES);
+ }
+ } break;
+ case MSG_LOAD_SIZES: {
+ synchronized (mEntriesMap) {
+ if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_SIZES acquired lock");
+ if (mCurComputingSizePkg != null) {
+ if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_SIZES releasing: currently computing");
+ return;
+ }
+
+ long now = SystemClock.uptimeMillis();
+ for (int i=0; i<mAppEntries.size(); i++) {
+ AppEntry entry = mAppEntries.get(i);
+ if (entry.size == SIZE_UNKNOWN || entry.sizeStale) {
+ if (entry.sizeLoadStart == 0 ||
+ (entry.sizeLoadStart < (now-20*1000))) {
+ if (!mRunning) {
+ mRunning = true;
+ Message m = mMainHandler.obtainMessage(
+ MainHandler.MSG_RUNNING_STATE_CHANGED, 1);
+ mMainHandler.sendMessage(m);
+ }
+ entry.sizeLoadStart = now;
+ mCurComputingSizePkg = entry.info.packageName;
+ mCurComputingSizeUserId = UserHandle.getUserId(entry.info.uid);
+ mPm.getPackageSizeInfo(mCurComputingSizePkg,
+ mCurComputingSizeUserId, mStatsObserver);
+ }
+ if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_SIZES releasing: now computing");
+ return;
+ }
+ }
+ if (!mMainHandler.hasMessages(MainHandler.MSG_ALL_SIZES_COMPUTED)) {
+ mMainHandler.sendEmptyMessage(MainHandler.MSG_ALL_SIZES_COMPUTED);
+ mRunning = false;
+ Message m = mMainHandler.obtainMessage(
+ MainHandler.MSG_RUNNING_STATE_CHANGED, 0);
+ mMainHandler.sendMessage(m);
+ }
+ if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_SIZES releasing lock");
+ }
+ } break;
+ }
+ }
+
+ final IPackageStatsObserver.Stub mStatsObserver = new IPackageStatsObserver.Stub() {
+ public void onGetStatsCompleted(PackageStats stats, boolean succeeded) {
+ boolean sizeChanged = false;
+ synchronized (mEntriesMap) {
+ if (DEBUG_LOCKING) Log.v(TAG, "onGetStatsCompleted acquired lock");
+ HashMap<String, AppEntry> userMap = mEntriesMap.get(stats.userHandle);
+ if (userMap == null) {
+ // The user must have been removed.
+ return;
+ }
+ AppEntry entry = userMap.get(stats.packageName);
+ if (entry != null) {
+ synchronized (entry) {
+ entry.sizeStale = false;
+ entry.sizeLoadStart = 0;
+ long externalCodeSize = stats.externalCodeSize
+ + stats.externalObbSize;
+ long externalDataSize = stats.externalDataSize
+ + stats.externalMediaSize;
+ long newSize = externalCodeSize + externalDataSize
+ + getTotalInternalSize(stats);
+ if (entry.size != newSize ||
+ entry.cacheSize != stats.cacheSize ||
+ entry.codeSize != stats.codeSize ||
+ entry.dataSize != stats.dataSize ||
+ entry.externalCodeSize != externalCodeSize ||
+ entry.externalDataSize != externalDataSize ||
+ entry.externalCacheSize != stats.externalCacheSize) {
+ entry.size = newSize;
+ entry.cacheSize = stats.cacheSize;
+ entry.codeSize = stats.codeSize;
+ entry.dataSize = stats.dataSize;
+ entry.externalCodeSize = externalCodeSize;
+ entry.externalDataSize = externalDataSize;
+ entry.externalCacheSize = stats.externalCacheSize;
+ entry.sizeStr = getSizeStr(entry.size);
+ entry.internalSize = getTotalInternalSize(stats);
+ entry.internalSizeStr = getSizeStr(entry.internalSize);
+ entry.externalSize = getTotalExternalSize(stats);
+ entry.externalSizeStr = getSizeStr(entry.externalSize);
+ if (DEBUG) Log.i(TAG, "Set size of " + entry.label + " " + entry
+ + ": " + entry.sizeStr);
+ sizeChanged = true;
+ }
+ }
+ if (sizeChanged) {
+ Message msg = mMainHandler.obtainMessage(
+ MainHandler.MSG_PACKAGE_SIZE_CHANGED, stats.packageName);
+ mMainHandler.sendMessage(msg);
+ }
+ }
+ if (mCurComputingSizePkg != null
+ && (mCurComputingSizePkg.equals(stats.packageName)
+ && mCurComputingSizeUserId == stats.userHandle)) {
+ mCurComputingSizePkg = null;
+ sendEmptyMessage(MSG_LOAD_SIZES);
+ }
+ if (DEBUG_LOCKING) Log.v(TAG, "onGetStatsCompleted releasing lock");
+ }
+ }
+ };
+ }
+
+ /**
+ * Receives notifications when applications are added/removed.
+ */
+ private class PackageIntentReceiver extends BroadcastReceiver {
+ void registerReceiver() {
+ IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
+ filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ filter.addDataScheme("package");
+ mContext.registerReceiver(this, filter);
+ // Register for events related to sdcard installation.
+ IntentFilter sdFilter = new IntentFilter();
+ sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
+ sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
+ mContext.registerReceiver(this, sdFilter);
+ // Register for events related to user creation/deletion.
+ IntentFilter userFilter = new IntentFilter();
+ userFilter.addAction(Intent.ACTION_USER_ADDED);
+ userFilter.addAction(Intent.ACTION_USER_REMOVED);
+ mContext.registerReceiver(this, userFilter);
+ }
+ void unregisterReceiver() {
+ mContext.unregisterReceiver(this);
+ }
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String actionStr = intent.getAction();
+ if (Intent.ACTION_PACKAGE_ADDED.equals(actionStr)) {
+ Uri data = intent.getData();
+ String pkgName = data.getEncodedSchemeSpecificPart();
+ for (int i = 0; i < mEntriesMap.size(); i++) {
+ addPackage(pkgName, mEntriesMap.keyAt(i));
+ }
+ } else if (Intent.ACTION_PACKAGE_REMOVED.equals(actionStr)) {
+ Uri data = intent.getData();
+ String pkgName = data.getEncodedSchemeSpecificPart();
+ for (int i = 0; i < mEntriesMap.size(); i++) {
+ removePackage(pkgName, mEntriesMap.keyAt(i));
+ }
+ } else if (Intent.ACTION_PACKAGE_CHANGED.equals(actionStr)) {
+ Uri data = intent.getData();
+ String pkgName = data.getEncodedSchemeSpecificPart();
+ for (int i = 0; i < mEntriesMap.size(); i++) {
+ invalidatePackage(pkgName, mEntriesMap.keyAt(i));
+ }
+ } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(actionStr) ||
+ Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(actionStr)) {
+ // When applications become available or unavailable (perhaps because
+ // the SD card was inserted or ejected) we need to refresh the
+ // AppInfo with new label, icon and size information as appropriate
+ // given the newfound (un)availability of the application.
+ // A simple way to do that is to treat the refresh as a package
+ // removal followed by a package addition.
+ String pkgList[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ if (pkgList == null || pkgList.length == 0) {
+ // Ignore
+ return;
+ }
+ boolean avail = Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(actionStr);
+ if (avail) {
+ for (String pkgName : pkgList) {
+ for (int i = 0; i < mEntriesMap.size(); i++) {
+ invalidatePackage(pkgName, mEntriesMap.keyAt(i));
+ }
+ }
+ }
+ } else if (Intent.ACTION_USER_ADDED.equals(actionStr)) {
+ addUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL));
+ } else if (Intent.ACTION_USER_REMOVED.equals(actionStr)) {
+ removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL));
+ }
+ }
+ }
+
+ public interface Callbacks {
+ void onRunningStateChanged(boolean running);
+ void onPackageListChanged();
+ void onRebuildComplete(ArrayList<AppEntry> apps);
+ void onPackageIconChanged();
+ void onPackageSizeChanged(String packageName);
+ void onAllSizesComputed();
+ void onLauncherInfoChanged();
+ void onLoadEntriesCompleted();
+ }
+
+ public static class SizeInfo {
+ public long cacheSize;
+ public long codeSize;
+ public long dataSize;
+ public long externalCodeSize;
+ public long externalDataSize;
+
+ // This is the part of externalDataSize that is in the cache
+ // section of external storage. Note that we don't just combine
+ // this with cacheSize because currently the platform can't
+ // automatically trim this data when needed, so it is something
+ // the user may need to manage. The externalDataSize also includes
+ // this value, since what this is here is really the part of
+ // externalDataSize that we can just consider to be "cache" files
+ // for purposes of cleaning them up in the app details UI.
+ public long externalCacheSize;
+ }
+
+ public static class AppEntry extends SizeInfo {
+ public final File apkFile;
+ public final long id;
+ public String label;
+ public long size;
+ public long internalSize;
+ public long externalSize;
+
+ public boolean mounted;
+
+ public boolean hasLauncherEntry;
+
+ public String getNormalizedLabel() {
+ if (normalizedLabel != null) {
+ return normalizedLabel;
+ }
+ normalizedLabel = normalize(label);
+ return normalizedLabel;
+ }
+
+ // Need to synchronize on 'this' for the following.
+ public ApplicationInfo info;
+ public Drawable icon;
+ public String sizeStr;
+ public String internalSizeStr;
+ public String externalSizeStr;
+ public boolean sizeStale;
+ public long sizeLoadStart;
+
+ public String normalizedLabel;
+
+ // A location where extra info can be placed to be used by custom filters.
+ public Object extraInfo;
+
+ AppEntry(Context context, ApplicationInfo info, long id) {
+ apkFile = new File(info.sourceDir);
+ this.id = id;
+ this.info = info;
+ this.size = SIZE_UNKNOWN;
+ this.sizeStale = true;
+ ensureLabel(context);
+ }
+
+ void ensureLabel(Context context) {
+ if (this.label == null || !this.mounted) {
+ if (!this.apkFile.exists()) {
+ this.mounted = false;
+ this.label = info.packageName;
+ } else {
+ this.mounted = true;
+ CharSequence label = info.loadLabel(context.getPackageManager());
+ this.label = label != null ? label.toString() : info.packageName;
+ }
+ }
+ }
+
+ boolean ensureIconLocked(Context context, PackageManager pm) {
+ if (this.icon == null) {
+ if (this.apkFile.exists()) {
+ this.icon = getBadgedIcon(pm);
+ return true;
+ } else {
+ this.mounted = false;
+ this.icon = context.getDrawable(
+ com.android.internal.R.drawable.sym_app_on_sd_unavailable_icon);
+ }
+ } else if (!this.mounted) {
+ // If the app wasn't mounted but is now mounted, reload
+ // its icon.
+ if (this.apkFile.exists()) {
+ this.mounted = true;
+ this.icon = getBadgedIcon(pm);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private Drawable getBadgedIcon(PackageManager pm) {
+ // Do badging ourself so that it comes from the user of the app not the current user.
+ return pm.getUserBadgedIcon(pm.loadUnbadgedItemIcon(info, info),
+ new UserHandle(UserHandle.getUserId(info.uid)));
+ }
+
+ public static String normalize(String str) {
+ String tmp = Normalizer.normalize(str, Form.NFD);
+ return REMOVE_DIACRITICALS_PATTERN.matcher(tmp)
+ .replaceAll("").toLowerCase();
+ }
+ }
+
+ public static final Comparator<AppEntry> ALPHA_COMPARATOR = new Comparator<AppEntry>() {
+ private final Collator sCollator = Collator.getInstance();
+ @Override
+ public int compare(AppEntry object1, AppEntry object2) {
+ return sCollator.compare(object1.label, object2.label);
+ }
+ };
+
+ public static final Comparator<AppEntry> SIZE_COMPARATOR
+ = new Comparator<AppEntry>() {
+ private final Collator sCollator = Collator.getInstance();
+ @Override
+ public int compare(AppEntry object1, AppEntry object2) {
+ if (object1.size < object2.size) return 1;
+ if (object1.size > object2.size) return -1;
+ return sCollator.compare(object1.label, object2.label);
+ }
+ };
+
+ public static final Comparator<AppEntry> INTERNAL_SIZE_COMPARATOR
+ = new Comparator<AppEntry>() {
+ private final Collator sCollator = Collator.getInstance();
+ @Override
+ public int compare(AppEntry object1, AppEntry object2) {
+ if (object1.internalSize < object2.internalSize) return 1;
+ if (object1.internalSize > object2.internalSize) return -1;
+ return sCollator.compare(object1.label, object2.label);
+ }
+ };
+
+ public static final Comparator<AppEntry> EXTERNAL_SIZE_COMPARATOR
+ = new Comparator<AppEntry>() {
+ private final Collator sCollator = Collator.getInstance();
+ @Override
+ public int compare(AppEntry object1, AppEntry object2) {
+ if (object1.externalSize < object2.externalSize) return 1;
+ if (object1.externalSize > object2.externalSize) return -1;
+ return sCollator.compare(object1.label, object2.label);
+ }
+ };
+
+ public interface AppFilter {
+ void init();
+ boolean filterApp(AppEntry info);
+ }
+
+ public static final AppFilter FILTER_PERSONAL = new AppFilter() {
+ private int mCurrentUser;
+
+ public void init() {
+ mCurrentUser = ActivityManager.getCurrentUser();
+ }
+
+ @Override
+ public boolean filterApp(AppEntry entry) {
+ return UserHandle.getUserId(entry.info.uid) == mCurrentUser;
+ }
+ };
+
+ public static final AppFilter FILTER_WORK = new AppFilter() {
+ private int mCurrentUser;
+
+ public void init() {
+ mCurrentUser = ActivityManager.getCurrentUser();
+ }
+
+ @Override
+ public boolean filterApp(AppEntry entry) {
+ return UserHandle.getUserId(entry.info.uid) != mCurrentUser;
+ }
+ };
+
+ public static final AppFilter FILTER_DOWNLOADED_AND_LAUNCHER = new AppFilter() {
+ public void init() {
+ }
+
+ @Override
+ public boolean filterApp(AppEntry entry) {
+ if ((entry.info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
+ return true;
+ } else if ((entry.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+ return true;
+ } else if (entry.hasLauncherEntry) {
+ return true;
+ }
+ return false;
+ }
+ };
+
+ public static final AppFilter FILTER_THIRD_PARTY = new AppFilter() {
+ public void init() {
+ }
+
+ @Override
+ public boolean filterApp(AppEntry entry) {
+ if ((entry.info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
+ return true;
+ } else if ((entry.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+ return true;
+ }
+ return false;
+ }
+ };
+
+ public static final AppFilter FILTER_DISABLED = new AppFilter() {
+ public void init() {
+ }
+
+ @Override
+ public boolean filterApp(AppEntry entry) {
+ return !entry.info.enabled;
+ }
+ };
+
+ public static final AppFilter FILTER_ALL_ENABLED = new AppFilter() {
+ public void init() {
+ }
+
+ @Override
+ public boolean filterApp(AppEntry entry) {
+ return entry.info.enabled;
+ }
+ };
+
+ public static final AppFilter FILTER_EVERYTHING = new AppFilter() {
+ public void init() {
+ }
+
+ @Override
+ public boolean filterApp(AppEntry entry) {
+ return true;
+ }
+ };
+
+ public static final AppFilter FILTER_WITH_DOMAIN_URLS = new AppFilter() {
+ public void init() {
+ }
+
+ @Override
+ public boolean filterApp(AppEntry entry) {
+ return (entry.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0;
+ }
+ };
+
+ public static class VolumeFilter implements AppFilter {
+ private final String mVolumeUuid;
+
+ public VolumeFilter(String volumeUuid) {
+ mVolumeUuid = volumeUuid;
+ }
+
+ @Override
+ public void init() {
+ }
+
+ @Override
+ public boolean filterApp(AppEntry info) {
+ return Objects.equals(info.info.volumeUuid, mVolumeUuid);
+ }
+ }
+
+ public static class CompoundFilter implements AppFilter {
+ private final AppFilter mFirstFilter;
+ private final AppFilter mSecondFilter;
+
+ public CompoundFilter(AppFilter first, AppFilter second) {
+ mFirstFilter = first;
+ mSecondFilter = second;
+ }
+
+ @Override
+ public void init() {
+ mFirstFilter.init();
+ mSecondFilter.init();
+ }
+
+ @Override
+ public boolean filterApp(AppEntry info) {
+ return mFirstFilter.filterApp(info) && mSecondFilter.filterApp(info);
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java b/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java
new file mode 100644
index 0000000..d34dd89
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java
@@ -0,0 +1,37 @@
+/*
+ * 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.settingslib.applications;
+
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+
+public class InterestingConfigChanges {
+ private final Configuration mLastConfiguration = new Configuration();
+ private int mLastDensity;
+
+ public boolean applyNewConfig(Resources res) {
+ int configChanges = mLastConfiguration.updateFrom(res.getConfiguration());
+ boolean densityChanged = mLastDensity != res.getDisplayMetrics().densityDpi;
+ if (densityChanged || (configChanges&(ActivityInfo.CONFIG_LOCALE
+ |ActivityInfo.CONFIG_UI_MODE|ActivityInfo.CONFIG_SCREEN_LAYOUT)) != 0) {
+ mLastDensity = res.getDisplayMetrics().densityDpi;
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index c026d77..de2f1f9 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -911,7 +911,7 @@
<string name="monitoring_description_device_owned">Your device is managed by <xliff:g id="organization">%1$s</xliff:g>.\n\nYour administrator can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information. For more information, contact your administrator.</string>
<!-- Monitoring dialog VPN text [CHAR LIMIT=400] -->
- <string name="monitoring_description_vpn">You gave an app permission to set up a VPN connection.\n\nThis app can monitor your device and network activity, including emails, apps and websites.</string>
+ <string name="monitoring_description_vpn">You gave an app permission to set up a VPN connection.\n\nThis app can monitor your device and network activity, including emails, apps, and websites.</string>
<!-- Monitoring dialog VPN with device owner text [CHAR LIMIT=400] -->
<string name="monitoring_description_vpn_device_owned">Your device is managed by <xliff:g id="organization">%1$s</xliff:g>.\n\nYour administrator can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nYou\'re connected to a VPN, which can monitor your network activity, including emails, apps, and websites.\n\nFor more information, contact your administrator.</string>
@@ -923,16 +923,16 @@
<string name="legacy_vpn_name">VPN</string>
<!-- Monitoring dialog text for single app (no profile or device owner) [CHAR LIMIT=400] -->
- <string name="monitoring_description_app">You\'re connected to <xliff:g id="application">%1$s</xliff:g>, which can monitor your network activity including emails, apps and websites.</string>
+ <string name="monitoring_description_app">You\'re connected to <xliff:g id="application">%1$s</xliff:g>, which can monitor your network activity including emails, apps, and websites.</string>
<!-- Monitoring dialog text for single app (inside personal profile) [CHAR LIMIT=400] -->
- <string name="monitoring_description_app_personal">You\'re connected to <xliff:g id="application">%1$s</xliff:g>, which can monitor your personal network activity, including emails, apps and websites.</string>
+ <string name="monitoring_description_app_personal">You\'re connected to <xliff:g id="application">%1$s</xliff:g>, which can monitor your personal network activity, including emails, apps, and websites.</string>
<!-- Monitoring dialog text for single app (inside work profile) [CHAR LIMIT=400] -->
- <string name="monitoring_description_app_work">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>. It is connected to <xliff:g id="application">%2$s</xliff:g>, which can monitor your work network activity, including emails, apps and websites.\n\nFor more information, contact your administrator.</string>
+ <string name="monitoring_description_app_work">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>. It is connected to <xliff:g id="application">%2$s</xliff:g>, which can monitor your work network activity, including emails, apps, and websites.\n\nFor more information, contact your administrator.</string>
<!-- Monitoring dialog text for multiple apps (in personal and work profiles) [CHAR LIMIT=400] -->
- <string name="monitoring_description_app_personal_work">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>. It is connected to <xliff:g id="application_work">%2$s</xliff:g>, which can monitor your work network activity, including emails, apps and websites.\n\nYou\'re also connected to <xliff:g id="application_personal">%3$s</xliff:g>, which can monitor your personal network activity.</string>
+ <string name="monitoring_description_app_personal_work">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>. It is connected to <xliff:g id="application_work">%2$s</xliff:g>, which can monitor your work network activity, including emails, apps, and websites.\n\nYou\'re also connected to <xliff:g id="application_personal">%3$s</xliff:g>, which can monitor your personal network activity.</string>
<!-- Monitoring dialog text for single app (with device owner) [CHAR LIMIT=400] -->
<string name="monitoring_description_vpn_app_device_owned">Your device is managed by <xliff:g id="organization">%1$s</xliff:g>.\n\nYour administrator can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nYou\'re connected to <xliff:g id="application">%2$s</xliff:g>, which can monitor your network activity, including emails, apps, and websites.\n\nFor more information, contact your administrator.</string>
@@ -1006,7 +1006,7 @@
<string name="volumeui_notification_text">Touch to restore the original.</string>
<!-- Toast shown when user unlocks screen and managed profile activity is in the foreground -->
- <string name="managed_profile_foreground_toast">You are in the Work profile</string>
+ <string name="managed_profile_foreground_toast">You are in the work profile</string>
<string-array name="volume_stream_titles" translatable="false">
<item>Voice calls</item> <!-- STREAM_VOICE_CALL -->
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 79af706..f129288 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -124,6 +124,14 @@
startAssist();
}
+ public void hideAssist() {
+ try {
+ mVoiceInteractionManagerService.hideCurrentSession();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to call hideCurrentSession", e);
+ }
+ }
+
private WindowManager.LayoutParams getLayoutParams() {
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
index 1f3a830..3f72125 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
@@ -82,11 +82,9 @@
sNotificationPulseStats.append();
}
- public static void traceDozing(Context context, boolean dozing) {
- if (!ENABLED) return;
- sPulsing = false;
+ private static void init(Context context) {
synchronized (DozeLog.class) {
- if (dozing && sMessages == null) {
+ if (sMessages == null) {
sTimes = new long[SIZE];
sMessages = new String[SIZE];
sSince = System.currentTimeMillis();
@@ -105,6 +103,12 @@
KeyguardUpdateMonitor.getInstance(context).registerCallback(sKeyguardCallback);
}
}
+ }
+
+ public static void traceDozing(Context context, boolean dozing) {
+ if (!ENABLED) return;
+ sPulsing = false;
+ init(context);
log("dozing " + dozing);
}
@@ -146,10 +150,12 @@
}
}
- public static void traceProximityResult(boolean near, long millis, int pulseReason) {
+ public static void traceProximityResult(Context context, boolean near, long millis,
+ int pulseReason) {
if (!ENABLED) return;
log("proximityResult reason=" + pulseReasonToString(pulseReason) + " near=" + near
+ " millis=" + millis);
+ init(context);
sProxStats[pulseReason][near ? 0 : 1].append();
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 8d27450..5d46712 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -235,7 +235,7 @@
public void onProximityResult(int result) {
final boolean isNear = result == RESULT_NEAR;
final long end = SystemClock.uptimeMillis();
- DozeLog.traceProximityResult(isNear, end - start, reason);
+ DozeLog.traceProximityResult(mContext, isNear, end - start, reason);
if (nonBlocking) {
// we already continued
return;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 86910fe..f00fed5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -455,7 +455,7 @@
@Override
public void onFingerprintAuthenticated(int userId) {
if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
- mViewMediatorCallback.keyguardDone(true);
+ mStatusBarKeyguardViewManager.notifyKeyguardAuthenticated();
} else {
mStatusBarKeyguardViewManager.animateCollapsePanels(
FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR);
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
index 88d0997..2a84362 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
@@ -96,6 +96,7 @@
.create();
mDialog.create();
+ mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setFilterTouchesWhenObscured(true);
((CheckBox) mDialog.findViewById(R.id.remember)).setOnCheckedChangeListener(this);
mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 6fb4b48..c945fc9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -92,6 +92,7 @@
import com.android.systemui.RecentsComponent;
import com.android.systemui.SwipeHelper;
import com.android.systemui.SystemUI;
+import com.android.systemui.assist.AssistManager;
import com.android.systemui.recents.Recents;
import com.android.systemui.statusbar.NotificationData.Entry;
import com.android.systemui.statusbar.phone.NavigationBarView;
@@ -240,6 +241,8 @@
private NotificationClicker mNotificationClicker = new NotificationClicker();
+ protected AssistManager mAssistManager;
+
@Override // NotificationData.Environment
public boolean isDeviceProvisioned() {
return mDeviceProvisioned;
@@ -1626,6 +1629,7 @@
// TODO: Dismiss Keyguard.
}
if (intent.isActivity()) {
+ mAssistManager.hideAssist();
overrideActivityPendingAppTransition(keyguardShowing
&& !afterKeyguardGone);
}
@@ -1644,7 +1648,7 @@
true /* force */, true /* delayed */);
visibilityChanged(false);
- return intent != null && intent.isActivity();
+ return true;
}
}, afterKeyguardGone);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 9ef495d..d444ea8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -903,12 +903,18 @@
return mShowingPublic ? mPublicLayout : mPrivateLayout;
}
+ @Override
+ public void setShowingLegacyBackground(boolean showing) {
+ super.setShowingLegacyBackground(showing);
+ mPrivateLayout.setShowingLegacyBackground(showing);
+ mPublicLayout.setShowingLegacyBackground(showing);
+ }
+
public void setExpansionLogger(ExpansionLogger logger, String key) {
mLogger = logger;
mLoggingKey = key;
}
-
private void logExpansionEvent(boolean userAction, boolean wasExpanded) {
final boolean nowExpanded = isExpanded();
if (wasExpanded != nowExpanded && mLogger != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index dec2fc7..8172a4d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -67,6 +67,8 @@
private final Paint mFadePaint = new Paint();
private boolean mAnimate;
private boolean mIsHeadsUp;
+ private boolean mShowingLegacyBackground;
+
private final ViewTreeObserver.OnPreDrawListener mEnableAnimationPredrawListener
= new ViewTreeObserver.OnPreDrawListener() {
@Override
@@ -421,7 +423,7 @@
public void setDark(boolean dark, boolean fade, long delay) {
if (mDark == dark || mContractedChild == null) return;
mDark = dark;
- mContractedWrapper.setDark(dark, fade, delay);
+ mContractedWrapper.setDark(dark && !mShowingLegacyBackground, fade, delay);
}
public void setHeadsUp(boolean headsUp) {
@@ -436,4 +438,8 @@
// layout, and saves us some layers.
return false;
}
+
+ public void setShowingLegacyBackground(boolean showing) {
+ mShowingLegacyBackground = showing;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 3d57d54..3737d05 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -228,4 +228,9 @@
ensureView();
return mKeyguardView.interceptMediaKey(event);
}
+
+ public void notifyKeyguardAuthenticated() {
+ ensureView();
+ mKeyguardView.finish();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 39dc480..9e1af82 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -36,6 +36,7 @@
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
+import android.view.animation.PathInterpolator;
import android.widget.FrameLayout;
import android.widget.TextView;
@@ -205,6 +206,10 @@
}
};
+ /** Interpolator to be used for animations that respond directly to a touch */
+ private final Interpolator mTouchResponseInterpolator =
+ new PathInterpolator(0.3f, 0f, 0.1f, 1f);
+
public NotificationPanelView(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(!DEBUG);
@@ -939,7 +944,7 @@
mQsExpansionFromOverscroll = false;
updateQsState();
}
- });
+ }, false /* isClick */);
}
private void onQsExpansionStarted() {
@@ -1390,10 +1395,11 @@
}
private void flingSettings(float vel, boolean expand) {
- flingSettings(vel, expand, null);
+ flingSettings(vel, expand, null, false /* isClick */);
}
- private void flingSettings(float vel, boolean expand, final Runnable onFinishRunnable) {
+ private void flingSettings(float vel, boolean expand, final Runnable onFinishRunnable,
+ boolean isClick) {
float target = expand ? mQsMaxExpansionHeight : mQsMinExpansionHeight;
if (target == mQsExpansionHeight) {
mScrollYOverride = -1;
@@ -1408,7 +1414,12 @@
}
mScrollView.setBlockFlinging(true);
ValueAnimator animator = ValueAnimator.ofFloat(mQsExpansionHeight, target);
- mFlingAnimationUtils.apply(animator, mQsExpansionHeight, target, vel);
+ if (isClick) {
+ animator.setInterpolator(mTouchResponseInterpolator);
+ animator.setDuration(368);
+ } else {
+ mFlingAnimationUtils.apply(animator, mQsExpansionHeight, target, vel);
+ }
if (belowFalsingThreshold) {
animator.setDuration(350);
}
@@ -1870,12 +1881,12 @@
if (v == mHeader) {
onQsExpansionStarted();
if (mQsExpanded) {
- flingSettings(0 /* vel */, false /* expand */);
+ flingSettings(0 /* vel */, false /* expand */, null, true /* isClick */);
} else if (mQsExpansionEnabled) {
EventLogTags.writeSysuiLockscreenGesture(
EventLogConstants.SYSUI_TAP_TO_OPEN_QS,
0, 0);
- flingSettings(0 /* vel */, true /* expand */);
+ flingSettings(0 /* vel */, true /* expand */, null, true /* isClick */);
}
}
}
@@ -2112,7 +2123,9 @@
public void setDozing(boolean dozing, boolean animate) {
if (dozing == mDozing) return;
mDozing = dozing;
- updateDozingVisibilities(animate);
+ if (mStatusBarState == StatusBarState.KEYGUARD) {
+ updateDozingVisibilities(animate);
+ }
}
private void updateDozingVisibilities(boolean animate) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index f1e51a5..569b918 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -32,7 +32,6 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
@@ -345,8 +344,6 @@
private int mNavigationIconHints = 0;
private HandlerThread mHandlerThread;
- private AssistManager mAssistManager;
-
// ensure quick settings is disabled until the current user makes it through the setup wizard
private boolean mUserSetup = false;
private ContentObserver mUserSetupObserver = new ContentObserver(new Handler()) {
@@ -412,6 +409,7 @@
private boolean mWaitingForKeyguardExit;
private boolean mDozing;
+ private boolean mDozingRequested;
private boolean mScrimSrcModeEnabled;
private Interpolator mLinearInterpolator = new LinearInterpolator();
@@ -2753,6 +2751,7 @@
final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
Runnable runnable = new Runnable() {
public void run() {
+ mAssistManager.hideAssist();
intent.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
int result = ActivityManager.START_CANCELED;
@@ -2776,10 +2775,13 @@
Runnable cancelRunnable = new Runnable() {
@Override
public void run() {
- callback.onActivityStarted(ActivityManager.START_CANCELED);
+ if (callback != null) {
+ callback.onActivityStarted(ActivityManager.START_CANCELED);
+ }
}
};
- executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShade, afterKeyguardGone);
+ executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShade,
+ afterKeyguardGone);
}
public void executeRunnableDismissingKeyguard(final Runnable runnable,
@@ -3478,9 +3480,6 @@
}
private void updateDozingState() {
- if (mState != StatusBarState.KEYGUARD && !mNotificationPanel.isDozing()) {
- return;
- }
boolean animate = !mDozing && mDozeScrimController.isPulsing();
mNotificationPanel.setDozing(mDozing, animate);
mStackScroller.setDark(mDozing, animate, mScreenOnTouchLocation);
@@ -3597,6 +3596,7 @@
mState = state;
mGroupManager.setStatusBarState(state);
mStatusBarWindowManager.setStatusBarState(state);
+ updateDozing();
}
@Override
@@ -3912,6 +3912,11 @@
}
}
+ private void updateDozing() {
+ mDozing = mDozingRequested && mState == StatusBarState.KEYGUARD;
+ updateDozingState();
+ }
+
private final class ShadeUpdates {
private final ArraySet<String> mVisibleNotifications = new ArraySet<String>();
private final ArraySet<String> mNewVisibleNotifications = new ArraySet<String>();
@@ -4017,10 +4022,10 @@
}
private void handleStartDozing(@NonNull Runnable ready) {
- if (!mDozing) {
- mDozing = true;
+ if (!mDozingRequested) {
+ mDozingRequested = true;
DozeLog.traceDozing(mContext, mDozing);
- updateDozingState();
+ updateDozing();
}
ready.run();
}
@@ -4030,10 +4035,10 @@
}
private void handleStopDozing() {
- if (mDozing) {
- mDozing = false;
+ if (mDozingRequested) {
+ mDozingRequested = false;
DozeLog.traceDozing(mContext, mDozing);
- updateDozingState();
+ updateDozing();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index 181926c..dfc6924 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -110,7 +110,6 @@
private NextAlarmController mNextAlarmController;
private QSPanel mQSPanel;
-
private final Rect mClipBounds = new Rect();
private boolean mCaptureValues;
@@ -121,6 +120,7 @@
private float mCurrentT;
private boolean mShowingDetail;
+ private boolean mDetailTransitioning;
public StatusBarHeaderView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -623,7 +623,7 @@
mSettingsButton.setTranslationX(values.settingsTranslation);
mSettingsButton.setRotation(values.settingsRotation);
applyAlpha(mEmergencyCallsOnly, values.emergencyCallsOnlyAlpha);
- if (!mShowingDetail) {
+ if (!mShowingDetail && !mDetailTransitioning) {
// Otherwise it needs to stay invisible
applyAlpha(mAlarmStatus, values.alarmStatusAlpha);
}
@@ -706,6 +706,7 @@
@Override
public void onShowingDetail(final QSTile.DetailAdapter detail) {
+ mDetailTransitioning = true;
post(new Runnable() {
@Override
public void run() {
@@ -788,6 +789,7 @@
if (!in) {
v.setVisibility(INVISIBLE);
}
+ mDetailTransitioning = false;
}
})
.start();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 6cb890a..fcf3a9c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -447,4 +447,12 @@
mPhoneStatusBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */,
false /* delayed */, speedUpFactor);
}
+
+ /**
+ * Notifies that the user has authenticated by other means than using the bouncer, for example,
+ * fingerprint.
+ */
+ public void notifyKeyguardAuthenticated() {
+ mBouncer.notifyKeyguardAuthenticated();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index eac5e79..c31244c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -96,6 +96,7 @@
private ExpandableNotificationRow mChildExpandingView;
private int mHeadsUpAppearHeightBottom;
private boolean mShadeExpanded;
+ private ArrayList<View> mChildrenToClearFromOverlay = new ArrayList<>();
public StackStateAnimator(NotificationStackScrollLayout hostLayout) {
mHostLayout = hostLayout;
@@ -794,6 +795,10 @@
private void onAnimationFinished() {
mHostLayout.onChildAnimationFinished();
+ for (View v : mChildrenToClearFromOverlay) {
+ mHostLayout.getOverlay().remove(v);
+ }
+ mChildrenToClearFromOverlay.clear();
}
/**
@@ -880,8 +885,20 @@
finalState.applyState(changingView, mTmpState);
} else if (event.animationType == NotificationStackScrollLayout
.AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR) {
- // This item is added, initialize it's properties.
mHeadsUpDisappearChildren.add(changingView);
+ if (mHostLayout.indexOfChild(changingView) == -1) {
+ // This notification was actually removed, so we need to add it to the overlay
+ mHostLayout.getOverlay().add(changingView);
+ ViewState viewState = new ViewState();
+ viewState.initFrom(changingView);
+ viewState.yTranslation = -changingView.getActualHeight();
+ // We temporarily enable Y animations, the real filter will be combined
+ // afterwards anyway
+ mAnimationFilter.animateY = true;
+ startViewAnimations(changingView, viewState, 0,
+ ANIMATION_DURATION_HEADS_UP_DISAPPEAR);
+ mChildrenToClearFromOverlay.add(changingView);
+ }
}
mNewEvents.add(event);
}
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 8c8be4e..14f8a00 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -1434,7 +1434,7 @@
final VolumeInfo vol = findVolumeById(volId);
try {
- mConnector.execute("volume", "format", vol.id);
+ mConnector.execute("volume", "format", vol.id, "auto");
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 1046b29..bedc729 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -468,12 +468,6 @@
*/
String mDeviceOwnerName;
- /**
- * Preferred activities to start on boot/user switch, as set by DevicePolicyManager. Indexed
- * by userId.
- */
- SparseArray<ComponentName> mPreferredSetupActivities = new SparseArray<>();
-
public class PendingAssistExtras extends Binder implements Runnable {
public final ActivityRecord activity;
public final Bundle extras;
@@ -3435,20 +3429,13 @@
// Factory test.
ai = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId);
} else {
- ComponentName preferredComponent = mPreferredSetupActivities.get(userId);
- if (preferredComponent != null) {
- ai = AppGlobals.getPackageManager().getActivityInfo(
- preferredComponent, flags, userId);
- }
- if (ai == null) {
- ResolveInfo info = AppGlobals.getPackageManager().resolveIntent(
- intent,
- intent.resolveTypeIfNeeded(mContext.getContentResolver()),
- flags, userId);
+ ResolveInfo info = AppGlobals.getPackageManager().resolveIntent(
+ intent,
+ intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+ flags, userId);
- if (info != null) {
- ai = info.activityInfo;
- }
+ if (info != null) {
+ ai = info.activityInfo;
}
}
} catch (RemoteException e) {
@@ -8919,22 +8906,6 @@
}
@Override
- public void updatePreferredSetupActivity(ComponentName preferredActivity, int userId) {
- final int callingUid = Binder.getCallingUid();
- if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
- throw new SecurityException(
- "updatePreferredSetupActivity called from non-system process");
- }
- synchronized (this) {
- if (preferredActivity == null) {
- mPreferredSetupActivities.delete(userId);
- } else {
- mPreferredSetupActivities.put(userId, preferredActivity);
- }
- }
- }
-
- @Override
public void updateDeviceOwner(String packageName) {
final int callingUid = Binder.getCallingUid();
if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index fd36b7e..b0d5765 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -22,6 +22,7 @@
import android.app.IUserSwitchObserver;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Environment;
import android.os.Handler;
@@ -73,13 +74,6 @@
private ClientMonitor mRemoveClient = null;
private final AppOpsManager mAppOps;
- // Message types. Used internally to dispatch messages to the correct callback.
- // Must agree with the list in fingerprint.h
- private static final int FINGERPRINT_ERROR = -1;
- private static final int FINGERPRINT_ACQUIRED = 1;
- private static final int FINGERPRINT_TEMPLATE_ENROLLING = 3;
- private static final int FINGERPRINT_TEMPLATE_REMOVED = 4;
- private static final int FINGERPRINT_AUTHENTICATED = 5;
private static final long MS_PER_SEC = 1000;
private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000;
private static final int MAX_FAILED_ATTEMPTS = 5;
@@ -207,7 +201,6 @@
if (mEnrollClient != null) {
if (mEnrollClient.sendEnrollResult(fingerId, groupId, remaining)) {
if (remaining == 0) {
- ContentResolver res = mContext.getContentResolver();
addTemplateForUser(mEnrollClient, fingerId);
removeClient(mEnrollClient);
}
@@ -262,14 +255,14 @@
}
void startEnrollment(IBinder token, byte[] cryptoToken, int groupId,
- IFingerprintServiceReceiver receiver, int flags) {
+ IFingerprintServiceReceiver receiver, int flags, boolean restricted) {
IFingerprintDaemon daemon = getFingerprintDaemon();
if (daemon == null) {
Slog.w(TAG, "enroll: no fingeprintd!");
return;
}
stopPendingOperations();
- mEnrollClient = new ClientMonitor(token, receiver, groupId);
+ mEnrollClient = new ClientMonitor(token, receiver, groupId, restricted);
final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC);
try {
final int result = daemon.enroll(cryptoToken, groupId, timeout);
@@ -328,14 +321,14 @@
}
void startAuthentication(IBinder token, long opId, int groupId,
- IFingerprintServiceReceiver receiver, int flags) {
+ IFingerprintServiceReceiver receiver, int flags, boolean restricted) {
IFingerprintDaemon daemon = getFingerprintDaemon();
if (daemon == null) {
Slog.w(TAG, "startAuthentication: no fingeprintd!");
return;
}
stopPendingOperations();
- mAuthClient = new ClientMonitor(token, receiver, groupId);
+ mAuthClient = new ClientMonitor(token, receiver, groupId, restricted);
if (inLockoutMode()) {
Slog.v(TAG, "In lockout mode; disallowing authentication");
if (!mAuthClient.sendError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT)) {
@@ -344,7 +337,6 @@
mAuthClient = null;
return;
}
- final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC);
try {
final int result = daemon.authenticate(opId, groupId);
if (result != 0) {
@@ -378,13 +370,14 @@
}
void startRemove(IBinder token, int fingerId, int userId,
- IFingerprintServiceReceiver receiver) {
+ IFingerprintServiceReceiver receiver, boolean restricted) {
IFingerprintDaemon daemon = getFingerprintDaemon();
if (daemon == null) {
Slog.w(TAG, "startRemove: no fingeprintd!");
return;
}
- mRemoveClient = new ClientMonitor(token, receiver, userId);
+
+ mRemoveClient = new ClientMonitor(token, receiver, userId, restricted);
// The fingerprint template ids will be removed when we get confirmation from the HAL
try {
final int result = daemon.remove(fingerId, userId);
@@ -404,6 +397,11 @@
return mFingerprintUtils.getFingerprintsForUser(mContext, groupId).size() > 0;
}
+ boolean hasPermission(String permission) {
+ return getContext().checkCallingOrSelfPermission(permission)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
void checkPermission(String permission) {
getContext().enforceCallingOrSelfPermission(permission,
"Must have " + permission + " permission.");
@@ -420,11 +418,14 @@
IBinder token;
IFingerprintServiceReceiver receiver;
int userId;
+ boolean restricted; // True if client does not have MANAGE_FINGERPRINT permission
- public ClientMonitor(IBinder token, IFingerprintServiceReceiver receiver, int userId) {
+ public ClientMonitor(IBinder token, IFingerprintServiceReceiver receiver, int userId,
+ boolean restricted) {
this.token = token;
this.receiver = receiver;
this.userId = userId;
+ this.restricted = restricted;
try {
token.linkToDeath(this, 0);
} catch (RemoteException e) {
@@ -498,7 +499,13 @@
boolean result = false;
if (receiver != null) {
try {
- receiver.onAuthenticated(mHalDeviceId, fpId, groupId);
+ if (fpId == 0) {
+ receiver.onAuthenticationFailed(mHalDeviceId);
+ } else {
+ Fingerprint fp = !restricted ?
+ new Fingerprint("" /* TODO */, groupId, fpId, mHalDeviceId) : null;
+ receiver.onAuthenticationSucceeded(mHalDeviceId, fp);
+ }
} catch (RemoteException e) {
Slog.w(TAG, "Failed to notify Authenticated:", e);
result = true; // client failed
@@ -592,14 +599,22 @@
final IFingerprintServiceReceiver receiver, final int flags) {
checkPermission(MANAGE_FINGERPRINT);
final byte [] cryptoClone = Arrays.copyOf(cryptoToken, cryptoToken.length);
+
+ final boolean restricted = isRestricted();
mHandler.post(new Runnable() {
@Override
public void run() {
- startEnrollment(token, cryptoClone, groupId, receiver, flags);
+ startEnrollment(token, cryptoClone, groupId, receiver, flags, restricted);
}
});
}
+ private boolean isRestricted() {
+ // Only give privileged apps (like Settings) access to fingerprint info
+ final boolean restricted = !hasPermission(MANAGE_FINGERPRINT);
+ return restricted;
+ }
+
@Override // Binder call
public void cancelEnrollment(final IBinder token) {
checkPermission(MANAGE_FINGERPRINT);
@@ -614,14 +629,15 @@
@Override // Binder call
public void authenticate(final IBinder token, final long opId, final int groupId,
final IFingerprintServiceReceiver receiver, final int flags, String opPackageName) {
- checkPermission(USE_FINGERPRINT);
+
if (!canUseFingerprint(opPackageName)) {
return;
}
+ final boolean restricted = isRestricted();
mHandler.post(new Runnable() {
@Override
public void run() {
- startAuthentication(token, opId, groupId, receiver, flags);
+ startAuthentication(token, opId, groupId, receiver, flags, restricted);
}
});
}
@@ -643,10 +659,11 @@
public void remove(final IBinder token, final int fingerId, final int groupId,
final IFingerprintServiceReceiver receiver) {
checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
+ final boolean restricted = isRestricted();
mHandler.post(new Runnable() {
@Override
public void run() {
- startRemove(token, fingerId, groupId, receiver);
+ startRemove(token, fingerId, groupId, receiver, restricted);
}
});
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintsUserState.java b/services/core/java/com/android/server/fingerprint/FingerprintsUserState.java
index 33177b4..902d970 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintsUserState.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintsUserState.java
@@ -57,7 +57,7 @@
private final File mFile;
@GuardedBy("this")
- private final ArrayList<Fingerprint> mFingerprints = new ArrayList<>();
+ private final ArrayList<Fingerprint> mFingerprints = new ArrayList<Fingerprint>();
private final Context mCtx;
public FingerprintsUserState(Context ctx, int userId) {
@@ -127,7 +127,7 @@
}
private ArrayList<Fingerprint> getCopy(ArrayList<Fingerprint> array) {
- ArrayList<Fingerprint> result = new ArrayList<>(array.size());
+ ArrayList<Fingerprint> result = new ArrayList<Fingerprint>(array.size());
for (int i = 0; i < array.size(); i++) {
Fingerprint fp = array.get(i);
result.add(new Fingerprint(fp.getName(), fp.getGroupId(), fp.getFingerId(),
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index fb98d94..ef7be30 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -454,6 +454,18 @@
return mInstaller.execute(builder.toString());
}
+
+ public int linkFile(String relativePath, String fromBase, String toBase) {
+ StringBuilder builder = new StringBuilder("linkfile");
+ builder.append(' ');
+ builder.append(relativePath);
+ builder.append(' ');
+ builder.append(fromBase);
+ builder.append(' ');
+ builder.append(toBase);
+ return mInstaller.execute(builder.toString());
+ }
+
/**
* Returns true iff. {@code instructionSet} is a valid instruction set.
*/
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 1cec750..b5ef3b7 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -166,6 +166,8 @@
@GuardedBy("mLock")
private final List<File> mResolvedInheritedFiles = new ArrayList<>();
@GuardedBy("mLock")
+ private final List<String> mResolvedInstructionSets = new ArrayList<>();
+ @GuardedBy("mLock")
private File mInheritedFilesBase;
private final Handler.Callback mHandlerCallback = new Handler.Callback() {
@@ -521,7 +523,11 @@
}
if (isLinkPossible(fromFiles, toDir)) {
- createDirsAndLinkFiles(fromFiles, toDir, mInheritedFilesBase);
+ if (!mResolvedInstructionSets.isEmpty()) {
+ final File oatDir = new File(toDir, "oat");
+ createOatDirs(mResolvedInstructionSets, oatDir);
+ }
+ linkFiles(fromFiles, toDir, mInheritedFilesBase);
} else {
// TODO: this should delegate to DCS so the system process
// avoids holding open FDs into containers.
@@ -706,21 +712,23 @@
final File oatDir = new File(packageInstallDir, "oat");
if (oatDir.exists()) {
final File[] archSubdirs = oatDir.listFiles();
- // Only add "oatDir" if it contains arch specific subdirs.
- if (archSubdirs != null && archSubdirs.length > 0) {
- mResolvedInheritedFiles.add(oatDir);
- }
- final String[] instructionSets = InstructionSets.getAllDexCodeInstructionSets();
- for (File archSubDir : archSubdirs) {
- // Skip any directory that isn't an ISA subdir.
- if (!ArrayUtils.contains(instructionSets, archSubDir.getName())) {
- continue;
- }
- List<File> oatFiles = Arrays.asList(archSubDir.listFiles());
- if (!oatFiles.isEmpty()) {
- mResolvedInheritedFiles.add(archSubDir);
- mResolvedInheritedFiles.addAll(oatFiles);
+ // Keep track of all instruction sets we've seen compiled output for.
+ // If we're linking (and not copying) inherited files, we can recreate the
+ // instruction set hierarchy and link compiled output.
+ if (archSubdirs != null && archSubdirs.length > 0) {
+ final String[] instructionSets = InstructionSets.getAllDexCodeInstructionSets();
+ for (File archSubDir : archSubdirs) {
+ // Skip any directory that isn't an ISA subdir.
+ if (!ArrayUtils.contains(instructionSets, archSubDir.getName())) {
+ continue;
+ }
+
+ mResolvedInstructionSets.add(archSubDir.getName());
+ List<File> oatFiles = Arrays.asList(archSubDir.listFiles());
+ if (!oatFiles.isEmpty()) {
+ mResolvedInheritedFiles.addAll(oatFiles);
+ }
}
}
}
@@ -802,71 +810,41 @@
return true;
}
- /**
- * Reparents the path of {@code file} from {@code oldBase} to {@code newBase}. {@code file}
- * must necessarily be a subpath of {@code oldBase}. It is an error for {@code file} to have
- * relative path components such as {@code "."} or {@code ".."}. For example, for we will
- * reparent {@code /foo/bar/baz} to {@code /foo2/bar/baz} if {@code oldBase} was {@code /foo}
- * and {@code newBase} was {@code /foo2}.
- */
- private static File reparentPath(File file, File oldBase, File newBase) throws IOException {
- final String oldBaseStr = oldBase.getAbsolutePath();
+ private static String getRelativePath(File file, File base) throws IOException {
final String pathStr = file.getAbsolutePath();
-
+ final String baseStr = base.getAbsolutePath();
// Don't allow relative paths.
if (pathStr.contains("/.") ) {
throw new IOException("Invalid path (was relative) : " + pathStr);
}
- if (pathStr.startsWith(oldBaseStr)) {
- final String relative = pathStr.substring(oldBaseStr.length());
- return new File(newBase, relative);
+ if (pathStr.startsWith(baseStr)) {
+ return pathStr.substring(baseStr.length());
}
- throw new IOException("File: " + pathStr + " outside base: " + oldBaseStr);
+ throw new IOException("File: " + pathStr + " outside base: " + baseStr);
}
- /**
- * Recreates a directory and file structure, specified by a list of files {@code fromFiles}
- * which are subpaths of {@code fromDir} to {@code toDir}. Directories are created with the
- * same permissions, and regular files are linked.
- *
- * TODO: Move this function to installd so that the system process doesn't have to
- * manipulate / relabel directories.
- */
- private static void createDirsAndLinkFiles(List<File> fromFiles, File toDir, File fromDir)
+ private void createOatDirs(List<String> instructionSets, File fromDir) {
+ for (String instructionSet : instructionSets) {
+ mPm.mInstaller.createOatDir(fromDir.getAbsolutePath(), instructionSet);
+ }
+ }
+
+ private void linkFiles(List<File> fromFiles, File toDir, File fromDir)
throws IOException {
for (File fromFile : fromFiles) {
- final File toFile = reparentPath(fromFile, fromDir, toDir);
- final StructStat stat;
- try {
- stat = Os.stat(fromFile.getAbsolutePath());
- } catch (ErrnoException e) {
- throw new IOException("Failed to stat: " + fromFile.getAbsolutePath(), e);
- }
+ final String relativePath = getRelativePath(fromFile, fromDir);
+ final int ret = mPm.mInstaller.linkFile(relativePath, fromDir.getAbsolutePath(),
+ toDir.getAbsolutePath());
- if (OsConstants.S_ISDIR(stat.st_mode)) {
- if (LOGD) Slog.d(TAG, "Creating directory " + toFile.getAbsolutePath());
- try {
- Os.mkdir(toFile.getAbsolutePath(), stat.st_mode);
- } catch (ErrnoException e) {
- throw new IOException("Failed to create dir: " + toFile.getAbsolutePath(), e);
- }
-
- // We do this to ensure that the oat/ directory is created with the right
- // label (data_dalvikcache_file) instead of apk_tmpfile.
- if (!SELinux.restorecon(toFile)) {
- throw new IOException("Failed to restorecon: " + toFile.getAbsolutePath());
- }
- } else {
- if (LOGD) Slog.d(TAG, "Linking " + fromFile + " to " + toFile);
- try {
- Os.link(fromFile.getAbsolutePath(), toFile.getAbsolutePath());
- } catch (ErrnoException e) {
- throw new IOException("Failed to link " + fromFile + " to " + toFile, e);
- }
+ if (ret < 0) {
+ // installd will log failure details.
+ throw new IOException("failed linkOrCreateDir(" + relativePath + ", "
+ + fromDir + ", " + toDir + ")");
}
}
+
Slog.d(TAG, "Linked " + fromFiles.size() + " files into " + toDir);
}
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 6dc1183..d7b202d 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -343,8 +343,7 @@
boolean applyExistingExitAnimation = mPostKeyguardExitAnimation != null
&& !winAnimator.mKeyguardGoingAwayAnimation
&& win.hasDrawnLw()
- && win.mAttachedWindow == null
- && mForceHiding != KEYGUARD_NOT_SHOWN;
+ && win.mAttachedWindow == null;
// If the window is already showing and we don't need to apply an existing
// Keyguard exit animation, skip.
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 825ef1a..feb0285 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -183,7 +183,6 @@
private static final String ATTR_PERMISSION_PROVIDER = "permission-provider";
private static final String ATTR_SETUP_COMPLETE = "setup-complete";
- private static final String ATTR_PREFERRED_SETUP_ACTIVITY = "setup-activity";
private static final String ATTR_PERMISSION_POLICY = "permission-policy";
private static final String ATTR_DELEGATED_CERT_INSTALLER = "delegated-cert-installer";
@@ -335,8 +334,6 @@
boolean doNotAskCredentialsOnBoot = false;
- ComponentName mPreferredSetupActivity;
-
public DevicePolicyData(int userHandle) {
mUserHandle = userHandle;
}
@@ -1436,12 +1433,6 @@
out.attribute(null, ATTR_DELEGATED_CERT_INSTALLER,
policy.mDelegatedCertInstallerPackage);
}
- if (policy.mPreferredSetupActivity != null) {
- out.attribute(null, ATTR_PREFERRED_SETUP_ACTIVITY,
- policy.mPreferredSetupActivity.flattenToString());
- } else {
- out.attribute(null, ATTR_PREFERRED_SETUP_ACTIVITY, "");
- }
final int N = policy.mAdminList.size();
for (int i=0; i<N; i++) {
@@ -1566,12 +1557,6 @@
}
policy.mDelegatedCertInstallerPackage = parser.getAttributeValue(null,
ATTR_DELEGATED_CERT_INSTALLER);
- String preferredSetupActivity =
- parser.getAttributeValue(null, ATTR_PREFERRED_SETUP_ACTIVITY);
- if (preferredSetupActivity != null) {
- policy.mPreferredSetupActivity =
- ComponentName.unflattenFromString(preferredSetupActivity);
- }
type = parser.next();
int outerDepth = parser.getDepth();
@@ -1695,7 +1680,6 @@
if (policy.mStatusBarDisabled) {
setStatusBarDisabledInternal(policy.mStatusBarDisabled, userHandle);
}
- updatePreferredSetupActivityLocked(userHandle);
}
private void updateLockTaskPackagesLocked(List<String> packages, int userId) {
@@ -4734,43 +4718,6 @@
}
@Override
- public void setPreferredSetupActivity(ComponentName who, ComponentName activity) {
- if (!mHasFeature) {
- return;
- }
- Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
- ActiveAdmin activeAdmin =
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- if (!isDeviceInitializer(activeAdmin.info.getPackageName())) {
- throw new SecurityException(
- "This method can only be called by device initializers");
- }
- int userHandle = UserHandle.getCallingUserId();
- DevicePolicyData userData = getUserData(userHandle);
- userData.mPreferredSetupActivity = activity;
- saveSettingsLocked(userHandle);
- updatePreferredSetupActivityLocked(userHandle);
- }
- }
-
- private void updatePreferredSetupActivityLocked(int userHandle) {
- if (!mHasFeature) {
- return;
- }
- IActivityManager am = ActivityManagerNative.getDefault();
- long ident = Binder.clearCallingIdentity();
- try {
- am.updatePreferredSetupActivity(
- getUserData(userHandle).mPreferredSetupActivity, userHandle);
- } catch (RemoteException e) {
- // Not gonna happen.
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
- @Override
public void setApplicationRestrictions(ComponentName who, String packageName, Bundle settings) {
Preconditions.checkNotNull(who, "ComponentName is null");
final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
@@ -6138,9 +6085,6 @@
if (!policy.mUserSetupComplete) {
policy.mUserSetupComplete = true;
synchronized (this) {
- // Clear the preferred setup activity.
- policy.mPreferredSetupActivity = null;
- updatePreferredSetupActivityLocked(userHandle);
// The DeviceInitializer was whitelisted but now should be removed.
removeDeviceInitializerFromLockTaskPackages(userHandle);
saveSettingsLocked(userHandle);
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 23057c4..633aee8 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -57,6 +57,7 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
+import android.telephony.TelephonyManager;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Log;
@@ -725,6 +726,10 @@
return false;
}
+ if (isCarrierApp(packageName)) {
+ return false;
+ }
+
if (mAppWidgetManager != null
&& mAppWidgetManager.isBoundWidgetPackage(packageName, userId)) {
return false;
@@ -754,6 +759,12 @@
return false;
}
+ private boolean isCarrierApp(String packageName) {
+ TelephonyManager telephonyManager = getContext().getSystemService(TelephonyManager.class);
+ return telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName)
+ == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
+ }
+
void informListeners(String packageName, int userId, boolean isIdle) {
for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
listener.onAppIdleStateChanged(packageName, userId, isIdle);
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 8834497..4cdf254 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -49,6 +49,7 @@
import android.service.voice.VoiceInteractionSession;
import android.speech.RecognitionService;
import android.text.TextUtils;
+import android.util.Log;
import android.util.Slog;
import com.android.internal.app.IVoiceInteractionManagerService;
@@ -475,11 +476,9 @@
Slog.w(TAG, "hideSessionFromSession without running voice interaction service");
return false;
}
- final int callingPid = Binder.getCallingPid();
- final int callingUid = Binder.getCallingUid();
final long caller = Binder.clearCallingIdentity();
try {
- return mImpl.hideSessionLocked(callingPid, callingUid);
+ return mImpl.hideSessionLocked();
} finally {
Binder.restoreCallingIdentity(caller);
}
@@ -744,6 +743,28 @@
}
@Override
+ public void hideCurrentSession() throws RemoteException {
+ enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
+ synchronized (this) {
+ if (mImpl == null) {
+ return;
+ }
+ final long caller = Binder.clearCallingIdentity();
+ try {
+ if (mImpl.mActiveSession != null && mImpl.mActiveSession.mSession != null) {
+ try {
+ mImpl.mActiveSession.mSession.closeSystemDialogs();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to call closeSystemDialogs", e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(caller);
+ }
+ }
+ }
+
+ @Override
public void launchVoiceAssistFromKeyguard() {
enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
synchronized (this) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index d8569bc..acd484d 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -144,7 +144,7 @@
return mActiveSession.showLocked(args, flags, showCallback);
}
- public boolean hideSessionLocked(int callingPid, int callingUid) {
+ public boolean hideSessionLocked() {
if (mActiveSession != null) {
return mActiveSession.hideLocked();
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index ccfaca7..b74b52d 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -380,8 +380,9 @@
/**
* Calling this method triggers telephony services to fetch the current carrier configuration.
* <p>
- * Normally this does not need to be called because the platform reloads config on its own. Call
- * this method if your app wants to update config at an arbitrary moment.
+ * Normally this does not need to be called because the platform reloads config on its own.
+ * This should be called by a carrier service app if it wants to update config at an arbitrary
+ * moment.
* </p>
* <p>
* This method returns before the reload has completed, and
@@ -389,9 +390,9 @@
* arbitrary thread.
* </p>
*/
- public void reloadCarrierConfigForSubId(int subId) {
+ public void notifyConfigChangedForSubId(int subId) {
try {
- getICarrierConfigLoader().reloadCarrierConfigForSubId(subId);
+ getICarrierConfigLoader().notifyConfigChangedForSubId(subId);
} catch (RemoteException ex) {
Rlog.e(TAG, "Error reloading config for subId=" + subId + ": " + ex.toString());
} catch (NullPointerException ex) {
diff --git a/telephony/java/android/telephony/ModemActivityInfo.aidl b/telephony/java/android/telephony/ModemActivityInfo.aidl
new file mode 100644
index 0000000..b85ef7a
--- /dev/null
+++ b/telephony/java/android/telephony/ModemActivityInfo.aidl
@@ -0,0 +1,20 @@
+/*
+**
+** Copyright 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.telephony;
+
+parcelable ModemActivityInfo;
diff --git a/telephony/java/android/telephony/ModemActivityInfo.java b/telephony/java/android/telephony/ModemActivityInfo.java
new file mode 100644
index 0000000..ea96e7c
--- /dev/null
+++ b/telephony/java/android/telephony/ModemActivityInfo.java
@@ -0,0 +1,159 @@
+/*
+ * 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Arrays;
+
+/**
+ * Reports modem activity information
+ * @hide
+ */
+public class ModemActivityInfo implements Parcelable {
+ /**
+ * Tx power index
+ * index 0 = tx_power < 0dBm
+ * index 1 = 0dBm < tx_power < 5dBm
+ * index 2 = 5dBm < tx_power < 15dBm
+ * index 3 = 15dBm < tx_power < 20dBm
+ * index 4 = tx_power > 20dBm
+ */
+ public static final int TX_POWER_LEVELS = 5;
+
+ private final long mTimestamp;
+ private final int mSleepTimeMs;
+ private final int mIdleTimeMs;
+ private final int [] mTxTimeMs = new int[TX_POWER_LEVELS];
+ private final int mRxTimeMs;
+ private final int mEnergyUsed;
+
+ public ModemActivityInfo(long timestamp, int sleepTimeMs, int idleTimeMs,
+ int[] txTimeMs, int rxTimeMs, int energyUsed) {
+ mTimestamp = timestamp;
+ mSleepTimeMs = sleepTimeMs;
+ mIdleTimeMs = idleTimeMs;
+ System.arraycopy(txTimeMs, 0, mTxTimeMs, 0, Math.min(txTimeMs.length, TX_POWER_LEVELS));
+ mRxTimeMs = rxTimeMs;
+ mEnergyUsed = energyUsed;
+ }
+
+ @Override
+ public String toString() {
+ return "ModemActivityInfo{"
+ + " mTimestamp=" + mTimestamp
+ + " mSleepTimeMs=" + mSleepTimeMs
+ + " mTxTimeMs[]=" + Arrays.toString(mTxTimeMs)
+ + " mRxTimeMs=" + mRxTimeMs
+ + " mEnergyUsed=" + mEnergyUsed
+ + "}";
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<ModemActivityInfo> CREATOR =
+ new Parcelable.Creator<ModemActivityInfo>() {
+ public ModemActivityInfo createFromParcel(Parcel in) {
+ long timestamp = in.readLong();
+ int sleepTimeMs = in.readInt();
+ int idleTimeMs = in.readInt();
+ int[] txTimeMs = new int[TX_POWER_LEVELS];
+ for (int i = 0; i < TX_POWER_LEVELS; i++) {
+ txTimeMs[i] = in.readInt();
+ }
+ int rxTimeMs = in.readInt();
+ int energyUsed = in.readInt();
+ return new ModemActivityInfo(timestamp, sleepTimeMs, idleTimeMs,
+ txTimeMs, rxTimeMs, energyUsed);
+ }
+
+ public ModemActivityInfo[] newArray(int size) {
+ return new ModemActivityInfo[size];
+ }
+ };
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(mTimestamp);
+ dest.writeInt(mSleepTimeMs);
+ dest.writeInt(mIdleTimeMs);
+ for (int i = 0; i < TX_POWER_LEVELS; i++) {
+ dest.writeInt(mTxTimeMs[i]);
+ }
+ dest.writeInt(mRxTimeMs);
+ dest.writeInt(mEnergyUsed);
+ }
+
+ /**
+ * @return timestamp of record creation
+ */
+ public long getTimestamp() {
+ return mTimestamp;
+ }
+
+ /**
+ * @return tx time in ms. It's an array of tx times
+ * with each index...
+ */
+ public int [] getTxTimeMillis() {
+ return mTxTimeMs;
+ }
+
+ /**
+ * @return sleep time in ms.
+ */
+ public int getSleepTimeMillis() {
+ return mSleepTimeMs;
+ }
+
+ /**
+ * @return idle time in ms.
+ */
+ public int getIdleTimeMillis() {
+ return mIdleTimeMs;
+ }
+
+ /**
+ * @return rx time in ms.
+ */
+ public int getRxTimeMillis() {
+ return mRxTimeMs;
+ }
+
+ /**
+ * product of current(mA), voltage(V) and time(ms)
+ * @return energy used
+ */
+ public int getEnergyUsed () {
+ return mEnergyUsed;
+ }
+
+ /**
+ * @return if the record is valid
+ */
+ public boolean isValid() {
+ int totalTxTimeMs = 0;
+ int txTime [] = getTxTimeMillis();
+ for (int i = 0; i < TX_POWER_LEVELS; i++) {
+ totalTxTimeMs += txTime[i];
+ }
+ return ((getIdleTimeMillis() != 0) || (totalTxTimeMs != 0)
+ || (getSleepTimeMillis() != 0) || (getIdleTimeMillis() != 0));
+ }
+}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 86f7ec3..1fe0f0b 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -3658,11 +3658,11 @@
/** @hide */
@SystemApi
- public int checkCarrierPrivilegesForPackage(String pkgname) {
+ public int checkCarrierPrivilegesForPackage(String pkgName) {
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.checkCarrierPrivilegesForPackage(pkgname);
+ return telephony.checkCarrierPrivilegesForPackage(pkgName);
} catch (RemoteException ex) {
Rlog.e(TAG, "checkCarrierPrivilegesForPackage RemoteException", ex);
} catch (NullPointerException ex) {
@@ -3673,6 +3673,21 @@
/** @hide */
@SystemApi
+ public int checkCarrierPrivilegesForPackageAnyPhone(String pkgName) {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null)
+ return telephony.checkCarrierPrivilegesForPackageAnyPhone(pkgName);
+ } catch (RemoteException ex) {
+ Rlog.e(TAG, "checkCarrierPrivilegesForPackageAnyPhone RemoteException", ex);
+ } catch (NullPointerException ex) {
+ Rlog.e(TAG, "checkCarrierPrivilegesForPackageAnyPhone NPE", ex);
+ }
+ return CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
+ }
+
+ /** @hide */
+ @SystemApi
public List<String> getCarrierPackageNamesForIntent(Intent intent) {
return getCarrierPackageNamesForIntentAndPhone(intent, getDefaultPhone());
}
@@ -4617,7 +4632,22 @@
}
} catch (RemoteException ex) {
}
+ return null;
+ }
+ /**
+ * Returns the modem activity info.
+ * @hide
+ */
+ public ModemActivityInfo getModemActivityInfo() {
+ try {
+ ITelephony service = getITelephony();
+ if (service != null) {
+ return service.getModemActivityInfo();
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelephony#getModemActivityInfo", e);
+ }
return null;
}
}
diff --git a/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl b/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
index cb53f51..d77b27f 100644
--- a/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
+++ b/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
@@ -25,7 +25,7 @@
PersistableBundle getConfigForSubId(int subId);
- void reloadCarrierConfigForSubId(int subId);
+ void notifyConfigChangedForSubId(int subId);
void updateConfigForPhoneId(int phoneId, String simState);
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 11d0ea6..c253b4f 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -23,6 +23,7 @@
import android.telephony.IccOpenLogicalChannelResponse;
import android.telephony.NeighboringCellInfo;
import android.telephony.RadioAccessFamily;
+import android.telephony.ModemActivityInfo;
import java.util.List;
@@ -739,9 +740,14 @@
int getCarrierPrivilegeStatus();
/**
- * Similar to above, but check for pkg whose name is pkgname.
+ * Similar to above, but check for the package whose name is pkgName.
*/
- int checkCarrierPrivilegesForPackage(String pkgname);
+ int checkCarrierPrivilegesForPackage(String pkgName);
+
+ /**
+ * Similar to above, but check across all phones.
+ */
+ int checkCarrierPrivilegesForPackageAnyPhone(String pkgName);
/**
* Returns list of the package names of the carrier apps that should handle the input intent
@@ -953,4 +959,10 @@
* if no locale could be derived.
*/
String getLocaleFromDefaultSim();
+
+ /**
+ * Return the modem activity info.
+ *@hide
+ */
+ ModemActivityInfo getModemActivityInfo();
}
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 12541d8..8d48c86 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -323,6 +323,7 @@
int RIL_REQUEST_START_LCE = 132;
int RIL_REQUEST_STOP_LCE = 133;
int RIL_REQUEST_PULL_LCEDATA = 134;
+ int RIL_REQUEST_GET_ACTIVITY_INFO = 135;
int RIL_UNSOL_RESPONSE_BASE = 1000;
int RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED = 1000;