getSELinuxBooleanNames(ComponentName admin, int userHandle) {
+ if (mService != null) {
+ try {
+ return mService.getSELinuxBooleanNames(admin, userHandle);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy server", e);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get the value of a SELinux boolean.
+ *
+ * The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_ENFORCE_SELINUX} to be able to call
+ * this method; if it has not, a security exception will be thrown.
+ *
+ *
The returned value is only meaningful if the current admin is a
+ * SELinux admin.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param name the name of the SELinux boolean
+ * @return the value of the SELinux boolean
+ * @hide
+ */
+ public boolean getSELinuxBooleanValue(ComponentName admin, String name) {
+ return getSELinuxBooleanValue(admin, name, UserHandle.myUserId());
+ }
+
+ /** @hide per-user version */
+ public boolean getSELinuxBooleanValue(ComponentName admin, String name, int userHandle) {
+ if (mService != null) {
+ try {
+ return mService.getSELinuxBooleanValue(admin, name, userHandle);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy server", e);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Set the value of a SELinux boolean.
+ *
+ *
The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_ENFORCE_SELINUX} to be able to call
+ * this method; if it has not, a security exception will be thrown.
+ *
+ *
The returned value is only meaningful if the current admin is a
+ * SELinux admin.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param name the name of the SELinux boolean
+ * @param value the desired value for the boolean
+ * @return false if Android was unable to set the desired mode
+ * @hide
+ */
+ public boolean setSELinuxBooleanValue(ComponentName admin, String name,
+ boolean value) {
+ return setSELinuxBooleanValue(admin, name, value, UserHandle.myUserId());
+ }
+
+ /** @hide per-user version */
+ public boolean setSELinuxBooleanValue(ComponentName admin, String name,
+ boolean value, int userHandle) {
+ if (mService != null) {
+ try {
+ return mService.setSELinuxBooleanValue(admin, name, value, userHandle);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy server", e);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Checks whether an admin app has control over SE Android MMAC policy.
+ *
+ *
The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_ENFORCE_MMAC} to be able to call
+ * this method; if it has not, a security exception will be thrown.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated,
+ * must be self
+ * @return true if admin app can control MMAC policy, false otherwise
+ * @hide
+ */
+ public boolean isMMACadmin(ComponentName admin) {
+ return isMMACadmin(admin, UserHandle.myUserId());
+ }
+
+ /** @hide per-user version */
+ public boolean isMMACadmin(ComponentName admin, int userHandle) {
+ if (mService != null) {
+ try {
+ return mService.isMMACadmin(admin, userHandle);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy server", e);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Called by an application that is administering the device to start or stop
+ * controlling SE Android MMAC policies, enforcement, etc. When an admin
+ * app gives up control of MMAC policies, the policy in place prior to the app
+ * taking control will be applied.
+ *
+ *
The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_ENFORCE_MMAC} to be able to call
+ * this method; if it has not, a security exception will be thrown.
+ *
+ *
When an application gains control of MMAC settings, it is called an
+ * MMAC administrator. Admistration applications will call this with true and
+ * ensure this method returned true before attempting to toggle MMAC settings.
+ * When apps intend to stop controlling MMAC settings, apps should call this
+ * with false.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated,
+ * must be self
+ * @param control true if the admin wishes to control MMAC, false if the admin
+ * wishes to give back control of MMAC
+ * @return true if the operation succeeded, false if the operation failed or
+ * MMAC was not enabled on the device.
+ * @hide
+ */
+ public boolean setMMACadmin(ComponentName admin, boolean control) {
+ return setMMACadmin(admin, control, UserHandle.myUserId());
+ }
+
+ /** @hide per-user version */
+ public boolean setMMACadmin(ComponentName admin, boolean control, int userHandle) {
+ if (mService != null) {
+ try {
+ return mService.setMMACadmin(admin, control, userHandle);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy server", e);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Called by an application that is a SEAndroid MMAC admin to set MMAC
+ * protections into enforcing or permissive mode. The system requires a
+ * reboot for the protections to take effect.
+ *
+ *
The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_ENFORCE_MMAC} to be able to call
+ * this method; if it has not, a security exception will be thrown.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param enforcing true for enforcing mode, false for permissive mode.
+ * @return false if Android was unable to set the desired mode
+ * @hide
+ */
+ public boolean setMMACenforcing(ComponentName admin, boolean enforcing) {
+ return setMMACenforcing(admin, enforcing, UserHandle.myUserId());
+ }
+
+ /** @hide per-user version */
+ public boolean setMMACenforcing(ComponentName admin, boolean enforcing, int userHandle) {
+ if (mService != null) {
+ try {
+ return mService.setMMACenforcing(admin, enforcing, userHandle);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy server", e);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Determine whether SE Android MMAC policies are being enforced by the
+ * current admin.
+ *
+ *
The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_ENFORCE_MMAC} to be able to call
+ * this method; if it has not, a security exception will be thrown.
+ *
+ *
The returned value is only meaningful if the current admin is a
+ * MMAC admin.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @hide
+ */
+ public boolean getMMACenforcing(ComponentName admin) {
+ return getMMACenforcing(admin, UserHandle.myUserId());
+ }
+
+ /** @hide per-user version */
+ public boolean getMMACenforcing(ComponentName admin, int userHandle) {
+ if (mService != null) {
+ try {
+ return mService.getMMACenforcing(admin, userHandle);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy server", e);
+ }
+ }
+ return false;
+ }
+
+ // Before changing these values, be sure to update
+ // DevicePolicyManagerService.java's POLICY_DESCRIPTIONS array.
+ /** @hide */
+ public static final int SEPOLICY_FILE_SEPOLICY = 0;
+ /** @hide */
+ public static final int SEPOLICY_FILE_PROPCTXS = 1;
+ /** @hide */
+ public static final int SEPOLICY_FILE_FILECTXS = 2;
+ /** @hide */
+ public static final int SEPOLICY_FILE_SEAPPCTXS = 3;
+ /** @hide */
+ public static final int MMAC_POLICY_FILE = 4;
+ /** @hide */
+ public static final int SEPOLICY_FILE_COUNT = MMAC_POLICY_FILE+1;
+
+ /**
+ * Sets a new policy file and reloads it at the proper time.
+ *
+ *
For {@link #SEPOLICY_FILE_SEPOLICY}, {@link #SEPOLICY_FILE_PROPCTXS},
+ * {@link #SEPOLICY_FILE_FILECTXS}, and {@link #SEPOLICY_FILE_SEAPPCTXS}, the admin
+ * must have requested {@link DeviceAdminInfo#USES_POLICY_ENFORCE_SELINUX}
+ * before calling this method. If it has not, a security exception will be
+ * thrown.
+ *
+ *
For {@link #SEPOLICY_FILE_SEPOLICY}, {@link #SEPOLICY_FILE_PROPCTXS},
+ * {@link #SEPOLICY_FILE_FILECTXS}, and {@link #SEPOLICY_FILE_SEAPPCTXS}, these
+ * files are reloaded before returning from the DevicePolicyManager.
+ *
+ *
For {@link #SEPOLICY_FILE_SEPOLICY}, {@link #SEPOLICY_FILE_PROPCTXS},
+ * {@link #SEPOLICY_FILE_FILECTXS}, and {@link #SEPOLICY_FILE_SEAPPCTXS}, the
+ * returned value is only meaingful if the current admin is a SELinux
+ * admin.
+ *
+ *
For {@link #MMAC_POLICY_FILE}, the admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_ENFORCE_MMAC} before calling this
+ * method. If it has not, a security exception will be thrown.
+ *
+ *
For {@link #MMAC_POLICY_FILE}, the MMAC policy file is reloaded on
+ * reboot.
+ *
+ *
For {@link #MMAC_POLICY_FILE}, the returned value is only meaingful
+ * if the current admin is a MMAC admin.
+ *
+ * @param admin which {@link DeviceAdminReceiver} this request is associated with
+ * @param policyType one of {@link #SEPOLICY_FILE_SEPOLICY}, {@link #SEPOLICY_FILE_PROPCTXS},
+ * {@link #SEPOLICY_FILE_FILECTXS}, {@link #SEPOLICY_FILE_SEAPPCTXS},
+ * or {@link #MMAC_POLICY_FILE}.
+ * @param policy the new policy file in bytes, or null if you wish to revert to
+ * the default policy
+ * @return false if Android was unable to set the new policy
+ * @hide
+ */
+ public boolean setCustomPolicyFile(ComponentName admin, int policyType, byte[] policy) {
+ return setCustomPolicyFile(admin, policyType, policy, UserHandle.myUserId());
+ }
+
+ /** @hide per-user version */
+ public boolean setCustomPolicyFile(ComponentName admin, int policyType, byte[] policy, int userHandle) {
+ if (mService != null) {
+ try {
+ return mService.setCustomPolicyFile(admin, policyType, policy, userHandle);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy server", e);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Determine whether this admin set a custom policy file.
+ *
+ *
For {@link #SEPOLICY_FILE_SEPOLICY}, {@link #SEPOLICY_FILE_PROPCTXS},
+ * {@link #SEPOLICY_FILE_FILECTXS}, and {@link #SEPOLICY_FILE_SEAPPCTXS}, the admin
+ * must have requested {@link DeviceAdminInfo#USES_POLICY_ENFORCE_SELINUX}
+ * before calling this method. If it has not, a security exception will be
+ * thrown.
+ *
+ *
For {@link #SEPOLICY_FILE_SEPOLICY}, {@link #SEPOLICY_FILE_PROPCTXS},
+ * {@link #SEPOLICY_FILE_FILECTXS}, and {@link #SEPOLICY_FILE_SEAPPCTXS}, the
+ * returned value is only meaingful if the current admin is a SELinux
+ * admin.
+ *
+ *
For {@link #MMAC_POLICY_FILE}, the admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_ENFORCE_MMAC} before calling this
+ * method. If it has not, a security exception will be thrown.
+ *
+ *
For {@link #MMAC_POLICY_FILE}, the returned value is only meaingful
+ * if the current admin is a MMAC admin.
+ *
+ * @param admin which {@link DeviceAdminReceiver} this request is associated with
+ * @param policyType one of {@link #SEPOLICY_FILE_SEPOLICY}, {@link #SEPOLICY_FILE_PROPCTXS},
+ * {@link #SEPOLICY_FILE_FILECTXS}, {@link #SEPOLICY_FILE_SEAPPCTXS}, or
+ * {@link #MMAC_POLICY_FILE}
+ * @return true if the admin set a custom policy file
+ * @hide
+ */
+ public boolean isCustomPolicyFile(ComponentName admin, int policyType) {
+ return isCustomPolicyFile(admin, policyType, UserHandle.myUserId());
+ }
+
+ /** @hide per-user version */
+ public boolean isCustomPolicyFile(ComponentName admin, int policyType, int userHandle) {
+ if (mService != null) {
+ try {
+ return mService.isCustomPolicyFile(admin, policyType, userHandle);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy server", e);
+ }
+ }
+ return false;
+ }
+
/**
* @hide
*/
@@ -1513,4 +1976,20 @@ public void reportSuccessfulPasswordAttempt(int userHandle) {
}
}
}
+
+ /**
+ * CM: check if secure keyguard is required
+ * @hide
+ */
+ public boolean requireSecureKeyguard() {
+ int encryptionStatus = getStorageEncryptionStatus();
+ if (getPasswordQuality(null) > PASSWORD_QUALITY_UNSPECIFIED ||
+ !KeyStore.getInstance().isEmpty() ||
+ encryptionStatus == DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE ||
+ encryptionStatus == DevicePolicyManager.ENCRYPTION_STATUS_ACTIVATING) {
+ // Require secure keyguard
+ return true;
+ }
+ return false;
+ }
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index e061ab354d7..5a04604db8a 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -93,6 +93,25 @@ interface IDevicePolicyManager {
void removeActiveAdmin(in ComponentName policyReceiver, int userHandle);
boolean hasGrantedPolicy(in ComponentName policyReceiver, int usesPolicy, int userHandle);
+ boolean setSELinuxAdmin(in ComponentName who, boolean control, int userHandle);
+ boolean isSELinuxAdmin(in ComponentName who, int userHandle);
+
+ boolean setSELinuxEnforcing(in ComponentName who, boolean enforcing, int userHandle);
+ boolean getSELinuxEnforcing(in ComponentName who, int userHandle);
+
+ List getSELinuxBooleanNames(in ComponentName who, int userHandle);
+ boolean getSELinuxBooleanValue(in ComponentName who, String name, int userHandle);
+ boolean setSELinuxBooleanValue(in ComponentName who, String name, boolean value, int userHandle);
+
+ boolean isMMACadmin(in ComponentName who, int userHandle);
+ boolean setMMACadmin(in ComponentName who, boolean control, int userHandle);
+
+ boolean setMMACenforcing(in ComponentName who, boolean enforcing, int userHandle);
+ boolean getMMACenforcing(in ComponentName who, int userHandle);
+
+ boolean setCustomPolicyFile(in ComponentName who, int policyType, in byte[] policy, int userHandle);
+ boolean isCustomPolicyFile(in ComponentName who, int policyType, int userHandle);
+
void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase,
int numbers, int symbols, int nonletter, int userHandle);
void reportFailedPasswordAttempt(int userHandle);
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 9ad33a5a410..0e835ed9f5b 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -440,21 +440,31 @@ protected void onRestoreFile(ParcelFileDescriptor data, long size,
basePath = getCacheDir().getCanonicalPath();
} else {
// Not a supported location
- Log.i(TAG, "Data restored from non-app domain " + domain + ", ignoring");
+ Log.i(TAG, "Unrecognized domain " + domain);
}
// Now that we've figured out where the data goes, send it on its way
if (basePath != null) {
+ // Canonicalize the nominal path and verify that it lies within the stated domain
File outFile = new File(basePath, path);
- if (DEBUG) Log.i(TAG, "[" + domain + " : " + path + "] mapped to " + outFile.getPath());
- onRestoreFile(data, size, outFile, type, mode, mtime);
- } else {
- // Not a supported output location? We need to consume the data
- // anyway, so just use the default "copy the data out" implementation
- // with a null destination.
- if (DEBUG) Log.i(TAG, "[ skipping data from unsupported domain " + domain + "]");
- FullBackup.restoreFile(data, size, type, mode, mtime, null);
+ String outPath = outFile.getCanonicalPath();
+ if (outPath.startsWith(basePath + File.separatorChar)) {
+ if (DEBUG) Log.i(TAG, "[" + domain + " : " + path + "] mapped to " + outPath);
+ onRestoreFile(data, size, outFile, type, mode, mtime);
+ return;
+ } else {
+ // Attempt to restore to a path outside the file's nominal domain.
+ if (DEBUG) {
+ Log.e(TAG, "Cross-domain restore attempt: " + outPath);
+ }
+ }
}
+
+ // Not a supported output location, or bad path: we need to consume the data
+ // anyway, so just use the default "copy the data out" implementation
+ // with a null destination.
+ if (DEBUG) Log.i(TAG, "[ skipping file " + path + "]");
+ FullBackup.restoreFile(data, size, type, mode, mtime, null);
}
// ----- Core implementation -----
diff --git a/core/java/android/appwidget/AppWidgetProvider.java b/core/java/android/appwidget/AppWidgetProvider.java
old mode 100755
new mode 100644
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
old mode 100755
new mode 100644
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
old mode 100755
new mode 100644
index 6367e160490..64cc2d8fd4c
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -948,7 +948,15 @@ public BluetoothServerSocket listenUsingRfcommOn(int channel) throws IOException
*/
public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid)
throws IOException {
- return createNewRfcommSocketAndRecord(name, uuid, true, true);
+ return createNewRfcommSocketAndRecord(name, -1, uuid, true, true);
+ }
+
+ /**
+ * @hide
+ */
+ public BluetoothServerSocket listenUsingRfcommWithServiceRecordOn(String name, int port, UUID uuid)
+ throws IOException {
+ return createNewRfcommSocketAndRecord(name, port, uuid, true, true);
}
/**
@@ -979,7 +987,7 @@ public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUI
*/
public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid)
throws IOException {
- return createNewRfcommSocketAndRecord(name, uuid, false, false);
+ return createNewRfcommSocketAndRecord(name, -1, uuid, false, false);
}
/**
@@ -1017,15 +1025,15 @@ public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String n
*/
public BluetoothServerSocket listenUsingEncryptedRfcommWithServiceRecord(
String name, UUID uuid) throws IOException {
- return createNewRfcommSocketAndRecord(name, uuid, false, true);
+ return createNewRfcommSocketAndRecord(name, -1, uuid, false, true);
}
- private BluetoothServerSocket createNewRfcommSocketAndRecord(String name, UUID uuid,
+ private BluetoothServerSocket createNewRfcommSocketAndRecord(String name, int port, UUID uuid,
boolean auth, boolean encrypt) throws IOException {
BluetoothServerSocket socket;
socket = new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, auth,
- encrypt, new ParcelUuid(uuid));
+ encrypt, port, new ParcelUuid(uuid));
socket.setServiceName(name);
int errno = socket.mSocket.bindListen();
if (errno != 0) {
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
old mode 100755
new mode 100644
index 4cc22b4ae90..74d50f1dad6
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -322,6 +322,9 @@ public final class BluetoothDevice implements Parcelable {
/**@hide*/
public static final int REQUEST_TYPE_PHONEBOOK_ACCESS = 2;
+ /**@hide*/
+ public static final int REQUEST_TYPE_MESSAGE_ACCESS = 3;
+
/**
* Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intents,
* Contains package name to return reply intent to.
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
old mode 100755
new mode 100644
diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java
old mode 100755
new mode 100644
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
old mode 100755
new mode 100644
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
old mode 100755
new mode 100644
diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java
index 96be8a2fb67..49601c5b55b 100644
--- a/core/java/android/bluetooth/BluetoothServerSocket.java
+++ b/core/java/android/bluetooth/BluetoothServerSocket.java
@@ -92,13 +92,14 @@ public final class BluetoothServerSocket implements Closeable {
* @param type type of socket
* @param auth require the remote device to be authenticated
* @param encrypt require the connection to be encrypted
+ * @param port remote port
* @param uuid uuid
* @throws IOException On error, for example Bluetooth not available, or
* insufficient privileges
*/
- /*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, ParcelUuid uuid)
+ /*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, int port, ParcelUuid uuid)
throws IOException {
- mSocket = new BluetoothSocket(type, -1, auth, encrypt, null, -1, uuid);
+ mSocket = new BluetoothSocket(type, -1, auth, encrypt, null, port, uuid);
mChannel = mSocket.getPort();
}
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index 59622351814..1a0bd0202b1 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -56,6 +56,10 @@ public final class BluetoothUuid {
ParcelUuid.fromString("00001105-0000-1000-8000-00805f9b34fb");
public static final ParcelUuid Hid =
ParcelUuid.fromString("00001124-0000-1000-8000-00805f9b34fb");
+ public static final ParcelUuid MessageAccessServer =
+ ParcelUuid.fromString("00001132-0000-1000-8000-00805f9b34fb");
+ public static final ParcelUuid MessageNotificationServer =
+ ParcelUuid.fromString("00001133-0000-1000-8000-00805f9b34fb");
public static final ParcelUuid PANU =
ParcelUuid.fromString("00001115-0000-1000-8000-00805F9B34FB");
public static final ParcelUuid NAP =
@@ -67,7 +71,7 @@ public final class BluetoothUuid {
public static final ParcelUuid[] RESERVED_UUIDS = {
AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget,
- ObexObjectPush, PANU, NAP};
+ ObexObjectPush, MessageAccessServer, MessageNotificationServer, PANU, NAP};
public static boolean isAudioSource(ParcelUuid uuid) {
return uuid.equals(AudioSource);
@@ -131,6 +135,14 @@ public static boolean isUuidPresent(ParcelUuid[] uuidArray, ParcelUuid uuid) {
return false;
}
+ public static boolean isMessageAccessServer(ParcelUuid uuid) {
+ return uuid.equals(MessageAccessServer);
+ }
+
+ public static boolean isMessageNotificationServer(ParcelUuid uuid) {
+ return uuid.equals(MessageNotificationServer);
+ }
+
/**
* Returns true if there any common ParcelUuids in uuidA and uuidB.
*
diff --git a/core/java/android/bluetooth/IBluetoothInputDevice.aidl b/core/java/android/bluetooth/IBluetoothInputDevice.aidl
old mode 100755
new mode 100644
diff --git a/core/java/android/bluetooth/IBluetoothManager.aidl b/core/java/android/bluetooth/IBluetoothManager.aidl
old mode 100755
new mode 100644
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 23d8f46029d..612ff0b3beb 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -238,7 +238,7 @@ public int update(Uri uri, ContentValues values, String selection,
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode)
throws FileNotFoundException {
- if (mode != null && mode.startsWith("rw")) enforceWritePermission(uri);
+ if (mode != null && mode.indexOf('w') != -1) enforceWritePermission(uri);
else enforceReadPermission(uri);
return ContentProvider.this.openFile(uri, mode);
}
@@ -246,7 +246,7 @@ public ParcelFileDescriptor openFile(Uri uri, String mode)
@Override
public AssetFileDescriptor openAssetFile(Uri uri, String mode)
throws FileNotFoundException {
- if (mode != null && mode.startsWith("rw")) enforceWritePermission(uri);
+ if (mode != null && mode.indexOf('w') != -1) enforceWritePermission(uri);
else enforceReadPermission(uri);
return ContentProvider.this.openAssetFile(uri, mode);
}
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 9e406d452fa..bde4d2ba277 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -518,7 +518,7 @@ public final OutputStream openOutputStream(Uri uri, String mode)
* ContentProvider.openFile}.
* @return Returns a new ParcelFileDescriptor pointing to the file. You
* own this descriptor and are responsible for closing it when done.
- * @throws FileNotFoundException Throws FileNotFoundException of no
+ * @throws FileNotFoundException Throws FileNotFoundException if no
* file exists under the URI or the mode is invalid.
* @see #openAssetFileDescriptor(Uri, String)
*/
@@ -1049,9 +1049,9 @@ public final IContentProvider acquireProvider(Uri uri) {
if (!SCHEME_CONTENT.equals(uri.getScheme())) {
return null;
}
- String auth = uri.getAuthority();
+ final String auth = uri.getAuthority();
if (auth != null) {
- return acquireProvider(mContext, uri.getAuthority());
+ return acquireProvider(mContext, auth);
}
return null;
}
@@ -1068,9 +1068,9 @@ public final IContentProvider acquireExistingProvider(Uri uri) {
if (!SCHEME_CONTENT.equals(uri.getScheme())) {
return null;
}
- String auth = uri.getAuthority();
+ final String auth = uri.getAuthority();
if (auth != null) {
- return acquireExistingProvider(mContext, uri.getAuthority());
+ return acquireExistingProvider(mContext, auth);
}
return null;
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 7aa2507975d..bd7868f2804 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1888,6 +1888,18 @@ public abstract boolean startInstrumentation(ComponentName className,
*/
public static final String NOTIFICATION_SERVICE = "notification";
+ /**
+ * Use with {@link #getSystemService} to retrieve a
+ * {@link android.app.ProfileManager} for setting
+ * notification profiles.
+ *
+ * @see #getSystemService
+ * @see android.app.ProfileManager
+ *
+ * @hide
+ */
+ public static final String PROFILE_SERVICE = "profile";
+
/**
* Use with {@link #getSystemService} to retrieve a
* {@link android.view.accessibility.AccessibilityManager} for giving the user
@@ -2254,6 +2266,16 @@ public abstract boolean startInstrumentation(ComponentName className,
*/
public static final String USER_SERVICE = "user";
+ /**
+ * Determine whether the application or calling application has
+ * privacy guard. This is a privacy feature intended to permit the user
+ * to control access to personal data. Applications and content providers
+ * can check this value if they wish to honor privacy guard.
+ *
+ * @hide
+ */
+ public abstract boolean isPrivacyGuardEnabled();
+
/**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 84ad6674309..4cd8d8fd440 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -495,6 +495,12 @@ public Object getSystemService(String name) {
return mBase.getSystemService(name);
}
+ /** @hide */
+ @Override
+ public boolean isPrivacyGuardEnabled() {
+ return mBase.isPrivacyGuardEnabled();
+ }
+
@Override
public int checkPermission(String permission, int pid, int uid) {
return mBase.checkPermission(permission, pid, uid);
diff --git a/core/java/android/content/IIntentReceiver.aidl b/core/java/android/content/IIntentReceiver.aidl
old mode 100755
new mode 100644
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index cf0603e3a84..16a74e4b29a 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006 The Android Open Source Project
+ * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -683,6 +684,38 @@ public class Intent implements Parcelable, Cloneable {
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_CREATE_SHORTCUT = "android.intent.action.CREATE_SHORTCUT";
+ /**
+ * PhoneWindowManager: Take Screenshot via takeScreenshot()
+ * Input: nothing
+ *
Output: nothing
+ * @hide
+ */
+ public static final String ACTION_SCREENSHOT = "android.intent.action.SCREENSHOT";
+
+ /**
+ * Global Action: Shows power menu dialog
+ *
Input: nothing
+ *
Output: nothing
+ * @hide
+ */
+ public static final String ACTION_POWERMENU = "android.intent.action.POWERMENU";
+
+ /**
+ * Global Action: Shows power menu reboot dialog
+ *
Input: nothing
+ *
Output: nothing
+ * @hide
+ */
+ public static final String ACTION_POWERMENU_REBOOT = "android.intent.action.POWERMENU_REBOOT";
+
+ /**
+ * Global Action: Shows power menu profile toggle dialog
+ *
Input: nothing
+ *
Output: nothing
+ * @hide
+ */
+ public static final String ACTION_POWERMENU_PROFILE = "android.intent.action.POWERMENU_PROFILE";
+
/**
* The name of the extra used to define the Intent of a shortcut.
*
@@ -2136,6 +2169,31 @@ public static Intent createChooser(Intent target, CharSequence title) {
public static final String ACTION_HEADSET_PLUG =
"android.intent.action.HEADSET_PLUG";
+ /**
+ * Broadcast Action: WiFi Display audio is enabled or disabled
+ *
+ *
The intent will have the following extra values:
+ *
+ * - state - 0 for disabled, 1 for enabled.
+ *
+ * @hide
+ */
+ public static final String ACTION_WIFI_DISPLAY_AUDIO =
+ "qualcomm.intent.action.WIFI_DISPLAY_AUDIO";
+
+ /**
+ * Broadcast Action: WiFi Display video is enabled or disabled
+ *
+ * The intent will have the following extra values:
+ *
+ * - state - 0 for disabled, 1 for enabled.
+ *
+ * @hide
+ */
+
+ public static final String ACTION_WIFI_DISPLAY_VIDEO =
+ "qualcomm.intent.action.WIFI_DISPLAY_VIDEO";
+
/**
* Broadcast Action: An analog audio speaker/headset plugged in or unplugged.
*
@@ -2266,6 +2324,25 @@ public static Intent createChooser(Intent target, CharSequence title) {
public static final String ACTION_NEW_OUTGOING_CALL =
"android.intent.action.NEW_OUTGOING_CALL";
+ /**
+ * Broadcast Action: An outgoing sms is about to be sent.
+ *
+ * The Intent will have the following extras:
+ * destAddr - the phone number originally intended to be dialled
+ * scAddr - the service center address
+ * multipart - indicate whether this is a multipart or single message
+ * parts - ArrayList of text parts (one item if multipart=false)
+ * sentIntents - ArrayList to send on send
+ * deliveryIntents - ArrayList to send on delivery
+ *
+ * Once the broadcast is finished, resultData is used as the actual
+ * number to text.
+ *
+ * @hide
+ */
+ public static final String ACTION_NEW_OUTGOING_SMS =
+ "android.intent.action.NEW_OUTGOING_SMS";
+
/**
* Broadcast Action: Have the device reboot. This is only for use by
* system code.
@@ -2465,6 +2542,19 @@ public static Intent createChooser(Intent target, CharSequence title) {
public static final String ACTION_QUICK_CLOCK =
"android.intent.action.QUICK_CLOCK";
+ /**
+ * Broadcast Action: Indicate that unrecoverable error happened during app launch.
+ * Could indicate that curently applied theme is malicious.
+ * @hide
+ */
+ public static final String ACTION_APP_LAUNCH_FAILURE = "com.tmobile.intent.action.APP_LAUNCH_FAILURE";
+
+ /**
+ * Broadcast Action: Request to reset the unrecoverable errors count to 0.
+ * @hide
+ */
+ public static final String ACTION_APP_LAUNCH_FAILURE_RESET = "com.tmobile.intent.action.APP_LAUNCH_FAILURE_RESET";
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Standard intent categories (see addCategory()).
@@ -2597,6 +2687,7 @@ public static Intent createChooser(Intent target, CharSequence title) {
*/
public static final String CATEGORY_FRAMEWORK_INSTRUMENTATION_TEST =
"android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST";
+
/**
* An activity to run when device is inserted into a car dock.
* Used with {@link #ACTION_MAIN} to launch an activity. For more
@@ -2633,6 +2724,14 @@ public static Intent createChooser(Intent target, CharSequence title) {
@SdkConstant(SdkConstantType.INTENT_CATEGORY)
public static final String CATEGORY_CAR_MODE = "android.intent.category.CAR_MODE";
+ /**
+ * Used to indicate that a theme package has been installed or un-installed.
+ *
+ * @hide
+ */
+ public static final String CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE =
+ "com.tmobile.intent.category.THEME_PACKAGE_INSTALL_STATE_CHANGE";
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Application launch intent categories (see addCategory()).
@@ -3078,7 +3177,6 @@ public static Intent createChooser(Intent target, CharSequence title) {
* places where the framework may automatically set the exclude flag).
*/
public static final int FLAG_INCLUDE_STOPPED_PACKAGES = 0x00000020;
-
/**
* If set, the new activity is not kept in the history stack. As soon as
* the user navigates away from it, the activity is finished. This may also
@@ -3294,6 +3392,11 @@ public static Intent createChooser(Intent target, CharSequence title) {
* saw. This can only be used in conjunction with {@link #FLAG_ACTIVITY_NEW_TASK}.
*/
public static final int FLAG_ACTIVITY_TASK_ON_HOME = 0X00004000;
+ /**
+ * If set, this intent will always match start up as a floating window
+ * in mutil window scenarios.
+ */
+ public static final int FLAG_FLOATING_WINDOW = 0x00002000;
/**
* If set, when sending a broadcast only registered receivers will be
* called -- no BroadcastReceiver components will be launched.
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 3b0d846cd23..642a37deba7 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -1384,6 +1384,15 @@ public final void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mHasPartialTypes ? 1 : 0);
}
+ /**
+ * {@hide}
+ * @param other
+ * @return
+ */
+ public int onCompareTie(IntentFilter other) {
+ return 0;
+ }
+
/**
* For debugging -- perform a check on the filter, return true if it passed
* or false if it failed.
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index e4b4b97715f..03c1c950234 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -16,6 +16,7 @@
package android.content;
+import com.android.internal.app.ThemeUtils;
import android.accounts.Account;
import android.accounts.AccountAndUser;
import android.accounts.AccountManager;
@@ -140,6 +141,7 @@ public class SyncManager {
private static final int MAX_SIMULTANEOUS_INITIALIZATION_SYNCS;
private Context mContext;
+ private Context mUiContext;
private static final AccountAndUser[] INITIAL_ACCOUNTS_ARRAY = new AccountAndUser[0];
@@ -198,6 +200,12 @@ public void onReceive(Context context, Intent intent) {
}
};
+ private BroadcastReceiver mThemeChangeReceiver = new BroadcastReceiver() {
+ public void onReceive(Context context, Intent intent) {
+ mUiContext = null;
+ }
+ };
+
private BroadcastReceiver mBackgroundDataSettingChanged = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
if (getConnectivityManager().getBackgroundDataSetting()) {
@@ -404,6 +412,8 @@ public void onServiceChanged(SyncAdapterType type, int userId, boolean removed)
mContext.registerReceiverAsUser(
mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null);
+ ThemeUtils.registerThemeChangeReceiver(mContext, mThemeChangeReceiver);
+
if (!factoryTest) {
mNotificationMgr = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
@@ -938,6 +948,13 @@ private void onUserRemoved(int userId) {
}
}
+ private Context getUiContext() {
+ if (mUiContext == null) {
+ mUiContext = ThemeUtils.createUiContext(mContext);
+ }
+ return mUiContext != null ? mUiContext : mContext;
+ }
+
/**
* @hide
*/
@@ -2567,7 +2584,7 @@ private void installHandleTooManyDeletesNotification(Account account, String aut
new Notification(R.drawable.stat_notify_sync_error,
mContext.getString(R.string.contentServiceSync),
System.currentTimeMillis());
- notification.setLatestEventInfo(mContext,
+ notification.setLatestEventInfo(getUiContext(),
mContext.getString(R.string.contentServiceSyncNotificationTitle),
String.format(tooManyDeletesDescFormat.toString(), authorityName),
pendingIntent);
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index e2ca1ddea37..ac4647ac27d 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007 The Android Open Source Project
+ * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -340,6 +341,10 @@ public class ActivityInfo extends ComponentInfo
* {@link android.R.attr#configChanges} attribute.
*/
public static final int CONFIG_ORIENTATION = 0x0080;
+ /**
+ * @hide
+ */
+ public static final int CONFIG_THEME_RESOURCE = 0x008000;
/**
* Bit in {@link #configChanges} that indicates that the activity
* can itself handle changes to the screen layout. Set from the
@@ -352,6 +357,12 @@ public class ActivityInfo extends ComponentInfo
* {@link android.R.attr#configChanges} attribute.
*/
public static final int CONFIG_UI_MODE = 0x0200;
+ /**
+ * Bit in {@link #configChanges} that indicates that the activity
+ * can itself handle the inverted ui mode. Set from the
+ * {@link android.R.attr#configChanges} attribute.
+ */
+ public static final int CONFIG_UI_INVERTED_MODE = 0x0300;
/**
* Bit in {@link #configChanges} that indicates that the activity
* can itself handle the screen size. Set from the
@@ -412,6 +423,7 @@ public class ActivityInfo extends ComponentInfo
0x0040, // NAVIGATION
0x0080, // ORIENTATION
0x0800, // SCREEN LAYOUT
+ 0x8000, // UI INVERTED MODE
0x1000, // UI MODE
0x0200, // SCREEN SIZE
0x2000, // SMALLEST SCREEN SIZE
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 32cc7fd5aa1..ab32e48d22d 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007 The Android Open Source Project
+ * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -397,6 +398,15 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
*/
public String[] resourceDirs;
+ /**
+ * String retrieved from the seinfo tag found in selinux policy. This value
+ * is useful in setting an SELinux security context on the process as well
+ * as its data directory.
+ *
+ * {@hide}
+ */
+ public String seinfo;
+
/**
* Paths to all shared libraries this application is linked against. This
* field is only set if the {@link PackageManager#GET_SHARED_LIBRARY_FILES
@@ -444,6 +454,30 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
* @hide
*/
public int enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+ /**
+ * Is given application theme agnostic, i.e. behaves properly when default theme is changed.
+ * {@hide}
+ */
+ public boolean isThemeable = false;
+
+ private static final String PLUTO_SCHEMA = "http://www.w3.org/2001/pluto.html";
+
+ /**
+ * @hide
+ */
+ public static final String PLUTO_ISTHEMEABLE_ATTRIBUTE_NAME = "isThemeable";
+
+ /**
+ * @hide
+ */
+ public static final String PLUTO_HANDLE_THEME_CONFIG_CHANGES_ATTRIBUTE_NAME = "handleThemeConfigChanges";
+
+ /**
+ * @hide
+ */
+ public static boolean isPlutoNamespace(String namespace) {
+ return namespace != null && namespace.equalsIgnoreCase(PLUTO_SCHEMA);
+ }
/**
* For convenient access to package's install location.
@@ -477,6 +511,9 @@ public void dump(Printer pw, String prefix) {
if (resourceDirs != null) {
pw.println(prefix + "resourceDirs=" + resourceDirs);
}
+ if (seinfo != null) {
+ pw.println(prefix + "seinfo=" + seinfo);
+ }
pw.println(prefix + "dataDir=" + dataDir);
if (sharedLibraryFiles != null) {
pw.println(prefix + "sharedLibraryFiles=" + sharedLibraryFiles);
@@ -544,6 +581,7 @@ public ApplicationInfo(ApplicationInfo orig) {
publicSourceDir = orig.publicSourceDir;
nativeLibraryDir = orig.nativeLibraryDir;
resourceDirs = orig.resourceDirs;
+ seinfo = orig.seinfo;
sharedLibraryFiles = orig.sharedLibraryFiles;
dataDir = orig.dataDir;
uid = orig.uid;
@@ -555,6 +593,7 @@ public ApplicationInfo(ApplicationInfo orig) {
descriptionRes = orig.descriptionRes;
uiOptions = orig.uiOptions;
backupAgentName = orig.backupAgentName;
+ isThemeable = orig.isThemeable;
}
@@ -583,6 +622,7 @@ public void writeToParcel(Parcel dest, int parcelableFlags) {
dest.writeString(publicSourceDir);
dest.writeString(nativeLibraryDir);
dest.writeStringArray(resourceDirs);
+ dest.writeString(seinfo);
dest.writeStringArray(sharedLibraryFiles);
dest.writeString(dataDir);
dest.writeInt(uid);
@@ -594,6 +634,7 @@ public void writeToParcel(Parcel dest, int parcelableFlags) {
dest.writeString(backupAgentName);
dest.writeInt(descriptionRes);
dest.writeInt(uiOptions);
+ dest.writeInt(isThemeable? 1 : 0);
}
public static final Parcelable.Creator CREATOR
@@ -621,6 +662,7 @@ private ApplicationInfo(Parcel source) {
publicSourceDir = source.readString();
nativeLibraryDir = source.readString();
resourceDirs = source.readStringArray();
+ seinfo = source.readString();
sharedLibraryFiles = source.readStringArray();
dataDir = source.readString();
uid = source.readInt();
@@ -632,6 +674,7 @@ private ApplicationInfo(Parcel source) {
backupAgentName = source.readString();
descriptionRes = source.readInt();
uiOptions = source.readInt();
+ isThemeable = source.readInt() != 0;
}
/**
diff --git a/core/java/android/content/pm/BaseThemeInfo.java b/core/java/android/content/pm/BaseThemeInfo.java
new file mode 100644
index 00000000000..0171137bac1
--- /dev/null
+++ b/core/java/android/content/pm/BaseThemeInfo.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2010, T-Mobile USA, Inc.
+ *
+ * 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.content.pm;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+import android.util.Log;
+import android.util.AttributeSet;
+import android.content.res.Resources;
+
+/**
+ * @hide
+ */
+public class BaseThemeInfo implements Parcelable {
+
+ /**
+ * Wallpaper drawable.
+ *
+ * @see wallpaperImage attribute
+ */
+ public int wallpaperResourceId;
+
+ /**
+ * The resource id of theme thumbnail.
+ * Specifies a theme thumbnail image resource as @drawable/foo.
+ *
+ * @see thumbnail attribute
+ *
+ */
+ public int thumbnailResourceId;
+
+ /**
+ * The theme id, which does not change when the theme is modified.
+ * Specifies an Android UI Style using style name.
+ *
+ * @see themeId attribute
+ *
+ */
+ public String themeId;
+
+ /**
+ * The style resource id of Android UI Style, supplied by the resource commpiler.
+ * Specifies an Android UI Style id.
+ *
+ * @see styleId attribute
+ *
+ */
+ public int styleResourceId = 0;
+
+ /**
+ * The name of the theme (as displayed by UI).
+ *
+ * @see name attribute
+ *
+ */
+ public String name;
+
+ /**
+ * The name of the call ringtone audio file.
+ * Specifies a relative path in assets subfolder.
+ * If the parent's name is "locked" - DRM protected.
+ *
+ * @see ringtoneFileName attribute
+ *
+ */
+ public String ringtoneFileName;
+
+ /**
+ * The name of the call ringtone as shown to user.
+ *
+ * @see ringtoneName attribute
+ *
+ */
+ public String ringtoneName;
+
+ /**
+ * The name of the notification ringtone audio file.
+ * Specifies a relative path in assets subfolder.
+ * If the parent's name is "locked" - DRM protected.
+ *
+ * @see notificationRingtoneFileName attribute
+ *
+ */
+ public String notificationRingtoneFileName;
+
+ /**
+ * The name of the notification ringtone as shown to user.
+ *
+ * @see notificationRingtoneName attribute
+ *
+ */
+ public String notificationRingtoneName;
+
+ /**
+ * The author name of the theme package.
+ *
+ * @see author attribute
+ *
+ */
+ public String author;
+
+ /**
+ * The copyright text.
+ *
+ * @see copyright attribute
+ *
+ */
+ public String copyright;
+
+ /**
+ * {@hide}
+ */
+ // There is no corresposponding flag in manifest file
+ // This flag is set to true iff any media resource is DRM protected
+ public boolean isDrmProtected = false;
+
+ /**
+ * The name of the "main" theme style (as displayed by UI).
+ *
+ * @see themeStyleName attribute
+ *
+ */
+ public String themeStyleName;
+
+ /**
+ * Preview image drawable.
+ *
+ * @see preview attribute
+ */
+ public int previewResourceId;
+
+ /**
+ * The name of a sound pack.
+ *
+ * @see soundpack attribute
+ *
+ */
+ public String soundPackName;
+
+
+ private static final String LOCKED_NAME = "locked/";
+
+ /*
+ * Describe the kinds of special objects contained in this Parcelable's
+ * marshalled representation.
+ *
+ * @return a bitmask indicating the set of special object types marshalled
+ * by the Parcelable.
+ *
+ * @see android.os.Parcelable#describeContents()
+ */
+ public int describeContents() {
+ return 0;
+ }
+
+ /*
+ * Flatten this object in to a Parcel.
+ *
+ * @param dest The Parcel in which the object should be written.
+ * @param flags Additional flags about how the object should be written.
+ * May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}.
+ *
+ * @see android.os.Parcelable#writeToParcel(android.os.Parcel, int)
+ */
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(wallpaperResourceId);
+ dest.writeInt(thumbnailResourceId);
+ dest.writeString(themeId);
+ dest.writeInt(styleResourceId);
+ dest.writeString(name);
+ dest.writeString(ringtoneFileName);
+ dest.writeString(notificationRingtoneFileName);
+ dest.writeString(ringtoneName);
+ dest.writeString(notificationRingtoneName);
+ dest.writeString(author);
+ dest.writeString(copyright);
+ dest.writeInt(isDrmProtected? 1 : 0);
+ dest.writeString(soundPackName);
+ dest.writeString(themeStyleName);
+ dest.writeInt(previewResourceId);
+ }
+
+ /** @hide */
+ public static final Parcelable.Creator CREATOR
+ = new Parcelable.Creator() {
+ public BaseThemeInfo createFromParcel(Parcel source) {
+ return new BaseThemeInfo(source);
+ }
+
+ public BaseThemeInfo[] newArray(int size) {
+ return new BaseThemeInfo[size];
+ }
+ };
+
+ /** @hide */
+ public final String getResolvedString(Resources res, AttributeSet attrs, int index) {
+ int resId = attrs.getAttributeResourceValue(index, 0);
+ if (resId !=0 ) {
+ return res.getString(resId);
+ }
+ return attrs.getAttributeValue(index);
+ }
+
+ protected BaseThemeInfo() {
+ }
+
+ protected BaseThemeInfo(Parcel source) {
+ wallpaperResourceId = source.readInt();
+ thumbnailResourceId = source.readInt();
+ themeId = source.readString();
+ styleResourceId = source.readInt();
+ name = source.readString();
+ ringtoneFileName = source.readString();
+ notificationRingtoneFileName = source.readString();
+ ringtoneName = source.readString();
+ notificationRingtoneName = source.readString();
+ author = source.readString();
+ copyright = source.readString();
+ isDrmProtected = (source.readInt() != 0);
+ soundPackName = source.readString();
+ themeStyleName = source.readString();
+ previewResourceId = source.readInt();
+ }
+
+ protected void changeDrmFlagIfNeeded(String resourcePath) {
+ if (resourcePath != null && resourcePath.contains(LOCKED_NAME)) {
+ isDrmProtected = true;
+ }
+ }
+}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index b9e432c120f..9aff1141108 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -42,6 +42,7 @@ import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
import android.content.pm.VerificationParams;
import android.content.pm.VerifierDeviceIdentity;
+import android.content.pm.ThemeInfo;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.content.IntentSender;
@@ -211,7 +212,11 @@ interface IPackageManager {
int getPreferredActivities(out List outFilters,
out List outActivities, String packageName);
-
+
+ boolean getPrivacyGuardSetting(in String packageName, int userId);
+
+ void setPrivacyGuardSetting(in String packageName, boolean enabled, int userId);
+
/**
* As per {@link android.content.pm.PackageManager#setComponentEnabledSetting}.
*/
@@ -385,4 +390,7 @@ interface IPackageManager {
/** Reflects current DeviceStorageMonitorService state */
boolean isStorageLow();
+
+ String[] getRevokedPermissions(String packageName);
+ void setRevokedPermissions(String packageName, in String[] perms);
}
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index 85f7aa5113a..79cc52878a6 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007 The Android Open Source Project
+ * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -218,9 +219,69 @@ public class PackageInfo implements Parcelable {
*/
public int installLocation = INSTALL_LOCATION_INTERNAL_ONLY;
+ // Is Theme Apk
+ /**
+ * {@hide}
+ */
+ public boolean isThemeApk = false;
+
+ // ThemeInfo
+ /**
+ * {@hide}
+ */
+ public ThemeInfo [] themeInfos;
+
public PackageInfo() {
}
+ /*
+ * Is Theme Apk is DRM protected (contains DRM-protected resources)
+ *
+ */
+ private boolean drmProtectedThemeApk = false;
+
+ /**
+ * @hide
+ *
+ * @return Is Theme Apk is DRM protected (contains DRM-protected resources)
+ */
+ public boolean isDrmProtectedThemeApk() {
+ return drmProtectedThemeApk;
+ }
+
+ /**
+ * @hide
+ *
+ * @param value if Theme Apk is DRM protected (contains DRM-protected resources)
+ */
+ public void setDrmProtectedThemeApk(boolean value) {
+ drmProtectedThemeApk = value;
+ }
+
+ /*
+ * If isThemeApk and isDrmProtectedThemeApk are true - path to hidden locked zip file
+ *
+ */
+ private String lockedZipFilePath;
+
+ /**
+ * @hide
+ *
+ * @return path for hidden locked zip file
+ */
+ public String getLockedZipFilePath() {
+ return lockedZipFilePath;
+ }
+
+ /**
+ * @hide
+ *
+ * @param value path for hidden locked zip file
+ */
+ public void setLockedZipFilePath(String value) {
+ lockedZipFilePath = value;
+ }
+
public String toString() {
return "PackageInfo{"
+ Integer.toHexString(System.identityHashCode(this))
@@ -258,6 +319,12 @@ public void writeToParcel(Parcel dest, int parcelableFlags) {
dest.writeTypedArray(configPreferences, parcelableFlags);
dest.writeTypedArray(reqFeatures, parcelableFlags);
dest.writeInt(installLocation);
+
+ /* Theme-specific. */
+ dest.writeInt((isThemeApk)? 1 : 0);
+ dest.writeInt((drmProtectedThemeApk)? 1 : 0);
+ dest.writeTypedArray(themeInfos, parcelableFlags);
+ dest.writeString(lockedZipFilePath);
}
public static final Parcelable.Creator CREATOR
@@ -296,5 +363,11 @@ private PackageInfo(Parcel source) {
configPreferences = source.createTypedArray(ConfigurationInfo.CREATOR);
reqFeatures = source.createTypedArray(FeatureInfo.CREATOR);
installLocation = source.readInt();
+
+ /* Theme-specific. */
+ isThemeApk = (source.readInt() != 0);
+ drmProtectedThemeApk = (source.readInt() != 0);
+ themeInfos = source.createTypedArray(ThemeInfo.CREATOR);
+ lockedZipFilePath = source.readString();
}
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 8ba19881f09..77d1a042b6e 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006 The Android Open Source Project
+ * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -644,6 +645,14 @@ public NameNotFoundException(String name) {
*/
public static final int INSTALL_FAILED_INTERNAL_ERROR = -110;
+ /**
+ * Installation failed return code: this is passed to the {@link IPackageInstallObserver} by
+ * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
+ * if the system failed to install the package because of a policy denial.
+ * @hide
+ */
+ public static final int INSTALL_FAILED_POLICY_REJECTED_PERMISSION = -111;
+
/**
* Flag parameter for {@link #deletePackage} to indicate that you don't want to delete the
* package's data directory.
@@ -1539,6 +1548,17 @@ public abstract ProviderInfo getProviderInfo(ComponentName component,
*/
public abstract List getInstalledPackages(int flags, int userId);
+ /**
+ * Return a List of all theme packages that are installed
+ * on the device.
+ *
+ * @return A List of PackageInfo objects, one for each theme package
+ * that is installed on the device.
+ *
+ * @hide
+ */
+ public abstract List getInstalledThemePackages();
+
/**
* Check whether a particular package has been granted a particular
* permission.
@@ -2912,6 +2932,22 @@ public abstract void setApplicationEnabledSetting(String packageName,
*/
public abstract int getApplicationEnabledSetting(String packageName);
+ /**
+ * @param packageName
+ * @return
+ *
+ * @hide
+ */
+ public abstract boolean getPrivacyGuardSetting(String packageName);
+
+ /**
+ * @param packageName
+ * @param enabled
+ *
+ * @hide
+ */
+ public abstract void setPrivacyGuardSetting(String packageName, boolean enabled);
+
/**
* Return whether the device has been booted into safe mode.
*/
@@ -2936,6 +2972,29 @@ public abstract void setApplicationEnabledSetting(String packageName,
public abstract void movePackage(
String packageName, IPackageMoveObserver observer, int flags);
+ /**
+ * Returns the revoked permissions for given package.
+ *
+ * NOTE: If the package has a shared uid then the revoked permissions for that
+ * uid will be returned.
+ *
+ * @param packageName Name of the package which revoked permissions are needed
+ * @hide
+ */
+ public abstract String[] getRevokedPermissions(String packageName);
+
+ /**
+ * Sets the revoked permissions for given package.
+ *
+ * NOTE: If the package has a shared uid then this method will revoke the
+ * permissions for that shared uid.
+ *
+ * @param packageName Name of the package which revoked permissions are needed
+ * @param the revoked permissions.
+ * @hide
+ */
+ public abstract void setRevokedPermissions(String packageName, String[] perms);
+
/**
* Returns the device identity that verifiers can use to associate their scheme to a particular
* device. This should not be used by anything other than a package verifier.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 3e8c2a8572d..6efab673a58 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007 The Android Open Source Project
+ * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -256,6 +257,17 @@ public static PackageInfo generatePackageInfo(PackageParser.Package p,
}
*/
+ public static String getLockedZipFilePath(String path) {
+ if (path == null) {
+ return null;
+ }
+ if (isPackageFilename(path)) {
+ return path.substring(0, path.length() - 4) + ".locked.zip";
+ } else {
+ return path + ".locked.zip";
+ }
+ }
+
/**
* Generate and return the {@link PackageInfo} for a parsed package.
*
@@ -287,6 +299,21 @@ public static PackageInfo generatePackageInfo(PackageParser.Package p,
pi.versionName = p.mVersionName;
pi.sharedUserId = p.mSharedUserId;
pi.sharedUserLabel = p.mSharedUserLabel;
+ pi.isThemeApk = p.mIsThemeApk;
+ pi.setDrmProtectedThemeApk(false);
+ if (pi.isThemeApk) {
+ int N = p.mThemeInfos.size();
+ if (N > 0) {
+ pi.themeInfos = new ThemeInfo[N];
+ for (int i = 0; i < N; i++) {
+ pi.themeInfos[i] = p.mThemeInfos.get(i);
+ pi.setDrmProtectedThemeApk(pi.isDrmProtectedThemeApk() || pi.themeInfos[i].isDrmProtected);
+ }
+ if (pi.isDrmProtectedThemeApk()) {
+ pi.setLockedZipFilePath(PackageParser.getLockedZipFilePath(p.mPath));
+ }
+ }
+ }
pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
pi.installLocation = p.installLocation;
pi.firstInstallTime = firstInstallTime;
@@ -504,7 +531,7 @@ public Package parsePackage(File sourceFile, String destCodePath,
int cookie = assmgr.addAssetPath(mArchiveSourcePath);
if (cookie != 0) {
res = new Resources(assmgr, metrics, null);
- assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Build.VERSION.RESOURCES_SDK_INT);
parser = assmgr.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
assetError = false;
@@ -719,7 +746,7 @@ public static PackageLite parsePackageLite(String packageFilePath, int flags) {
final Resources res;
try {
assmgr = new AssetManager();
- assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Build.VERSION.RESOURCES_SDK_INT);
int cookie = assmgr.addAssetPath(packageFilePath);
@@ -1287,7 +1314,10 @@ private Package parsePackage(
// Just skip this tag
XmlUtils.skipCurrentTag(parser);
continue;
-
+ } else if (tagName.equals("theme")) {
+ // this is a theme apk.
+ pkg.mIsThemeApk = true;
+ pkg.mThemeInfos.add(new ThemeInfo(parser, res, attrs));
} else if (RIGID_PARSER) {
outError[0] = "Bad element under : "
+ parser.getName();
@@ -1378,6 +1408,9 @@ private Package parsePackage(
>= android.os.Build.VERSION_CODES.DONUT)) {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
}
+ if (pkg.mIsThemeApk) {
+ pkg.applicationInfo.isThemeable = false;
+ }
return pkg;
}
@@ -1683,12 +1716,43 @@ private Instrumentation parseInstrumentation(Package owner, Resources res,
return a;
}
+ private void parseApplicationThemeAttributes(XmlPullParser parser, AttributeSet attrs,
+ ApplicationInfo appInfo) {
+ for (int i = 0; i < attrs.getAttributeCount(); i++) {
+ if (!ApplicationInfo.isPlutoNamespace(parser.getAttributeNamespace(i))) {
+ continue;
+ }
+ String attrName = attrs.getAttributeName(i);
+ if (attrName.equalsIgnoreCase(ApplicationInfo.PLUTO_ISTHEMEABLE_ATTRIBUTE_NAME)) {
+ appInfo.isThemeable = attrs.getAttributeBooleanValue(i, false);
+ return;
+ }
+ }
+ }
+
+ private void parseActivityThemeAttributes(XmlPullParser parser, AttributeSet attrs,
+ ActivityInfo ai) {
+ for (int i = 0; i < attrs.getAttributeCount(); i++) {
+ if (!ApplicationInfo.isPlutoNamespace(parser.getAttributeNamespace(i))) {
+ continue;
+ }
+ String attrName = attrs.getAttributeName(i);
+ if (attrName.equalsIgnoreCase(ApplicationInfo.PLUTO_HANDLE_THEME_CONFIG_CHANGES_ATTRIBUTE_NAME)) {
+ ai.configChanges |= ActivityInfo.CONFIG_THEME_RESOURCE;
+ }
+ }
+ }
+
private boolean parseApplication(Package owner, Resources res,
XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
throws XmlPullParserException, IOException {
final ApplicationInfo ai = owner.applicationInfo;
final String pkgName = owner.applicationInfo.packageName;
+ // assume that this package is themeable unless explicitly set to false.
+ ai.isThemeable = true;
+ parseApplicationThemeAttributes(parser, attrs, ai);
+
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifestApplication);
@@ -2229,6 +2293,8 @@ private Activity parseActivity(Package owner, Resources res,
return null;
}
+ parseActivityThemeAttributes(parser, attrs, a.info);
+
int outerDepth = parser.getDepth();
int type;
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
@@ -3222,6 +3288,12 @@ public final static class Package {
// For use by package manager to keep track of where it has done dexopt.
public boolean mDidDexOpt;
+
+ // Is Theme Apk
+ public boolean mIsThemeApk = false;
+
+ // Theme info
+ public final ArrayList mThemeInfos = new ArrayList(0);
// // User set enabled state.
// public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 357997781ed..91ef1bc149f 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -29,6 +29,7 @@ public class PackageUserState {
public boolean notLaunched;
public boolean installed;
public int enabled;
+ public boolean privacyGuard;
public HashSet disabledComponents;
public HashSet enabledComponents;
@@ -36,6 +37,7 @@ public class PackageUserState {
public PackageUserState() {
installed = true;
enabled = COMPONENT_ENABLED_STATE_DEFAULT;
+ privacyGuard = false;
}
public PackageUserState(PackageUserState o) {
@@ -43,6 +45,7 @@ public PackageUserState(PackageUserState o) {
stopped = o.stopped;
notLaunched = o.notLaunched;
enabled = o.enabled;
+ privacyGuard = o.privacyGuard;
disabledComponents = o.disabledComponents != null
? new HashSet(o.disabledComponents) : null;
enabledComponents = o.enabledComponents != null
diff --git a/core/java/android/content/pm/ThemeInfo.aidl b/core/java/android/content/pm/ThemeInfo.aidl
new file mode 100644
index 00000000000..acbc85e9c8b
--- /dev/null
+++ b/core/java/android/content/pm/ThemeInfo.aidl
@@ -0,0 +1,3 @@
+package android.content.pm;
+
+parcelable ThemeInfo;
diff --git a/core/java/android/content/pm/ThemeInfo.java b/core/java/android/content/pm/ThemeInfo.java
new file mode 100644
index 00000000000..e51dbb6ae8c
--- /dev/null
+++ b/core/java/android/content/pm/ThemeInfo.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2010, T-Mobile USA, Inc.
+ *
+ * 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.content.pm;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParser;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.content.res.Resources;
+
+/**
+ * Overall information about "theme" package. This corresponds
+ * to the information collected from AndroidManifest.xml (theme tag).
+ *
+ * Below is an example of theme tag
+ *
+ *
+ * @hide
+ */
+public final class ThemeInfo extends BaseThemeInfo {
+ private enum AttributeIndex {
+ THEME_PACKAGE_INDEX,
+ PREVIEW_INDEX,
+ AUTHOR_INDEX,
+ THEME_INDEX,
+ THEME_STYLE_NAME_INDEX,
+ THUMBNAIL_INDEX,
+ RINGTONE_FILE_NAME_INDEX,
+ NOTIFICATION_RINGTONE_FILE_NAME_INDEX,
+ WALLPAPER_IMAGE_INDEX,
+ COPYRIGHT_INDEX,
+ RINGTONE_NAME_INDEX,
+ NOTIFICATION_RINGTONE_NAME_INDEX,
+ STYLE_INDEX;
+
+ public static AttributeIndex get(int ordinal) {
+ return values()[ordinal];
+ }
+ };
+
+ private static final String [] compulsoryAttributes = new String [] {
+ "name",
+ "preview",
+ "author",
+ "themeId",
+ "styleName",
+ };
+
+ private static final String [] optionalAttributes = new String [] {
+ "thumbnail",
+ "ringtoneFileName",
+ "notificationRingtoneFileName",
+ "wallpaperImage",
+ "copyright",
+ "ringtoneName",
+ "notificationRingtoneName",
+ "styleId",
+ };
+
+ private static final Map sAttributesLookupTable;
+
+ static {
+ sAttributesLookupTable = new HashMap();
+ for (int i = 0; i < compulsoryAttributes.length; i++) {
+ sAttributesLookupTable.put(compulsoryAttributes[i], AttributeIndex.get(i));
+ }
+
+ for (int i = 0; i < optionalAttributes.length; i++) {
+ sAttributesLookupTable.put(optionalAttributes[i],
+ AttributeIndex.get(compulsoryAttributes.length + i));
+ }
+ }
+
+ public ThemeInfo(XmlPullParser parser, Resources res, AttributeSet attrs) throws XmlPullParserException {
+ super();
+
+ Map tempMap =
+ new HashMap(sAttributesLookupTable);
+ int numberOfCompulsoryAttributes = 0;
+ for (int i = 0; i < attrs.getAttributeCount(); i++) {
+ if (!ApplicationInfo.isPlutoNamespace(parser.getAttributeNamespace(i))) {
+ continue;
+ }
+ String key = attrs.getAttributeName(i);
+ if (tempMap.containsKey(key)) {
+ AttributeIndex index = tempMap.get(key);
+ tempMap.remove(key);
+
+ if (index.ordinal() < compulsoryAttributes.length) {
+ numberOfCompulsoryAttributes++;
+ }
+ switch (index) {
+ case THEME_PACKAGE_INDEX:
+ // theme name
+ name = getResolvedString(res, attrs, i);
+ break;
+
+ case THUMBNAIL_INDEX:
+ // theme thumbprint
+ thumbnailResourceId = attrs.getAttributeResourceValue(i, 0);
+ break;
+
+ case AUTHOR_INDEX:
+ // theme author
+ author = getResolvedString(res, attrs, i);
+ break;
+
+ case THEME_INDEX:
+ // androidUiStyle attribute
+ themeId = attrs.getAttributeValue(i);
+ break;
+
+ case THEME_STYLE_NAME_INDEX:
+ themeStyleName = getResolvedString(res, attrs, i);
+ break;
+
+ case RINGTONE_FILE_NAME_INDEX:
+ // ringtone
+ ringtoneFileName = attrs.getAttributeValue(i);
+ changeDrmFlagIfNeeded(ringtoneFileName);
+ break;
+
+ case NOTIFICATION_RINGTONE_FILE_NAME_INDEX:
+ // notification ringtone
+ notificationRingtoneFileName = attrs.getAttributeValue(i);
+ changeDrmFlagIfNeeded(notificationRingtoneFileName);
+ break;
+
+ case WALLPAPER_IMAGE_INDEX:
+ // wallpaperImage attribute
+ wallpaperResourceId = attrs.getAttributeResourceValue(i, 0);
+ break;
+
+ case COPYRIGHT_INDEX:
+ // themeCopyright attribute
+ copyright = getResolvedString(res, attrs, i);
+ break;
+
+ case RINGTONE_NAME_INDEX:
+ // ringtone UI name
+ ringtoneName = attrs.getAttributeValue(i);
+ break;
+
+ case NOTIFICATION_RINGTONE_NAME_INDEX:
+ // notification ringtone UI name
+ notificationRingtoneName = attrs.getAttributeValue(i);
+ break;
+
+ case STYLE_INDEX:
+ styleResourceId = attrs.getAttributeResourceValue(i, 0);
+ break;
+
+ case PREVIEW_INDEX:
+ // theme thumbprint
+ previewResourceId = attrs.getAttributeResourceValue(i, 0);
+ break;
+ }
+ }
+ }
+ if (numberOfCompulsoryAttributes < compulsoryAttributes.length) {
+ throw new XmlPullParserException("Not all compulsory attributes are specified in ");
+ }
+ }
+
+ public static final Parcelable.Creator CREATOR
+ = new Parcelable.Creator() {
+ public ThemeInfo createFromParcel(Parcel source) {
+ return new ThemeInfo(source);
+ }
+
+ public ThemeInfo[] newArray(int size) {
+ return new ThemeInfo[size];
+ }
+ };
+
+ private ThemeInfo(Parcel source) {
+ super(source);
+ }
+}
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index ffefaa27a85..669c2c62639 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006 The Android Open Source Project
+ * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +19,7 @@
import android.os.ParcelFileDescriptor;
import android.util.Log;
+import android.util.SparseArray;
import android.util.TypedValue;
import java.io.FileNotFoundException;
@@ -77,6 +79,20 @@ public final class AssetManager {
private boolean mOpen = true;
private HashMap mRefStacks;
+ private String mAssetDir;
+ private String mAppName;
+
+ private boolean mThemeSupport;
+ private String mThemePackageName;
+ private int mThemeCookie;
+
+ /**
+ * Organize all added redirection maps using Java strong references to keep
+ * the native layer cleanup simple (that is, finalize() in Java will be
+ * responsible for delete in C++).
+ */
+ private SparseArray mRedirections;
+
/**
* Create a new AssetManager containing only the basic system assets.
* Applications will not generally use this method, instead retrieving the
@@ -252,6 +268,12 @@ public void close() {
}
}
+ /*package*/ final void recreateStringBlocks() {
+ synchronized (this) {
+ makeStringBlocks(true);
+ }
+ }
+
/*package*/ final void makeStringBlocks(boolean copyFromSystem) {
final int sysNum = copyFromSystem ? sSystem.mStringBlocks.length : 0;
final int num = getStringBlockCount();
@@ -458,6 +480,18 @@ public final XmlResourceParser openXmlResourceParser(int cookie,
return rp;
}
+ /**
+ * {@hide}
+ * Split a theme package with DRM-protected resources into two files.
+ *
+ * @param packageFileName Original theme package file name.
+ * @param lockedFileName Name of the new "locked" file with DRM resources.
+ * @param drmProtectedresources Array of names of DRM-protected assets.
+ */
+ public final int splitDrmProtectedThemePackage(String packageFileName, String lockedFileName, String [] drmProtectedresources) {
+ return splitThemePackage(packageFileName, lockedFileName, drmProtectedresources);
+ }
+
/**
* {@hide}
* Retrieve a non-asset as a compiled XML file. Not for use by
@@ -624,6 +658,110 @@ public final int[] addAssetPaths(String[] paths) {
return cookies;
}
+ /**
+ * Delete a set of theme assets from the asset manager. Not for use by
+ * applications. Returns true if succeeded or false on failure.
+ *
+ * @hide
+ */
+ public native final boolean detachThemePath(String packageName, int cookie);
+
+ /**
+ * Attach a set of theme assets to the asset manager. If necessary, this
+ * method will forcefully update the internal ResTable data structure.
+ *
+ * @return Cookie of the added asset or 0 on failure.
+ * @hide
+ */
+ public native final int attachThemePath(String path);
+
+ /**
+ * Sets a flag indicating that this AssetManager should have themes
+ * attached, according to the initial request to create it by the
+ * ApplicationContext.
+ *
+ * {@hide}
+ */
+ public final void setThemeSupport(boolean themeSupport) {
+ mThemeSupport = themeSupport;
+ }
+
+ /**
+ * Should this AssetManager have themes attached, according to the initial
+ * request to create it by the ApplicationContext?
+ *
+ * {@hide}
+ */
+ public final boolean hasThemeSupport() {
+ return mThemeSupport;
+ }
+
+ /**
+ * Apply a heuristic to match-up all attributes from the source style with
+ * attributes in the destination style. For each match, an entry in the
+ * package redirection map will be inserted.
+ *
+ * {@hide}
+ */
+ public native final boolean generateStyleRedirections(int resMapNative, int sourceStyle,
+ int destStyle);
+
+ /**
+ * Get package name of current theme (may return null).
+ * {@hide}
+ */
+ public String getThemePackageName() {
+ return mThemePackageName;
+ }
+
+ /**
+ * Sets package name and highest level style id for current theme (null, 0 is allowed).
+ * {@hide}
+ */
+ public void setThemePackageName(String packageName) {
+ mThemePackageName = packageName;
+ }
+
+ /**
+ * Get asset cookie for current theme (may return 0).
+ * {@hide}
+ */
+ public int getThemeCookie() {
+ return mThemeCookie;
+ }
+
+ /**
+ * Sets asset cookie for current theme (0 if not a themed asset manager).
+ * {@hide}
+ */
+ public void setThemeCookie(int cookie) {
+ mThemeCookie = cookie;
+ }
+
+ /**
+ * Add a redirection map to the asset manager. All future resource lookups
+ * will consult this map.
+ * {@hide}
+ */
+ public void addRedirections(PackageRedirectionMap map) {
+ if (mRedirections == null) {
+ mRedirections = new SparseArray(2);
+ }
+ mRedirections.append(map.getPackageId(), map);
+ addRedirectionsNative(map.getNativePointer());
+ }
+
+ /**
+ * Clear redirection map for the asset manager.
+ * {@hide}
+ */
+ public void clearRedirections() {
+ if (mRedirections != null) {
+ mRedirections.clear();
+ }
+ clearRedirectionsNative();
+ }
+
/**
* Determine whether the state in this asset manager is up-to-date with
* the files on the filesystem. If false is returned, you need to
@@ -653,7 +791,7 @@ public native final void setConfiguration(int mcc, int mnc, String locale,
int orientation, int touchscreen, int density, int keyboard,
int keyboardHidden, int navigation, int screenWidth, int screenHeight,
int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp,
- int screenLayout, int uiMode, int majorVersion);
+ int screenLayout, int uiInvertedMode, int uiMode, int majorVersion);
/**
* Retrieve the resource identifier for the given resource name.
@@ -741,6 +879,26 @@ private native final int loadResourceBagValue(int ident, int bagEntryId, TypedVa
private native final int[] getArrayStringInfo(int arrayRes);
/*package*/ native final int[] getArrayIntResource(int arrayRes);
+ private native final int splitThemePackage(String srcFileName, String dstFileName, String [] drmProtectedAssetNames);
+
+ /**
+ * {@hide}
+ */
+ public native final int getBasePackageCount();
+
+ /**
+ * {@hide}
+ */
+ public native final String getBasePackageName(int index);
+
+ /**
+ * {@hide}
+ */
+ public native final int getBasePackageId(int index);
+
+ private native final void addRedirectionsNative(int redirectionMapNativePointer);
+ private native final void clearRedirectionsNative();
+
private native final void init();
private native final void destroy();
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index 28c751c373f..789d25e914c 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -92,9 +92,15 @@ public class CompatibilityInfo implements Parcelable {
*/
public final float applicationInvertedScale;
+ /**
+ * Whether the application supports third-party theming.
+ */
+ public final boolean isThemeable;
+
public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, int sw,
boolean forceCompat) {
int compatFlags = 0;
+ isThemeable = appInfo.isThemeable;
if (appInfo.requiresSmallestWidthDp != 0 || appInfo.compatibleWidthLimitDp != 0
|| appInfo.largestWidthLimitDp != 0) {
@@ -242,17 +248,19 @@ public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, int sw,
}
private CompatibilityInfo(int compFlags,
- int dens, float scale, float invertedScale) {
+ int dens, float scale, float invertedScale, boolean isThemeable) {
mCompatibilityFlags = compFlags;
applicationDensity = dens;
applicationScale = scale;
applicationInvertedScale = invertedScale;
+ this.isThemeable = isThemeable;
}
private CompatibilityInfo() {
this(NEVER_NEEDS_COMPAT, DisplayMetrics.DENSITY_DEVICE,
1.0f,
- 1.0f);
+ 1.0f,
+ true);
}
/**
@@ -524,6 +532,7 @@ public boolean equals(Object o) {
if (applicationDensity != oc.applicationDensity) return false;
if (applicationScale != oc.applicationScale) return false;
if (applicationInvertedScale != oc.applicationInvertedScale) return false;
+ if (isThemeable != oc.isThemeable) return false;
return true;
} catch (ClassCastException e) {
return false;
@@ -561,6 +570,7 @@ public int hashCode() {
result = 31 * result + applicationDensity;
result = 31 * result + Float.floatToIntBits(applicationScale);
result = 31 * result + Float.floatToIntBits(applicationInvertedScale);
+ result = 31 * result + (isThemeable ? 1 : 0);
return result;
}
@@ -575,6 +585,7 @@ public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(applicationDensity);
dest.writeFloat(applicationScale);
dest.writeFloat(applicationInvertedScale);
+ dest.writeInt(isThemeable ? 1 : 0);
}
public static final Parcelable.Creator CREATOR
@@ -593,5 +604,6 @@ private CompatibilityInfo(Parcel source) {
applicationDensity = source.readInt();
applicationScale = source.readFloat();
applicationInvertedScale = source.readFloat();
+ isThemeable = source.readInt() == 1 ? true : false;
}
}
diff --git a/core/java/android/content/res/Configuration.aidl b/core/java/android/content/res/Configuration.aidl
old mode 100755
new mode 100644
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 86d6ee77ae7..7a283a711fa 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
+ * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +22,9 @@
import android.os.Parcelable;
import android.text.TextUtils;
import android.view.View;
+import android.util.Log;
+import android.os.SystemProperties;
+import android.text.TextUtils;
import java.util.Locale;
@@ -65,6 +69,11 @@ public final class Configuration implements Parcelable, ComparableThe {@link #UI_MODE_TYPE_MASK} bits define the overall ui mode of the
* device. They may be one of {@link #UI_MODE_TYPE_UNDEFINED},
* {@link #UI_MODE_TYPE_NORMAL}, {@link #UI_MODE_TYPE_DESK},
- * {@link #UI_MODE_TYPE_CAR}, {@link #UI_MODE_TYPE_TELEVISION}, or
- * {@link #UI_MODE_TYPE_APPLIANCE}.
+ * {@link #UI_MODE_TYPE_CAR}, {@link #UI_MODE_TYPE_TELEVISION},
+ * {@link #UI_MODE_TYPE_APPLIANCE}
*
* The {@link #UI_MODE_NIGHT_MASK} defines whether the screen
* is in a special mode. They may be one of {@link #UI_MODE_NIGHT_UNDEFINED},
@@ -569,6 +629,7 @@ public void setTo(Configuration o) {
navigationHidden = o.navigationHidden;
orientation = o.orientation;
screenLayout = o.screenLayout;
+ uiInvertedMode = o.uiInvertedMode;
uiMode = o.uiMode;
screenWidthDp = o.screenWidthDp;
screenHeightDp = o.screenHeightDp;
@@ -578,6 +639,9 @@ public void setTo(Configuration o) {
compatScreenHeightDp = o.compatScreenHeightDp;
compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp;
seq = o.seq;
+ if (o.customTheme != null) {
+ customTheme = (CustomTheme) o.customTheme.clone();
+ }
}
public String toString() {
@@ -653,6 +717,13 @@ public String toString() {
case ORIENTATION_PORTRAIT: sb.append(" port"); break;
default: sb.append(" orien="); sb.append(orientation); break;
}
+ switch (uiInvertedMode) {
+ case UI_INVERTED_MODE_UNDEFINED: sb.append(" ?uiInvertedmode"); break;
+ case UI_INVERTED_MODE_NORMAL: break;
+ case UI_INVERTED_MODE_YES: sb.append(" inverted"); break;
+ case UI_INVERTED_MODE_NO: sb.append(" notinverted"); break;
+ default: sb.append(" uiInvertedmode="); sb.append(uiInvertedMode); break;
+ }
switch ((uiMode&UI_MODE_TYPE_MASK)) {
case UI_MODE_TYPE_UNDEFINED: sb.append(" ?uimode"); break;
case UI_MODE_TYPE_NORMAL: /* normal is not interesting to print */ break;
@@ -713,6 +784,8 @@ public String toString() {
sb.append(" s.");
sb.append(seq);
}
+ sb.append(" themeResource=");
+ sb.append(customTheme);
sb.append('}');
return sb.toString();
}
@@ -733,12 +806,14 @@ public void setToDefaults() {
navigationHidden = NAVIGATIONHIDDEN_UNDEFINED;
orientation = ORIENTATION_UNDEFINED;
screenLayout = SCREENLAYOUT_UNDEFINED;
+ uiInvertedMode = UI_INVERTED_MODE_UNDEFINED;
uiMode = UI_MODE_TYPE_UNDEFINED;
screenWidthDp = compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED;
screenHeightDp = compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED;
smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
densityDpi = DENSITY_DPI_UNDEFINED;
seq = 0;
+ customTheme = null;
}
/** {@hide} */
@@ -831,6 +906,11 @@ public int updateFrom(Configuration delta) {
screenLayout = delta.screenLayout;
}
}
+ if (delta.uiInvertedMode != UI_INVERTED_MODE_UNDEFINED
+ && uiInvertedMode != delta.uiInvertedMode) {
+ changed |= ActivityInfo.CONFIG_UI_INVERTED_MODE;
+ uiInvertedMode = delta.uiInvertedMode;
+ }
if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)
&& uiMode != delta.uiMode) {
changed |= ActivityInfo.CONFIG_UI_MODE;
@@ -853,11 +933,13 @@ public int updateFrom(Configuration delta) {
changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
screenHeightDp = delta.screenHeightDp;
}
- if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
- changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
+ if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
+ && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
+ changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
smallestScreenWidthDp = delta.smallestScreenWidthDp;
}
- if (delta.densityDpi != DENSITY_DPI_UNDEFINED) {
+ if (delta.densityDpi != DENSITY_DPI_UNDEFINED &&
+ densityDpi != delta.densityDpi) {
changed |= ActivityInfo.CONFIG_DENSITY;
densityDpi = delta.densityDpi;
}
@@ -873,7 +955,13 @@ public int updateFrom(Configuration delta) {
if (delta.seq != 0) {
seq = delta.seq;
}
-
+
+ if (delta.customTheme != null
+ && (customTheme == null || !customTheme.equals(delta.customTheme))) {
+ changed |= ActivityInfo.CONFIG_THEME_RESOURCE;
+ customTheme = (CustomTheme)delta.customTheme.clone();
+ }
+
return changed;
}
@@ -958,6 +1046,10 @@ && getScreenLayoutNoDirection(screenLayout) !=
getScreenLayoutNoDirection(delta.screenLayout)) {
changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
}
+ if (delta.uiInvertedMode != UI_INVERTED_MODE_UNDEFINED
+ && uiInvertedMode != delta.uiInvertedMode) {
+ changed |= ActivityInfo.CONFIG_UI_INVERTED_MODE;
+ }
if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)
&& uiMode != delta.uiMode) {
changed |= ActivityInfo.CONFIG_UI_MODE;
@@ -978,7 +1070,10 @@ && getScreenLayoutNoDirection(screenLayout) !=
&& densityDpi != delta.densityDpi) {
changed |= ActivityInfo.CONFIG_DENSITY;
}
-
+ if (delta.customTheme != null &&
+ (customTheme == null || !customTheme.equals(delta.customTheme))) {
+ changed |= ActivityInfo.CONFIG_THEME_RESOURCE;
+ }
return changed;
}
@@ -994,7 +1089,9 @@ && getScreenLayoutNoDirection(screenLayout) !=
* @return Return true if the resource needs to be loaded, else false.
*/
public static boolean needNewResources(int configChanges, int interestingChanges) {
- return (configChanges & (interestingChanges|ActivityInfo.CONFIG_FONT_SCALE)) != 0;
+ return (configChanges & (interestingChanges |
+ ActivityInfo.CONFIG_FONT_SCALE |
+ ActivityInfo.CONFIG_THEME_RESOURCE)) != 0;
}
/**
@@ -1058,6 +1155,7 @@ public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(navigationHidden);
dest.writeInt(orientation);
dest.writeInt(screenLayout);
+ dest.writeInt(uiInvertedMode);
dest.writeInt(uiMode);
dest.writeInt(screenWidthDp);
dest.writeInt(screenHeightDp);
@@ -1067,6 +1165,14 @@ public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(compatScreenHeightDp);
dest.writeInt(compatSmallestScreenWidthDp);
dest.writeInt(seq);
+
+ if (customTheme == null) {
+ dest.writeInt(0);
+ } else {
+ dest.writeInt(1);
+ dest.writeString(customTheme.getThemeId());
+ dest.writeString(customTheme.getThemePackageName());
+ }
}
public void readFromParcel(Parcel source) {
@@ -1086,6 +1192,7 @@ public void readFromParcel(Parcel source) {
navigationHidden = source.readInt();
orientation = source.readInt();
screenLayout = source.readInt();
+ uiInvertedMode = source.readInt();
uiMode = source.readInt();
screenWidthDp = source.readInt();
screenHeightDp = source.readInt();
@@ -1095,6 +1202,12 @@ public void readFromParcel(Parcel source) {
compatScreenHeightDp = source.readInt();
compatSmallestScreenWidthDp = source.readInt();
seq = source.readInt();
+
+ if (source.readInt() != 0) {
+ String themeId = source.readString();
+ String themePackage = source.readString();
+ customTheme = new CustomTheme(themeId, themePackage);
+ }
}
public static final Parcelable.Creator CREATOR
@@ -1153,6 +1266,8 @@ public int compareTo(Configuration that) {
if (n != 0) return n;
n = this.screenLayout - that.screenLayout;
if (n != 0) return n;
+ n = this.uiInvertedMode - that.uiInvertedMode;
+ if (n != 0) return n;
n = this.uiMode - that.uiMode;
if (n != 0) return n;
n = this.screenWidthDp - that.screenWidthDp;
@@ -1163,6 +1278,17 @@ public int compareTo(Configuration that) {
if (n != 0) return n;
n = this.densityDpi - that.densityDpi;
//if (n != 0) return n;
+ if (this.customTheme == null) {
+ if (that.customTheme != null) return 1;
+ } else if (that.customTheme == null) {
+ return -1;
+ } else {
+ n = this.customTheme.getThemeId().compareTo(that.customTheme.getThemeId());
+ if (n != 0) return n;
+ n = this.customTheme.getThemePackageName().compareTo(that.customTheme.getThemePackageName());
+ if (n != 0) return n;
+ }
+
return n;
}
@@ -1194,11 +1320,14 @@ public int hashCode() {
result = 31 * result + navigationHidden;
result = 31 * result + orientation;
result = 31 * result + screenLayout;
+ result = 31 * result + uiInvertedMode;
result = 31 * result + uiMode;
result = 31 * result + screenWidthDp;
result = 31 * result + screenHeightDp;
result = 31 * result + smallestScreenWidthDp;
result = 31 * result + densityDpi;
+ result = 31 * result + (this.customTheme != null ?
+ this.customTheme.hashCode() : 0);
return result;
}
diff --git a/core/java/android/content/res/CustomTheme.java b/core/java/android/content/res/CustomTheme.java
new file mode 100644
index 00000000000..364fb11e77d
--- /dev/null
+++ b/core/java/android/content/res/CustomTheme.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2010, T-Mobile USA, Inc.
+ *
+ * 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.content.res;
+
+import android.os.SystemProperties;
+import android.text.TextUtils;
+
+/**
+ * @hide
+ */
+public final class CustomTheme implements Cloneable {
+ private final String mThemeId;
+ private final String mThemePackageName;
+
+ private static final CustomTheme sBootTheme = new CustomTheme();
+ private static final CustomTheme sSystemTheme = new CustomTheme("", "");
+
+ private CustomTheme() {
+ mThemeId = SystemProperties.get("persist.sys.themeId");
+ mThemePackageName = SystemProperties.get("persist.sys.themePackageName");
+ }
+
+ public CustomTheme(String themeId, String packageName) {
+ mThemeId = themeId;
+ mThemePackageName = packageName;
+ }
+
+ @Override
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (object == this) {
+ return true;
+ }
+ if (object instanceof CustomTheme) {
+ CustomTheme o = (CustomTheme) object;
+ if (!mThemeId.equals(o.mThemeId)) {
+ return false;
+ }
+ String currentPackageName = (mThemePackageName == null)? "" : mThemePackageName;
+ String newPackageName = (o.mThemePackageName == null)? "" : o.mThemePackageName;
+ String currentThemeId = (mThemeId == null)? "" : mThemeId;
+ String newThemeId = (o.mThemeId == null)? "" : o.mThemeId;
+
+ /* uhh, why are we trimming here instead of when the object is
+ * constructed? actually, why are we trimming at all? */
+ return (currentPackageName.trim().equalsIgnoreCase(newPackageName.trim())) &&
+ (currentThemeId.trim().equalsIgnoreCase(newThemeId.trim()));
+ }
+ return false;
+ }
+
+ @Override
+ public final String toString() {
+ StringBuilder result = new StringBuilder();
+ if (!TextUtils.isEmpty(mThemePackageName) && !TextUtils.isEmpty(mThemeId)) {
+ result.append(mThemePackageName);
+ result.append('(');
+ result.append(mThemeId);
+ result.append(')');
+ } else {
+ result.append("system");
+ }
+ return result.toString();
+ }
+
+ @Override
+ public synchronized int hashCode() {
+ return mThemeId.hashCode() + mThemePackageName.hashCode();
+ }
+
+ public String getThemeId() {
+ return mThemeId;
+ }
+
+ public String getThemePackageName() {
+ return mThemePackageName;
+ }
+
+ /**
+ * Represents the theme that the device booted into. This is used to
+ * simulate a "default" configuration based on the user's last known
+ * preference until the theme is switched at runtime.
+ */
+ public static CustomTheme getBootTheme() {
+ return sBootTheme;
+ }
+
+ /**
+ * Represents the system framework theme, perceived by the system as there
+ * being no theme applied.
+ */
+ public static CustomTheme getSystemTheme() {
+ return sSystemTheme;
+ }
+}
diff --git a/core/java/android/content/res/ObbInfo.aidl b/core/java/android/content/res/ObbInfo.aidl
old mode 100755
new mode 100644
diff --git a/core/java/android/content/res/PackageRedirectionMap.aidl b/core/java/android/content/res/PackageRedirectionMap.aidl
new file mode 100644
index 00000000000..4f475255486
--- /dev/null
+++ b/core/java/android/content/res/PackageRedirectionMap.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2011, T-Mobile USA, Inc.
+ *
+ * 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.content.res;
+
+/**
+ * @hide
+ */
+parcelable PackageRedirectionMap;
diff --git a/core/java/android/content/res/PackageRedirectionMap.java b/core/java/android/content/res/PackageRedirectionMap.java
new file mode 100644
index 00000000000..55c4282e2dc
--- /dev/null
+++ b/core/java/android/content/res/PackageRedirectionMap.java
@@ -0,0 +1,90 @@
+package android.content.res;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Native transport for package asset redirection information coming from the
+ * AssetRedirectionManagerService.
+ *
+ * @hide
+ */
+public class PackageRedirectionMap implements Parcelable {
+ private final int mNativePointer;
+
+ public static final Parcelable.Creator CREATOR
+ = new Parcelable.Creator() {
+ public PackageRedirectionMap createFromParcel(Parcel in) {
+ return new PackageRedirectionMap(in);
+ }
+
+ public PackageRedirectionMap[] newArray(int size) {
+ return new PackageRedirectionMap[size];
+ }
+ };
+
+ public PackageRedirectionMap() {
+ this(nativeConstructor());
+ }
+
+ private PackageRedirectionMap(Parcel in) {
+ this(nativeCreateFromParcel(in));
+ }
+
+ private PackageRedirectionMap(int nativePointer) {
+ if (nativePointer == 0) {
+ throw new RuntimeException();
+ }
+ mNativePointer = nativePointer;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ nativeDestructor(mNativePointer);
+ }
+
+ public int getNativePointer() {
+ return mNativePointer;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ if (!nativeWriteToParcel(mNativePointer, dest)) {
+ throw new RuntimeException();
+ }
+ }
+
+ public int getPackageId() {
+ return nativeGetPackageId(mNativePointer);
+ }
+
+ public void addRedirection(int fromIdent, int toIdent) {
+ nativeAddRedirection(mNativePointer, fromIdent, toIdent);
+ }
+
+ // Used for debugging purposes only.
+ public int[] getRedirectionKeys() {
+ return nativeGetRedirectionKeys(mNativePointer);
+ }
+
+ // Used for debugging purposes only.
+ public int lookupRedirection(int fromIdent) {
+ return nativeLookupRedirection(mNativePointer, fromIdent);
+ }
+
+ private static native int nativeConstructor();
+ private static native void nativeDestructor(int nativePointer);
+
+ private static native int nativeCreateFromParcel(Parcel p);
+ private static native boolean nativeWriteToParcel(int nativePointer, Parcel p);
+
+ private native void nativeAddRedirection(int nativePointer, int fromIdent, int toIdent);
+ private native int nativeGetPackageId(int nativePointer);
+ private native int[] nativeGetRedirectionKeys(int nativePointer);
+ private native int nativeLookupRedirection(int nativePointer, int fromIdent);
+}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
old mode 100755
new mode 100644
index b316f230a94..137644535a9
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1447,7 +1447,15 @@ public void updateConfiguration(Configuration config,
mTmpConfig.setLayoutDirection(mTmpConfig.locale);
}
configChanges = mConfiguration.updateFrom(mTmpConfig);
- configChanges = ActivityInfo.activityInfoConfigToNative(configChanges);
+
+ /* This is ugly, but modifying the activityInfoConfigToNative
+ * adapter would be messier */
+ if ((configChanges & ActivityInfo.CONFIG_THEME_RESOURCE) != 0) {
+ configChanges = ActivityInfo.activityInfoConfigToNative(configChanges);
+ configChanges |= ActivityInfo.CONFIG_THEME_RESOURCE;
+ } else {
+ configChanges = ActivityInfo.activityInfoConfigToNative(configChanges);
+ }
}
if (mConfiguration.locale == null) {
mConfiguration.locale = Locale.getDefault();
@@ -1489,7 +1497,8 @@ public void updateConfiguration(Configuration config,
keyboardHidden, mConfiguration.navigation, width, height,
mConfiguration.smallestScreenWidthDp,
mConfiguration.screenWidthDp, mConfiguration.screenHeightDp,
- mConfiguration.screenLayout, mConfiguration.uiMode,
+ mConfiguration.screenLayout,
+ mConfiguration.uiInvertedMode, mConfiguration.uiMode,
Build.VERSION.RESOURCES_SDK_INT);
if (DEBUG_CONFIG) {
@@ -1514,6 +1523,18 @@ public void updateConfiguration(Configuration config,
private void clearDrawableCache(
LongSparseArray> cache,
int configChanges) {
+ /*
+ * Quick test to find out if the config change that occurred should
+ * trigger a full cache wipe.
+ */
+ if (Configuration.needNewResources(configChanges, 0)) {
+ if (DEBUG_CONFIG) {
+ Log.d(TAG, "Clear drawable cache from config changes: 0x"
+ + Integer.toHexString(configChanges));
+ }
+ cache.clear();
+ return;
+ }
int N = cache.size();
if (DEBUG_CONFIG) {
Log.d(TAG, "Cleaning up drawables config changes: 0x"
@@ -1886,6 +1907,13 @@ private boolean verifyPreloadConfig(TypedValue value, String name) {
return true;
}
+ /** @hide */
+ public final void updateStringCache() {
+ synchronized (mTmpValue) {
+ mAssets.recreateStringBlocks();
+ }
+ }
+
/*package*/ Drawable loadDrawable(TypedValue value, int id)
throws NotFoundException {
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index 1fc12263e4e..e2d97245197 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -791,6 +791,18 @@ public static long queryNumEntries(SQLiteDatabase db, String table, String selec
selectionArgs);
}
+ /**
+ * Query the table to check whether a table is empty or not
+ * @param db the database the table is in
+ * @param table the name of the table to query
+ * @return True if the table is empty
+ * @hide
+ */
+ public static boolean queryIsEmpty(SQLiteDatabase db, String table) {
+ long isEmpty = longForQuery(db, "select exists(select 1 from " + table + ")", null);
+ return isEmpty == 0;
+ }
+
/**
* Utility method to run the query on the db and return the value in the
* first column of the first row.
diff --git a/core/java/android/database/IContentObserver.aidl b/core/java/android/database/IContentObserver.aidl
old mode 100755
new mode 100644
diff --git a/core/java/android/database/MemoryCursor.java b/core/java/android/database/MemoryCursor.java
new file mode 100644
index 00000000000..e22281977a2
--- /dev/null
+++ b/core/java/android/database/MemoryCursor.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package android.database;
+
+import android.database.AbstractWindowedCursor;
+import android.database.Cursor;
+import android.database.CursorWindow;
+import android.database.DatabaseUtils;
+
+/**
+ * Implementation of an in-memory cursor backed by a cursor window.
+ *
+ * @hide
+ */
+public class MemoryCursor extends AbstractWindowedCursor {
+ private CursorWindow mDeactivatedWindow;
+ private final String[] mColumnNames;
+
+ public MemoryCursor(String name, String[] columnNames) {
+ setWindow(new CursorWindow(name));
+ mColumnNames = columnNames;
+ }
+
+ public void fillFromCursor(Cursor cursor) {
+ DatabaseUtils.cursorFillWindow(cursor, 0, getWindow());
+ }
+
+ @Override
+ public int getCount() {
+ return getWindow().getNumRows();
+ }
+
+ @Override
+ public String[] getColumnNames() {
+ return mColumnNames;
+ }
+
+ @Override
+ public boolean requery() {
+ if (mDeactivatedWindow != null) {
+ setWindow(mDeactivatedWindow);
+ mDeactivatedWindow = null;
+ }
+ return super.requery();
+ }
+
+ @Override
+ protected void onDeactivateOrClose() {
+ // when deactivating the cursor, we need to keep our in-memory cursor
+ // window as we have no chance of requerying it later on
+ if (!isClosed() && getWindow() != null) {
+ mDeactivatedWindow = getWindow();
+ mWindow = null;
+ }
+ super.onDeactivateOrClose();
+ if (isClosed() && mDeactivatedWindow != null) {
+ mDeactivatedWindow.close();
+ mDeactivatedWindow = null;
+ }
+ }
+}
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index 6f7c1f38594..747f16233cb 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -30,9 +30,9 @@
import android.util.LruCache;
import android.util.Printer;
-import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Date;
import java.util.Map;
import java.util.regex.Pattern;
@@ -216,6 +216,13 @@ private void open() {
setJournalSizeLimit();
setAutoCheckpointInterval();
setLocaleFromConfiguration();
+
+ // Register custom functions.
+ final int functionCount = mConfiguration.customFunctions.size();
+ for (int i = 0; i < functionCount; i++) {
+ SQLiteCustomFunction function = mConfiguration.customFunctions.get(i);
+ nativeRegisterCustomFunction(mConnectionPtr, function);
+ }
}
private void dispose(boolean finalized) {
@@ -974,7 +981,7 @@ private void bindArguments(PreparedStatement statement, Object[] bindArgs) {
if (count != statement.mNumParameters) {
throw new SQLiteBindOrColumnIndexOutOfRangeException(
"Expected " + statement.mNumParameters + " bind arguments but "
- + bindArgs.length + " were provided.");
+ + count + " were provided.");
}
if (count == 0) {
return;
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index e2d44f2ab37..60ccc6180eb 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -1481,6 +1481,9 @@ public long insertWithOnConflict(String table, String nullColumnHack,
* @param table the table to delete from
* @param whereClause the optional WHERE clause to apply when deleting.
* Passing null will delete all rows.
+ * @param whereArgs You may include ?s in the where clause, which
+ * will be replaced by the values from whereArgs. The values
+ * will be bound as Strings.
* @return the number of rows affected if a whereClause is passed in, 0
* otherwise. To remove all rows and get a count pass "1" as the
* whereClause.
@@ -1508,6 +1511,9 @@ public int delete(String table, String whereClause, String[] whereArgs) {
* valid value that will be translated to NULL.
* @param whereClause the optional WHERE clause to apply when updating.
* Passing null will update all rows.
+ * @param whereArgs You may include ?s in the where clause, which
+ * will be replaced by the values from whereArgs. The values
+ * will be bound as Strings.
* @return the number of rows affected
*/
public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
@@ -1522,6 +1528,9 @@ public int update(String table, ContentValues values, String whereClause, String
* valid value that will be translated to NULL.
* @param whereClause the optional WHERE clause to apply when updating.
* Passing null will update all rows.
+ * @param whereArgs You may include ?s in the where clause, which
+ * will be replaced by the values from whereArgs. The values
+ * will be bound as Strings.
* @param conflictAlgorithm for update conflict resolver
* @return the number of rows affected
*/
diff --git a/core/java/android/database/sqlite/SQLiteSession.java b/core/java/android/database/sqlite/SQLiteSession.java
index beb5b3a31cf..d80ab1f2e86 100644
--- a/core/java/android/database/sqlite/SQLiteSession.java
+++ b/core/java/android/database/sqlite/SQLiteSession.java
@@ -926,7 +926,7 @@ private void throwIfTransactionMarkedSuccessful() {
}
private void throwIfNestedTransaction() {
- if (mTransactionStack == null && mTransactionStack.mParent != null) {
+ if (hasNestedTransaction()) {
throw new IllegalStateException("Cannot perform this operation because "
+ "a nested transaction is in progress.");
}
diff --git a/core/java/android/ddm/package.html b/core/java/android/ddm/package.html
old mode 100755
new mode 100644
diff --git a/core/java/android/debug/package.html b/core/java/android/debug/package.html
old mode 100755
new mode 100644
diff --git a/core/java/android/gesture/Gesture.aidl b/core/java/android/gesture/Gesture.aidl
new file mode 100644
index 00000000000..cd0f295bae0
--- /dev/null
+++ b/core/java/android/gesture/Gesture.aidl
@@ -0,0 +1,3 @@
+package android.gesture;
+
+parcelable Gesture;
\ No newline at end of file
diff --git a/core/java/android/gesture/Gesture.java b/core/java/android/gesture/Gesture.java
old mode 100755
new mode 100644
diff --git a/core/java/android/gesture/GestureOverlayView.java b/core/java/android/gesture/GestureOverlayView.java
old mode 100755
new mode 100644
index b6c260fd3e0..fab8ca3dbd7
--- a/core/java/android/gesture/GestureOverlayView.java
+++ b/core/java/android/gesture/GestureOverlayView.java
@@ -87,6 +87,8 @@ public class GestureOverlayView extends FrameLayout {
private final Rect mInvalidRect = new Rect();
private final Path mPath = new Path();
private boolean mGestureVisible = true;
+ protected boolean mClearPerformedGesture = true;
+ protected boolean mInputEnabled = true;
private float mX;
private float mY;
@@ -201,6 +203,7 @@ public void setOrientation(int orientation) {
public void setGestureColor(int color) {
mCertainGestureColor = color;
+ setCurrentColor(color);
}
public void setUncertainGestureColor(int color) {
@@ -491,7 +494,7 @@ protected void onDetachedFromWindow() {
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
- if (isEnabled()) {
+ if (isEnabled() && mInputEnabled) {
final boolean cancelDispatch = (mIsGesturing || (mCurrentGesture != null &&
mCurrentGesture.getStrokesCount() > 0 && mPreviousWasGesturing)) &&
mInterceptEvents;
@@ -567,7 +570,7 @@ private void touchDown(MotionEvent event) {
// if there is fading out going on, stop it.
if (mFadingHasStarted) {
cancelClearAnimation();
- } else if (mIsFadingOut) {
+ } else if (mIsFadingOut || !mClearPerformedGesture) {
setPaintAlpha(255);
mIsFadingOut = false;
mFadingHasStarted = false;
@@ -689,8 +692,13 @@ private void touchUp(MotionEvent event, boolean cancel) {
listeners.get(i).onGestureEnded(this, event);
}
- clear(mHandleGestureActions && mFadeEnabled, mHandleGestureActions && mIsGesturing,
- false);
+ if (mClearPerformedGesture)
+ clear(mHandleGestureActions && mFadeEnabled, mHandleGestureActions && mIsGesturing,
+ false);
+ else if (mHandleGestureActions && mIsGesturing) {
+ mIsFadingOut = false;
+ postDelayed(mFadingOut, mFadeOffset);
+ }
} else {
cancelGesture(event);
@@ -763,9 +771,12 @@ public void run() {
fireOnGesturePerformed();
mFadingHasStarted = false;
- mPath.rewind();
- mCurrentGesture = null;
- mPreviousWasGesturing = false;
+ if (mClearPerformedGesture) {
+ mPath.rewind();
+ mCurrentGesture = null;
+ mPreviousWasGesturing = false;
+ } else
+ mResetGesture = true;
setPaintAlpha(255);
}
diff --git a/core/java/android/gesture/GestureUtils.java b/core/java/android/gesture/GestureUtils.java
old mode 100755
new mode 100644
diff --git a/core/java/android/gesture/Instance.java b/core/java/android/gesture/Instance.java
old mode 100755
new mode 100644
diff --git a/core/java/android/gesture/Learner.java b/core/java/android/gesture/Learner.java
old mode 100755
new mode 100644
diff --git a/core/java/android/gesture/Prediction.java b/core/java/android/gesture/Prediction.java
old mode 100755
new mode 100644
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index a30077641f2..cb07a643606 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -996,6 +996,12 @@ public void setAutoFocusMoveCallback(AutoFocusMoveCallback cb) {
private native void enableFocusMoveCallback(int enable);
+ /**
+ * Send a raw command to the camera driver
+ * @hide
+ */
+ public native void sendRawCommand(int arg1, int arg2, int arg3);
+
/**
* Callback interface used to signal the moment of actual image capture.
*
@@ -1487,6 +1493,7 @@ public final void setErrorCallback(ErrorCallback cb)
* @see #getParameters()
*/
public void setParameters(Parameters params) {
+ Log.v(TAG, "setParameters:"+params.flatten());
native_setParameters(params.flatten());
}
@@ -1685,6 +1692,7 @@ public class Parameters {
private static final String KEY_SCENE_MODE = "scene-mode";
private static final String KEY_FLASH_MODE = "flash-mode";
private static final String KEY_FOCUS_MODE = "focus-mode";
+ private static final String KEY_ISO_MODE = "iso";
private static final String KEY_FOCUS_AREAS = "focus-areas";
private static final String KEY_MAX_NUM_FOCUS_AREAS = "max-num-focus-areas";
private static final String KEY_FOCAL_LENGTH = "focal-length";
@@ -1715,6 +1723,9 @@ public class Parameters {
private static final String KEY_VIDEO_SNAPSHOT_SUPPORTED = "video-snapshot-supported";
private static final String KEY_VIDEO_STABILIZATION = "video-stabilization";
private static final String KEY_VIDEO_STABILIZATION_SUPPORTED = "video-stabilization-supported";
+ private static final String KEY_POWER_MODE_SUPPORTED = "power-mode-supported";
+
+ private static final String KEY_POWER_MODE = "power-mode";
// Parameter key suffix for supported values.
private static final String SUPPORTED_VALUES_SUFFIX = "-values";
@@ -1749,6 +1760,10 @@ public class Parameters {
public static final String ANTIBANDING_60HZ = "60hz";
public static final String ANTIBANDING_OFF = "off";
+ // Values for POWER MODE
+ public static final String LOW_POWER = "Low_Power";
+ public static final String NORMAL_POWER = "Normal_Power";
+
// Values for flash mode settings.
/**
* Flash will not be fired.
@@ -1778,6 +1793,32 @@ public class Parameters {
*/
public static final String FLASH_MODE_TORCH = "torch";
+ //Values for ISO settings
+ /** @hide */
+ public static final String ISO_AUTO = "auto";
+ /** @hide */
+ public static final String ISO_HJR = "ISO_HJR";
+ /** @hide */
+ public static final String ISO_SPORTS = "ISO_SPORTS";
+ /** @hide */
+ public static final String ISO_NIGHT = "ISO_NIGHT";
+ /** @hide */
+ public static final String ISO_MOVIE = "ISO_MOVIE";
+ /** @hide */
+ public static final String ISO_100 = "ISO100";
+ /** @hide */
+ public static final String ISO_200 = "ISO200";
+ /** @hide */
+ public static final String ISO_400 = "ISO400";
+ /** @hide */
+ public static final String ISO_800 = "ISO800";
+ /** @hide */
+ public static final String ISO_1600 = "ISO1600";
+ /** @hide */
+ public static final String ISO_3200 = "ISO3200";
+ /** @hide */
+ public static final String ISO_6400 = "ISO6400";
+
/**
* Scene mode is off.
*/
@@ -2891,6 +2932,7 @@ public String getSceneMode() {
* @see #getSceneMode()
*/
public void setSceneMode(String value) {
+ if(getSupportedSceneModes() == null) return;
set(KEY_SCENE_MODE, value);
}
@@ -2928,6 +2970,7 @@ public String getFlashMode() {
* @see #getFlashMode()
*/
public void setFlashMode(String value) {
+ if(getSupportedFlashModes() == null) return;
set(KEY_FLASH_MODE, value);
}
@@ -2943,6 +2986,28 @@ public List getSupportedFlashModes() {
return split(str);
}
+ /**
+ * Sets the Power mode.
+ *
+ * @param value Power mode.
+ * @see #getPowerMode()
+ */
+ public void setPowerMode(String value) {
+ set(KEY_POWER_MODE, value);
+ }
+
+ /**
+ * Gets the current power mode setting.
+ *
+ * @return current power mode. null if power mode setting is not
+ * supported.
+ * @see #POWER_MODE_LOW
+ * @see #POWER_MODE_NORMAL
+ */
+ public String getPowerMode() {
+ return get(KEY_POWER_MODE);
+ }
+
/**
* Gets the current focus mode setting.
*
@@ -3287,6 +3352,39 @@ public boolean isSmoothZoomSupported() {
return TRUE.equals(str);
}
+ /**
+ * Gets the current ISO setting.
+ *
+ * @return one of ISO_XXX string constant. null if ISO
+ * setting is not supported.
+ * @hide
+ */
+ public String getISOValue() {
+ return get(KEY_ISO_MODE);
+ }
+
+ /**
+ * Sets the ISO.
+ *
+ * @param iso ISO_XXX string constant.
+ * @hide
+ */
+ public void setISOValue(String iso) {
+ set(KEY_ISO_MODE, iso);
+ }
+
+ /**
+ * Gets the supported ISO values.
+ *
+ * @return a List of ISO_MODE_XXX string constants. null if iso mode
+ * setting is not supported.
+ * @hide
+ */
+ public List getSupportedIsoValues() {
+ String str = get(KEY_ISO_MODE + SUPPORTED_VALUES_SUFFIX);
+ return split(str);
+ }
+
/**
* Gets the distances from the camera to where an object appears to be
* in focus. The object is sharpest at the optimal focus distance. The
@@ -3526,6 +3624,14 @@ public boolean isVideoSnapshotSupported() {
return TRUE.equals(str);
}
+ /**
+ * @return true if full size video snapshot is supported.
+ */
+ public boolean isPowerModeSupported() {
+ String str = get(KEY_POWER_MODE_SUPPORTED);
+ return TRUE.equals(str);
+ }
+
/**
*
Enables and disables video stabilization. Use
* {@link #isVideoStabilizationSupported} to determine if calling this
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 0204e94df6b..fe360a50e06 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -24,6 +24,8 @@
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
+import android.os.SystemProperties;
+import android.util.FloatMath;
import java.util.ArrayList;
import java.util.List;
@@ -36,6 +38,10 @@
*/
public class SystemSensorManager extends SensorManager {
private static final int SENSOR_DISABLE = -1;
+ private static final long SENSOR_LOOPMINMS = SystemProperties.getLong( "sensor.loop.minms", 0); // minimal duration of a sensor loop => sleep to prevent notification storm if faster than that.
+ private static final float MAGNITUDE_THRESHOLD = ((float)SystemProperties.getLong( "sensor.magnitude.threshold", 0))/1000.0f;
+
+
private static boolean sSensorModuleInitialized = false;
private static ArrayList sFullSensorsList = new ArrayList();
/* The thread and the sensor list are global to the process
@@ -120,6 +126,8 @@ public void run() {
while (true) {
// wait for an event
final int sensor = sensors_data_poll(sQueue, values, status, timestamp);
+ long lastLoopMS = System.currentTimeMillis();
+ long timeToSleep = SENSOR_LOOPMINMS;
int accuracy = status[0];
synchronized (sListeners) {
@@ -137,21 +145,31 @@ public void run() {
break;
}
final Sensor sensorObject = sHandleToSensor.get(sensor);
+
if (sensorObject != null) {
- // report the sensor event to all listeners that
- // care about it.
- final int size = sListeners.size();
- for (int i=0 ; i MAGNITUDE_THRESHOLD) {
+ // report the sensor event to all listeners that
+ // care about it.
+ final int size = sListeners.size();
+ for (int i=0 ; i0) Thread.sleep(timeToSleep);}
+ catch(InterruptedException e) {;}
+
}
//Log.d(TAG, "exiting main sensor thread");
}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
old mode 100755
new mode 100644
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index 5275314b036..c101cc7f745 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -31,6 +31,7 @@
import android.os.Message;
import android.os.RemoteException;
import android.os.ResultReceiver;
+import android.provider.Settings;
import android.util.Log;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputBinding;
@@ -67,7 +68,8 @@ class IInputMethodWrapper extends IInputMethod.Stub
private static final int DO_SHOW_SOFT_INPUT = 60;
private static final int DO_HIDE_SOFT_INPUT = 70;
private static final int DO_CHANGE_INPUTMETHOD_SUBTYPE = 80;
-
+
+ private static Context mContext;
final WeakReference mTarget;
final HandlerCaller mCaller;
final WeakReference mInputMethod;
@@ -79,7 +81,6 @@ static class Notifier {
// NOTE: we should have a cache of these.
static class InputMethodSessionCallbackWrapper implements InputMethod.SessionCallback {
- final Context mContext;
final IInputMethodCallback mCb;
InputMethodSessionCallbackWrapper(Context context, IInputMethodCallback cb) {
mContext = context;
@@ -105,6 +106,7 @@ public IInputMethodWrapper(AbstractInputMethodService context,
mCaller = new HandlerCaller(context.getApplicationContext(), this);
mInputMethod = new WeakReference(inputMethod);
mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
+ mContext = context;
}
public InputMethod getInternalInputMethod() {
@@ -119,6 +121,9 @@ public void executeMessage(Message msg) {
return;
}
+ boolean formalText = Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.FORMAL_TEXT_INPUT, 0) == 1;
+
switch (msg.what) {
case DO_DUMP: {
AbstractInputMethodService target = mTarget.get();
@@ -157,6 +162,7 @@ public void executeMessage(Message msg) {
? new InputConnectionWrapper(inputContext) : null;
EditorInfo info = (EditorInfo)args.arg2;
info.makeCompatible(mTargetSdkVersion);
+ info.formalTextInput(formalText);
inputMethod.startInput(ic, info);
args.recycle();
return;
@@ -168,6 +174,7 @@ public void executeMessage(Message msg) {
? new InputConnectionWrapper(inputContext) : null;
EditorInfo info = (EditorInfo)args.arg2;
info.makeCompatible(mTargetSdkVersion);
+ info.formalTextInput(formalText);
inputMethod.restartInput(ic, info);
args.recycle();
return;
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 6f1cc942c96..4fd37bb531d 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -28,6 +28,7 @@
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
import android.os.ResultReceiver;
import android.os.SystemClock;
@@ -248,6 +249,20 @@ public class InputMethodService extends AbstractInputMethodService {
*/
public static final int IME_VISIBLE = 0x2;
+ int mVolumeKeyCursorControl = 0;
+ /**
+ * @hide
+ */
+ public static final int VOLUME_CURSOR_OFF = 0;
+ /**
+ * @hide
+ */
+ public static final int VOLUME_CURSOR_ON = 1;
+ /**
+ * @hide
+ */
+ public static final int VOLUME_CURSOR_ON_REVERSE = 2;
+
InputMethodManager mImm;
int mTheme = 0;
@@ -302,6 +317,9 @@ public class InputMethodService extends AbstractInputMethodService {
int mStatusIcon;
int mBackDisposition;
+ boolean mForcedAutoRotate;
+ Handler mHandler;
+
final Insets mTmpInsets = new Insets();
final int[] mTmpLocation = new int[2];
@@ -424,7 +442,7 @@ public void showSoftInput(int flags, ResultReceiver resultReceiver) {
showWindow(true);
}
// If user uses hard keyboard, IME button should always be shown.
- boolean showing = onEvaluateInputViewShown();
+ boolean showing = isInputViewShown();
mImm.setImeWindowStatus(mToken, IME_ACTIVE | (showing ? IME_VISIBLE : 0),
mBackDisposition);
if (resultReceiver != null) {
@@ -706,6 +724,8 @@ void initViews() {
mCandidatesVisibility = getCandidatesHiddenVisibility();
mCandidatesFrame.setVisibility(mCandidatesVisibility);
mInputFrame.setVisibility(View.GONE);
+
+ mHandler = new Handler();
}
@Override public void onDestroy() {
@@ -871,7 +891,14 @@ public EditorInfo getCurrentInputEditorInfo() {
* is currently running in fullscreen mode.
*/
public void updateFullscreenMode() {
- boolean isFullscreen = mShowInputRequested && onEvaluateFullscreenMode();
+ boolean fullScreenOverride = Settings.System.getInt(getContentResolver(),
+ Settings.System.DISABLE_FULLSCREEN_KEYBOARD, 0) != 0;
+ boolean isFullscreen;
+ if (fullScreenOverride) {
+ isFullscreen = false;
+ } else {
+ isFullscreen = mShowInputRequested && onEvaluateFullscreenMode();
+ }
boolean changed = mLastShowInputRequested != mShowInputRequested;
if (mIsFullscreen != isFullscreen || !mFullscreenApplied) {
changed = true;
@@ -1408,6 +1435,20 @@ public void showWindow(boolean showInput) {
mWindowWasVisible = true;
mInShowWindow = false;
}
+ int mKeyboardRotationTimeout = Settings.System.getInt(getContentResolver(),
+ Settings.System.KEYBOARD_ROTATION_TIMEOUT, 0);
+ if (mKeyboardRotationTimeout > 0) {
+ mHandler.removeCallbacks(restoreAutoRotation);
+ if (!mForcedAutoRotate) {
+ boolean isAutoRotate = (Settings.System.getInt(getContentResolver(),
+ Settings.System.ACCELEROMETER_ROTATION, 0) == 1);
+ if (!isAutoRotate) {
+ mForcedAutoRotate = true;
+ Settings.System.putInt(getContentResolver(),
+ Settings.System.ACCELEROMETER_ROTATION, 1);
+ }
+ }
+ }
}
void showWindowInner(boolean showInput) {
@@ -1490,8 +1531,24 @@ public void hideWindow() {
onWindowHidden();
mWindowWasVisible = false;
}
+ int mKeyboardRotationTimeout = Settings.System.getInt(getContentResolver(),
+ Settings.System.KEYBOARD_ROTATION_TIMEOUT, 0);
+ if (mKeyboardRotationTimeout > 0) {
+ mHandler.removeCallbacks(restoreAutoRotation);
+ if (mForcedAutoRotate) {
+ mHandler.postDelayed(restoreAutoRotation, mKeyboardRotationTimeout);
+ }
+ }
}
+ final Runnable restoreAutoRotation = new Runnable() {
+ @Override public void run() {
+ Settings.System.putInt(getContentResolver(),
+ Settings.System.ACCELEROMETER_ROTATION, 0);
+ mForcedAutoRotate = false;
+ }
+ };
+
/**
* Called when the input method window has been shown to the user, after
* previously not being visible. This is done after all of the UI setup
@@ -1760,6 +1817,26 @@ public boolean onKeyDown(int keyCode, KeyEvent event) {
}
return false;
}
+ if (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP) {
+ mVolumeKeyCursorControl = Settings.System.getInt(getContentResolver(),
+ Settings.System.VOLUME_KEY_CURSOR_CONTROL, 0);
+ if (isInputViewShown() && (mVolumeKeyCursorControl != VOLUME_CURSOR_OFF)) {
+ sendDownUpKeyEvents((mVolumeKeyCursorControl == VOLUME_CURSOR_ON_REVERSE)
+ ? KeyEvent.KEYCODE_DPAD_RIGHT : KeyEvent.KEYCODE_DPAD_LEFT);
+ return true;
+ }
+ return false;
+ }
+ if (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN) {
+ mVolumeKeyCursorControl = Settings.System.getInt(getContentResolver(),
+ Settings.System.VOLUME_KEY_CURSOR_CONTROL, 0);
+ if (isInputViewShown() && (mVolumeKeyCursorControl != VOLUME_CURSOR_OFF)) {
+ sendDownUpKeyEvents((mVolumeKeyCursorControl == VOLUME_CURSOR_ON_REVERSE)
+ ? KeyEvent.KEYCODE_DPAD_LEFT : KeyEvent.KEYCODE_DPAD_RIGHT);
+ return true;
+ }
+ return false;
+ }
return doMovementKey(keyCode, event, MOVEMENT_DOWN);
}
@@ -1805,7 +1882,15 @@ public boolean onKeyUp(int keyCode, KeyEvent event) {
&& !event.isCanceled()) {
return handleBack(true);
}
-
+ if (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP
+ || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
+ mVolumeKeyCursorControl = Settings.System.getInt(getContentResolver(),
+ Settings.System.VOLUME_KEY_CURSOR_CONTROL, 0);
+ if (isInputViewShown() && (mVolumeKeyCursorControl != VOLUME_CURSOR_OFF)) {
+ return true;
+ }
+ return false;
+ }
return doMovementKey(keyCode, event, MOVEMENT_UP);
}
diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java
index 3a06dc0c41c..4c0e89a83fc 100644
--- a/core/java/android/net/EthernetDataTracker.java
+++ b/core/java/android/net/EthernetDataTracker.java
@@ -178,6 +178,7 @@ public void run() {
mLinkProperties = dhcpInfoInternal.makeLinkProperties();
mLinkProperties.setInterfaceName(mIface);
+ mNetworkInfo.setIsAvailable(true);
mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr);
Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
msg.sendToTarget();
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index b35d61ca42c..c88e9e66ab8 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -341,6 +341,9 @@ public String getTcpBufferSizesPropName() {
case TelephonyManager.NETWORK_TYPE_HSPAP:
networkTypeStr = "hspap";
break;
+ case TelephonyManager.NETWORK_TYPE_DCHSPAP:
+ networkTypeStr = "hspap";
+ break;
case TelephonyManager.NETWORK_TYPE_CDMA:
networkTypeStr = "cdma";
break;
diff --git a/core/java/android/net/Uri.aidl b/core/java/android/net/Uri.aidl
old mode 100755
new mode 100644
diff --git a/core/java/android/net/http/package.html b/core/java/android/net/http/package.html
old mode 100755
new mode 100644
diff --git a/core/java/android/net/package.html b/core/java/android/net/package.html
old mode 100755
new mode 100644
diff --git a/core/java/android/net/wimax/WimaxHelper.java b/core/java/android/net/wimax/WimaxHelper.java
new file mode 100644
index 00000000000..f6c7a409b5f
--- /dev/null
+++ b/core/java/android/net/wimax/WimaxHelper.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2011 The CyanogenMod 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.wimax;
+
+import dalvik.system.DexClassLoader;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.ServiceManager;
+import android.util.Log;
+import android.provider.Settings;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+/**
+ * {@hide}
+ */
+public class WimaxHelper {
+
+ private static final String TAG = "WimaxHelper";
+
+ private static final String WIMAX_CONTROLLER_CLASSNAME = "com.htc.net.wimax.WimaxController";
+ private static final String WIMAX_MANAGER_CLASSNAME = "android.net.fourG.wimax.Wimax4GManager";
+
+ private static DexClassLoader sWimaxClassLoader;
+ private static String sWimaxManagerClassname, sIsWimaxEnabledMethodname,
+ sSetWimaxEnabledMethodname, sGetWimaxStateMethodname;
+
+ public static boolean isWimaxSupported(Context context) {
+ return context.getResources().getBoolean(
+ com.android.internal.R.bool.config_wimaxEnabled);
+ }
+
+ public static DexClassLoader getWimaxClassLoader(Context context) {
+ if (isWimaxSupported(context)) {
+ if (sWimaxClassLoader == null) {
+ sWimaxManagerClassname = context.getResources().getString(
+ com.android.internal.R.string.config_wimaxManagerClassname);
+
+ // WimaxController::getWimaxState == Wimax4GManager::get4GState.
+ // However, Wimax4GManager also implements a different getWimaxState
+ // method, which returns a WimaxState object describing the connection
+ // state, not the enabled state. Other methods are similarly renamed.
+ if (sWimaxManagerClassname.equals(WIMAX_CONTROLLER_CLASSNAME)) {
+ sIsWimaxEnabledMethodname = "isWimaxEnabled";
+ sSetWimaxEnabledMethodname = "setWimaxEnabled";
+ sGetWimaxStateMethodname = "getWimaxState";
+ } else if (sWimaxManagerClassname.equals(WIMAX_MANAGER_CLASSNAME)) {
+ sIsWimaxEnabledMethodname = "is4GEnabled";
+ sSetWimaxEnabledMethodname = "set4GEnabled";
+ sGetWimaxStateMethodname = "get4GState";
+ }
+
+ String wimaxJarLocation = context.getResources().getString(
+ com.android.internal.R.string.config_wimaxServiceJarLocation);
+ String wimaxLibLocation = context.getResources().getString(
+ com.android.internal.R.string.config_wimaxNativeLibLocation);
+ sWimaxClassLoader = new DexClassLoader(wimaxJarLocation,
+ new ContextWrapper(context).getCacheDir().getAbsolutePath(),
+ wimaxLibLocation,ClassLoader.getSystemClassLoader());
+ }
+ return sWimaxClassLoader;
+ }
+ return null;
+ }
+
+ public static Object createWimaxService(Context context, Handler handler) {
+ Object controller = null;
+
+ try {
+ DexClassLoader wimaxClassLoader = getWimaxClassLoader(context);
+ if (sWimaxManagerClassname.equals(WIMAX_CONTROLLER_CLASSNAME)) {
+ // Load supersonic's and speedy's WimaxController.
+ IBinder b = ServiceManager.getService(WimaxManagerConstants.WIMAX_SERVICE);
+ if (b != null) {
+ Class> klass = wimaxClassLoader.loadClass("com.htc.net.wimax.IWimaxController$Stub");
+ if (klass != null) {
+ Method asInterface = klass.getMethod("asInterface", IBinder.class);
+ Object wc = asInterface.invoke(null, b);
+ if (wc != null) {
+ klass = wimaxClassLoader.loadClass(WIMAX_CONTROLLER_CLASSNAME);
+ if (klass != null) {
+ Constructor> ctor = klass.getDeclaredConstructors()[1];
+ controller = ctor.newInstance(wc, handler);
+ }
+ }
+ }
+ }
+ } else if (sWimaxManagerClassname.equals(WIMAX_MANAGER_CLASSNAME)) {
+ // Load crespo4g's (and epicmtd's) Wimax4GManager.
+ // Note that crespo4g's implementation grabs WIMAX_SERVICE internally, so
+ // it doesn't need to be passed in. Other implementations (may) require
+ // WIMAX_SERVICE to be grabbed externally, so check Wimax4GManager::.
+ Class> klass = wimaxClassLoader.loadClass(WIMAX_MANAGER_CLASSNAME);
+ if (klass != null) {
+ Constructor> ctor = klass.getDeclaredConstructors()[0];
+ controller = ctor.newInstance();
+ }
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to create WimaxController instance", e);
+ }
+
+ return controller;
+ }
+
+ public static boolean isWimaxEnabled(Context context) {
+ boolean ret = false;
+ try {
+ Object wimaxService = context.getSystemService(WimaxManagerConstants.WIMAX_SERVICE);
+ Method m = wimaxService.getClass().getMethod(sIsWimaxEnabledMethodname);
+ ret = (Boolean) m.invoke(wimaxService);
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to get WiMAX enabled state!", e);
+ }
+ return ret;
+ }
+
+ public static boolean setWimaxEnabled(Context context, boolean enabled) {
+ boolean ret = false;
+ try {
+ Object wimaxService = context.getSystemService(WimaxManagerConstants.WIMAX_SERVICE);
+ Method m = wimaxService.getClass().getMethod(sSetWimaxEnabledMethodname, boolean.class);
+ ret = (Boolean) m.invoke(wimaxService, enabled);
+ if (ret)
+ Settings.Secure.putInt(context.getContentResolver(),
+ Settings.Secure.WIMAX_ON, (Boolean) enabled ? 1 : 0);
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to set WiMAX state!", e);
+ }
+ return ret;
+ }
+
+ public static int getWimaxState(Context context) {
+ int ret = 0;
+ try {
+ Object wimaxService = context.getSystemService(WimaxManagerConstants.WIMAX_SERVICE);
+ Method m = wimaxService.getClass().getMethod(sGetWimaxStateMethodname);
+ ret = (Integer) m.invoke(wimaxService);
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to get WiMAX state!", e);
+ }
+ return ret;
+ }
+
+ public static boolean wimaxRescan(Context context) {
+ boolean ret = false;
+ try {
+ Object wimaxService = context.getSystemService(WimaxManagerConstants.WIMAX_SERVICE);
+ Method wimaxRescan = wimaxService.getClass().getMethod("wimaxRescan");
+ if (wimaxRescan != null) {
+ wimaxRescan.invoke(wimaxService);
+ ret = true;
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to perform WiMAX rescan!", e);
+ }
+ return ret;
+ }
+
+ private static Object getWimaxInfo(Context context) {
+ Object wimaxInfo = null;
+ try {
+ Object wimaxService = context.getSystemService(WimaxManagerConstants.WIMAX_SERVICE);
+ Method getConnectionInfo = wimaxService.getClass().getMethod("getConnectionInfo");
+ wimaxInfo = getConnectionInfo.invoke(wimaxService);
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to get a WimaxInfo object!", e);
+ }
+ return wimaxInfo;
+ }
+}
diff --git a/core/java/android/net/wimax/WimaxManagerConstants.java b/core/java/android/net/wimax/WimaxManagerConstants.java
index b4aaf5bffe0..adb7166d292 100644
--- a/core/java/android/net/wimax/WimaxManagerConstants.java
+++ b/core/java/android/net/wimax/WimaxManagerConstants.java
@@ -24,7 +24,7 @@ public class WimaxManagerConstants
* The lookup key for an int that indicates whether Wimax is enabled,
* disabled, enabling, disabling, or unknown.
*/
- public static final String EXTRA_WIMAX_STATUS = "wimax_status";
+ public static final String EXTRA_4G_STATE = "4g_state";
/**
* Broadcast intent action indicating that Wimax state has been changed
@@ -48,7 +48,6 @@ public class WimaxManagerConstants
* initializing, initialized, unknown and ready.
*/
public static final String EXTRA_WIMAX_STATE = "WimaxState";
- public static final String EXTRA_4G_STATE = "4g_state";
public static final String EXTRA_WIMAX_STATE_INT = "WimaxStateInt";
/**
* The lookup key for an int that indicates whether state of Wimax
@@ -66,11 +65,21 @@ public class WimaxManagerConstants
*/
public static final int NET_4G_STATE_DISABLED = 1;
+ /**
+ * Indicatates Wimax is disabling.
+ */
+ public static final int NET_4G_STATE_DISABLING = 0;
+
/**
* Indicatates Wimax is enabled.
*/
public static final int NET_4G_STATE_ENABLED = 3;
+ /**
+ * Indicatates Wimax is enabling.
+ */
+ public static final int NET_4G_STATE_ENABLING = 2;
+
/**
* Indicatates Wimax status is known.
*/
@@ -101,4 +110,9 @@ public class WimaxManagerConstants
*/
public static final int WIMAX_STATE_DISCONNECTED = 9;
+ /**
+ * Constants for HTC/SQN WiMAX implementation
+ */
+ public static final String WIMAX_ENABLED_CHANGED_ACTION = "com.htc.net.wimax.WIMAX_ENABLED_CHANGED";
+ public static final String CURRENT_WIMAX_ENABLED_STATE = "curWimaxEnabledState";
}
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
old mode 100644
new mode 100755
index f2cd232e2e4..d73951d5ddd
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -27,6 +27,8 @@
import android.nfc.tech.NfcBarcode;
import android.nfc.tech.NfcF;
import android.nfc.tech.NfcV;
+import android.nfc.tech.IsoPcdA;
+import android.nfc.tech.IsoPcdB;
import android.nfc.tech.TagTechnology;
import android.os.Bundle;
import android.os.Parcel;
@@ -188,6 +190,12 @@ private String[] generateTechStringList(int[] techList) {
case TagTechnology.NFC_BARCODE:
strings[i] = NfcBarcode.class.getName();
break;
+ case TagTechnology.ISO_PCD_A:
+ strings[i] = IsoPcdA.class.getName();
+ break;
+ case TagTechnology.ISO_PCD_B:
+ strings[i] = IsoPcdB.class.getName();
+ break;
default:
throw new IllegalArgumentException("Unknown tech type " + techList[i]);
}
diff --git a/core/java/android/nfc/tech/BasicTagTechnology.java b/core/java/android/nfc/tech/BasicTagTechnology.java
old mode 100644
new mode 100755
diff --git a/core/java/android/nfc/tech/IsoPcdA.java b/core/java/android/nfc/tech/IsoPcdA.java
new file mode 100755
index 00000000000..0795fc64d4b
--- /dev/null
+++ b/core/java/android/nfc/tech/IsoPcdA.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * HOST CARD EMULATION PATCH 0.01
+ * Author: doug yeager (doug@simplytapp.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc.tech;
+
+import android.nfc.ErrorCodes;
+import android.nfc.Tag;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.io.IOException;
+
+/**
+ * Provides access to ISO-PCD type A (ISO 14443-4) properties and I/O operations on a {@link Tag}.
+ *
+ * Acquire an {@link IsoPcdA} object using {@link #get}.
+ *
The primary ISO-PCD type A I/O operation is {@link #transceive}. Applications must
+ * implement their own protocol stack on top of {@link #transceive}.
+ *
+ *
Note: Methods that perform I/O operations
+ * require the {@link android.Manifest.permission#NFC} permission.
+ * @hide
+ */
+public final class IsoPcdA extends BasicTagTechnology {
+
+ /**
+ * Get an instance of {@link IsoPcdA} for the given tag.
+ *
Does not cause any RF activity and does not block.
+ *
Returns null if {@link IsoPcdA} was not enumerated in {@link Tag#getTechList}.
+ * This indicates the tag does not support ISO-PCD type A.
+ *
+ * @param tag an ISO-PCD type A compatible PCD
+ * @return ISO-PCD type A object
+ */
+ public static IsoPcdA get(Tag tag) {
+ if (!tag.hasTech(TagTechnology.ISO_PCD_A)) return null;
+ try {
+ return new IsoPcdA(tag);
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /** @hide */
+ public IsoPcdA(Tag tag)
+ throws RemoteException {
+ super(tag, TagTechnology.ISO_PCD_A);
+ Bundle extras = tag.getTechExtras(TagTechnology.ISO_PCD_A);
+ }
+
+ /**
+ * Send raw ISO-PCD type A data to the PCD and receive the response.
+ *
+ *
Applications must only send the INF payload, and not the start of frame and
+ * end of frame indicators. Applications do not need to fragment the payload, it
+ * will be automatically fragmented and defragmented by {@link #transceive} if
+ * it exceeds FSD/FSC limits.
+ *
+ *
Use {@link #getMaxTransceiveLength} to retrieve the maximum number of bytes
+ * that can be sent with {@link #transceive}.
+ *
+ *
This is an I/O operation and will block until complete. It must
+ * not be called from the main application thread. A blocked call will be canceled with
+ * {@link IOException} if {@link #close} is called from another thread.
+ *
+ *
Requires the {@link android.Manifest.permission#NFC} permission.
+ *
+ * @param data - on the first call to transceive after PCD activation, the data sent to the method will be ignored
+ * @return response bytes received, will not be null
+ * @throws TagLostException if the tag leaves the field
+ * @throws IOException if there is an I/O failure, or this operation is canceled
+ */
+ public byte[] transceive(byte[] data) throws IOException {
+ return transceive(data, true);
+ }
+
+ /**
+ * Return the maximum number of bytes that can be sent with {@link #transceive}.
+ * @return the maximum number of bytes that can be sent with {@link #transceive}.
+ */
+ public int getMaxTransceiveLength() {
+ return getMaxTransceiveLengthInternal();
+ }
+}
diff --git a/core/java/android/nfc/tech/IsoPcdB.java b/core/java/android/nfc/tech/IsoPcdB.java
new file mode 100755
index 00000000000..88f28af86bb
--- /dev/null
+++ b/core/java/android/nfc/tech/IsoPcdB.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * HOST CARD EMULATION PATCH 0.01
+ * Author: doug yeager (doug@simplytapp.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc.tech;
+
+import android.nfc.ErrorCodes;
+import android.nfc.Tag;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.io.IOException;
+
+/**
+ * Provides access to ISO-PCD type B (ISO 14443-4) properties and I/O operations on a {@link Tag}.
+ *
+ *
Acquire an {@link IsoPcdB} object using {@link #get}.
+ *
The primary ISO-PCD type B I/O operation is {@link #transceive}. Applications must
+ * implement their own protocol stack on top of {@link #transceive}.
+ *
+ *
Note: Methods that perform I/O operations
+ * require the {@link android.Manifest.permission#NFC} permission.
+ * @hide
+ */
+public final class IsoPcdB extends BasicTagTechnology {
+
+ /**
+ * Get an instance of {@link IsoPcdB} for the given tag.
+ *
Does not cause any RF activity and does not block.
+ *
Returns null if {@link IsoPcdB} was not enumerated in {@link Tag#getTechList}.
+ * This indicates the tag does not support ISO-PCD type B.
+ *
+ * @param tag an ISO-PCD type B compatible PCD
+ * @return ISO-PCD type B object
+ */
+ public static IsoPcdB get(Tag tag) {
+ if (!tag.hasTech(TagTechnology.ISO_PCD_B)) return null;
+ try {
+ return new IsoPcdB(tag);
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /** @hide */
+ public IsoPcdB(Tag tag)
+ throws RemoteException {
+ super(tag, TagTechnology.ISO_PCD_B);
+ Bundle extras = tag.getTechExtras(TagTechnology.ISO_PCD_B);
+ }
+
+ /**
+ * Send raw ISO-PCD type B data to the PCD and receive the response.
+ *
+ *
Applications must only send the INF payload, and not the start of frame and
+ * end of frame indicators. Applications do not need to fragment the payload, it
+ * will be automatically fragmented and defragmented by {@link #transceive} if
+ * it exceeds FSD/FSC limits.
+ *
+ *
Use {@link #getMaxTransceiveLength} to retrieve the maximum number of bytes
+ * that can be sent with {@link #transceive}.
+ *
+ *
This is an I/O operation and will block until complete. It must
+ * not be called from the main application thread. A blocked call will be canceled with
+ * {@link IOException} if {@link #close} is called from another thread.
+ *
+ *
Requires the {@link android.Manifest.permission#NFC} permission.
+ *
+ * @param data - on the first call to transceive after PCD activation, the data sent to the method will be ignored
+ * @return response bytes received, will not be null
+ * @throws TagLostException if the tag leaves the field
+ * @throws IOException if there is an I/O failure, or this operation is canceled
+ */
+ public byte[] transceive(byte[] data) throws IOException {
+ return transceive(data, true);
+ }
+
+ /**
+ * Return the maximum number of bytes that can be sent with {@link #transceive}.
+ * @return the maximum number of bytes that can be sent with {@link #transceive}.
+ */
+ public int getMaxTransceiveLength() {
+ return getMaxTransceiveLengthInternal();
+ }
+}
diff --git a/core/java/android/nfc/tech/TagTechnology.java b/core/java/android/nfc/tech/TagTechnology.java
old mode 100644
new mode 100755
index 3493ea7142d..dd207b9e711
--- a/core/java/android/nfc/tech/TagTechnology.java
+++ b/core/java/android/nfc/tech/TagTechnology.java
@@ -156,6 +156,24 @@ public interface TagTechnology extends Closeable {
*/
public static final int NFC_BARCODE = 10;
+ /**
+ * This technology is an instance of {@link IsoPcdA}.
+ *
Support for this technology type is optional. If a stack doesn't support this technology
+ * type tags using it must still be discovered and present the lower level radio interface
+ * technologies in use.
+ * @hide
+ */
+ public static final int ISO_PCD_A = 100;
+
+ /**
+ * This technology is an instance of {@link IsoPcdB}.
+ *
Support for this technology type is optional. If a stack doesn't support this technology
+ * type tags using it must still be discovered and present the lower level radio interface
+ * technologies in use.
+ * @hide
+ */
+ public static final int ISO_PCD_B = 101;
+
/**
* Get the {@link Tag} object backing this {@link TagTechnology} object.
* @return the {@link Tag} backing this {@link TagTechnology} object.
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 2e38960ed3d..98222190e3b 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -26,6 +26,12 @@ public class BatteryManager {
* integer containing the current status constant.
*/
public static final String EXTRA_STATUS = "status";
+
+ /**
+ * Integer containing the current status constant for the dock battery.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_STATUS = "dock_status";
/**
* Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
@@ -38,14 +44,26 @@ public class BatteryManager {
* boolean indicating whether a battery is present.
*/
public static final String EXTRA_PRESENT = "present";
-
+
+ /**
+ * Integer containing the current status constant for the dock battery.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_PRESENT = "dock_present";
+
/**
* Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
* integer field containing the current battery level, from 0 to
* {@link #EXTRA_SCALE}.
*/
public static final String EXTRA_LEVEL = "level";
-
+
+ /**
+ * Integer field containing the current dock battery level.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_LEVEL = "dock_level";
+
/**
* Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
* integer containing the maximum battery level.
@@ -109,6 +127,13 @@ public class BatteryManager {
public static final int BATTERY_HEALTH_UNSPECIFIED_FAILURE = 6;
public static final int BATTERY_HEALTH_COLD = 7;
+ /** @hide */
+ public static final int DOCK_BATTERY_STATUS_UNKNOWN = 1;
+ /** @hide */
+ public static final int DOCK_BATTERY_STATUS_CHARGING = 2;
+ /** @hide */
+ public static final int DOCK_BATTERY_STATUS_NOT_CHARGING = 4;
+
// values of the "plugged" field in the ACTION_BATTERY_CHANGED intent.
// These must be powers of 2.
/** Power source is an AC charger. */
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 9821824502b..94bd20868fe 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -826,12 +826,15 @@ public abstract long getPhoneSignalScanningTime(
public static final int DATA_CONNECTION_EVDO_B = 12;
public static final int DATA_CONNECTION_LTE = 13;
public static final int DATA_CONNECTION_EHRPD = 14;
- public static final int DATA_CONNECTION_OTHER = 15;
+ public static final int DATA_CONNECTION_HSPAP = 15;
+ public static final int DATA_CONNECTION_DCHSPAP = 16;
+ public static final int DATA_CONNECTION_OTHER = 17;
+
static final String[] DATA_CONNECTION_NAMES = {
"none", "gprs", "edge", "umts", "cdma", "evdo_0", "evdo_A",
"1xrtt", "hsdpa", "hsupa", "hspa", "iden", "evdo_b", "lte",
- "ehrpd", "other"
+ "ehrpd", "hspap", "dchspap", "other"
};
public static final int NUM_DATA_CONNECTION_TYPES = DATA_CONNECTION_OTHER+1;
diff --git a/core/java/android/os/CommonTimeUtils.java b/core/java/android/os/CommonTimeUtils.java
index 9081ee411d6..20755d92d2d 100644
--- a/core/java/android/os/CommonTimeUtils.java
+++ b/core/java/android/os/CommonTimeUtils.java
@@ -19,6 +19,7 @@
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetSocketAddress;
+import java.util.Locale;
import static libcore.io.OsConstants.*;
class CommonTimeUtils {
@@ -192,10 +193,11 @@ public InetSocketAddress transactGetSockaddr(int method_code)
if (AF_INET == type) {
int addr = reply.readInt();
port = reply.readInt();
- addrStr = String.format("%d.%d.%d.%d", (addr >> 24) & 0xFF,
- (addr >> 16) & 0xFF,
- (addr >> 8) & 0xFF,
- addr & 0xFF);
+ addrStr = String.format(Locale.US, "%d.%d.%d.%d",
+ (addr >> 24) & 0xFF,
+ (addr >> 16) & 0xFF,
+ (addr >> 8) & 0xFF,
+ addr & 0xFF);
} else if (AF_INET6 == type) {
int addr1 = reply.readInt();
int addr2 = reply.readInt();
@@ -207,11 +209,11 @@ public InetSocketAddress transactGetSockaddr(int method_code)
int flowinfo = reply.readInt();
int scope_id = reply.readInt();
- addrStr = String.format("[%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X]",
- (addr1 >> 16) & 0xFFFF, addr1 & 0xFFFF,
- (addr2 >> 16) & 0xFFFF, addr2 & 0xFFFF,
- (addr3 >> 16) & 0xFFFF, addr3 & 0xFFFF,
- (addr4 >> 16) & 0xFFFF, addr4 & 0xFFFF);
+ addrStr = String.format(Locale.US, "[%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X]",
+ (addr1 >> 16) & 0xFFFF, addr1 & 0xFFFF,
+ (addr2 >> 16) & 0xFFFF, addr2 & 0xFFFF,
+ (addr3 >> 16) & 0xFFFF, addr3 & 0xFFFF,
+ (addr4 >> 16) & 0xFFFF, addr4 & 0xFFFF);
}
if (null != addrStr) {
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index e50c94813a7..4a1e98fd9a6 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -130,7 +130,7 @@ public static class MemoryInfo implements Parcelable {
public int otherSharedDirty;
/** @hide */
- public static final int NUM_OTHER_STATS = 9;
+ public static final int NUM_OTHER_STATS = 10;
private int[] otherStats = new int[NUM_OTHER_STATS*3];
@@ -177,15 +177,16 @@ public int getOtherSharedDirty(int which) {
/* @hide */
public static String getOtherLabel(int which) {
switch (which) {
- case 0: return "Cursor";
- case 1: return "Ashmem";
- case 2: return "Other dev";
- case 3: return ".so mmap";
- case 4: return ".jar mmap";
- case 5: return ".apk mmap";
- case 6: return ".ttf mmap";
- case 7: return ".dex mmap";
- case 8: return "Other mmap";
+ case 0: return "Stack";
+ case 1: return "Cursor";
+ case 2: return "Ashmem";
+ case 3: return "Other dev";
+ case 4: return ".so mmap";
+ case 5: return ".jar mmap";
+ case 6: return ".apk mmap";
+ case 7: return ".ttf mmap";
+ case 8: return ".dex mmap";
+ case 9: return "Other mmap";
default: return "????";
}
}
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 2bec1c17690..f3f17252b5e 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -54,6 +54,13 @@ public class FileUtils {
public static native int setPermissions(String file, int mode, int uid, int gid);
+ /** returns the UUID for the volume mounted
+ * at the given mount point, or -1 for failure
+ * @param mountPoint point for volume
+ * @return UUID or -1
+ */
+ public static native int getVolumeUUID(String mountPoint);
+
/** returns the FAT file system volume ID for the volume mounted
* at the given mount point, or -1 for failure
* @param mountPoint point for FAT volume
diff --git a/core/java/android/os/IHardwareService.aidl b/core/java/android/os/IHardwareService.aidl
old mode 100755
new mode 100644
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 6d6d147b8a5..f743f3a5cb5 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -51,4 +51,11 @@ interface IPowerManager
// sets the attention light (used by phone app only)
void setAttentionLight(boolean on, int color);
+
+ void cpuBoost(int duration);
+
+ void setKeyboardVisibility(boolean visible);
+
+ void setKeyboardLight(boolean on, int key);
+
}
diff --git a/core/java/android/os/IVibratorService.aidl b/core/java/android/os/IVibratorService.aidl
old mode 100755
new mode 100644
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 736762f67ff..d5f070f2d8f 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -237,6 +237,12 @@ public final class PowerManager {
*/
public static final int BRIGHTNESS_ON = 255;
+ /**
+ * Brightness value for dim backlight.
+ * @hide
+ */
+ public static final int BRIGHTNESS_DIM = 20;
+
/**
* Brightness value for fully off.
* @hide
@@ -334,6 +340,19 @@ public int getDefaultScreenBrightnessSetting() {
com.android.internal.R.integer.config_screenBrightnessSettingDefault);
}
+ /**
+ * Gets the minimum screen brightness.
+ * This is the lowest possible screen brightness; the screen will
+ * never become dimmer than that.
+ * @hide
+ */
+ public int getMinimumAbsoluteScreenBrightness() {
+ int minSetting = getMinimumScreenBrightnessSetting();
+ int dimSetting = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_screenBrightnessDim);
+ return Math.min(minSetting, dimSetting);
+ }
+
/**
* Returns true if the screen auto-brightness adjustment setting should
* be available in the UI. This setting is experimental and disabled by default.
@@ -605,6 +624,24 @@ public void reboot(String reason) {
}
}
+ /**
+ * Boost the CPU. Boosts the cpu for the given duration in microseconds.
+ * Requires the {@link android.Manifest.permission#CPU_BOOST} permission.
+ *
+ * @param duration in microseconds to boost the CPU
+ *
+ * @hide
+ */
+ public void cpuBoost(int duration)
+ {
+ try {
+ if (mService != null) {
+ mService.cpuBoost(duration);
+ }
+ } catch (RemoteException e) {
+ }
+ }
+
/**
* A wake lock is a mechanism to indicate that your application needs
* to have the device stay on.
@@ -824,4 +861,35 @@ public String toString() {
}
}
}
+
+ /**
+ * @hide
+ */
+ public void setKeyboardVisibility(boolean visible)
+ {
+ try {
+ if (mService != null) {
+ mService.setKeyboardVisibility(visible);
+ }
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * sets the keyboard LED state
+ *
+ * @param on boolean state
+ * @param key 1 for caps, 2 for fn
+ *
+ * {@hide}
+ */
+ public void setKeyboardLight(boolean on, int key)
+ {
+ try {
+ mService.setKeyboardLight(on, key);
+ } catch (RemoteException e) {
+ }
+ }
+
+
}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 05099fba14d..c0139db3c71 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -379,7 +379,7 @@ public class Process {
* @param gids Additional group-ids associated with the process.
* @param debugFlags Additional flags.
* @param targetSdkVersion The target SDK version for the app.
- * @param seInfo null-ok SE Android information for the new process.
+ * @param seInfo null-ok SELinux information for the new process.
* @param zygoteArgs Additional arguments to supply to the zygote process.
*
* @return An object that describes the result of the attempt to start the process.
@@ -559,7 +559,7 @@ private static ProcessStartResult zygoteSendArgsAndGetResult(ArrayList a
* new process should setgroup() to.
* @param debugFlags Additional flags.
* @param targetSdkVersion The target SDK version for the app.
- * @param seInfo null-ok SE Android information for the new process.
+ * @param seInfo null-ok SELinux information for the new process.
* @param extraArgs Additional arguments to supply to the zygote process.
* @return An object that describes the result of the attempt to start the process.
* @throws ZygoteStartFailedEx if process start failed for any reason
@@ -1010,4 +1010,29 @@ public static final class ProcessStartResult {
*/
public boolean usingWrapper;
}
+
+ private static final int[] PROCESS_STATE_FORMAT = new int[] {
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM|PROC_PARENS, // 1: name
+ PROC_SPACE_TERM|PROC_OUT_STRING, // 2: state
+ };
+
+ /**
+ * Returns true if the process can be found and is not a zombie
+ * @param pid the process id
+ * @hide
+ */
+ public static final boolean isAlive(int pid) {
+ boolean ret = false;
+ String[] processStateString = new String[1];
+ if (Process.readProcFile("/proc/" + pid + "/stat",
+ PROCESS_STATE_FORMAT, processStateString, null, null)) {
+ ret = true;
+ // Log.i(LOG_TAG,"State of process " + pid + " is " + processStateString[0]);
+ if (processStateString[0].equals("Z")) {
+ ret = false;
+ }
+ }
+ return ret;
+ }
}
diff --git a/core/java/android/os/SELinux.java b/core/java/android/os/SELinux.java
index c05a9747ba6..c9dd5d7ad64 100644
--- a/core/java/android/os/SELinux.java
+++ b/core/java/android/os/SELinux.java
@@ -45,7 +45,7 @@ public class SELinux {
/**
* Set whether SELinux is permissive or enforcing.
- * @param boolean representing whether to set SELinux to enforcing
+ * @param value representing whether to set SELinux to enforcing
* @return a boolean representing whether the desired mode was set
*/
public static final native boolean setSELinuxEnforce(boolean value);
@@ -60,7 +60,7 @@ public class SELinux {
/**
* Change the security context of an existing file object.
* @param path representing the path of file object to relabel.
- * @param con new security context given as a String.
+ * @param context new security context given as a String.
* @return a boolean indicating whether the operation succeeded.
*/
public static final native boolean setFileContext(String path, String context);
@@ -87,8 +87,6 @@ public class SELinux {
/**
* Gets the security context of a given process id.
- * Use of this function is discouraged for Binder transactions.
- * Use Binder.getCallingSecctx() instead.
* @param pid an int representing the process id to check.
* @return a String representing the security context of the given pid.
*/
@@ -102,15 +100,15 @@ public class SELinux {
/**
* Gets the value for the given SELinux boolean name.
- * @param String The name of the SELinux boolean.
+ * @param name The name of the SELinux boolean.
* @return a boolean indicating whether the SELinux boolean is set.
*/
public static final native boolean getBooleanValue(String name);
/**
* Sets the value for the given SELinux boolean name.
- * @param String The name of the SELinux boolean.
- * @param Boolean The new value of the SELinux boolean.
+ * @param name The name of the SELinux boolean.
+ * @param value The new value of the SELinux boolean.
* @return a boolean indicating whether or not the operation succeeded.
*/
public static final native boolean setBooleanValue(String name, boolean value);
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index 156600e378e..a9584d05ba1 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006 The Android Open Source Project
+ * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,6 +33,8 @@ public class SystemProperties
public static final int PROP_NAME_MAX = 31;
public static final int PROP_VALUE_MAX = 91;
+ public static final boolean QCOM_HARDWARE = native_get_boolean("com.qc.hardware", false);
+
private static final ArrayList sChangeCallbacks = new ArrayList();
private static native String native_get(String key);
@@ -153,4 +156,49 @@ static void callChangeCallbacks() {
}
}
}
+
+ /**
+ * Get the value for the given key.
+ * @return def string if the key isn't found
+ */
+ public static String getLongString(String key, String def) {
+ if (key.length() + 1 > PROP_NAME_MAX) {
+ throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);
+ }
+ int chunks = getInt(key + '0', 0);
+ if (chunks == 0) {
+ return def;
+ }
+ StringBuffer sb = new StringBuffer();
+ for (int i = 1; i <= chunks; i++) {
+ sb.append(native_get(key + Integer.toString(i)));
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Set the value for the given key.
+ * @throws IllegalArgumentException if the key exceeds 32 characters
+ */
+ public static void setLongString(String key, String val) {
+ if (key.length() + 1 > PROP_NAME_MAX) {
+ throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);
+ }
+ int chunks = 0;
+ if (val != null && val.length() > 0) {
+ chunks = 1 + val.length() / (PROP_VALUE_MAX + 1);
+ }
+ native_set(key + '0', Integer.toString(chunks));
+ if (chunks > 0) {
+ for (int i = 1, start = 0; i <= chunks; i++) {
+ int end = start + PROP_VALUE_MAX;
+ if (end > val.length()) {
+ end = val.length();
+ }
+ native_set(key + Integer.toString(i), val.substring(start, end));
+ start = end;
+ }
+ }
+ }
+
}
diff --git a/core/java/android/os/TokenWatcher.java b/core/java/android/os/TokenWatcher.java
old mode 100755
new mode 100644
diff --git a/core/java/android/preference/DialogPreference.java b/core/java/android/preference/DialogPreference.java
index a643c8a578e..8577f985135 100644
--- a/core/java/android/preference/DialogPreference.java
+++ b/core/java/android/preference/DialogPreference.java
@@ -274,10 +274,26 @@ protected void onClick() {
* @param state Optional instance state to restore on the dialog
*/
protected void showDialog(Bundle state) {
+ // Create the dialog
+ final Dialog dialog = mDialog = createDialog();
+ if (state != null) {
+ dialog.onRestoreInstanceState(state);
+ }
+ if (needInputMethod()) {
+ requestInputMethod(dialog);
+ }
+ dialog.setOnDismissListener(this);
+ dialog.show();
+ }
+
+ /**
+ * @hide
+ */
+ protected Dialog createDialog() {
Context context = getContext();
mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE;
-
+
mBuilder = new AlertDialog.Builder(context)
.setTitle(mDialogTitle)
.setIcon(mDialogIcon)
@@ -291,21 +307,12 @@ protected void showDialog(Bundle state) {
} else {
mBuilder.setMessage(mDialogMessage);
}
-
+
onPrepareDialogBuilder(mBuilder);
-
+
getPreferenceManager().registerOnActivityDestroyListener(this);
-
- // Create the dialog
- final Dialog dialog = mDialog = mBuilder.create();
- if (state != null) {
- dialog.onRestoreInstanceState(state);
- }
- if (needInputMethod()) {
- requestInputMethod(dialog);
- }
- dialog.setOnDismissListener(this);
- dialog.show();
+
+ return mBuilder.create();
}
/**
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index 336960e234e..7f4da95f8ff 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -1071,6 +1071,9 @@ public int compareTo(Preference another) {
|| (mOrder == DEFAULT_ORDER && another.mOrder != DEFAULT_ORDER)) {
// Do order comparison
return mOrder - another.mOrder;
+ } else if (mTitle == another.mTitle) {
+ // If titles are null or share same object comparison
+ return 0;
} else if (mTitle == null) {
return 1;
} else if (another.mTitle == null) {
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 09ff7bec739..6ab04fbd965 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -31,6 +31,7 @@
import android.os.Message;
import android.os.Parcel;
import android.os.Parcelable;
+import android.provider.Settings;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
@@ -150,6 +151,10 @@ public abstract class PreferenceActivity extends ListActivity implements
*/
public static final String EXTRA_SHOW_FRAGMENT_TITLE = ":android:show_fragment_title";
+ // fix for title text for startPreferencePanel in a single pane mode
+ /** @hide */
+ public static final String EXTRA_SHOW_FRAGMENT_TITLE_TEXT = ":android:show_fragment_title_text";
+
/**
* When starting this activity and using {@link #EXTRA_SHOW_FRAGMENT},
* this extra can also be specify to supply the short title to be shown for
@@ -158,6 +163,11 @@ public abstract class PreferenceActivity extends ListActivity implements
public static final String EXTRA_SHOW_FRAGMENT_SHORT_TITLE
= ":android:show_fragment_short_title";
+ // fix for short title text for startPreferencePanel in a single pane mode
+ /** @hide */
+ public static final String EXTRA_SHOW_FRAGMENT_SHORT_TITLE_TEXT
+ = ":android:show_fragment_short_title_text";
+
/**
* When starting this activity, the invoking Intent can contain this extra
* boolean that the header list should not be displayed. This is most often
@@ -542,6 +552,13 @@ protected void onCreate(Bundle savedInstanceState) {
CharSequence initialShortTitleStr = initialShortTitle != 0
? getText(initialShortTitle) : null;
showBreadCrumbs(initialTitleStr, initialShortTitleStr);
+ } else {
+ CharSequence initialTitleStr = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT_TITLE_TEXT);
+ if ( initialTitleStr != null ) {
+ CharSequence initialShortTitleStr
+ = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT_SHORT_TITLE_TEXT);
+ showBreadCrumbs(initialTitleStr, initialShortTitleStr);
+ }
}
} else {
@@ -575,6 +592,13 @@ protected void onCreate(Bundle savedInstanceState) {
CharSequence initialShortTitleStr = initialShortTitle != 0
? getText(initialShortTitle) : null;
showBreadCrumbs(initialTitleStr, initialShortTitleStr);
+ } else {
+ CharSequence initialTitleStr = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT_TITLE_TEXT);
+ if ( initialTitleStr != null ) {
+ CharSequence initialShortTitleStr
+ = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT_SHORT_TITLE_TEXT);
+ showBreadCrumbs(initialTitleStr, initialShortTitleStr);
+ }
}
} else if (mHeaders.size() > 0) {
setListAdapter(new HeaderAdapter(this, mHeaders));
@@ -681,6 +705,16 @@ public boolean isMultiPane() {
public boolean onIsMultiPane() {
boolean preferMultiPane = getResources().getBoolean(
com.android.internal.R.bool.preferences_prefer_dual_pane);
+ int multiPaneMode = Settings.System.getInt(getContentResolver(),
+ Settings.System.DUAL_PANE_PREFS, (preferMultiPane ? 1 : 0));
+ switch (multiPaneMode) {
+ case 0:
+ preferMultiPane = false;
+ break;
+ case 1:
+ preferMultiPane = true;
+ break;
+ }
return preferMultiPane;
}
@@ -895,6 +929,8 @@ protected void onStop() {
@Override
protected void onDestroy() {
+ mHandler.removeMessages(MSG_BIND_PREFERENCES);
+ mHandler.removeMessages(MSG_BUILD_HEADERS);
super.onDestroy();
if (mPreferenceManager != null) {
@@ -1026,7 +1062,21 @@ public Intent onBuildStartFragmentIntent(String fragmentName, Bundle args,
intent.putExtra(EXTRA_NO_HEADERS, true);
return intent;
}
-
+
+ // fix for title text for startPreferencePanel in a single pane mode
+ /** @hide */
+ public Intent onBuildStartFragmentIntent(String fragmentName, Bundle args,
+ CharSequence titleText, CharSequence shortTitleText) {
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClass(this, getClass());
+ intent.putExtra(EXTRA_SHOW_FRAGMENT, fragmentName);
+ intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);
+ intent.putExtra(EXTRA_SHOW_FRAGMENT_TITLE_TEXT, titleText);
+ intent.putExtra(EXTRA_SHOW_FRAGMENT_SHORT_TITLE_TEXT, shortTitleText);
+ intent.putExtra(EXTRA_NO_HEADERS, true);
+ return intent;
+ }
+
/**
* Like {@link #startWithFragment(String, Bundle, Fragment, int, int, int)}
* but uses a 0 titleRes.
@@ -1063,6 +1113,18 @@ public void startWithFragment(String fragmentName, Bundle args,
}
}
+ // fix for title text for startPreferencePanel in a single pane mode
+ /** @hide */
+ public void startWithFragment(String fragmentName, Bundle args, Fragment resultTo,
+ int resultRequestCode, CharSequence titleText, CharSequence shortTitleText) {
+ Intent intent = onBuildStartFragmentIntent(fragmentName, args, titleText, shortTitleText);
+ if (resultTo == null) {
+ startActivity(intent);
+ } else {
+ resultTo.startActivityForResult(intent, resultRequestCode);
+ }
+ }
+
/**
* Change the base title of the bread crumbs for the current preferences.
* This will normally be called for you. See
@@ -1259,7 +1321,12 @@ public void startPreferenceFragment(Fragment fragment, boolean push) {
public void startPreferencePanel(String fragmentClass, Bundle args, int titleRes,
CharSequence titleText, Fragment resultTo, int resultRequestCode) {
if (mSinglePane) {
- startWithFragment(fragmentClass, args, resultTo, resultRequestCode, titleRes, 0);
+ // fix for title text for startPreferencePanel in a single pane mode
+ if (titleRes == 0 && titleText != null) {
+ startWithFragment(fragmentClass, args, resultTo, resultRequestCode, titleText, null);
+ } else {
+ startWithFragment(fragmentClass, args, resultTo, resultRequestCode, titleRes, 0);
+ }
} else {
Fragment f = Fragment.instantiate(this, fragmentClass, args);
if (resultTo != null) {
diff --git a/core/java/android/preference/VolumePreference.java b/core/java/android/preference/VolumePreference.java
index caf55d70226..b7630225c18 100644
--- a/core/java/android/preference/VolumePreference.java
+++ b/core/java/android/preference/VolumePreference.java
@@ -146,6 +146,11 @@ protected void onSampleStarting(SeekBarVolumizer volumizer) {
}
}
+ /** @hide */
+ protected boolean onVolumeChange(SeekBarVolumizer volumizer, int value) {
+ return true;
+ }
+
@Override
protected Parcelable onSaveInstanceState() {
final Parcelable superState = super.onSaveInstanceState();
@@ -305,10 +310,14 @@ public void onProgressChanged(SeekBar seekBar, int progress,
}
void postSetVolume(int progress) {
- // Do the volume changing separately to give responsive UI
- mLastProgress = progress;
- mHandler.removeCallbacks(this);
- mHandler.post(this);
+ if (onVolumeChange(this, progress)) {
+ // Do the volume changing separately to give responsive UI
+ mLastProgress = progress;
+ mHandler.removeCallbacks(this);
+ mHandler.post(this);
+ } else {
+ mSeekBar.setProgress(mLastProgress);
+ }
}
public void onStartTrackingTouch(SeekBar seekBar) {
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
old mode 100755
new mode 100644
index 8f54a38523e..09050bd8c3e
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -300,6 +300,28 @@ public static final class Preferences {
* @hide
*/
public static final int DISPLAY_ORDER_ALTERNATIVE = 2;
+
+ /**
+ * A key in the {@link android.provider.Settings android.provider.Settings} provider
+ * that stores the preferred view mode for contacts (standard vs. compact).
+ *
+ * @hide
+ */
+ public static final String VIEW_MODE = "android.contacts.VIEW_MODE";
+
+ /**
+ * The value for the VIEW_MODE key corresponding to displaying a standard list view.
+ *
+ * @hide
+ */
+ public static final int VIEW_MODE_STANDARD = 1;
+
+ /**
+ * The value for the VIEW_MODE key corresponding to displaying a compact list view.
+ *
+ * @hide
+ */
+ public static final int VIEW_MODE_COMPACT = 2;
}
/**
@@ -752,6 +774,8 @@ protected interface BaseSyncColumns {
public static final String SYNC3 = "sync3";
/** Generic column for use by sync adapters. */
public static final String SYNC4 = "sync4";
+ /** Facebook Sync Hack */
+ public static final String IS_RESTRICTED = "is_restricted";
}
/**
@@ -833,6 +857,13 @@ protected interface ContactOptionsColumns {
*/
public static final String CUSTOM_RINGTONE = "custom_ringtone";
+ /**
+ * URI for a custom notification associated with the contact. If null or missing,
+ * the default notification is used.
+ * Type: TEXT (URI to the notification)
+ */
+ public static final String CUSTOM_NOTIFICATION = "custom_notification";
+
/**
* Whether the contact should always be sent to voicemail. If missing,
* defaults to false.
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 0e7ab525bc9..cb6300f691f 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -1324,6 +1324,18 @@ public static String keyFor(String name) {
}
public static final class Media implements AudioColumns {
+
+ private static final String[] EXTERNAL_PATHS;
+
+ static {
+ String secondary_storage = System.getenv("SECONDARY_STORAGE");
+ if (secondary_storage != null) {
+ EXTERNAL_PATHS = secondary_storage.split(":");
+ } else {
+ EXTERNAL_PATHS = new String[0];
+ }
+ }
+
/**
* Get the content:// style URI for the audio media table on the
* given volume.
@@ -1337,6 +1349,12 @@ public static Uri getContentUri(String volumeName) {
}
public static Uri getContentUriForPath(String path) {
+ for (String ep : EXTERNAL_PATHS) {
+ if (path.startsWith(ep)) {
+ return EXTERNAL_CONTENT_URI;
+ }
+ }
+
return (path.startsWith(Environment.getExternalStorageDirectory().getPath()) ?
EXTERNAL_CONTENT_URI : INTERNAL_CONTENT_URI);
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 4dbc4b4fa0f..00e7b349c07 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -18,6 +18,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.app.ActivityManagerNative;
import android.app.SearchManager;
import android.app.WallpaperManager;
import android.content.ComponentName;
@@ -37,6 +38,7 @@
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.BatteryManager;
+import android.os.Binder;
import android.os.Bundle;
import android.os.DropBoxManager;
import android.os.IBinder;
@@ -55,6 +57,7 @@
import com.android.internal.widget.ILockSettings;
import java.net.URISyntaxException;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -174,7 +177,6 @@ public final class Settings {
/**
* Activity Action: Show settings to allow configuration of Wi-Fi.
-
*
* In some cases, a matching Activity may not exist, so ensure you
* safeguard against this.
@@ -182,7 +184,6 @@ public final class Settings {
* Input: Nothing.
*
* Output: Nothing.
-
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_WIFI_SETTINGS =
@@ -274,6 +275,20 @@ public final class Settings {
public static final String ACTION_DISPLAY_SETTINGS =
"android.settings.DISPLAY_SETTINGS";
+ /**
+ * Activity Action: Show settings to allow configuration of display.
+ *
+ * In some cases, a matching Activity may not exist, so ensure you
+ * safeguard against this.
+ *
+ * Input: Nothing.
+ *
+ * Output: Nothing.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_NOTIFICATION_SHORTCUTS_SETTINGS =
+ "android.settings.carbon.notificationshortcuts.NOTIFICATION_SHORTCUTS";
+
/**
* Activity Action: Show settings to allow configuration of locale.
*
@@ -900,6 +915,8 @@ public static final class System extends NameValueTable {
MOVED_TO_SECURE.add(Secure.LOCK_BIOMETRIC_WEAK_FLAGS);
MOVED_TO_SECURE.add(Secure.LOCK_PATTERN_ENABLED);
MOVED_TO_SECURE.add(Secure.LOCK_PATTERN_VISIBLE);
+ MOVED_TO_SECURE.add(Secure.LOCK_SHOW_ERROR_PATH);
+ MOVED_TO_SECURE.add(Secure.LOCK_DOTS_VISIBLE);
MOVED_TO_SECURE.add(Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED);
MOVED_TO_SECURE.add(Secure.LOGGING_ID);
MOVED_TO_SECURE.add(Secure.PARENTAL_CONTROL_ENABLED);
@@ -1008,6 +1025,20 @@ public static String getStringForUser(ContentResolver resolver, String name,
return sNameValueCache.getStringForUser(resolver, name, userHandle);
}
+ /**
+ * Look up a name in the database.
+ * @param resolver to access the database with
+ * @param name to look up in the table
+ * @param defaultValue returned if value is null
+ * @return the corresponding value, or default if not present
+ */
+ public synchronized static String getString(ContentResolver resolver,
+ String name, String defaultValue) {
+
+ String value = getString(resolver, name);
+ return value == null ? defaultValue: value;
+ }
+
/**
* Store a name/value pair into the database.
* @param resolver to access the database with
@@ -1117,6 +1148,32 @@ public static int getIntForUser(ContentResolver cr, String name, int userHandle)
}
}
+ /**
+ * @hide
+ * Convenience function for retrieving a single system settings value
+ * as a boolean. Note that internally setting values are always
+ * stored as strings; this function converts the string to a boolean
+ * for you. It will only return true if the stored value is "1"
+ *
+ * @param cr The ContentResolver to access.
+ * @param name The name of the setting to retrieve.
+ * @param def Value to return if the setting is not defined.
+ *
+ * @return The setting's current value, or 'def' if it is not defined
+ * or not a valid integer.
+ */
+ public static boolean getBoolean(ContentResolver cr, String name, boolean def) {
+ String v = getString(cr, name);
+ try {
+ if(v != null)
+ return "1".equals(v);
+ else
+ return def;
+ } catch (NumberFormatException e) {
+ return def;
+ }
+ }
+
/**
* Convenience function for updating a single settings value as an
* integer. This will either create a new entry in the table if the
@@ -1140,6 +1197,57 @@ public static boolean putIntForUser(ContentResolver cr, String name, int value,
return putStringForUser(cr, name, Integer.toString(value), userHandle);
}
+ /**
+ * @hide
+ * Convenience function for updating a single settings value as a
+ * boolean. This will either create a new entry in the table if the
+ * given name does not exist, or modify the value of the existing row
+ * with that name. Note that internally setting values are always
+ * stored as strings, so this function converts the given value to a
+ * string (1 or 0) before storing it.
+ *
+ * @param cr The ContentResolver to access.
+ * @param name The name of the setting to modify.
+ * @param value The new value for the setting.
+ * @return true if the value was set, false on database errors
+ */
+ public static boolean putBoolean(ContentResolver cr, String name, boolean value) {
+ return putString(cr, name, value ? "1" : "0");
+ }
+
+ /**
+ * @hide
+ * Methods to handle storing and retrieving arraylists
+ *
+ * @param cr The ContentResolver to access.
+ * @param name The name of the setting to modify.
+ * @param value The new value for the setting.
+ * @return true if the value was set, false on database errors
+ */
+ public static boolean putArrayList(ContentResolver cr, String name, ArrayList list) {
+ if (list != null && list.size() > 0) {
+ String joined = TextUtils.join("|",list);
+ return putString(cr, name, joined);
+ } else {
+ return putString(cr, name, "");
+ }
+ }
+
+
+ public static ArrayList getArrayList(ContentResolver cr, String name) {
+ String v = getString(cr, name);
+ ArrayList list = new ArrayList();
+ if (v != null) {
+ if (!v.isEmpty()){
+ String[] split = v.split("\\|");
+ for (String i : split) {
+ list.add(i);
+ }
+ }
+ }
+ return list;
+ }
+
/**
* Convenience function for retrieving a single system settings value
* as a {@code long}. Note that internally setting values are always
@@ -1591,6 +1699,23 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean
@Deprecated
public static final String WIFI_STATIC_DNS2 = "wifi_static_dns2";
+ /**
+ * Allows automatic retrieval of mms contents
+ * Type: INT
+ * 0 -- false
+ * 1 -- true
+ * @hide
+ */
+ public static final String MMS_AUTO_RETRIEVAL = "mms_auto_retrieval";
+
+ /**
+ * Allows automatic retrieval of mms contents during roaming
+ * Type: INT
+ * 0 -- false
+ * 1 -- true
+ * @hide
+ */
+ public static final String MMS_AUTO_RETRIEVAL_ON_ROAMING = "mms_auto_on_roaming";
/**
* Determines whether remote devices may discover and/or connect to
@@ -1702,6 +1827,54 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean
*/
public static final int SCREEN_BRIGHTNESS_MODE_AUTOMATIC = 1;
+ /**
+ * Custom automatic brightness light sensor levels.
+ * The value is a comma separated int array with length N.
+ * Example: "100,300,3000".
+ *
+ * @hide
+ */
+ public static final String AUTO_BRIGHTNESS_LUX = "auto_brightness_lux";
+
+ /**
+ * Custom automatic brightness display backlight brightness values.
+ * The value is a comma separated int array with length N+1.
+ * Example: "10,50,100,255".
+ *
+ * @hide
+ */
+ public static final String AUTO_BRIGHTNESS_BACKLIGHT = "auto_brightness_backlight";
+
+ /**
+ * Correction factor for auto-brightness adjustment light sensor
+ * debounce times.
+ * Smaller factors will make the adjustment more responsive, but might
+ * cause flicker and/or cause higher CPU usage.
+ * Valid range is 0.2 ... 3
+ *
+ * @hide
+ */
+ public static final String AUTO_BRIGHTNESS_RESPONSIVENESS = "auto_brightness_responsiveness";
+
+ /**
+ * Touch Key Light Duration
+ *
+ * @hide
+ */
+ public static final String TOUCHKEY_LIGHT_DUR = "touchkey_light_dir";
+
+ /**
+ * Whether to enable the electron beam animation when turning screen on
+ *
+ * @hide */
+ public static final String ELECTRON_BEAM_ANIMATION_ON = "electron_beam_animation_on";
+
+ /**
+ * Whether to enable the electron beam animation when turning screen off
+ *
+ * @hide */
+ public static final String ELECTRON_BEAM_ANIMATION_OFF = "electron_beam_animation_off";
+
/**
* Control whether the process CPU usage meter should be shown.
*
@@ -1720,6 +1893,33 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean
@Deprecated
public static final String ALWAYS_FINISH_ACTIVITIES = Global.ALWAYS_FINISH_ACTIVITIES;
+ /**
+ * Volume Overlay Mode, This is behaviour of the volume overlay panel
+ * Defaults to 0 - which is simple
+ * @hide
+ */
+ public static final String MODE_VOLUME_OVERLAY = "mode_volume_overlay";
+
+ /** @hide */
+ public static final int VOLUME_OVERLAY_SINGLE = 0;
+ /** @hide */
+ public static final int VOLUME_OVERLAY_EXPANDABLE = 1;
+ /** @hide */
+ public static final int VOLUME_OVERLAY_EXPANDED = 2;
+ /** @hide */
+ public static final int VOLUME_OVERLAY_NONE = 3;
+
+ /**
+ * Ability to enable/disable Daul pane prefs.
+ */
+ public static final String DUAL_PANE_PREFS = "dual_pane_prefs";
+
+ /**
+ * Lock Volume Keys, Whether to lock ringer volume changes in silent mode.
+ * @hide
+ */
+ public static final String LOCK_VOLUME_KEYS = "lock_volume_keys";
+
/**
* Determines which streams are affected by ringer mode changes. The
* stream type's bit should be set to 1 if it should be muted when going
@@ -1796,6 +1996,12 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean
*/
public static final String VOLUME_BLUETOOTH_SCO = "volume_bluetooth_sco";
+ /**
+ * Whether to prevent loud volume levels when headset is first plugged in.
+ * @hide
+ */
+ public static final String SAFE_HEADSET_VOLUME = "safe_headset_volume";
+
/**
* Master volume (float in the range 0.0f to 1.0f).
* @hide
@@ -1809,6 +2015,16 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean
*/
public static final String VOLUME_MASTER_MUTE = "volume_master_mute";
+ /**
+ * @hide
+ */
+ public static final String SYSTEM_POWER_ENABLE_CRT_OFF = "system_power_enable_crt_off";
+
+ /**
+ * @hide
+ */
+ public static final String SYSTEM_POWER_ENABLE_CRT_ON = "system_power_enable_crt_on";
+
/**
* Whether the notifications should use the ring volume (value of 1) or
* a separate notification volume (value of 0). In most cases, users
@@ -1827,6 +2043,30 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean
public static final String NOTIFICATIONS_USE_RING_VOLUME =
"notifications_use_ring_volume";
+ /**
+ * Whether the blacklisting feature for phone calls is enabled
+ * @hide
+ */
+ public static final String PHONE_BLACKLIST_ENABLED = "phone_blacklist_enabled";
+
+ /**
+ * Whether the phone ringtone should be played in an increasing manner
+ * @hide
+ */
+ public static final String INCREASING_RING = "increasing_ring";
+
+ /**
+ * Minimum volume index for increasing ring volume
+ * @hide
+ */
+ public static final String INCREASING_RING_MIN_VOLUME = "increasing_ring_min_vol";
+
+ /**
+ * Time (in ms) between ringtone volume increases
+ * @hide
+ */
+ public static final String INCREASING_RING_INTERVAL = "increasing_ring_interval";
+
/**
* Whether silent mode should allow vibration feedback. This is used
* internally in AudioService and the Sound settings activity to
@@ -2022,6 +2262,19 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean
*/
public static final String ACCELEROMETER_ROTATION = "accelerometer_rotation";
+ /**
+ * Control the type of rotation which can be performed using the accelerometer
+ * if ACCELEROMETER_ROTATION is enabled.
+ * Value is a bitwise combination of
+ * 1 = 0 degrees (portrait)
+ * 2 = 90 degrees (left)
+ * 4 = 180 degrees (inverted portrait)
+ * 8 = 270 degrees (right)
+ * Setting to 0 is effectively orientation lock
+ * @hide
+ */
+ public static final String ACCELEROMETER_ROTATION_ANGLES = "accelerometer_rotation_angles";
+
/**
* Default screen rotation when no other policy applies.
* When {@link #ACCELEROMETER_ROTATION} is zero and no on-screen Activity expresses a
@@ -2093,6 +2346,13 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean
*/
public static final String TTY_MODE = "tty_mode";
+ /**
+ * Whether noise suppression is enabled. The value is
+ * boolean (1 or 0).
+ * @hide
+ */
+ public static final String NOISE_SUPPRESSION = "noise_suppression";
+
/**
* Whether the sounds effects (key clicks, lid open ...) are enabled. The value is
* boolean (1 or 0).
@@ -2119,6 +2379,109 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean
*/
public static final String NOTIFICATION_LIGHT_PULSE = "notification_light_pulse";
+ /**
+ * What color to use for the notification LED by default
+ * @hide
+ */
+ public static final String NOTIFICATION_LIGHT_PULSE_DEFAULT_COLOR = "notification_light_pulse_default_color";
+
+ /**
+ * How long to flash the notification LED by default
+ * @hide
+ */
+ public static final String NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_ON = "notification_light_pulse_default_led_on";
+
+ /**
+ * How long to wait between flashes for the notification LED by default
+ * @hide
+ */
+ public static final String NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_OFF = "notification_light_pulse_default_led_off";
+
+ /**
+ * What color to use for the missed call notification LED
+ * @hide
+ */
+ public static final String NOTIFICATION_LIGHT_PULSE_CALL_COLOR = "notification_light_pulse_call_color";
+
+ /**
+ * How long to flash the missed call notification LED
+ * @hide
+ */
+ public static final String NOTIFICATION_LIGHT_PULSE_CALL_LED_ON = "notification_light_pulse_call_led_on";
+
+ /**
+ * How long to wait between flashes for the missed call notification LED
+ * @hide
+ */
+ public static final String NOTIFICATION_LIGHT_PULSE_CALL_LED_OFF = "notification_light_pulse_call_led_off";
+
+ /**
+ * What color to use for the voicemail notification LED
+ * @hide
+ */
+ public static final String NOTIFICATION_LIGHT_PULSE_VMAIL_COLOR = "notification_light_pulse_vmail_color";
+
+ /**
+ * How long to flash the voicemail notification LED
+ * @hide
+ */
+ public static final String NOTIFICATION_LIGHT_PULSE_VMAIL_LED_ON = "notification_light_pulse_vmail_led_on";
+
+ /**
+ * How long to wait between flashes for the voicemail notification LED
+ * @hide
+ */
+ public static final String NOTIFICATION_LIGHT_PULSE_VMAIL_LED_OFF = "notification_light_pulse_vmail_led_off";
+
+ /**
+ * Whether to use the custom LED values for the notification pulse LED.
+ * @hide
+ */
+ public static final String NOTIFICATION_LIGHT_PULSE_CUSTOM_ENABLE = "notification_light_pulse_custom_enable";
+
+ /**
+ * Which custom LED values to use for the notification pulse LED.
+ * @hide
+ */
+ public static final String NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES = "notification_light_pulse_custom_values";
+
+ /**
+ * Whether the battery light should be enabled (if hardware supports it)
+ * The value is boolean (1 or 0).
+ * @hide
+ */
+ public static final String BATTERY_LIGHT_ENABLED = "battery_light_enabled";
+
+ /**
+ * Whether the battery LED should repeatedly flash when the battery is low
+ * on charge. The value is boolean (1 or 0).
+ * @hide
+ */
+ public static final String BATTERY_LIGHT_PULSE = "battery_light_pulse";
+
+ /**
+ * What color to use for the battery LED while charging - low
+ * @hide
+ */
+ public static final String BATTERY_LIGHT_LOW_COLOR = "battery_light_low_color";
+
+ /**
+ * What color to use for the battery LED while charging - medium
+ * @hide
+ */
+ public static final String BATTERY_LIGHT_MEDIUM_COLOR = "battery_light_medium_color";
+
+ /**
+ * What color to use for the battery LED while charging - full
+ * @hide
+ */
+ public static final String BATTERY_LIGHT_FULL_COLOR = "battery_light_full_color";
+
+ /** Sprint MWI Quirk: Show message wait indicator notifications
+ * @hide
+ */
+ public static final String ENABLE_MWI_NOTIFICATION = "enable_mwi_notification";
+
/**
* Show pointer location on screen?
* 0 = no
@@ -2127,6 +2490,14 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean
*/
public static final String POINTER_LOCATION = "pointer_location";
+ /**
+ * Show icon when stylus is used?
+ * 0 = no
+ * 1 = yes
+ * @hide
+ */
+ public static final String STYLUS_ICON_ENABLED = "stylus_icon_enabled";
+
/**
* Show touch positions on screen?
* 0 = no
@@ -2154,125 +2525,2138 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean
public static final String POWER_SOUNDS_ENABLED = Global.POWER_SOUNDS_ENABLED;
/**
- * @deprecated Use {@link android.provider.Settings.Global#DOCK_SOUNDS_ENABLED}
- * instead
+ * @deprecated Use {@link android.provider.Settings.Global#DOCK_SOUNDS_ENABLED}
+ * instead
+ * @hide
+ */
+ @Deprecated
+ public static final String DOCK_SOUNDS_ENABLED = Global.DOCK_SOUNDS_ENABLED;
+
+ /**
+ * Whether to play sounds when the keyguard is shown and dismissed.
+ * @hide
+ */
+ public static final String LOCKSCREEN_SOUNDS_ENABLED = "lockscreen_sounds_enabled";
+
+ /**
+ * Whether the lockscreen should be completely disabled.
+ * @hide
+ */
+ public static final String LOCKSCREEN_DISABLED = "lockscreen.disabled";
+
+ /**
+ * @deprecated Use {@link android.provider.Settings.Global#LOW_BATTERY_SOUND}
+ * instead
+ * @hide
+ */
+ @Deprecated
+ public static final String LOW_BATTERY_SOUND = Global.LOW_BATTERY_SOUND;
+
+ /**
+ * @deprecated Use {@link android.provider.Settings.Global#DESK_DOCK_SOUND}
+ * instead
+ * @hide
+ */
+ @Deprecated
+ public static final String DESK_DOCK_SOUND = Global.DESK_DOCK_SOUND;
+
+ /**
+ * User configurable background for qs tiles
+ * 0 = random colors
+ * 1 = colorpicker preference
+ * 2 = default background
+ * @hide
+ */
+ public static final String QUICK_SETTINGS_BACKGROUND_STYLE = "quick_settings_background_style";
+
+ /**
+ * User color for tile background
+ * @hide
+ */
+ public static final String QUICK_SETTINGS_BACKGROUND_COLOR = "quick_settings_background_color";
+
+ /**
+ * User color for tile background pressed
+ * @hide
+ */
+ public static final String QUICK_SETTINGS_BACKGROUND_PRESSED_COLOR = "quick_settings_background_pressed_color";
+
+ /**
+ * User color for text background
+ * @hide
+ */
+ public static final String QUICK_SETTINGS_TEXT_COLOR = "quick_settings_text_color";
+
+ /**
+ * @deprecated Use {@link android.provider.Settings.Global#DESK_UNDOCK_SOUND}
+ * instead
+ * @hide
+ */
+ @Deprecated
+ public static final String DESK_UNDOCK_SOUND = Global.DESK_UNDOCK_SOUND;
+
+ /**
+ * @deprecated Use {@link android.provider.Settings.Global#CAR_DOCK_SOUND}
+ * instead
+ * @hide
+ */
+ @Deprecated
+ public static final String CAR_DOCK_SOUND = Global.CAR_DOCK_SOUND;
+
+ /**
+ * @deprecated Use {@link android.provider.Settings.Global#CAR_UNDOCK_SOUND}
+ * instead
+ * @hide
+ */
+ @Deprecated
+ public static final String CAR_UNDOCK_SOUND = Global.CAR_UNDOCK_SOUND;
+
+ /**
+ * @deprecated Use {@link android.provider.Settings.Global#LOCK_SOUND}
+ * instead
+ * @hide
+ */
+ @Deprecated
+ public static final String LOCK_SOUND = Global.LOCK_SOUND;
+
+ /**
+ * @deprecated Use {@link android.provider.Settings.Global#UNLOCK_SOUND}
+ * instead
+ * @hide
+ */
+ @Deprecated
+ public static final String UNLOCK_SOUND = Global.UNLOCK_SOUND;
+
+ /**
+ * Receive incoming SIP calls?
+ * 0 = no
+ * 1 = yes
+ * @hide
+ */
+ public static final String SIP_RECEIVE_CALLS = "sip_receive_calls";
+
+ /**
+ * Random user selected colors
+ * @hide
+ */
+ public static final String RANDOM_COLOR_ONE = "random_color_one";
+
+ /**
+ * @hide
+ */
+ public static final String RANDOM_COLOR_TWO = "random_color_two";
+
+ /**
+ * @hide
+ */
+ public static final String RANDOM_COLOR_THREE = "random_color_three";
+
+ /**
+ * @hide
+ */
+ public static final String RANDOM_COLOR_FOUR = "random_color_four";
+
+ /**
+ * @hide
+ */
+ public static final String RANDOM_COLOR_FIVE = "random_color_five";
+
+ /**
+ * @hide
+ */
+ public static final String RANDOM_COLOR_SIX = "random_color_six";
+
+ /**
+ * Call Preference String.
+ * "SIP_ALWAYS" : Always use SIP with network access
+ * "SIP_ADDRESS_ONLY" : Only if destination is a SIP address
+ * "SIP_ASK_ME_EACH_TIME" : Always ask me each time
+ * @hide
+ */
+ public static final String SIP_CALL_OPTIONS = "sip_call_options";
+
+ /**
+ * One of the sip call options: Always use SIP with network access.
+ * @hide
+ */
+ public static final String SIP_ALWAYS = "SIP_ALWAYS";
+
+ /**
+ * One of the sip call options: Only if destination is a SIP address.
+ * @hide
+ */
+ public static final String SIP_ADDRESS_ONLY = "SIP_ADDRESS_ONLY";
+
+ /**
+ * One of the sip call options: Always ask me each time.
+ * @hide
+ */
+ public static final String SIP_ASK_ME_EACH_TIME = "SIP_ASK_ME_EACH_TIME";
+
+ /**
+ * Torch state (flashlight)
+ * @hide
+ */
+ public static final String TORCH_STATE = "torch_state";
+ /**
+ * Pointer speed setting.
+ * This is an integer value in a range between -7 and +7, so there are 15 possible values.
+ * -7 = slowest
+ * 0 = default speed
+ * +7 = fastest
+ * @hide
+ */
+ public static final String POINTER_SPEED = "pointer_speed";
+
+ /**
+ * Use the Notification Power Widget? (Who wouldn't!)
+ *
+ * @hide
+ */
+ public static final String EXPANDED_VIEW_WIDGET = "expanded_view_widget";
+
+ /**
+ * Whether to hide the notification screen after clicking on a widget
+ * button
+ *
+ * @hide
+ */
+ public static final String EXPANDED_HIDE_ONCHANGE = "expanded_hide_onchange";
+
+ /**
+ * Hide scroll bar in power widget
+ *
+ * @hide
+ */
+ public static final String EXPANDED_HIDE_SCROLLBAR = "expanded_hide_scrollbar";
+
+ /**
+ * Haptic feedback in power widget
+ *
+ * @hide
+ */
+ public static final String EXPANDED_HAPTIC_FEEDBACK = "expanded_haptic_feedback";
+
+ /**
+ * Widget Buttons to Use
+ *
+ * @hide
+ */
+ public static final String WIDGET_BUTTONS = "expanded_widget_buttons";
+
+ /**
+ * Widget Buttons to Use - Tablet
+ *
+ * @hide
+ */
+ public static final String WIDGET_BUTTONS_TABLET = "expanded_widget_buttons_tablet";
+
+ /**
+ * Navigation controls to Use
+ *
+ * @hide
+ */
+ public static final String NAV_BUTTONS = "nav_buttons";
+
+ /**
+ * Notification Power Widget - Custom Brightness Mode
+ * @hide
+ */
+ public static final String EXPANDED_BRIGHTNESS_MODE = "expanded_brightness_mode";
+
+ /**
+ * Notification Power Widget - Custom Network Mode
+ * @hide
+ */
+ public static final String EXPANDED_NETWORK_MODE = "expanded_network_mode";
+
+ /**
+ * Notification Power Widget - Custom Screen Timeout
+ * @hide
+ */
+ public static final String EXPANDED_SCREENTIMEOUT_MODE = "expanded_screentimeout_mode";
+
+ /**
+ * Notification Power Widget - Custom Ring Mode
+ * @hide
+ */
+ public static final String EXPANDED_RING_MODE = "expanded_ring_mode";
+
+ /**
+ * Notification Power Widget - Custom Torch Mode
+ * @hide
+ */
+ public static final String EXPANDED_FLASH_MODE = "expanded_flash_mode";
+
+ /**
+ * AutoHide CombinedBar on tablets.
+ * @hide
+ */
+ public static final String COMBINED_BAR_AUTO_HIDE = "combined_bar_auto_hide";
+
+ /**
+ * Display style of the status bar battery information
+ * 0: Display the stock battery information
+ * 1: Display cm battery percentage implementation / dont show stock icon
+ * 2: Display cm circle battery implementation without percentage
+ * 3: Display cm circle battery implementation with percentage
+ * 4: Hide the battery information
+ * default: 0
+ * @hide
+ */
+ public static final String STATUS_BAR_BATTERY = "status_bar_battery";
+
+ /**
+ * Whether to show the clock in status bar
+ * of the stock battery icon
+ * 0: don't show the clock
+ * 1: show the clock
+ * default: 1
+ * @hide
+ */
+ public static final String STATUS_BAR_CLOCK = "status_bar_clock";
+
+ /**
+ * Whether to show the signal text or signal bars.
+ * default: 0
+ * 0: show signal bars
+ * 1: show signal text numbers
+ * 2: show signal text numbers w/small dBm appended
+ * @hide
+ */
+ public static final String STATUS_BAR_SIGNAL_TEXT = "status_bar_signal";
+
+ /**
+ * AM/PM Style for clock options
+ * 0 - Normal AM/PM
+ * 1 - Small AM/PM
+ * 2 - No AM/PM
+ * @hide
+ */
+ public static final String STATUSBAR_CLOCK_AM_PM_STYLE = "statusbar_clock_am_pm_style";
+
+ /**
+ * Status Bar notification icon opacity
+ * @hide
+ */
+ public static final String STATUS_BAR_NOTIF_ICON_OPACITY = "status_bar_notif_icon_opacity";
+
+ /**
+ * Style of clock
+ * 0 - Hide Clock
+ * 1 - Right Clock
+ * 2 - Center Clock
+ * @hide
+ */
+ public static final String STATUSBAR_CLOCK_STYLE = "statusbar_clock_style";
+
+ /**
+ * Setting for clock color
+ * @hide
+ */
+ public static final String STATUSBAR_CLOCK_COLOR = "statusbar_clock_color";
+
+ /**
+ * @hide
+ * Shows custom date before clock time
+ * 0 - No Date
+ * 1 - Small Date
+ * 2 - Normal Date
+ */
+ public static final String STATUSBAR_CLOCK_DATE_DISPLAY = "statusbar_clock_date_display";
+
+ /**
+ * @hide
+ * Sets the date string style
+ * 0 - Regular style
+ * 1 - Lowercase
+ * 2 - Uppercase
+ */
+ public static final String STATUSBAR_CLOCK_DATE_STYLE = "statusbar_clock_date_style";
+
+ /**
+ * @hide
+ * Stores the java DateFormat string for the date
+ */
+ public static final String STATUSBAR_CLOCK_DATE_FORMAT = "statusbar_clock_date_format";
+
+ /**
+ * Whether to control brightness from status bar
+ *
+ * @hide
+ */
+ public static final String STATUS_BAR_BRIGHTNESS_CONTROL = "status_bar_brightness_control";
+
+ /**
+ * Whether to show the IME switcher in the status bar
+ * @hide
+ */
+ public static final String STATUS_BAR_IME_SWITCHER = "status_bar_ime_switcher";
+
+ /**
+ * Override and forcefully disable the fullscreen keyboard
+ * @hide
+ */
+ public static final String DISABLE_FULLSCREEN_KEYBOARD = "disable_fullscreen_keyboard";
+
+ /**
+ * whether circle RAM meter is used
+ * @hide
+ */
+ public static final String RECENTS_RAM_CIRCLE = "recents_ram_circle";
+
+ /**
+ * whether which Ram Usage Bar mode is used on recent switcher
+ * 0 = none, 1 = only app use, 2 = app and cache use, 3 = app, cache and system use
+ * @hide
+ */
+ public static final String RECENTS_RAM_BAR_MODE = "recents_ram_bar_mode";
+
+ /**
+ * Ram Usage Bar system mem color
+ *
+ * @hide
+ */
+ public static final String RECENTS_RAM_BAR_MEM_COLOR = "recents_ram_bar_mem_color";
+
+ /**
+ * Ram Usage Bar cached mem color
+ *
+ * @hide
+ */
+ public static final String RECENTS_RAM_BAR_CACHE_COLOR = "recents_ram_bar_cache_color";
+
+ /**
+ * Ram Usage Bar app mem color
+ *
+ * @hide
+ */
+ public static final String RECENTS_RAM_BAR_ACTIVE_APPS_COLOR = "recents_ram_bar_active_apps_color";
+
+ /**
+ * Choose side for Clear button on Recents window
+ * 0 = left, 1 = right
+ * @hide
+ */
+ public static final String CLEAR_RECENTS_POSITION = "clear_recents_position";
+
+ /**
+ * Whether Status bar should be hiidden when there are no
+ * notifications
+ * @hide
+ */
+ public static final String AUTO_HIDE_STATUSBAR = "auto_hide_statusbar";
+
+ /**
+ * Whether Status Bar is currently hidden or not
+ * @hide
+ */
+ public static final String HIDE_STATUSBAR = "hide_statusbar";
+
+ /**
+ * Whether Status Bar is currently hidden or not for notification
+ * toggle notification shade
+ *
+ * @hide
+ */
+ public static final String TOGGLE_NOTIFICATION_AND_QS_SHADE = "toggle_notification_and_qs_shade";
+
+ /**
+ * Peek at stausbar when it is hidden by swiping down from top
+ * end of the screen
+ *
+ * @hide
+ */
+ public static final String STATUSBAR_PEEK = "statusbar_peek";
+
+ /**
+ * Whether Expanded desktop is currently running or not
+ * @hide
+ */
+ public static final String EXPANDED_DESKTOP_STATE = "expanded_desktop_state";
+
+ /**
+ * Expanded desktop mode
+ * 0 = none, 1 = hide only navbar, 2 = hide only statusbar, 3 = hide both
+ * @hide
+ */
+ public static final String EXPANDED_DESKTOP_MODE = "expanded_desktop_mode";
+
+ /**
+ * Quick Settings Disable Panel
+ *
+ * @hide
+ */
+ public static final String QS_DISABLE_PANEL = "qs_disable_panel";
+
+ /**
+ * Whether to use a separate delay for "slide to unlock" and security
+ * lock
+ * @hide
+ */
+ public static final String SCREEN_LOCK_SLIDE_DELAY_TOGGLE = "screen_lock_slide_delay_toggle";
+
+ /**
+ * How many ms to delay before enabling the "slide to unlock" screen
+ * lock when the screen goes off due to timeout
+ * @hide
+ */
+ public static final String SCREEN_LOCK_SLIDE_TIMEOUT_DELAY = "screen_lock_slide_timeout_delay";
+
+ /**
+ * How many ms to delay before enabling the "slide to unlock" screen
+ * lock when the screen is turned off by the user
+ * @hide
+ */
+ public static final String SCREEN_LOCK_SLIDE_SCREENOFF_DELAY = "screen_lock_slide_screenoff_delay";
+
+ /**
+ * Sets the portrait background of notification drawer
+ * @hide
+ */
+ public static final String NOTIFICATION_BACKGROUND = "notification_background";
+
+ /**
+ * Sets the landscape background of notification drawer
+ * @hide
+ */
+ public static final String NOTIFICATION_BACKGROUND_LANDSCAPE = "notification_background_landscape";
+
+ /**
+ * Sets the alpha (transparency) of notification wallpaper
+ * @hide
+ */
+ public static final String NOTIF_WALLPAPER_ALPHA = "notif_wallpaper_alpha";
+
+ /**
+ * Sets the alpha (transparency) of notifications
+ * @hide
+ */
+ public static final String NOTIF_ALPHA = "notif_alpha";
+
+ /**
+ * Automatic keyboard rotation timeout. 0 to disable completely.
+ * @hide
+ */
+ public static final String KEYBOARD_ROTATION_TIMEOUT = "keyboard_rotation_timeout";
+
+ /**
+ * Forces formal text input. 1 to replace emoticon key with enter key.
+ * @hide
+ */
+ public static final String FORMAL_TEXT_INPUT = "formal_text_input";
+
+ /**
+ * Show the pending notification counts as overlays on the status bar
+ * @hide
+ */
+ public static final String STATUS_BAR_NOTIF_COUNT = "status_bar_notif_count";
+
+ /**
+ *
+ * @hide
+ */
+ public static final String LOCKSCREEN_GLOW_TORCH = "lockscreen_glow_torch";
+
+ /**
+ * Whether to use the custom quick unlock screen control
+ * @hide
+ */
+ public static final String LOCKSCREEN_QUICK_UNLOCK_CONTROL = "lockscreen_quick_unlock_control";
+
+ /**
+ * Whether to use keyguard or homescreen widgets
+ * @hide
+ */
+ public static final String LOCKSCREEN_ALL_WIDGETS = "lockscreen_all_widgets";
+
+ /**
+ * Whether to enable lockscreen rotation
+ * @hide
+ */
+ public static final String LOCKSCREEN_AUTO_ROTATE = "lockscreen_auto_rotate";
+
+ /**
+ * custom lockscreen text color
+ * @hide
+ */
+ public static final String LOCKSCREEN_CUSTOM_TEXT_COLOR = "lockscreen_custom_text_color";
+
+ /**
+ * Volume Adjust Sounds Enable, This is the noise made when using volume hard buttons
+ * Defaults to 1 - sounds enabled
+ * @hide
+ */
+ public static final String VOLUME_ADJUST_SOUNDS_ENABLED = "volume_adjust_sounds_enabled";
+
+ /**
+ * Boolean value whether to link ringtone and notification volumes
+ *
+ * @hide
+ */
+ public static final String VOLUME_LINK_NOTIFICATION = "volume_link_notification";
+
+ /**
+ * NFC polling mode configuration key
+ *
+ * @hide
+ */
+ public static final String NFC_POLLING_MODE = "nfc_polling_mode";
+
+ /**
+ * Whether to unlock the menu key. The value is boolean (1 or 0).
+ * @hide
+ */
+ public static final String MENU_UNLOCK_SCREEN = "menu_unlock_screen";
+
+ /**
+ * Whether to wake the screen with the volume keys, the value is boolean.
+ * @hide
+ */
+ public static final String VOLUME_WAKE_SCREEN = "volume_wake_screen";
+
+ /**
+ * Whether or not volume button music controls should be enabled to seek media tracks
+ * @hide
+ */
+ public static final String VOLBTN_MUSIC_CONTROLS = "volbtn_music_controls";
+
+ /**
+ * Whether or not to launch default music player when headset is connected
+ * @hide
+ */
+ public static final String HEADSET_CONNECT_PLAYER = "headset_connect_player";
+
+ /**
+ * Whether national data roaming should be used.
+ * @hide
+ */
+ public static final String MVNO_ROAMING = "mvno_roaming";
+
+ public static final String THEME_WALLPAPER = "theme_wallpaper";
+
+ /**
+ * Whether to enable quiet hours.
+ * @hide
+ */
+ public static final String QUIET_HOURS_ENABLED = "quiet_hours_enabled";
+
+ /**
+ * Sets when quiet hours starts. This is stored in minutes from the start of the day.
+ * @hide
+ */
+ public static final String QUIET_HOURS_START = "quiet_hours_start";
+
+ /**
+ * Sets when quiet hours end. This is stored in minutes from the start of the day.
+ * @hide
+ */
+ public static final String QUIET_HOURS_END = "quiet_hours_end";
+
+ /**
+ * Whether to remove the sound from outgoing notifications during quiet hours.
+ * @hide
+ */
+ public static final String QUIET_HOURS_MUTE = "quiet_hours_mute";
+
+ /**
+ * Whether to disable haptic feedback during quiet hours.
+ * @hide
+ */
+ public static final String QUIET_HOURS_HAPTIC = "quiet_hours_haptic";
+
+ /**
+ * Whether to remove the vibration from outgoing notifications during quiet hours.
+ * @hide
+ */
+ public static final String QUIET_HOURS_STILL = "quiet_hours_still";
+
+ /**
+ * Whether to attempt to dim the LED color during quiet hours.
+ * @hide
+ */
+ public static final String QUIET_HOURS_DIM = "quiet_hours_dim";
+
+ /**
+ * Sets the lockscreen background style
+ * @hide
+ */
+ public static final String LOCKSCREEN_BACKGROUND = "lockscreen_background";
+
+ /**
+ * Action for long-pressing back button on lock screen
+ * @hide
+ */
+ public static final String LOCKSCREEN_LONG_BACK_ACTION = "lockscreen_long_back_action";
+
+ /**
+ * Action for long-pressing home button on lock screen
+ * @hide
+ */
+ public static final String LOCKSCREEN_LONG_HOME_ACTION = "lockscreen_long_home_action";
+
+ /**
+ * Action for long-pressing menu button on lock screen
+ * @hide
+ */
+ public static final String LOCKSCREEN_LONG_MENU_ACTION = "lockscreen_long_menu_action";
+
+ /**
+ * Action for long-pressing assist button on lock screen
+ * @hide
+ */
+ public static final String LOCKSCREEN_LONG_ASSIST_ACTION = "lockscreen_long_assist_action";
+
+ /**
+ * Action for long-pressing app switch button on lock screen
+ * @hide
+ */
+ public static final String LOCKSCREEN_LONG_APP_SWITCH_ACTION = "lockscreen_long_app_switch_action";
+
+ /**
+ * Action for long-pressing camera button on lock screen
+ * @hide
+ */
+ public static final String LOCKSCREEN_LONG_CAMERA_ACTION = "lockscreen_long_camera_action";
+
+ /**
+ * Always show the battery status on the lockscreen
+ * @hide
+ */
+ public static final String LOCKSCREEN_ALWAYS_SHOW_BATTERY = "lockscreen_always_show_battery";
+
+ /**
+ * Enable Stylus Gestures
+ *
+ * @hide
+ */
+ public static final String ENABLE_STYLUS_GESTURES = "enable_stylus_gestures";
+
+ /**
+ * Left Swipe Action
+ *
+ * @hide
+ */
+ public static final String GESTURES_LEFT_SWIPE = "gestures_left_swipe";
+
+ /**
+ * Right Swipe Action
+ *
+ * @hide
+ */
+ public static final String GESTURES_RIGHT_SWIPE = "gestures_right_swipe";
+
+ /**
+ * Up Swipe Action
+ *
+ * @hide
+ */
+ public static final String GESTURES_UP_SWIPE = "gestures_up_swipe";
+
+ /**
+ * down Swipe Action
+ *
+ * @hide
+ */
+ public static final String GESTURES_DOWN_SWIPE = "gestures_down_swipe";
+
+ /**
+ * Long press Action
+ *
+ * @hide
+ */
+ public static final String GESTURES_LONG_PRESS = "gestures_long_press";
+
+ /**
+ * double tap Action
+ *
+ * @hide
+ */
+ public static final String GESTURES_DOUBLE_TAP = "gestures_double_tap";
+
+ /**
+ * Whether system profiles are enabled
+ * @hide
+ */
+ public static final String SYSTEM_PROFILES_ENABLED = "system_profiles_enabled";
+
+ /**
+ * Whether the power menu reboot menu is enabled
+ * @hide
+ */
+ public static final String POWER_MENU_REBOOT_ENABLED = "power_menu_reboot_enabled";
+
+ /**
+ * Whether power menu screenshot is enabled
+ * @hide
+ */
+ public static final String POWER_MENU_SCREENSHOT_ENABLED = "power_menu_screenshot_enabled";
+
+ /**
+ * Whether power menu torch is enabled
+ * @hide
+ */
+ public static final String POWER_MENU_TORCH_ENABLED = "power_menu_torch_enabled";
+
+ /**
+ * Whether power menu expanded desktop is enabled
+ * @hide
+ */
+ public static final String POWER_MENU_EXPANDED_DESKTOP_ENABLED = "power_menu_expanded_desktop_enabled";
+
+ /**
+ * Whether power menu profiles switcher is enabled
+ * @hide
+ */
+ public static final String POWER_MENU_PROFILES_ENABLED = "power_menu_profiles_enabled";
+
+ /**
+ * Whether power menu airplane toggle is enabled
+ * @hide
+ */
+ public static final String POWER_MENU_AIRPLANE_ENABLED = "power_menu_airplane_enabled";
+
+ /**
+ * Whether power menu user switcher is enabled
+ * @hide
+ */
+ public static final String POWER_MENU_USER_ENABLED = "power_menu_user_enabled";
+
+ /**
+ * Whether power menu silent mode is enabled
+ * @hide
+ */
+ public static final String POWER_MENU_SOUND_ENABLED = "power_menu_silent_enabled";
+
+ /**
+ * Whether to unlock the screen with the home key. The value is boolean (1 or 0).
+ * @hide
+ */
+ public static final String HOME_UNLOCK_SCREEN = "home_unlock_screen";
+
+ /**
+ * Whether the lockscreen vibrate should be enabled.
+ * @hide
+ */
+ public static final String LOCKSCREEN_VIBRATE_ENABLED = "lockscreen.vibrate_enabled";
+
+ /**
+ * Whether to control torch by holding power button with screen off
+ * @hide
+ */
+ public static final String POWER_BUTTON_TORCH = "power_button_torch";
+
+ /**
+ * Whether to wake the screen with the home, power, or both keys.
+ * @hide
+ */
+ public static final String BUTTON_WAKE_SCREEN = "button_wake_screen";
+
+ /**
+ * Whether to enable custom rebindings of the actions performed on
+ * certain key press events.
+ * @hide
+ */
+ public static final String HARDWARE_KEY_REBINDING = "hardware_key_rebinding";
+
+ /**
+ * Action to perform when the home key pressed. (Default is 1)
+ * 0 - Nothing
+ * 1 - Home
+ * 2 - Back
+ * 3 - Menu
+ * 4 - App-switch
+ * 5 - Search
+ * 6 - Voice Search
+ * 7 - In-App Search
+ * 8 - Power Off
+ * 9 - Notification shade toggle
+ * 10 - Expanded desktop toggle
+ * 11 - Kill App
+ * 12 - Last App
+ * 13 - Custom App
+ * 14 - Camera button
+ * @hide
+ */
+
+ public static final String KEY_HOME_ACTION = "key_home_action";
+
+ /**
+ * Action to perform when the home key is long pressed. (Default is 4)
+ * (See KEY_HOME_LONG_PRESS_ACTION for valid values)
+ * @hide
+ */
+ public static final String KEY_HOME_LONG_PRESS_ACTION = "key_home_long_press_action";
+
+ /**
+ * Action to perform when the back key is pressed. (Default is 2)
+ * (See KEY_HOME_LONG_PRESS_ACTION for valid values)
+ * @hide
+ */
+ public static final String KEY_BACK_ACTION = "key_back_action";
+
+ /**
+ * Action to perform when the back key is long-pressed. (Default is 8)
+ * (See KEY_HOME_LONG_PRESS_ACTION for valid values)
+ * @hide
+ */
+ public static final String KEY_BACK_LONG_PRESS_ACTION = "key_back_long_press_action";
+
+ /**
+ * Action to perform when the menu key is pressed. (Default is 3)
+ * (See KEY_HOME_LONG_PRESS_ACTION for valid values)
+ * @hide
+ */
+ public static final String KEY_MENU_ACTION = "key_menu_action";
+
+ /**
+ * Action to perform when the menu key is long-pressed.
+ * (Default is 0 on devices with a search key, 5 on devices without)
+ * (See KEY_HOME_LONG_PRESS_ACTION for valid values)
+ * @hide
+ */
+ public static final String KEY_MENU_LONG_PRESS_ACTION = "key_menu_long_press_action";
+
+ /**
+ * Action to perform when the assistant (search) key is pressed. (Default is 5)
+ * (See KEY_HOME_LONG_PRESS_ACTION for valid values)
+ * @hide
+ */
+ public static final String KEY_ASSIST_ACTION = "key_assist_action";
+
+ /**
+ * Action to perform when the assistant (search) key is long-pressed. (Default is 6)
+ * (See KEY_HOME_LONG_PRESS_ACTION for valid values)
+ * @hide
+ */
+ public static final String KEY_ASSIST_LONG_PRESS_ACTION = "key_assist_long_press_action";
+
+ /**
+ * Action to perform when the app switch key is pressed. (Default is 4)
+ * (See KEY_HOME_LONG_PRESS_ACTION for valid values)
+ * @hide
+ */
+ public static final String KEY_APP_SWITCH_ACTION = "key_app_switch_action";
+
+ /**
+ * Action to perform when the app switch key is long-pressed. (Default is 0)
+ * (See KEY_HOME_LONG_PRESS_ACTION for valid values)
+ * @hide
+ */
+ public static final String KEY_APP_SWITCH_LONG_PRESS_ACTION = "key_app_switch_long_press_action";
+
+ /**
+ * Action to perform when the camera key is pressed. (Default is 16)
+ * (See KEY_HOME_LONG_PRESS_ACTION for valid values)
+ * @hide
+ */
+ public static final String KEY_CAMERA_ACTION = "key_camera_action";
+
+ /**
+ * Action to perform when the app camera is long-pressed. (Default is 0)
+ * (See KEY_HOME_LONG_PRESS_ACTION for valid values)
+ * @hide
+ */
+ public static final String KEY_CAMERA_LONG_PRESS_ACTION = "key_camera_long_press_action";
+
+ /**
+ * Whether to show the battery bar
+ * @hide
+ */
+ public static final String STATUSBAR_BATTERY_BAR = "statusbar_battery_bar";
+
+ /**
+ * @hide
+ */
+ public static final String STATUSBAR_BATTERY_BAR_COLOR = "statusbar_battery_bar_color";
+
+ /**
+ * @hide
+ */
+ public static final String STATUSBAR_BATTERY_BAR_THICKNESS = "statusbar_battery_bar_thickness";
+
+ /**
+ * @hide
+ */
+ public static final String STATUSBAR_BATTERY_BAR_STYLE = "statusbar_battery_bar_style";
+
+ /**
+ * @hide
+ */
+ public static final String STATUSBAR_BATTERY_BAR_ANIMATE = "statusbar_battery_bar_animate";
+
+ /**
+ * @hide
+ * Style of Battery
+ * 0 - Icon Only
+ * 1 - Text Only
+ * 2 - Icon Text
+ * 3 - Icon Centered Text
+ * 4 - Icon Circle
+ * 5 - Hide
+ */
+ public static final String STATUSBAR_BATTERY_ICON = "statusbar_battery_icon";
+
+ /**
+ * Weather to minimize lockscreen challenge on screen turned on
+ * @hide
+ */
+ public static final String LOCKSCREEN_MAXIMIZE_WIDGETS = "lockscreen_maximize_widgets";
+
+ /**
+ * Circle battery icon color
+ * in statusbar
+ */
+ public static final String STATUS_BAR_CIRCLE_BATTERY_COLOR = "status_bar_circle_battery_color";
+
+ /**
+ * Circle battery icon text color
+ * in statusbar
+ */
+ public static final String STATUS_BAR_CIRCLE_BATTERY_TEXT_COLOR = "status_bar_circle_battery_text_color";
+
+ /**
+ * Circle battery animation speed during charge
+ * in statusbar
+ */
+ public static final String STATUS_BAR_CIRCLE_BATTERY_ANIMATIONSPEED = "status_bar_circle_battery_animationspeed";
+
+ /**
+ * Circle battery icon reset helper
+ * in statusbar
+ */
+ public static final String STATUS_BAR_CIRCLE_BATTERY_RESET = "status_bar_circle_battery_reset";
+
+ /**
+ * Control the display of the action overflow button within app UI.
+ * 0 = use system default
+ * 1 = force on
+ * @hide
+ */
+ public static final String UI_FORCE_OVERFLOW_BUTTON = "ui_force_overflow_button";
+
+ /**
+ * Volume keys control cursor in text fields (default is 0)
+ * 0 - Disabled
+ * 1 - Volume up/down moves cursor left/right
+ * 2 - Volume up/down moves cursor right/left
+ * @hide
+ */
+ public static final String VOLUME_KEY_CURSOR_CONTROL = "volume_key_cursor_control";
+
+ /**
+ * Lefty mode
+ * @hide
+ */
+ public static final String NAVIGATION_BAR_LEFTY_MODE = "navigation_bar_lefty_mode";
+
+ /**
+ *
+ * @hide
+ */
+ public static final String SYSTEMUI_NAVRING_AMOUNT = "systemui_navring_amount";
+
+ /**
+ *
+ * @hide
+ */
+ public static final String SYSTEMUI_NAVRING_LONG_ENABLE = "systemui_navring_long_enable";
+
+ /**
+ * Custom navring actions
+ *
+ * @hide
+ */
+ public static final String[] SYSTEMUI_NAVRING = new String[] {
+ "navring_0",
+ "navring_1",
+ "navring_2",
+ "navring_3",
+ "navring_4",
+ };
+
+ /**
+ * Custom navring long press actions
+ *
+ * @hide
+ */
+ public static final String[] SYSTEMUI_NAVRING_LONG = new String[] {
+ "navring_long_0",
+ "navring_long_1",
+ "navring_long_2",
+ "navring_long_3",
+ "navring_long_4",
+ };
+
+ /**
+ * Custom navring icons
+ *
+ * @hide
+ */
+ public static final String[] SYSTEMUI_NAVRING_ICON = new String[] {
+ "navring_icon_0",
+ "navring_icon_1",
+ "navring_icon_2",
+ "navring_icon_3",
+ "navring_icon_4",
+ };
+
+ /**
+ * Clock Actions 0 = single, 1 = long, 2 = double click
+ *
+ * @hide
+ */
+ public static final String[] NOTIFICATION_CLOCK = new String[] {
+ "notification_clock_0",
+ "notification_clock_1",
+ "notification_clock_2",
+ };
+
+ /**
+ * Custom carrier label
+ */
+ public static final String CUSTOM_CARRIER_LABEL = "custom_carrier_label";
+
+ /**
+ * Screenshot toggle delay
+ * @hide
+ */
+ public static final String SCREENSHOT_TOGGLE_DELAY = "screenshot_toggle_delay";
+
+ /**
+ * User configurable flag for determining if NavBar is enabled
+ *
+ * @hide
+ */
+ public static final String NAVIGATION_BAR_SHOW = "navigation_bar_show";
+
+
+ /**
+ * Used as a flag to determine if we are showing the NavBar *NOW* or is it hidden
+ * @hide
+ */
+ public static final String NAVIGATION_BAR_SHOW_NOW = "navigation_bar_show_now";
+
+ /**
+ * Used as a flag to determine if we have statusbar hidden
+ * @hide
+ */
+ public static final String STATUSBAR_HIDDEN = "statusbar_hidden";
+
+ /**
+ * Statusbar toggle for quick settings
+ * &hide
+ */
+ public static final String STATUSBAR_QUICK_TOGGLE = "statusbar_quick_toggle";
+
+ /**
+ * Show the NavBar dialog in Power menu
+ * @hide
+ */
+ public static final String POWER_DIALOG_SHOW_NAVBAR_HIDE = "power_dialog_show_navbar_hide";
+
+ /**
+ * If checked hide extra system bar stuff
+ * ie compatmode button and extra ime switcher.
+ */
+ public static final String HIDE_EXTRAS_SYSTEM_BAR = "hide_extras_system_bar";
+
+ /**
+ * @hide
+ */
+ public static final String NAVIGATION_BAR_HEIGHT = "navigation_bar_height";
+
+ /**
+ * Pie will not rotate. Should default to 1 (yes, do not rotate)
+ * @hide
+ */
+ public static final String NAVIGATION_BAR_HEIGHT_LANDSCAPE = "navigation_bar_height_landscape";
+
+ /**
+ * @hide
+ */
+ public static final String NAVIGATION_BAR_WIDTH = "navigation_bar_width";
+
+ /**
+ * Pie menu, should default to 0 (no, show only when needed)
+ * Restart Launcher
+ * @hide
+ */
+ public static final String EXPANDED_DESKTOP_RESTART_LAUNCHER = "expanded_desktop_restart_launcher";
+
+ /**
+ * On or off the Pie.
+ * @hide
+ */
+ public static final String PIE_CONTROLS = "pie_controls";
+
+ /**
+ * Pie menu, should default to 1 (yes, show)
+ * @hide
+ */
+ public static final String PIE_MENU = "pie_menu";
+
+ /**
+ * Pie search, should default to 1 (yes, show)
+ * @hide
+ */
+ public static final String PIE_SEARCH = "pie_search";
+
+ /**
+ * Pie will not rotate. Should default to 1 (yes, do not rotate)
+ * @hide
+ */
+ public static final String PIE_STICK = "pie_stick";
+
+ /**
+ * Center Pie? Should default to 1 (yes, center)
+ * @hide
+ */
+ public static final String PIE_CENTER = "pie_center";
+
+ /**
+ * Pie last app, should default to 0 (no, show only when needed)
+ * @hide
+ */
+ public static final String PIE_LAST_APP = "pie_last_app";
+
+ /**
+ * Pie kill task, default to 0 (off)
+ * @hide
+ */
+ public static final String PIE_KILL_TASK = "pie_kill_task";
+
+ /**
+ * Pie action widgets, default to off
+ * @hide
+ */
+ public static final String PIE_APP_WINDOW = "pie_app_window";
+
+ /**
+ * Pie action notifications, default to off
+ * @hide
+ */
+ public static final String PIE_ACT_NOTIF = "pie_act_notif";
+
+ /**
+ * Pie action quicksettings, default to off
+ * @hide
+ */
+ public static final String PIE_ACT_QS = "pie_act_qs";
+
+ /*
+ * Pie gap angle, should default to 2
+ * @hide
+ */
+ public static final String PIE_GAP = "pie_gap";
+
+ /**
+ * Pie empty angle, should default to 12
+ * @hide
+ */
+ public static final String PIE_ANGLE = "pie_angle";
+
+ /**
+ * Pie trigger fraction, should default to 1
+ * @hide
+ */
+ public static final String PIE_TRIGGER = "pie_trigger";
+
+ /**
+ * Location of the pie in the screen
+ * 0 = Gravity.LEFT
+ * 1 = Gravity.TOP
+ * 2 = Gravity.RIGHT
+ * 3 = Gravity.BOTTOM (default)
+ * @hide
+ */
+ public static final String PIE_GRAVITY = "pie_gravity";
+
+ /**
+ * Pie status report
+ * 0 = Bare
+ * 1 = Quick
+ * 2 = Default
+ * 3 = Slow
+ * @hide
+ */
+ public static final String PIE_MODE = "pie_mode";
+
+ /**
+ * Pie size fraction, default is 1.0f (normal)
+ * @hide
+ */
+ public static final String PIE_SIZE = "pie_size";
+
+ /**
+ * Pie Notification Ability
+ * @hide
+ */
+ public static final String PIE_NOTIFICATIONS = "pie_notifications";
+
+ // PIE COLORS EVERYWHERE! //
+
+ /**
+ * @hide
+ */
+ public static final String PIE_ENABLE_COLOR = "pie_enable_color";
+
+ /**
+ * @hide
+ */
+ public static final String PIE_JUICE = "pie_juice";
+
+ /**
+ * @hide
+ */
+ public static final String PIE_BUTTON_COLOR = "pie_button_color";
+
+ /**
+ * @hide
+ */
+ public static final String PIE_SNAP_BACKGROUND = "pie_snap_background";
+
+ /**
+ * @hide
+ */
+ public static final String PIE_BACKGROUND = "pie_background";
+
+ /**
+ * @hide
+ */
+ public static final String PIE_SELECT = "pie_select";
+
+ /**
+ * @hide
+ */
+ public static final String PIE_OUTLINES = "pie_outlines";
+
+ /**
+ * @hide
+ */
+ public static final String PIE_STATUS_CLOCK = "pie_status_clock";
+
+ /**
+ * @hide
+ */
+ public static final String PIE_STATUS = "pie_status";
+
+ /**
+ * @hide
+ */
+ public static final String PIE_CHEVRON_LEFT = "pie_chevron_left";
+
+ /**
+ * @hide
+ */
+ public static final String PIE_CHEVRON_RIGHT = "pie_chevron_right";
+
+ // PIE COLORS EVERYWHERE! //
+
+ /**
+ * HALO, should default to 0 (no, do not show)
+ * @hide
+ */
+ public static final String HALO_ACTIVE = "halo_active";
+
+ /**
+ * HALO reversed?, should default to 1 (yes, reverse)
+ * @hide
+ */
+ public static final String HALO_REVERSED = "halo_reversed";
+
+ /**
+ * HALO hide?, should default to 0 (no, do not hide)
+ * @hide
+ */
+ public static final String HALO_HIDE = "halo_hide";
+
+ /**
+ * HALO pause activities?, defaults to 0 (no, do not pause) on devices which isLargeRAM() == true
+ * otherwise it defaults to 1 (yes, do pause)
+ * @hide
+ */
+ public static final String HALO_PAUSE = "halo_pause";
+
+ /**
+ * HALO enabled, should default to 0 (HALO is disabled)
+ * @hide
+ */
+ public static final String HALO_ENABLED = "halo_enabled";
+
+ /**
+ * HALO colors
+ * @hide
+ */
+ public static final String HALO_COLORS = "halo_colors";
+
+ /**
+ * HALO speech bubble color
+ * @hide
+ */
+ public static final String HALO_BUBBLE_COLOR = "halo_bubble_color";
+
+ /**
+ * HALO speech bubble text color
+ * @hide
+ */
+ public static final String HALO_BUBBLE_TEXT_COLOR = "halo_bubble_text_color";
+
+ /**
+ * HALO effect color
+ * @hide
+ */
+ public static final String HALO_EFFECT_COLOR = "halo_effect_color";
+
+ /**
+ * HALO circle bg color
+ * @hide
+ */
+ public static final String HALO_CIRCLE_COLOR = "halo_circle_color";
+
+ /**
+ * HALO size fraction, default is 1.0f (normal)
+ * @hide
+ */
+ public static final String HALO_SIZE = "halo_size";
+
+ /**
+ * Swap volume buttons when the screen is rotated by 90 or 180 degrees
+ * @hide
+ */
+ public static final String SWAP_VOLUME_KEYS = "swap_volume_keys";
+
+ /**
+ *
+ * @hide
+ */
+ public static final String NAVIGATION_BAR_WIDTH_PORT = "navigation_bar_width_port";
+
+ /**
+ *
+ * @hide
+ */
+ public static final String NAVIGATION_BAR_WIDTH_LAND = "navigation_bar_width_land";
+
+ /**
+ * @hide
+ */
+ public static final String NAV_HIDE_TIMEOUT = "nav_hide_timeout";
+
+ /**
+ * @hide
+ */
+ public static final String NAV_HIDE_ENABLE = "nav_hide_enable";
+
+ /**
+ * @hide
+ */
+ public static final String DRAG_HANDLE_WEIGHT = "drag_handle_weight";
+
+ /**
+ * @hide
+ */
+ public static final String DRAG_HANDLE_OPACITY = "drag_handle_opacity";
+
+ /**
+ * @hide
+ */
+ public static final String MENU_LOCATION = "menu_location";
+
+ /**
+ * @hide
+ */
+ public static final String MENU_VISIBILITY = "menu_visibility";
+
+ /**
+ * @hide
+ */
+ public static final String NAVIGATION_BAR_BUTTONS_QTY = "navigation_bar_buttons_qty";
+
+ /**
+ * @hide
+ */
+ public static final String[] NAVIGATION_CUSTOM_ACTIVITIES = new String[] {
+ "navigation_custom_app_intent_0",
+ "navigation_custom_app_intent_1",
+ "navigation_custom_app_intent_2",
+ "navigation_custom_app_intent_3",
+ "navigation_custom_app_intent_4",
+ "navigation_custom_app_intent_5",
+ "navigation_custom_app_intent_6",
+ };
+
+ /**
+ * @hide
+ */
+ public static final String[] NAVIGATION_LONGPRESS_ACTIVITIES = new String[] {
+ "navigation_longpress_app_intent_0",
+ "navigation_longpress_app_intent_1",
+ "navigation_longpress_app_intent_2",
+ "navigation_longpress_app_intent_3",
+ "navigation_longpress_app_intent_4",
+ "navigation_longpress_app_intent_5",
+ "navigation_longpress_app_intent_6",
+ };
+
+ /**
+ * @hide
+ */
+ public static final String[] NAVIGATION_CUSTOM_APP_ICONS = new String[] {
+ "navigation_custom_app_icon_0",
+ "navigation_custom_app_icon_1",
+ "navigation_custom_app_icon_2",
+ "navigation_custom_app_icon_3",
+ "navigation_custom_app_icon_4",
+ "navigation_custom_app_icon_5",
+ "navigation_custom_app_icon_6",
+ };
+
+ /**
+ * Widgets to show, should be separated by |
+ */
+ public static final String NAVIGATION_BAR_WIDGETS = "navigation_bar_widgets";
+
+ /**
+ * @hide
+ */
+ public static final String NAVIGATION_BAR_BUTTON_ALPHA = "navigation_bar_button_alpha";
+
+ /**
+ * @hide
+ */
+ public static final String NAVIGATION_BAR_TINT = "navigation_bar_tint";
+
+ /**
+ * Option To Colorize ALL Nav Icons
+ */
+ public static final String NAVIGATION_BAR_ALLCOLOR = "navigation_bar_allcolor";
+
+ /**
+ * @hide
+ */
+ public static final String NAVIGATION_BAR_GLOW_TINT = "navigation_bar_glow_tint";
+
+ /**
+ * @hide
+ */
+ public static final String[] NAVIGATION_BAR_GLOW_DURATION = new String[] {
+ "navigation_bar_glow_duration_off",
+ "navigation_bar_glow_duration_on",
+ };
+
+ /**
+ * Wether the hints for the left and right widgets are shown when the screen is turned on
+ * @hide
+ */
+ public static final String LOCKSCREEN_HIDE_INITIAL_PAGE_HINTS = "lockscreen_hide_initial_page_hints";
+
+ /**
+ * Whether to use the carousel as widget container
+ * @hide
+ */
+ public static final String LOCKSCREEN_USE_WIDGET_CONTAINER_CAROUSEL = "lockscreen_use_widget_container_carousel";
+
+ /**
+ * enabled and order of quick toggles
+ *
+ * @hide
+ */
+ public static final String QUICK_TOGGLES = "quick_toggles";
+
+ /**
+ * number of tiles per row in quick settings
+ *
+ * @hide
+ */
+ public static final String QUICK_TOGGLES_PER_ROW = "quick_toggles_per_row";
+
+ /**
+ * favorite contact for quick settings
+ *
+ * @hide
+ */
+ public static final String QUICK_TOGGLE_FAV_CONTACT = "quick_toggle_fav_contact";
+
+ /**
+ *
+ * @hide
+ */
+ public static final String LOCKSCREEN_TARGETS_LONGPRESS = "lockscreen_targets_longpress";
+
+ /**
+ * @hide
+ */
+ public static final String[] LOCKSCREEN_TARGETS_SHORT = new String[] {
+ "lockscreen_targets_short_0",
+ "lockscreen_targets_short_1",
+ "lockscreen_targets_short_2",
+ "lockscreen_targets_short_3",
+ "lockscreen_targets_short_4",
+ "lockscreen_targets_short_5",
+ "lockscreen_targets_short_6",
+ "lockscreen_targets_short_7",
+ };
+
+ /**
+ * @hide
+ */
+ public static final String[] LOCKSCREEN_TARGETS_LONG = new String[] {
+ "lockscreen_targets_long_0",
+ "lockscreen_targets_long_1",
+ "lockscreen_targets_long_2",
+ "lockscreen_targets_long_3",
+ "lockscreen_targets_long_4",
+ "lockscreen_targets_long_5",
+ "lockscreen_targets_long_6",
+ "lockscreen_targets_long_7",
+ };
+
+ /**
+ * @hide
+ */
+ public static final String[] LOCKSCREEN_TARGETS_ICON = new String[] {
+ "lockscreen_targets_icon_0",
+ "lockscreen_targets_icon_1",
+ "lockscreen_targets_icon_2",
+ "lockscreen_targets_icon_3",
+ "lockscreen_targets_icon_4",
+ "lockscreen_targets_icon_5",
+ "lockscreen_targets_icon_6",
+ "lockscreen_targets_icon_7",
+ };
+
+ /**
+ * Ribbon Targets
+ *
+ * @hide
+ */
+ public static final String[] RIBBON_TARGETS_SHORT = new String[] {
+ "ribbon_targets_short_lockscreen",
+ "ribbon_targets_short_notification",
+ "ribbon_targets_short_swipe",
+ "ribbon_targets_short_quicksettings",
+ "ribbon_targets_short_swipe_right",
+ "ribbon_targets_short_swipe_bottom",
+ };
+
+ /**
+ * Ribbon Targets
+ *
+ * @hide
+ */
+ public static final String[] RIBBON_TARGETS_LONG = new String[] {
+ "ribbon_targets_long_lockscreen",
+ "ribbon_targets_long_notification",
+ "ribbon_targets_long_swipe",
+ "ribbon_targets_long_quicksettings",
+ "ribbon_targets_long_swipe_right",
+ "ribbon_targets_long_swipe_bottom",
+ };
+
+ /**
+ * Ribbon Targets
+ *
+ * @hide
+ */
+ public static final String[] RIBBON_TARGETS_ICONS = new String[] {
+ "ribbon_targets_icons_lockscreen",
+ "ribbon_targets_icons_notification",
+ "ribbon_targets_icons_swipe",
+ "ribbon_targets_icons_quicksettings",
+ "ribbon_targets_icons_swipe_right",
+ "ribbon_targets_icons_swipe_bottom",
+ };
+
+ /**
+ * Ribbon Targets
+ *
+ * @hide
+ */
+ public static final String[] ENABLE_RIBBON_TEXT = new String[] {
+ "ribbon_text_lockscreen",
+ "ribbon_text_notification",
+ "ribbon_text_swipe",
+ "ribbon_text_quicksettings",
+ "ribbon_text_swipe_right",
+ "ribbon_text_swipe_bottom",
+ };
+
+ /**
+ * Ribbon Targets
+ *
+ * @hide
+ */
+ public static final String[] RIBBON_TEXT_COLOR = new String[] {
+ "color_text_lockscreen",
+ "color_text_notification",
+ "color_text_swipe",
+ "color_text_quicksettings",
+ "color_text_swipe_right",
+ "color_text_swipe_bottom",
+ };
+
+ /**
+ * Ribbon Targets
+ *
+ * @hide
+ */
+ public static final String[] RIBBON_ICON_SIZE = new String[] {
+ "ribbon_icon_lockscreen",
+ "ribbon_icon_notification",
+ "ribbon_icon_swipe",
+ "ribbon_icon_quicksettings",
+ "ribbon_icon_swipe_right",
+ "ribbon_icon_swipe_bottom",
+ };
+
+ public static final String[] ENABLE_RIBBON_LOCATION = new String[] {
+ "ribbon_swipe_bottom",
+ "ribbon_swipe_left",
+ "ribbon_swipe_right",
+ };
+
+ /**
+ *
+ * @hide
+ */
+ public static final String[] RIBBON_ICON_SPACE = new String[] {
+ "ribbon_icon_lockscreen_space",
+ "ribbon_icon_notification_space",
+ "ribbon_icon_swipe_space_left",
+ "ribbon_icon_quicksettings_space",
+ "ribbon_icon_swipe_space_right",
+ "ribbon_icon_swipe_space_bottom",
+ };
+
+ /**
+ * Ribbon Targets
+ *
+ * @hide
+ */
+ public static final String[] RIBBON_ICON_VIBRATE = new String[] {
+ "ribbon_icon_lockscreen_vibrate",
+ "ribbon_icon_notification_vibrate",
+ "ribbon_icon_swipe_vibrate",
+ "ribbon_icon_quicksettings_vibrate",
+ "ribbon_icon_swipe_vibrate_right",
+ "ribbon_icon_swipe_vibrate_bottom",
+ };
+
+ /**
+ * Ribbon Targets
+ *
+ * @hide
+ */
+ public static final String[] RIBBON_ICON_COLORIZE = new String[] {
+ "ribbon_icon_lockscreen_colorize",
+ "ribbon_icon_notification_colorize",
+ "ribbon_icon_swipe_colorize",
+ "ribbon_icon_quicksettings_colorize",
+ "ribbon_icon_swipe_colorize_right",
+ "ribbon_icon_swipe_colorize_bottom",
+ };
+
+ /**
+ *
+ * @hide
+ */
+ public static final String[] RIBBON_HIDE_TIMEOUT = new String[] {
+ "ribbon_hide_timeout_left",
+ "ribbon_hide_timeout_right",
+ "ribbon_hide_timeout_bottom",
+ };
+
+ /**
+ *
+ * @hide
+ */
+ public static final String[] SWIPE_RIBBON_OPACITY = new String[] {
+ "swipe_ribbon_opacity_left",
+ "swipe_ribbon_opacity_right",
+ "swipe_ribbon_opacity_bottom",
+ };
+
+ /**
+ *
+ * @hide
+ */
+ public static final String[] SWIPE_RIBBON_COLOR = new String[] {
+ "swipe_ribbon_color_left",
+ "swipe_ribbon_color_right",
+ "swipe_ribbon_color_bottom",
+ };
+
+ /**
+ *
+ * @hide
+ */
+ public static final String[] SWIPE_RIBBON_TOGGLES = new String[] {
+ "swipe_ribbon_toggles_left",
+ "swipe_ribbon_toggles_right",
+ "swipe_ribbon_toggles_bottom",
+ };
+
+ /**
+ *
+ * @hide
+ */
+ public static final String[] RIBBON_LONG_PRESS = new String[] {
+ "ribbon_long_press_left",
+ "ribbon_long_press_right",
+ "ribbon_long_press_bottom",
+ };
+
+ /**
+ *
+ * @hide
+ */
+ public static final String[] RIBBON_LONG_SWIPE = new String[] {
+ "ribbon_long_swipe_left",
+ "ribbon_long_swipe_right",
+ "ribbon_long_swipe_bottom",
+ };
+
+ /**
+ *
+ * @hide
+ */
+ public static final String[] RIBBON_ANIMATION_DURATION = new String[] {
+ "ribbon_animation_duration_left",
+ "ribbon_animation_duration_right",
+ "ribbon_animation_duration_bottom",
+ };
+
+ /**
+ * Ribbon Targets
+ *
+ * @hide
+ */
+ public static final String[] RIBBON_DISMISS = new String[] {
+ "ribbon_left_dismiss",
+ "ribbon_right_dismiss",
+ "ribbon_bottom_dismiss",
+
+ };
+
+ /**
+ *
+ * @hide
+ */
+ public static final String APP_WINDOW_ANIMATION_DURATION = "app_window_animation_duration";
+
+ /**
+ * Ribbon Targets
+ *
+ * @hide
+ */
+ public static final String[] RIBBON_DRAG_HANDLE_WEIGHT = new String[] {
+ "ribbon_drag_handle_weight_left",
+ "ribbon_drag_handle_weight_right",
+ "ribbon_drag_handle_weight_bottom",
+
+ };
+
+ /**
+ *
+ * @hide
+ */
+ public static final String APP_WINDOW_COLOR_BG = "app_window_color_bg";
+
+ /**
+ *
+ * @hide
+ */
+ public static final String APP_WINDOW_COLUMNS = "app_window_columns";
+
+ /**
+ *
+ * @hide
+ */
+ public static final String APP_WINDOW_COLOR_TEXT = "app_window_color_text";
+
+ /**
+ *
+ * @hide
+ */
+ public static final String APP_WINDOW_OPACITY = "app_window_opacity";
+
+ /**
+ *
+ * @hide
+ */
+ public static final String APP_WINDOW_HIDDEN_APPS = "app_window_hidden_apps";
+
+ /**
+ *
+ * @hide
+ */
+ public static final String APP_WINDOW_ANIMATION_TYPE = "app_window_animation_type";
+
+ /**
+ *
+ * @hide
+ */
+ public static final String LAUNCH_APP_ANIMATION = "launch_app_animation";
+
+ /**
+ *
+ * @hide
+ */
+ public static final String APP_WINDOW_SPACING = "app_window_spacing";
+
+ /**
+ * Ribbon Targets
+ *
+ * @hide
+ */
+ public static final String[] RIBBON_DRAG_HANDLE_LOCATION = new String[] {
+ "ribbon_drag_handle_location_left",
+ "ribbon_drag_handle_location_right",
+ "ribbon_drag_handle_location_bottom",
+
+ };
+
+ /**
+ * Ribbon Targets
+ *
+ * @hide
+ */
+ public static final String[] RIBBON_HIDE_IME = new String[] {
+ "ribbon_hide_ime_left",
+ "ribbon_hide_ime_right",
+ "ribbon_hide_ime_bottom",
+
+ };
+
+ /**
+ * Ribbon Targets
+ *
+ * @hide
+ */
+ public static final String[] RIBBON_TOGGLE_BUTTON_LOCATION = new String[] {
+ "ribbon_toggle_button_location_left",
+ "ribbon_toggle_button_location_right",
+ "ribbon_toggle_button_location_bottom",
+
+ };
+
+ /**
+ * Ribbon Targets
+ *
+ * @hide
+ */
+ public static final String[] RIBBON_ANIMATION_TYPE = new String[] {
+ "ribbon_animation_type_left",
+ "ribbon_animation_type_right",
+ "ribbon_animation_type_bottom",
+ };
+
+ /**
+ *
+ * @hide
+ */
+ public static final String[] RIBBON_ICON_LOCATION = new String[] {
+ "ribbon_icon_location_left",
+ "ribbon_icon_location_right",
+ };
+
+ /**
+ * Ribbon Targets
+ *
+ * @hide
+ */
+ public static final String[] SWIPE_RIBBON_VIBRATE = new String[] {
+ "swipe_ribbon_vibrate_left",
+ "swipe_ribbon_vibrate_right",
+ "swipe_ribbon_vibrate_bottom",
+
+ };
+
+ /**
+ * Ribbon Targets
+ *
+ * @hide
+ */
+ public static final String[] RIBBON_DRAG_HANDLE_HEIGHT = new String[] {
+ "ribbon_drag_handle_height_left",
+ "ribbon_drag_handle_height_right",
+ "ribbon_drag_handle_height_bottom",
+
+ };
+
+ /**
+ * Ribbon Targets
+ *
+ * @hide
+ */
+ public static final String[] RIBBON_DRAG_HANDLE_OPACITY = new String[] {
+ "ribbon_drag_handle_opacity_left",
+ "ribbon_drag_handle_opacity_right",
+ "ribbon_drag_handle_opacity_bottom",
+
+ };
+
+ /**
+ * enable and disable fast toggle in settings
+ *
+ * @hide
+ */
+ public static final String FAST_TOGGLE = "fast_toggle";
+
+ /**
+ * enable and disable fast toggle in settings
+ *
+ * @hide
+ */
+ public static final String CHOOSE_FASTTOGGLE_SIDE = "choose_fasttoggle_side";
+
+ /**
+ * Current UI Mode
+ *
+ * 0 = Phone UI
+ * 1 = Tablet UI
+ * 2 = Phablet UI
+ * @hide
+ */
+ public static final String CURRENT_UI_MODE = "current_ui_mode";
+
+ /**
+ * enable and disable shade collapse on click
+ *
+ * @hide
+ */
+ public static final String SHADE_COLLAPSE_ALL = "shade_collapse_all";
+
+ /**
+ * User selected UI Mode
+ *
+ * 0 = Phone UI
+ * 1 = Tablet UI
+ * 2 = Phablet UI
+ * @hide
+ */
+ public static final String USER_UI_MODE = "user_ui_mode";
+
+ /**
+ * MediaScanner behavior on boot.
+ * 0 = enabled
+ * 1 = ask (notification)
+ * 2 = disabled
+ * @hide
+ */
+ public static final String MEDIA_SCANNER_ON_BOOT = "media_scanner_on_boot";
+
+ /**
+ * Allows to show the background activity back the lockscreen
* @hide
*/
- @Deprecated
- public static final String DOCK_SOUNDS_ENABLED = Global.DOCK_SOUNDS_ENABLED;
+ public static final String LOCKSCREEN_SEE_THROUGH = "lockscreen_see_through";
- /**
- * Whether to play sounds when the keyguard is shown and dismissed.
+ /**
+ * Give MMS Notifications a breathing effect
* @hide
*/
- public static final String LOCKSCREEN_SOUNDS_ENABLED = "lockscreen_sounds_enabled";
+ public static final String MMS_BREATH = "mms_breath";
- /**
- * Whether the lockscreen should be completely disabled.
+ /**
+ * Give MMS Notifications a breathing effect
* @hide
*/
- public static final String LOCKSCREEN_DISABLED = "lockscreen.disabled";
+ public static final String MISSED_CALL_BREATH = "missed_call_breath";
- /**
- * @deprecated Use {@link android.provider.Settings.Global#LOW_BATTERY_SOUND}
- * instead
+ /**
* @hide
*/
- @Deprecated
- public static final String LOW_BATTERY_SOUND = Global.LOW_BATTERY_SOUND;
+ public static final String CUSTOM_TOGGLE_REVERT = "custom_toggle_revert";
/**
- * @deprecated Use {@link android.provider.Settings.Global#DESK_DOCK_SOUND}
- * instead
* @hide
*/
- @Deprecated
- public static final String DESK_DOCK_SOUND = Global.DESK_DOCK_SOUND;
+ public static final String CUSTOM_TOGGLE_STATE = "custom_toggle_state";
/**
- * @deprecated Use {@link android.provider.Settings.Global#DESK_UNDOCK_SOUND}
- * instead
* @hide
*/
- @Deprecated
- public static final String DESK_UNDOCK_SOUND = Global.DESK_UNDOCK_SOUND;
+ public static final String DCLICK_TOGGLE_REVERT = "dclick_toggle_revert";
/**
- * @deprecated Use {@link android.provider.Settings.Global#CAR_DOCK_SOUND}
- * instead
* @hide
*/
- @Deprecated
- public static final String CAR_DOCK_SOUND = Global.CAR_DOCK_SOUND;
+ public static final String MATCH_ACTION_ICON = "match_action_icon";
/**
- * @deprecated Use {@link android.provider.Settings.Global#CAR_UNDOCK_SOUND}
- * instead
* @hide
*/
- @Deprecated
- public static final String CAR_UNDOCK_SOUND = Global.CAR_UNDOCK_SOUND;
+ public static final String COLLAPSE_SHADE = "collapse_shade";
/**
- * @deprecated Use {@link android.provider.Settings.Global#LOCK_SOUND}
- * instead
* @hide
*/
- @Deprecated
- public static final String LOCK_SOUND = Global.LOCK_SOUND;
+ public static final String CUSTOM_TOGGLE_QTY = "custom_toggle_qty";
/**
- * @deprecated Use {@link android.provider.Settings.Global#UNLOCK_SOUND}
- * instead
* @hide
*/
- @Deprecated
- public static final String UNLOCK_SOUND = Global.UNLOCK_SOUND;
+ public static final String[] CUSTOM_PRESS_TOGGLE = new String[] {
+ "toggle_custom_app_intent_0",
+ "toggle_custom_app_intent_1",
+ "toggle_custom_app_intent_2",
+ "toggle_custom_app_intent_3",
+ "toggle_custom_app_intent_4",
+ };
/**
- * Receive incoming SIP calls?
- * 0 = no
- * 1 = yes
* @hide
*/
- public static final String SIP_RECEIVE_CALLS = "sip_receive_calls";
+ public static final String[] CUSTOM_LONGPRESS_TOGGLE = new String[] {
+ "toggle_custom_app_longintent_0",
+ "toggle_custom_app_longintent_1",
+ "toggle_custom_app_longintent_2",
+ "toggle_custom_app_longintent_3",
+ "toggle_custom_app_longintent_4",
+ };
/**
- * Call Preference String.
- * "SIP_ALWAYS" : Always use SIP with network access
- * "SIP_ADDRESS_ONLY" : Only if destination is a SIP address
- * "SIP_ASK_ME_EACH_TIME" : Always ask me each time
* @hide
*/
- public static final String SIP_CALL_OPTIONS = "sip_call_options";
+ public static final String[] CUSTOM_TOGGLE_ICONS = new String[] {
+ "custom_toggle_icons_0",
+ "custom_toggle_icons_1",
+ "custom_toggle_icons_2",
+ "custom_toggle_icons_3",
+ "custom_toggle_icons_4",
+ };
/**
- * One of the sip call options: Always use SIP with network access.
+ * Battery warning preferences
+ *
+ * 0 = show dialog + play sound (default)
+ * 1 = fire notification + play sound
+ * 2 = show dialog only
+ * 3 = fire notification only
+ * 4 = play sound only
+ * 5 = none
* @hide
*/
- public static final String SIP_ALWAYS = "SIP_ALWAYS";
+ public static final String POWER_UI_LOW_BATTERY_WARNING_POLICY = "power_ui_low_battery_warning_policy";
/**
- * One of the sip call options: Only if destination is a SIP address.
- * @hide
+ * Use alternative application resolver
*/
- public static final String SIP_ADDRESS_ONLY = "SIP_ADDRESS_ONLY";
+ public static final String ACTIVITY_RESOLVER_USE_ALT = "activity_resolver_use_alt";
/**
- * One of the sip call options: Always ask me each time.
* @hide
- */
- public static final String SIP_ASK_ME_EACH_TIME = "SIP_ASK_ME_EACH_TIME";
-
+ */
+ public static final String KG_CAMERA_WIDGET = "kg_camera_widget";
+
/**
- * Pointer speed setting.
- * This is an integer value in a range between -7 and +7, so there are 15 possible values.
- * -7 = slowest
- * 0 = default speed
- * +7 = fastest
+ * Volume key controls ringtone or media sound stream
+ *
* @hide
*/
- public static final String POINTER_SPEED = "pointer_speed";
+ public static final String VOLUME_KEYS_CONTROL_RING_STREAM = "volume_keys_control_ring_stream";
/**
* Settings to backup. This is here so that it's in the same place as the settings
@@ -2292,6 +4676,8 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean
WIFI_STATIC_NETMASK,
WIFI_STATIC_DNS1,
WIFI_STATIC_DNS2,
+ MMS_AUTO_RETRIEVAL,
+ MMS_AUTO_RETRIEVAL_ON_ROAMING,
BLUETOOTH_DISCOVERABILITY,
BLUETOOTH_DISCOVERABILITY_TIMEOUT,
DIM_SCREEN,
@@ -2325,10 +4711,13 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean
AUTO_TIME_ZONE, // moved to global
TIME_12_24,
DATE_FORMAT,
+ ACCELEROMETER_ROTATION,
+ USER_ROTATION,
DTMF_TONE_WHEN_DIALING,
DTMF_TONE_TYPE_WHEN_DIALING,
HEARING_AID,
TTY_MODE,
+ NOISE_SUPPRESSION,
SOUND_EFFECTS_ENABLED,
HAPTIC_FEEDBACK_ENABLED,
POWER_SOUNDS_ENABLED, // moved to global
@@ -2336,10 +4725,28 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean
LOCKSCREEN_SOUNDS_ENABLED,
SHOW_WEB_SUGGESTIONS,
NOTIFICATION_LIGHT_PULSE,
+ NOTIFICATION_LIGHT_PULSE_DEFAULT_COLOR,
+ NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_ON,
+ NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_OFF,
SIP_CALL_OPTIONS,
SIP_RECEIVE_CALLS,
POINTER_SPEED,
- VIBRATE_WHEN_RINGING
+ QUIET_HOURS_ENABLED,
+ QUIET_HOURS_START,
+ QUIET_HOURS_END,
+ QUIET_HOURS_MUTE,
+ QUIET_HOURS_STILL,
+ QUIET_HOURS_DIM,
+ SYSTEM_PROFILES_ENABLED,
+ POWER_MENU_SCREENSHOT_ENABLED,
+ POWER_MENU_TORCH_ENABLED,
+ POWER_MENU_REBOOT_ENABLED,
+ POWER_MENU_PROFILES_ENABLED,
+ POWER_MENU_AIRPLANE_ENABLED,
+ POWER_MENU_SOUND_ENABLED,
+ POWER_MENU_USER_ENABLED,
+ LOCKSCREEN_VIBRATE_ENABLED,
+ LOCKSCREEN_ALWAYS_SHOW_BATTERY,
};
// Settings moved to Settings.Secure
@@ -2469,6 +4876,13 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean
public static final String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON =
Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON;
+ /**
+ * wake up when plugged or unplugged
+ *
+ * @hide
+ */
+ public static final String WAKEUP_WHEN_PLUGGED_UNPLUGGED = "wakeup_when_plugged_unplugged";
+
/**
* @deprecated Use
* {@link android.provider.Settings.Global#WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY} instead
@@ -2571,6 +4985,115 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean
@Deprecated
public static final String WIFI_WATCHDOG_PING_TIMEOUT_MS =
Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS;
+
+ /**
+ * @hide
+ */
+ public static final String STATUS_BAR_BRIGHTNESS_SLIDER = "statusbar_brightness_slider";
+
+ /**
+ * @hide
+ */
+ public static final String STATUSBAR_TOGGLES_BRIGHTNESS_LOC = "statusbar_toggles_brightness_loc";
+
+ /**
+ * Navigation bar color.
+ *
+ * @hide
+ */
+ public static final String NAVIGATION_BAR_COLOR = "navigation_bar_color";
+
+ /**
+ * @hide
+ */
+ public static final String NAVIGATION_BAR_ALPHA_CONFIG = "navigation_bar_alpha_config";
+
+ /**
+ * @hide
+ */
+ public static final String STATUS_BAR_ALPHA_CONFIG = "status_bar_alpha_config";
+
+ /**
+ * @hide
+ * Show Wifi network name in notification shade
+ * 0 - don't show
+ * 1 - show
+ */
+ public static final String NOTIFICATION_SHOW_WIFI_SSID = "notification_show_wifi_ssid";
+
+ /**
+ * Whether to allow notification vibration while notification alerts are disabled
+ * (e.g. during phone calls). The vibration pattern to be used will be a subtle one;
+ * custom vibration is disabled at that point.
+ * @hide
+ */
+ public static final String NOTIFICATION_VIBRATE_DURING_ALERTS_DISABLED = "vibrate_while_no_alerts";
+
+ /**
+ * Whether to enable notification shortcuts (toggle)
+ *
+ * @hide
+ */
+
+ public static final String NOTIFICATION_SHORTCUTS_TOGGLE = "pref_notification_shortcuts_toggle";
+
+ /**
+ * Stores the number of notification shortcuts to display settings for
+ * @hide
+ */
+ public static final String NOTIFICATION_SHORTCUTS_QUANTITY = "pref_notification_shortcuts_quantity";
+
+ /**
+ * Stores values for notification shortcut targets
+ * @hide
+ */
+ public static final String NOTIFICATION_SHORTCUTS_TARGETS = "notification_shortcuts_targets";
+
+ /**
+ * Stores the value for notification shortcuts icon color
+ * @hide
+ */
+ public static final String NOTIFICATION_SHORTCUTS_COLOR = "notification_shortcuts_color";
+
+ /**
+ * Whether to colorize the default application icons
+ * @hide
+ */
+ public static final String NOTIFICATION_SHORTCUTS_COLORIZE_TOGGLE = "notification_shortcuts_colorize_toggle";
+
+ /**
+ * Whether to colorize the default application icons
+ * @hide
+ */
+ public static final String NOTIFICATION_SHORTCUTS_HIDE_CARRIER = "notification_shortcuts_hide_carrier";
+
+ /**
+ * boolean value. toggles using arrow key locations on nav bar
+ * as left and right dpad keys
+ * @hide
+ */
+ public static final String NAVIGATION_BAR_MENU_ARROW_KEYS = "navigation_bar_menu_arrow_keys";
+
+ /**
+ * @hide
+ */
+ public static final String LOCKSCREEN_ALPHA_CONFIG = "lockscreen_alpha_config";
+
+ /**
+ * 0 == QuickSettings Tile
+ * 1 == Toggle Switch (Not implemented Yet)
+ * 2 == Traditional
+ * 3 == Traditional (Scrolling)
+ * @hide
+ */
+ public static final String TOGGLES_STYLE = "toggls_style";
+
+ /**
+ * toggle to "fix" the following: (found in NotificationManagerService)
+ * new in 4.2: if there was supposed to be a sound and we're in vibrate mode,
+ * we always vibrate, even if no vibration was specified
+ */
+ public static final String NOTIFICATION_CONVERT_SOUND_TO_VIBRATION = "convert_sound_to_vibration";
}
/**
@@ -2604,7 +5127,11 @@ public static final class Secure extends NameValueTable {
MOVED_TO_LOCK_SETTINGS = new HashSet(3);
MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_PATTERN_ENABLED);
MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_PATTERN_VISIBLE);
+ MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_SHOW_ERROR_PATH);
+ MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_DOTS_VISIBLE);
MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED);
+ MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_GESTURE_ENABLED);
+ MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_GESTURE_VISIBLE);
MOVED_TO_GLOBAL = new HashSet();
MOVED_TO_GLOBAL.add(Settings.Global.ADB_ENABLED);
@@ -2670,6 +5197,7 @@ public static final class Secure extends NameValueTable {
MOVED_TO_GLOBAL.add(Settings.Global.USE_GOOGLE_MAIL);
MOVED_TO_GLOBAL.add(Settings.Global.WEB_AUTOFILL_QUERY_URL);
MOVED_TO_GLOBAL.add(Settings.Global.WIFI_COUNTRY_CODE);
+ MOVED_TO_GLOBAL.add(Settings.Global.WIFI_COUNTRY_CODE_USER);
MOVED_TO_GLOBAL.add(Settings.Global.WIFI_FRAMEWORK_SCAN_INTERVAL_MS);
MOVED_TO_GLOBAL.add(Settings.Global.WIFI_FREQUENCY_BAND);
MOVED_TO_GLOBAL.add(Settings.Global.WIFI_IDLE_MS);
@@ -3091,6 +5619,24 @@ public static boolean putFloatForUser(ContentResolver cr, String name, float val
@Deprecated
public static final String ADB_ENABLED = Global.ADB_ENABLED;
+ /**
+ * The TCP/IP port to run ADB on, or -1 for USB
+ * @hide
+ */
+ public static final String ADB_PORT = "adb_port";
+
+ /**
+ * Whether to display the ADB notification.
+ * @hide
+ */
+ public static final String ADB_NOTIFY = "adb_notify";
+
+ /**
+ * The hostname for this device
+ * @hide
+ */
+ public static final String DEVICE_HOSTNAME = "device_hostname";
+
/**
* Setting to allow mock locations and location provider status to be injected into the
* LocationManager service for testing purposes during application development. These
@@ -3222,6 +5768,30 @@ public static boolean putFloatForUser(ContentResolver cr, String name, float val
public static final String
LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED = "lock_pattern_tactile_feedback_enabled";
+ /**
+ * Whether lock pattern will show dots (0 = false, 1 = true)
+ * @hide
+ */
+ public static final String LOCK_DOTS_VISIBLE = "lock_pattern_dotsvisible";
+
+ /**
+ * Whether lockscreen error pattern is visible (0 = false, 1 = true)
+ * @hide
+ */
+ public static final String LOCK_SHOW_ERROR_PATH = "lock_pattern_show_error_path";
+
+ /**
+ * Whether autolock is enabled (0 = false, 1 = true)
+ * @hide
+ */
+ public static final String LOCK_GESTURE_ENABLED = "lock_gesture_autolock";
+
+ /**
+ * Whether lock gesture is visible as user enters (0 = false, 1 = true)
+ * @hide
+ */
+ public static final String LOCK_GESTURE_VISIBLE = "lock_gesture_visible_pattern";
+
/**
* This preference allows the device to be locked given time after screen goes off,
* subject to current DeviceAdmin policy limits.
@@ -3264,6 +5834,27 @@ public static boolean putFloatForUser(ContentResolver cr, String name, float val
public static final String LOCK_SCREEN_OWNER_INFO_ENABLED =
"lock_screen_owner_info_enabled";
+ /**
+ * Whether the unsecure widget screen will be shown before a secure
+ * lock screen
+ * @hide
+ */
+ public static final String LOCK_BEFORE_UNLOCK =
+ "lock_before_unlock";
+
+ /**
+ * Determines the width and height of the LockPatternView widget
+ * @hide
+ */
+ public static final String LOCK_PATTERN_SIZE =
+ "lock_pattern_size";
+
+ /**
+ * External GPS source/device
+ * @hide
+ */
+ public static final String EXTERNAL_GPS_BT_DEVICE = "0";
+
/**
* The Logging ID (a unique 64-bit value) as a hex string.
* Used as a pseudonymous identifier for logging.
@@ -3302,6 +5893,25 @@ public static boolean putFloatForUser(ContentResolver cr, String name, float val
// TODO: 881807
public static final String SETTINGS_CLASSNAME = "settings_classname";
+ /**
+ * SELinux enforcing status.
+ * 1 - SELinux is in enforcing mode.
+ * 0 - SELinux is in permissive mode.
+ *
+ * @hide
+ */
+ public static final String SELINUX_ENFORCING = "selinux_enforcing";
+
+ /**
+ * Stores the values of the SELinux booleans. Stored as a comma
+ * seperated list of values, each value being of the form
+ * {@code boolean_name:value} where value is 1 if the boolean is set
+ * and 0 otherwise. Example: {@code bool1:1,bool2:0}.
+ *
+ * @hide
+ */
+ public static final String SELINUX_BOOLEANS = "selinux_booleans";
+
/**
* @deprecated Use {@link android.provider.Settings.Global#USB_MASS_STORAGE_ENABLED} instead
*/
@@ -3682,6 +6292,12 @@ public static boolean putFloatForUser(ContentResolver cr, String name, float val
public static final String WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS =
Global.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS;
+ /**
+ * Whether the Wimax should be on. Only the WiMAX service should touch this.
+ * @hide
+ */
+ public static final String WIMAX_ON = "wimax_on";
+
/**
* Whether background data usage is allowed.
*
@@ -3984,6 +6600,36 @@ public static boolean putFloatForUser(ContentResolver cr, String name, float val
public static final int INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT =
INCALL_POWER_BUTTON_BEHAVIOR_SCREEN_OFF;
+ /**
+ * What happens when the user presses the Home button when the
+ * phone is ringing.
+ * Values:
+ * 1 - Nothing happens. (Default behavior)
+ * 2 - The Home button answer the current call.
+ *
+ * @hide
+ */
+ public static final String RING_HOME_BUTTON_BEHAVIOR = "ring_home_button_behavior";
+
+ /**
+ * RING_HOME_BUTTON_BEHAVIOR value for "do nothing".
+ * @hide
+ */
+ public static final int RING_HOME_BUTTON_BEHAVIOR_DO_NOTHING = 0x1;
+
+ /**
+ * RING_HOME_BUTTON_BEHAVIOR value for "answer".
+ * @hide
+ */
+ public static final int RING_HOME_BUTTON_BEHAVIOR_ANSWER = 0x2;
+
+ /**
+ * RING_HOME_BUTTON_BEHAVIOR default value.
+ * @hide
+ */
+ public static final int RING_HOME_BUTTON_BEHAVIOR_DEFAULT =
+ RING_HOME_BUTTON_BEHAVIOR_DO_NOTHING;
+
/**
* The current night mode that has been selected by the user. Owned
* and controlled by UiModeManagerService. Constants are as per
@@ -3992,6 +6638,13 @@ public static boolean putFloatForUser(ContentResolver cr, String name, float val
*/
public static final String UI_NIGHT_MODE = "ui_night_mode";
+ /**
+ * Whether user activated inverted UI mode or default UI mode. Owned
+ * and controlled by UiModeManagerService.
+ * @hide
+ */
+ public static final String UI_INVERTED_MODE = "ui_inverted_mode";
+
/**
* Whether screensavers are enabled.
* @hide
@@ -4027,6 +6680,26 @@ public static boolean putFloatForUser(ContentResolver cr, String name, float val
*/
public static final String SCREENSAVER_DEFAULT_COMPONENT = "screensaver_default_component";
+ /**
+ * Notifications Expand Behaviour
+ * @hide
+ */
+ public static final String NOTIFICATIONS_BEHAVIOUR = "notifications_behaviour";
+
+ /**
+ * If screensavers are enabled, whether the screensaver should be automatically launched
+ * when charging wirelessly.
+ */
+ public static final String SCREENSAVER_ACTIVATE_ON_WIRELESS_CHARGE = "screensaver_activate_on_wireless_charger";
+
+ public static final String ENABLE_PERMISSIONS_MANAGEMENT = "enable_permissions_management";
+
+ /**
+ * Whether newly installed apps should run with privacy guard by default
+ * @hide
+ */
+ public static final String PRIVACY_GUARD_DEFAULT = "privacy_guard_default";
+
/**
* This are the settings to be backed up.
*
@@ -4052,6 +6725,8 @@ public static boolean putFloatForUser(ContentResolver cr, String name, float val
TOUCH_EXPLORATION_ENABLED,
ACCESSIBILITY_ENABLED,
ACCESSIBILITY_SPEAK_PASSWORD,
+ SELINUX_ENFORCING,
+ SELINUX_BOOLEANS,
TTS_USE_DEFAULTS,
TTS_DEFAULT_RATE,
TTS_DEFAULT_PITCH,
@@ -4068,8 +6743,10 @@ public static boolean putFloatForUser(ContentResolver cr, String name, float val
MOUNT_UMS_PROMPT,
MOUNT_UMS_NOTIFY_ENABLED,
UI_NIGHT_MODE,
+ UI_INVERTED_MODE,
LOCK_SCREEN_OWNER_INFO,
- LOCK_SCREEN_OWNER_INFO_ENABLED
+ LOCK_SCREEN_OWNER_INFO_ENABLED,
+ PRIVACY_GUARD_DEFAULT
};
/**
@@ -4091,6 +6768,13 @@ public static final boolean isLocationProviderEnabled(ContentResolver cr, String
* @hide
*/
public static final boolean isLocationProviderEnabledForUser(ContentResolver cr, String provider, int userId) {
+ try {
+ if (ActivityManagerNative.getDefault().isPrivacyGuardEnabledForProcess(Binder.getCallingPid())) {
+ return false;
+ }
+ } catch (RemoteException e) {
+ // ignore
+ }
String allowedProviders = Settings.Secure.getStringForUser(cr,
LOCATION_PROVIDERS_ALLOWED, userId);
return TextUtils.delimitedStringContains(allowedProviders, ',', provider);
@@ -4295,6 +6979,24 @@ public static final class Global extends NameValueTable {
*/
public static final String POWER_SOUNDS_ENABLED = "power_sounds_enabled";
+ /**
+ * Whether to sound when charger power is connected/disconnected
+ * @hide
+ */
+ public static final String POWER_NOTIFICATIONS_ENABLED = "power_notifications_enabled";
+
+ /**
+ * Whether to vibrate when charger power is connected/disconnected
+ * @hide
+ */
+ public static final String POWER_NOTIFICATIONS_VIBRATE = "power_notifications_vibrate";
+
+ /**
+ * URI for power notification sounds
+ * @hide
+ */
+ public static final String POWER_NOTIFICATIONS_RINGTONE = "power_notifications_ringtone";
+
/**
* URI for the "wireless charging started" sound.
* @hide
@@ -4780,6 +7482,12 @@ public static final class Global extends NameValueTable {
* @hide
*/
public static final String WIFI_COUNTRY_CODE = "wifi_country_code";
+
+ /**
+ * 802.11 country code in ISO 3166 format custom user value
+ * @hide
+ */
+ public static final String WIFI_COUNTRY_CODE_USER = "wifi_country_code_user";
/**
* The interval in milliseconds to issue wake up scans when wifi needs
@@ -5364,6 +8072,9 @@ public static final String getBluetoothInputDevicePriorityKey(String address) {
AUTO_TIME,
AUTO_TIME_ZONE,
POWER_SOUNDS_ENABLED,
+ POWER_NOTIFICATIONS_ENABLED,
+ POWER_NOTIFICATIONS_VIBRATE,
+ POWER_NOTIFICATIONS_RINGTONE,
DOCK_SOUNDS_ENABLED,
USB_MASS_STORAGE_ENABLED,
ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED,
diff --git a/core/java/android/server/package.html b/core/java/android/server/package.html
old mode 100755
new mode 100644
diff --git a/core/java/android/speech/tts/ITextToSpeechCallback.aidl b/core/java/android/speech/tts/ITextToSpeechCallback.aidl
old mode 100755
new mode 100644
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
old mode 100755
new mode 100644
index 5e367cb56aa..7c3e7bbe957
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -31,6 +31,7 @@
import android.text.TextUtils;
import android.util.Log;
+import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -1188,6 +1189,7 @@ private void copyFloatParam(Bundle bundle, HashMap params, Strin
@Deprecated
public int setOnUtteranceCompletedListener(final OnUtteranceCompletedListener listener) {
mUtteranceProgressListener = UtteranceProgressListener.from(listener);
+ mCallback.setUtteranceProgressListener(mUtteranceProgressListener);
return TextToSpeech.SUCCESS;
}
@@ -1203,6 +1205,7 @@ public int setOnUtteranceCompletedListener(final OnUtteranceCompletedListener li
*/
public int setOnUtteranceProgressListener(UtteranceProgressListener listener) {
mUtteranceProgressListener = listener;
+ mCallback.setUtteranceProgressListener(mUtteranceProgressListener);
return TextToSpeech.SUCCESS;
}
@@ -1253,34 +1256,8 @@ public List getEngines() {
return mEnginesHelper.getEngines();
}
-
private class Connection implements ServiceConnection {
private ITextToSpeechService mService;
- private final ITextToSpeechCallback.Stub mCallback = new ITextToSpeechCallback.Stub() {
- @Override
- public void onDone(String utteranceId) {
- UtteranceProgressListener listener = mUtteranceProgressListener;
- if (listener != null) {
- listener.onDone(utteranceId);
- }
- }
-
- @Override
- public void onError(String utteranceId) {
- UtteranceProgressListener listener = mUtteranceProgressListener;
- if (listener != null) {
- listener.onError(utteranceId);
- }
- }
-
- @Override
- public void onStart(String utteranceId) {
- UtteranceProgressListener listener = mUtteranceProgressListener;
- if (listener != null) {
- listener.onStart(utteranceId);
- }
- }
- };
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
@@ -1394,4 +1371,38 @@ public String toString() {
}
+ private final TextToSpeechCallback mCallback = new TextToSpeechCallback();
+}
+
+class TextToSpeechCallback extends ITextToSpeechCallback.Stub {
+
+ private volatile WeakReference mUtteranceProgressListener = null;
+
+ public void setUtteranceProgressListener(UtteranceProgressListener aUtteranceProgressListener) {
+ mUtteranceProgressListener = new WeakReference(aUtteranceProgressListener);
+ }
+
+ @Override
+ public void onDone(String utteranceId) {
+ UtteranceProgressListener listener = mUtteranceProgressListener.get();
+ if (listener != null) {
+ listener.onDone(utteranceId);
+ }
+ }
+
+ @Override
+ public void onError(String utteranceId) {
+ UtteranceProgressListener listener = mUtteranceProgressListener.get();
+ if (listener != null) {
+ listener.onError(utteranceId);
+ }
+ }
+
+ @Override
+ public void onStart(String utteranceId) {
+ UtteranceProgressListener listener = mUtteranceProgressListener.get();
+ if (listener != null) {
+ listener.onStart(utteranceId);
+ }
+ }
}
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index d909362357e..122f8a171d0 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -503,8 +503,15 @@ void updateBlocks(int startLine, int endLine, int newLineCount) {
mNumberOfBlocks = newNumberOfBlocks;
final int deltaLines = newLineCount - (endLine - startLine + 1);
- for (int i = firstBlock + numAddedBlocks; i < mNumberOfBlocks; i++) {
- mBlockEndLines[i] += deltaLines;
+ if (deltaLines != 0) {
+ // Display list whose index is >= mIndexFirstChangedBlock is valid
+ // but it needs to update its drawing location.
+ mIndexFirstChangedBlock = firstBlock + numAddedBlocks;
+ for (int i = mIndexFirstChangedBlock; i < mNumberOfBlocks; i++) {
+ mBlockEndLines[i] += deltaLines;
+ }
+ } else {
+ mIndexFirstChangedBlock = mNumberOfBlocks;
}
int blockIndex = firstBlock;
@@ -559,6 +566,20 @@ public int getNumberOfBlocks() {
return mNumberOfBlocks;
}
+ /**
+ * @hide
+ */
+ public int getIndexFirstChangedBlock() {
+ return mIndexFirstChangedBlock;
+ }
+
+ /**
+ * @hide
+ */
+ public void setIndexFirstChangedBlock(int i) {
+ mIndexFirstChangedBlock = i;
+ }
+
@Override
public int getLineCount() {
return mInts.size() - 1;
@@ -697,6 +718,8 @@ public int getEllipsisCount(int line) {
private int[] mBlockIndices;
// Number of items actually currently being used in the above 2 arrays
private int mNumberOfBlocks;
+ // The first index of the blocks whose locations are changed
+ private int mIndexFirstChangedBlock;
private int mTopPadding, mBottomPadding;
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 123accae4f6..b59b01ae4b8 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -134,8 +134,9 @@ protected Layout(CharSequence text, TextPaint paint,
int width, Alignment align, TextDirectionHeuristic textDir,
float spacingMult, float spacingAdd) {
- if (width < 0)
- throw new IllegalArgumentException("Layout: " + width + " < 0");
+ if (width < 0) {
+ width = 0;
+ }
// Ensure paint doesn't have baselineShift set.
// While normally we don't modify the paint the user passed in,
@@ -164,7 +165,7 @@ protected Layout(CharSequence text, TextPaint paint,
int width, Alignment align,
float spacingmult, float spacingadd) {
if (width < 0) {
- throw new IllegalArgumentException("Layout: " + width + " < 0");
+ width = 0;
}
mText = text;
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index 0f30d25f7d1..5455b65d15e 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -613,12 +613,8 @@ private void setSpan(boolean send, Object what, int start, int end, int flags) {
// 0-length Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
if (flagsStart == POINT && flagsEnd == MARK && start == end) {
- if (send) Log.e("SpannableStringBuilder",
- "SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length");
- // Silently ignore invalid spans when they are created from this class.
- // This avoids the duplication of the above test code before all the
- // calls to setSpan that are done in this class
- return;
+ return;
+ // Silently ignore invalid spans when they are found, because honey badger doesn't currrrrr.
}
int nstart = start;
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index bcce61dc00a..5a20cebedb2 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -43,11 +43,6 @@ public class DateUtils
private static String sElapsedFormatMMSS;
private static String sElapsedFormatHMMSS;
- private static final String FAST_FORMAT_HMMSS = "%1$d:%2$02d:%3$02d";
- private static final String FAST_FORMAT_MMSS = "%1$02d:%2$02d";
- private static final char TIME_SEPARATOR = ':';
-
-
public static final long SECOND_IN_MILLIS = 1000;
public static final long MINUTE_IN_MILLIS = SECOND_IN_MILLIS * 60;
public static final long HOUR_IN_MILLIS = MINUTE_IN_MILLIS * 60;
@@ -434,20 +429,7 @@ public static CharSequence getRelativeTimeSpanString(long time, long now, long m
}
}
} else if (duration < WEEK_IN_MILLIS && minResolution < WEEK_IN_MILLIS) {
- count = getNumberOfDaysPassed(time, now);
- if (past) {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_num_days_ago;
- } else {
- resId = com.android.internal.R.plurals.num_days_ago;
- }
- } else {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_in_num_days;
- } else {
- resId = com.android.internal.R.plurals.in_num_days;
- }
- }
+ return getRelativeDayString(r, time, now);
} else {
// We know that we won't be showing the time, so it is safe to pass
// in a null context.
@@ -458,24 +440,6 @@ public static CharSequence getRelativeTimeSpanString(long time, long now, long m
return String.format(format, count);
}
- /**
- * Returns the number of days passed between two dates.
- *
- * @param date1 first date
- * @param date2 second date
- * @return number of days passed between to dates.
- */
- private synchronized static long getNumberOfDaysPassed(long date1, long date2) {
- if (sThenTime == null) {
- sThenTime = new Time();
- }
- sThenTime.set(date1);
- int day1 = Time.getJulianDay(date1, sThenTime.gmtoff);
- sThenTime.set(date2);
- int day2 = Time.getJulianDay(date2, sThenTime.gmtoff);
- return Math.abs(day2 - day1);
- }
-
/**
* Return string describing the elapsed time since startTime formatted like
* "[relative time/date], [time]".
@@ -534,28 +498,29 @@ public static CharSequence getRelativeDateTimeString(Context c, long time, long
* today this function returns "Today", if the day was a week ago it returns "7 days ago", and
* if the day is in 2 weeks it returns "in 14 days".
*
- * @param r the resources to get the strings from
+ * @param r the resources
* @param day the relative day to describe in UTC milliseconds
* @param today the current time in UTC milliseconds
- * @return a formatting string
*/
private static final String getRelativeDayString(Resources r, long day, long today) {
+ Locale locale = r.getConfiguration().locale;
+ if (locale == null) {
+ locale = Locale.getDefault();
+ }
+
+ // TODO: use TimeZone.getOffset instead.
Time startTime = new Time();
startTime.set(day);
+ int startDay = Time.getJulianDay(day, startTime.gmtoff);
+
Time currentTime = new Time();
currentTime.set(today);
-
- int startDay = Time.getJulianDay(day, startTime.gmtoff);
int currentDay = Time.getJulianDay(today, currentTime.gmtoff);
int days = Math.abs(currentDay - startDay);
boolean past = (today > day);
// TODO: some locales name other days too, such as de_DE's "Vorgestern" (today - 2).
- Locale locale = r.getConfiguration().locale;
- if (locale == null) {
- locale = Locale.getDefault();
- }
if (days == 1) {
if (past) {
return LocaleData.get(locale).yesterday;
@@ -640,19 +605,18 @@ public static String formatElapsedTime(long elapsedSeconds) {
}
/**
- * Formats an elapsed time in the form "MM:SS" or "H:MM:SS"
- * for display on the call-in-progress screen.
+ * Formats an elapsed time in a format like "MM:SS" or "H:MM:SS" (using a form
+ * suited to the current locale), similar to that used on the call-in-progress
+ * screen.
*
- * @param recycle {@link StringBuilder} to recycle, if possible
+ * @param recycle {@link StringBuilder} to recycle, or null to use a temporary one.
* @param elapsedSeconds the elapsed time in seconds.
*/
public static String formatElapsedTime(StringBuilder recycle, long elapsedSeconds) {
- initFormatStrings();
-
+ // Break the elapsed seconds into hours, minutes, and seconds.
long hours = 0;
long minutes = 0;
long seconds = 0;
-
if (elapsedSeconds >= 3600) {
hours = elapsedSeconds / 3600;
elapsedSeconds -= hours * 3600;
@@ -663,70 +627,23 @@ public static String formatElapsedTime(StringBuilder recycle, long elapsedSecond
}
seconds = elapsedSeconds;
- String result;
- if (hours > 0) {
- return formatElapsedTime(recycle, sElapsedFormatHMMSS, hours, minutes, seconds);
- } else {
- return formatElapsedTime(recycle, sElapsedFormatMMSS, minutes, seconds);
- }
- }
-
- private static void append(StringBuilder sb, long value, boolean pad, char zeroDigit) {
- if (value < 10) {
- if (pad) {
- sb.append(zeroDigit);
- }
- } else {
- sb.append((char) (zeroDigit + (value / 10)));
- }
- sb.append((char) (zeroDigit + (value % 10)));
- }
-
- /**
- * Fast formatting of h:mm:ss.
- */
- private static String formatElapsedTime(StringBuilder recycle, String format, long hours,
- long minutes, long seconds) {
- if (FAST_FORMAT_HMMSS.equals(format)) {
- char zeroDigit = LocaleData.get(Locale.getDefault()).zeroDigit;
-
- StringBuilder sb = recycle;
- if (sb == null) {
- sb = new StringBuilder(8);
- } else {
- sb.setLength(0);
- }
- append(sb, hours, false, zeroDigit);
- sb.append(TIME_SEPARATOR);
- append(sb, minutes, true, zeroDigit);
- sb.append(TIME_SEPARATOR);
- append(sb, seconds, true, zeroDigit);
- return sb.toString();
+ // Create a StringBuilder if we weren't given one to recycle.
+ // TODO: if we cared, we could have a thread-local temporary StringBuilder.
+ StringBuilder sb = recycle;
+ if (sb == null) {
+ sb = new StringBuilder(8);
} else {
- return String.format(format, hours, minutes, seconds);
+ sb.setLength(0);
}
- }
- /**
- * Fast formatting of mm:ss.
- */
- private static String formatElapsedTime(StringBuilder recycle, String format, long minutes,
- long seconds) {
- if (FAST_FORMAT_MMSS.equals(format)) {
- char zeroDigit = LocaleData.get(Locale.getDefault()).zeroDigit;
-
- StringBuilder sb = recycle;
- if (sb == null) {
- sb = new StringBuilder(8);
- } else {
- sb.setLength(0);
- }
- append(sb, minutes, false, zeroDigit);
- sb.append(TIME_SEPARATOR);
- append(sb, seconds, true, zeroDigit);
- return sb.toString();
+ // Format the broken-down time in a locale-appropriate way.
+ // TODO: use icu4c when http://unicode.org/cldr/trac/ticket/3407 is fixed.
+ Formatter f = new Formatter(sb, Locale.getDefault());
+ initFormatStrings();
+ if (hours > 0) {
+ return f.format(sElapsedFormatHMMSS, hours, minutes, seconds).toString();
} else {
- return String.format(format, minutes, seconds);
+ return f.format(sElapsedFormatMMSS, minutes, seconds).toString();
}
}
diff --git a/core/java/android/text/method/CharacterPickerDialog.java b/core/java/android/text/method/CharacterPickerDialog.java
index 880e46daf1a..c06fab812ed 100644
--- a/core/java/android/text/method/CharacterPickerDialog.java
+++ b/core/java/android/text/method/CharacterPickerDialog.java
@@ -44,7 +44,6 @@ public class CharacterPickerDialog extends Dialog
private String mOptions;
private boolean mInsert;
private LayoutInflater mInflater;
- private Button mCancelButton;
/**
* Creates a new CharacterPickerDialog that presents the specified
@@ -71,15 +70,13 @@ protected void onCreate(Bundle savedInstanceState) {
params.token = mView.getApplicationWindowToken();
params.type = params.TYPE_APPLICATION_ATTACHED_DIALOG;
params.flags = params.flags | Window.FEATURE_NO_TITLE;
+ setCanceledOnTouchOutside(true);
setContentView(R.layout.character_picker);
GridView grid = (GridView) findViewById(R.id.characterPicker);
grid.setAdapter(new OptionsAdapter(getContext()));
grid.setOnItemClickListener(this);
-
- mCancelButton = (Button) findViewById(R.id.cancel);
- mCancelButton.setOnClickListener(this);
}
/**
@@ -90,6 +87,16 @@ public void onItemClick(AdapterView parent, View view, int position, long id) {
replaceCharacterAndClose(result);
}
+ /**
+ * Handles clicks on the character buttons.
+ */
+ public void onClick(View v) {
+ if (v instanceof Button) {
+ CharSequence result = ((Button) v).getText();
+ replaceCharacterAndClose(result);
+ }
+ }
+
private void replaceCharacterAndClose(CharSequence replace) {
int selEnd = Selection.getSelectionEnd(mText);
if (mInsert || selEnd == 0) {
@@ -101,18 +108,6 @@ private void replaceCharacterAndClose(CharSequence replace) {
dismiss();
}
- /**
- * Handles clicks on the Cancel button.
- */
- public void onClick(View v) {
- if (v == mCancelButton) {
- dismiss();
- } else if (v instanceof Button) {
- CharSequence result = ((Button) v).getText();
- replaceCharacterAndClose(result);
- }
- }
-
private class OptionsAdapter extends BaseAdapter {
public OptionsAdapter(Context context) {
diff --git a/core/java/android/text/method/MetaKeyKeyListener.java b/core/java/android/text/method/MetaKeyKeyListener.java
index 0a097f99bd0..293b5127653 100644
--- a/core/java/android/text/method/MetaKeyKeyListener.java
+++ b/core/java/android/text/method/MetaKeyKeyListener.java
@@ -23,6 +23,9 @@
import android.view.KeyEvent;
import android.view.View;
import android.view.KeyCharacterMap;
+import android.os.IPowerManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
/**
* This base class encapsulates the behavior for tracking the state of
@@ -214,6 +217,14 @@ public static void adjustMetaAfterKeypress(Spannable content) {
adjust(content, CAP);
adjust(content, ALT);
adjust(content, SYM);
+ try {
+ IPowerManager power = IPowerManager.Stub.asInterface(
+ ServiceManager.getService("power"));
+ if (getMetaState(content, META_SHIFT_ON) <= 0)
+ power.setKeyboardLight(false, 1);
+ if (getMetaState(content, META_ALT_ON) <= 0)
+ power.setKeyboardLight(false, 2);
+ } catch (RemoteException doe) {}
}
/**
@@ -266,12 +277,32 @@ private static void resetLock(Spannable content, Object what) {
public boolean onKeyDown(View view, Editable content, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
press(content, CAP);
+ try {
+ IPowerManager power = IPowerManager.Stub.asInterface(
+ ServiceManager.getService("power"));
+ int state = content.getSpanFlags(CAP);
+ if (state == PRESSED || state == LOCKED) {
+ power.setKeyboardLight(true, 1);
+ } else {
+ power.setKeyboardLight(false, 1);
+ }
+ } catch (RemoteException doe) {}
return true;
}
if (keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT
|| keyCode == KeyEvent.KEYCODE_NUM) {
press(content, ALT);
+ try {
+ IPowerManager power = IPowerManager.Stub.asInterface(
+ ServiceManager.getService("power"));
+ int state = content.getSpanFlags(ALT);
+ if (state == PRESSED || state == LOCKED) {
+ power.setKeyboardLight(true, 2);
+ } else {
+ power.setKeyboardLight(false, 2);
+ }
+ } catch (RemoteException doe) {}
return true;
}
diff --git a/core/java/android/text/method/QwertyKeyListener.java b/core/java/android/text/method/QwertyKeyListener.java
index c5261f32e36..0dcc7a89fc2 100644
--- a/core/java/android/text/method/QwertyKeyListener.java
+++ b/core/java/android/text/method/QwertyKeyListener.java
@@ -133,6 +133,12 @@ public boolean onKeyDown(View view, Editable content,
return true;
}
+ if (i == KeyCharacterMap.DOT_WWW_INPUT || i == KeyCharacterMap.DOT_COM_INPUT) {
+ content.replace(selStart, selEnd, selStart == 0 ? "www." : ".com");
+ adjustMetaAfterKeypress(content);
+ return true;
+ }
+
if (i == KeyCharacterMap.HEX_INPUT) {
int start;
@@ -427,78 +433,75 @@ public static void markAsReplaced(Spannable content, int start, int end,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
- private static SparseArray PICKER_SETS =
- new SparseArray();
+ private static SparseArray SYM_PICKER_RES_ID =
+ new SparseArray();
+
static {
- PICKER_SETS.put('A', "\u00C0\u00C1\u00C2\u00C4\u00C6\u00C3\u00C5\u0104\u0100");
- PICKER_SETS.put('C', "\u00C7\u0106\u010C");
- PICKER_SETS.put('D', "\u010E");
- PICKER_SETS.put('E', "\u00C8\u00C9\u00CA\u00CB\u0118\u011A\u0112");
- PICKER_SETS.put('G', "\u011E");
- PICKER_SETS.put('L', "\u0141");
- PICKER_SETS.put('I', "\u00CC\u00CD\u00CE\u00CF\u012A\u0130");
- PICKER_SETS.put('N', "\u00D1\u0143\u0147");
- PICKER_SETS.put('O', "\u00D8\u0152\u00D5\u00D2\u00D3\u00D4\u00D6\u014C");
- PICKER_SETS.put('R', "\u0158");
- PICKER_SETS.put('S', "\u015A\u0160\u015E");
- PICKER_SETS.put('T', "\u0164");
- PICKER_SETS.put('U', "\u00D9\u00DA\u00DB\u00DC\u016E\u016A");
- PICKER_SETS.put('Y', "\u00DD\u0178");
- PICKER_SETS.put('Z', "\u0179\u017B\u017D");
- PICKER_SETS.put('a', "\u00E0\u00E1\u00E2\u00E4\u00E6\u00E3\u00E5\u0105\u0101");
- PICKER_SETS.put('c', "\u00E7\u0107\u010D");
- PICKER_SETS.put('d', "\u010F");
- PICKER_SETS.put('e', "\u00E8\u00E9\u00EA\u00EB\u0119\u011B\u0113");
- PICKER_SETS.put('g', "\u011F");
- PICKER_SETS.put('i', "\u00EC\u00ED\u00EE\u00EF\u012B\u0131");
- PICKER_SETS.put('l', "\u0142");
- PICKER_SETS.put('n', "\u00F1\u0144\u0148");
- PICKER_SETS.put('o', "\u00F8\u0153\u00F5\u00F2\u00F3\u00F4\u00F6\u014D");
- PICKER_SETS.put('r', "\u0159");
- PICKER_SETS.put('s', "\u00A7\u00DF\u015B\u0161\u015F");
- PICKER_SETS.put('t', "\u0165");
- PICKER_SETS.put('u', "\u00F9\u00FA\u00FB\u00FC\u016F\u016B");
- PICKER_SETS.put('y', "\u00FD\u00FF");
- PICKER_SETS.put('z', "\u017A\u017C\u017E");
- PICKER_SETS.put(KeyCharacterMap.PICKER_DIALOG_INPUT,
- "\u2026\u00A5\u2022\u00AE\u00A9\u00B1[]{}\\|");
- PICKER_SETS.put('/', "\\");
-
- // From packages/inputmethods/LatinIME/res/xml/kbd_symbols.xml
-
- PICKER_SETS.put('1', "\u00b9\u00bd\u2153\u00bc\u215b");
- PICKER_SETS.put('2', "\u00b2\u2154");
- PICKER_SETS.put('3', "\u00b3\u00be\u215c");
- PICKER_SETS.put('4', "\u2074");
- PICKER_SETS.put('5', "\u215d");
- PICKER_SETS.put('7', "\u215e");
- PICKER_SETS.put('0', "\u207f\u2205");
- PICKER_SETS.put('$', "\u00a2\u00a3\u20ac\u00a5\u20a3\u20a4\u20b1");
- PICKER_SETS.put('%', "\u2030");
- PICKER_SETS.put('*', "\u2020\u2021");
- PICKER_SETS.put('-', "\u2013\u2014");
- PICKER_SETS.put('+', "\u00b1");
- PICKER_SETS.put('(', "[{<");
- PICKER_SETS.put(')', "]}>");
- PICKER_SETS.put('!', "\u00a1");
- PICKER_SETS.put('"', "\u201c\u201d\u00ab\u00bb\u02dd");
- PICKER_SETS.put('?', "\u00bf");
- PICKER_SETS.put(',', "\u201a\u201e");
-
- // From packages/inputmethods/LatinIME/res/xml/kbd_symbols_shift.xml
-
- PICKER_SETS.put('=', "\u2260\u2248\u221e");
- PICKER_SETS.put('<', "\u2264\u00ab\u2039");
- PICKER_SETS.put('>', "\u2265\u00bb\u203a");
+ SYM_PICKER_RES_ID.put('A', com.android.internal.R.string.symbol_picker_A);
+ SYM_PICKER_RES_ID.put('C', com.android.internal.R.string.symbol_picker_C);
+ SYM_PICKER_RES_ID.put('D', com.android.internal.R.string.symbol_picker_D);
+ SYM_PICKER_RES_ID.put('E', com.android.internal.R.string.symbol_picker_E);
+ SYM_PICKER_RES_ID.put('G', com.android.internal.R.string.symbol_picker_G);
+ SYM_PICKER_RES_ID.put('L', com.android.internal.R.string.symbol_picker_L);
+ SYM_PICKER_RES_ID.put('I', com.android.internal.R.string.symbol_picker_I);
+ SYM_PICKER_RES_ID.put('N', com.android.internal.R.string.symbol_picker_N);
+ SYM_PICKER_RES_ID.put('O', com.android.internal.R.string.symbol_picker_O);
+ SYM_PICKER_RES_ID.put('R', com.android.internal.R.string.symbol_picker_R);
+ SYM_PICKER_RES_ID.put('S', com.android.internal.R.string.symbol_picker_S);
+ SYM_PICKER_RES_ID.put('T', com.android.internal.R.string.symbol_picker_T);
+ SYM_PICKER_RES_ID.put('U', com.android.internal.R.string.symbol_picker_U);
+ SYM_PICKER_RES_ID.put('Y', com.android.internal.R.string.symbol_picker_Y);
+ SYM_PICKER_RES_ID.put('Z', com.android.internal.R.string.symbol_picker_Z);
+ SYM_PICKER_RES_ID.put('a', com.android.internal.R.string.symbol_picker_a);
+ SYM_PICKER_RES_ID.put('c', com.android.internal.R.string.symbol_picker_c);
+ SYM_PICKER_RES_ID.put('d', com.android.internal.R.string.symbol_picker_d);
+ SYM_PICKER_RES_ID.put('e', com.android.internal.R.string.symbol_picker_e);
+ SYM_PICKER_RES_ID.put('g', com.android.internal.R.string.symbol_picker_g);
+ SYM_PICKER_RES_ID.put('i', com.android.internal.R.string.symbol_picker_i);
+ SYM_PICKER_RES_ID.put('l', com.android.internal.R.string.symbol_picker_l);
+ SYM_PICKER_RES_ID.put('n', com.android.internal.R.string.symbol_picker_n);
+ SYM_PICKER_RES_ID.put('o', com.android.internal.R.string.symbol_picker_o);
+ SYM_PICKER_RES_ID.put('r', com.android.internal.R.string.symbol_picker_r);
+ SYM_PICKER_RES_ID.put('s', com.android.internal.R.string.symbol_picker_s);
+ SYM_PICKER_RES_ID.put('t', com.android.internal.R.string.symbol_picker_t);
+ SYM_PICKER_RES_ID.put('u', com.android.internal.R.string.symbol_picker_u);
+ SYM_PICKER_RES_ID.put('y', com.android.internal.R.string.symbol_picker_y);
+ SYM_PICKER_RES_ID.put('z', com.android.internal.R.string.symbol_picker_z);
+ SYM_PICKER_RES_ID.put('1', com.android.internal.R.string.symbol_picker_1);
+ SYM_PICKER_RES_ID.put('2', com.android.internal.R.string.symbol_picker_2);
+ SYM_PICKER_RES_ID.put('3', com.android.internal.R.string.symbol_picker_3);
+ SYM_PICKER_RES_ID.put('4', com.android.internal.R.string.symbol_picker_4);
+ SYM_PICKER_RES_ID.put('5', com.android.internal.R.string.symbol_picker_5);
+ SYM_PICKER_RES_ID.put('7', com.android.internal.R.string.symbol_picker_7);
+ SYM_PICKER_RES_ID.put('0', com.android.internal.R.string.symbol_picker_0);
+ SYM_PICKER_RES_ID.put(KeyCharacterMap.PICKER_DIALOG_INPUT,com.android.internal.R.string.symbol_picker_sym);
+ SYM_PICKER_RES_ID.put('/', com.android.internal.R.string.symbol_picker_slash);
+ SYM_PICKER_RES_ID.put('$', com.android.internal.R.string.symbol_picker_dollar);
+ SYM_PICKER_RES_ID.put('%', com.android.internal.R.string.symbol_picker_percent);
+ SYM_PICKER_RES_ID.put('*', com.android.internal.R.string.symbol_picker_star);
+ SYM_PICKER_RES_ID.put('-', com.android.internal.R.string.symbol_picker_minus);
+ SYM_PICKER_RES_ID.put('+', com.android.internal.R.string.symbol_picker_plus);
+ SYM_PICKER_RES_ID.put('(', com.android.internal.R.string.symbol_picker_opening_parenthesis);
+ SYM_PICKER_RES_ID.put(')', com.android.internal.R.string.symbol_picker_closing_parenthesis);
+ SYM_PICKER_RES_ID.put('!', com.android.internal.R.string.symbol_picker_exclamation);
+ SYM_PICKER_RES_ID.put('"', com.android.internal.R.string.symbol_picker_quote);
+ SYM_PICKER_RES_ID.put('?', com.android.internal.R.string.symbol_picker_question);
+ SYM_PICKER_RES_ID.put(',', com.android.internal.R.string.symbol_picker_comma);
+ SYM_PICKER_RES_ID.put('=', com.android.internal.R.string.symbol_picker_equal);
+ SYM_PICKER_RES_ID.put('<', com.android.internal.R.string.symbol_picker_lt);
+ SYM_PICKER_RES_ID.put('>', com.android.internal.R.string.symbol_picker_gt);
};
private boolean showCharacterPicker(View view, Editable content, char c,
boolean insert, int count) {
- String set = PICKER_SETS.get(c);
- if (set == null) {
+ Integer resId = SYM_PICKER_RES_ID.get(c);
+
+ if (resId == null) {
return false;
}
+ String set = view.getContext().getString(resId);
+
if (count == 1) {
new CharacterPickerDialog(view.getContext(),
view, content, set, insert).show();
diff --git a/core/java/android/util/FloatMath.java b/core/java/android/util/FloatMath.java
index 955622396aa..0ffd5bd6109 100644
--- a/core/java/android/util/FloatMath.java
+++ b/core/java/android/util/FloatMath.java
@@ -17,12 +17,10 @@
package android.util;
/**
- * Math routines similar to those found in {@link java.lang.Math}. Performs
- * computations on {@code float} values directly without incurring the overhead
- * of conversions to and from {@code double}.
- *
- * On one platform, {@code FloatMath.sqrt(100)} executes in one third of the
- * time required by {@code java.lang.Math.sqrt(100)}.
+ * Math routines similar to those found in {@link java.lang.Math}. On
+ * versions of Android with a JIT, these are significantly slower than
+ * the equivalent {@code Math} functions, which should be used in preference
+ * to these.
*/
public class FloatMath {
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 2b6cbcf8c68..152fe61b2c5 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -265,4 +265,9 @@ interface IWindowManager
* credentials.
*/
void showAssistant();
+
+ /**
+ * Update the application display metrics
+ */
+ void updateDisplayMetrics();
}
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
old mode 100755
new mode 100644
diff --git a/core/java/android/view/InputEvent.java b/core/java/android/view/InputEvent.java
old mode 100755
new mode 100644
diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java
index 2cb724f31b1..e44ce2055f2 100644
--- a/core/java/android/view/KeyCharacterMap.java
+++ b/core/java/android/view/KeyCharacterMap.java
@@ -121,6 +121,18 @@ public class KeyCharacterMap implements Parcelable {
*/
public static final char PICKER_DIALOG_INPUT = '\uEF01';
+ /**
+ * Private use character denoting a .com suffix
+ * @hide
+ */
+ public static final char DOT_COM_INPUT = '\uEF03';
+
+ /**
+ * Private use character denoting a www. prefix
+ * @hide
+ */
+ public static final char DOT_WWW_INPUT = '\uEF04';
+
/**
* Modifier keys may be chorded with character keys.
*
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
old mode 100755
new mode 100644
index c2a3e5816ea..4649a8b85d8
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -628,8 +628,8 @@ public class KeyEvent extends InputEvent implements Parcelable {
// NOTE: If you add a new keycode here you must also add it to:
// isSystem()
- // native/include/android/keycodes.h
- // frameworks/base/include/ui/KeycodeLabels.h
+ // frameworks/native/include/android/keycodes.h
+ // frameworks/base/include/androidfw/KeycodeLabels.h
// external/webkit/WebKit/android/plugins/ANPKeyCodes.h
// frameworks/base/core/res/res/values/attrs.xml
// emulator?
diff --git a/core/java/android/view/OrientationEventListener.java b/core/java/android/view/OrientationEventListener.java
old mode 100755
new mode 100644
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f05371ac437..4684ff7e3c3 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2540,6 +2540,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
private int mOverScrollMode;
+ private boolean mHasDoubleClick = false;
+ private boolean mIsFirstClick = true;
+ private final DoSingleClick mDoSingleClick = new DoSingleClick(this);
+
/**
* The parent this view is attached to.
* {@hide}
@@ -2954,6 +2958,13 @@ static class ListenerInfo {
*/
protected OnLongClickListener mOnLongClickListener;
+ /**
+ * Listener used to dispatch double click events.
+ * This field should be made private, so it is hidden from the SDK.
+ * {@hide}
+ */
+ private OnDoubleClickListener mOnDoubleClickListener;
+
/**
* Listener used to build the context menu.
* This field should be made private, so it is hidden from the SDK.
@@ -4173,6 +4184,23 @@ public void setOnLongClickListener(OnLongClickListener l) {
getListenerInfo().mOnLongClickListener = l;
}
+ /**
+ *
+ *
+ * @param l The callback that will run
+ *
+ * @see #setClickable(boolean)
+ */
+ public void setOnDoubleClickListener(OnDoubleClickListener l) {
+ if (l != null) {
+ if (!isClickable()) {
+ setClickable(true);
+ }
+ mHasDoubleClick = true;
+ getListenerInfo().mOnDoubleClickListener = l;
+ }
+ }
+
/**
* Register a callback to be invoked when the context menu for this view is
* being built. If this view is not long clickable, it becomes long clickable.
@@ -4199,10 +4227,15 @@ public boolean performClick() {
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
ListenerInfo li = mListenerInfo;
- if (li != null && li.mOnClickListener != null) {
- playSoundEffect(SoundEffectConstants.CLICK);
- li.mOnClickListener.onClick(this);
- return true;
+ if (li != null && ((li.mOnClickListener != null) || (li.mOnDoubleClickListener != null))) {
+ if (mHasDoubleClick) {
+ passForDoubleClick();
+ return true;
+ } else {
+ playSoundEffect(SoundEffectConstants.CLICK);
+ li.mOnClickListener.onClick(this);
+ return true;
+ }
}
return false;
@@ -4217,14 +4250,30 @@ public boolean performClick() {
* otherwise is returned.
*/
public boolean callOnClick() {
- ListenerInfo li = mListenerInfo;
- if (li != null && li.mOnClickListener != null) {
- li.mOnClickListener.onClick(this);
- return true;
+ if (mListenerInfo != null && mListenerInfo.mOnClickListener != null) {
+ if (mHasDoubleClick) {
+ passForDoubleClick();
+ return true;
+ } else {
+ mListenerInfo.mOnClickListener.onClick(this);
+ return true;
+ }
}
return false;
}
+ private void passForDoubleClick() {
+ if (!mIsFirstClick) {
+ mIsFirstClick = true;
+ mAttachInfo.mHandler.removeCallbacks(mDoSingleClick);
+ mListenerInfo.mOnDoubleClickListener.onDoubleClick(this);
+ return;
+ } else {
+ mIsFirstClick = false;
+ mAttachInfo.mHandler.postDelayed(mDoSingleClick, 250);
+ }
+ }
+
/**
* Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
* OnLongClickListener did not consume the event.
@@ -8071,8 +8120,7 @@ && pointInView(event.getX(), event.getY())) {
// in onHoverEvent.
// Note that onGenericMotionEvent will be called by default when
// onHoverEvent returns false (refer to dispatchGenericMotionEvent).
- dispatchGenericMotionEventInternal(event);
- return true;
+ return dispatchGenericMotionEventInternal(event);
}
return false;
@@ -10526,8 +10574,9 @@ protected boolean hasOpaqueScrollbars() {
* handler can be used to pump events in the UI events queue.
*/
public Handler getHandler() {
- if (mAttachInfo != null) {
- return mAttachInfo.mHandler;
+ final AttachInfo attachInfo = mAttachInfo;
+ if (attachInfo != null) {
+ return attachInfo.mHandler;
}
return null;
}
@@ -17519,6 +17568,23 @@ public interface OnClickListener {
void onClick(View v);
}
+ /**
+ * Interface definition for a callback to be invoked when a view is double clicked.
+ */
+ public interface OnDoubleClickListener {
+ /**
+ * Called when a view has been single clicked.
+ *
+ * @param v The view that was clicked.
+ */
+ void onSingleClick(View v);
+ /**
+ * Called when a view has been double clicked.
+ *
+ */
+ void onDoubleClick(View v);
+ }
+
/**
* Interface definition for a callback to be invoked when the context menu
* for this view is being built.
@@ -18400,4 +18466,15 @@ private static void dumpFlag(HashMap found, String name, int val
final String output = bits + " " + name;
found.put(key, output);
}
+
+ public class DoSingleClick implements Runnable {
+ private View mPassedView;
+ public DoSingleClick(View view) {
+ this.mPassedView = view;
+ }
+ public void run() {
+ mIsFirstClick = true;
+ mListenerInfo.mOnDoubleClickListener.onSingleClick(mPassedView);
+ }
+ }
}
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 499075e1b6a..86e5b664872 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -223,6 +223,8 @@ public class ViewConfiguration {
private boolean sHasPermanentMenuKey;
private boolean sHasPermanentMenuKeySet;
+ private Context mContext;
+
static final SparseArray sConfigurations =
new SparseArray(2);
@@ -270,6 +272,8 @@ private ViewConfiguration(Context context) {
sizeAndDensity = density;
}
+ mContext = context;
+
mEdgeSlop = (int) (sizeAndDensity * EDGE_SLOP + 0.5f);
mFadingEdgeLength = (int) (sizeAndDensity * FADING_EDGE_LENGTH + 0.5f);
mMinimumFlingVelocity = (int) (density * MINIMUM_FLING_VELOCITY + 0.5f);
@@ -678,7 +682,18 @@ public static float getScrollFriction() {
* @return true if a permanent menu key is present, false otherwise.
*/
public boolean hasPermanentMenuKey() {
- return sHasPermanentMenuKey;
+ // The action overflow button within app UI can
+ // be controlled with a system setting
+ boolean showOverflowButton = Settings.System.getBoolean(
+ mContext.getContentResolver(),
+ Settings.System.UI_FORCE_OVERFLOW_BUTTON, false);
+ if (showOverflowButton) {
+ // Force overflow button on by reporting that
+ // the device has no permanent menu key
+ return false;
+ } else {
+ return sHasPermanentMenuKey;
+ }
}
/**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index dbbcde6d0f2..c2676f18a76 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1472,9 +1472,9 @@ protected boolean dispatchHoverEvent(MotionEvent event) {
if (lastHoverTarget != null) {
lastHoverTarget.next = hoverTarget;
} else {
- lastHoverTarget = hoverTarget;
mFirstHoverTarget = hoverTarget;
}
+ lastHoverTarget = hoverTarget;
// Dispatch the event to the child.
if (action == MotionEvent.ACTION_HOVER_ENTER) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index b6016e93be5..19c0bedf9f4 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -3780,6 +3780,13 @@ private void deliverKeyEventPostIme(QueuedInputEvent q) {
finishInputEvent(q, true);
return;
}
+ } else {
+ // find the best view to give focus to in this non-touch-mode with no-focus
+ View v = focusSearch(null, direction);
+ if (v != null && v.requestFocus(direction)) {
+ finishInputEvent(q, true);
+ return;
+ }
}
}
}
diff --git a/core/java/android/view/ViewStub.java b/core/java/android/view/ViewStub.java
index 69a26c25490..a5dc3ae12bd 100644
--- a/core/java/android/view/ViewStub.java
+++ b/core/java/android/view/ViewStub.java
@@ -212,7 +212,8 @@ protected void dispatchDraw(Canvas canvas) {
/**
* When visibility is set to {@link #VISIBLE} or {@link #INVISIBLE},
* {@link #inflate()} is invoked and this StubbedView is replaced in its parent
- * by the inflated layout resource.
+ * by the inflated layout resource. After that calls to this function are passed
+ * through to the inflated view.
*
* @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
*
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index 001d0206e7b..4bfd3d717ba 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -27,6 +27,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
+import android.database.ContentObserver;
import android.media.AudioManager;
import android.media.AudioService;
import android.media.AudioSystem;
@@ -35,7 +36,9 @@
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
+import android.os.RemoteException;
import android.os.Vibrator;
+import android.provider.Settings;
import android.util.Log;
import android.view.WindowManager.LayoutParams;
import android.widget.ImageView;
@@ -99,12 +102,19 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
private static final int STREAM_MASTER = -100;
// Pseudo stream type for remote volume is defined in AudioService.STREAM_REMOTE_MUSIC
+ public static final int VOLUME_OVERLAY_SINGLE = 0;
+ public static final int VOLUME_OVERLAY_EXPANDABLE = 1;
+ public static final int VOLUME_OVERLAY_EXPANDED = 2;
+ public static final int VOLUME_OVERLAY_NONE = 3;
+
protected Context mContext;
private AudioManager mAudioManager;
protected AudioService mAudioService;
private boolean mRingIsSilent;
private boolean mShowCombinedVolumes;
private boolean mVoiceCapable;
+ private boolean mVolumeLinkNotification;
+ private int mCurrentOverlayStyle = -1;
// True if we want to play tones on the system stream when the master stream is specified.
private final boolean mPlayMasterStreamTones;
@@ -138,7 +148,7 @@ private enum StreamResources {
R.string.volume_icon_description_ringer,
R.drawable.ic_audio_ring_notif,
R.drawable.ic_audio_ring_notif_mute,
- false),
+ true),
VoiceStream(AudioManager.STREAM_VOICE_CALL,
R.string.volume_icon_description_incall,
R.drawable.ic_audio_phone,
@@ -148,7 +158,7 @@ private enum StreamResources {
R.string.volume_alarm,
R.drawable.ic_audio_alarm,
R.drawable.ic_audio_alarm_mute,
- false),
+ true),
MediaStream(AudioManager.STREAM_MUSIC,
R.string.volume_icon_description_media,
R.drawable.ic_audio_vol,
@@ -213,6 +223,17 @@ private class StreamControl {
private ToneGenerator mToneGenerators[];
private Vibrator mVibrator;
+ private ContentObserver mSettingsObserver = new ContentObserver(this) {
+ @Override
+ public void onChange(boolean selfChange) {
+ mVolumeLinkNotification = Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.VOLUME_LINK_NOTIFICATION, 1) == 1;
+ final int overlayStyle = Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.MODE_VOLUME_OVERLAY, VOLUME_OVERLAY_EXPANDABLE);
+ changeOverlayStyle(overlayStyle);
+ }
+ };
+
private static AlertDialog sConfirmSafeVolumeDialog;
private static Object sConfirmSafeVolumeLock = new Object();
@@ -262,7 +283,7 @@ public VolumePanel(final Context context, AudioService volumeService) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View view = mView = inflater.inflate(R.layout.volume_adjust, null);
+ mView = inflater.inflate(R.layout.volume_adjust, null);
mView.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
resetTimeout();
@@ -309,24 +330,32 @@ public void onDismiss(DialogInterface dialog) {
mToneGenerators = new ToneGenerator[AudioSystem.getNumStreamTypes()];
mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
-
mVoiceCapable = context.getResources().getBoolean(R.bool.config_voice_capable);
- mShowCombinedVolumes = !mVoiceCapable && !useMasterVolume;
- // If we don't want to show multiple volumes, hide the settings button and divider
- if (!mShowCombinedVolumes) {
- mMoreButton.setVisibility(View.GONE);
- mDivider.setVisibility(View.GONE);
- } else {
- mMoreButton.setOnClickListener(this);
- }
+ // Get the user's preferences
+ mVolumeLinkNotification = Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.VOLUME_LINK_NOTIFICATION, 1) == 1;
+ final int chosenStyle = Settings.System.getInt(context.getContentResolver(),
+ Settings.System.MODE_VOLUME_OVERLAY, VOLUME_OVERLAY_EXPANDABLE);
+ changeOverlayStyle(chosenStyle);
+
+ context.getContentResolver().registerContentObserver(
+ Settings.System.getUriFor(Settings.System.VOLUME_LINK_NOTIFICATION), false,
+ mSettingsObserver);
+ context.getContentResolver().registerContentObserver(
+ Settings.System.getUriFor(Settings.System.MODE_VOLUME_OVERLAY), false,
+ mSettingsObserver);
+
+ // This is new with 4.2 it seems
boolean masterVolumeOnly = context.getResources().getBoolean(
com.android.internal.R.bool.config_useMasterVolume);
boolean masterVolumeKeySounds = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_useVolumeKeySounds);
mPlayMasterStreamTones = masterVolumeOnly && masterVolumeKeySounds;
+ // End this is new
+ mMoreButton.setOnClickListener(this);
listenToRingerMode();
}
@@ -346,13 +375,37 @@ public void onReceive(Context context, Intent intent) {
}, filter);
}
- private boolean isMuted(int streamType) {
- if (streamType == STREAM_MASTER) {
- return mAudioManager.isMasterMute();
- } else if (streamType == AudioService.STREAM_REMOTE_MUSIC) {
- return (mAudioService.getRemoteStreamVolume() <= 0);
- } else {
- return mAudioManager.isStreamMute(streamType);
+ private void changeOverlayStyle(int newStyle) {
+ Log.i("VolumePanel", "changeOverlayStyle : " + newStyle);
+ // Don't change to the same style
+ if (newStyle == mCurrentOverlayStyle) return;
+ switch (newStyle) {
+ case VOLUME_OVERLAY_SINGLE :
+ mMoreButton.setVisibility(View.GONE);
+ mDivider.setVisibility(View.GONE);
+ mShowCombinedVolumes = false;
+ mCurrentOverlayStyle = VOLUME_OVERLAY_SINGLE;
+ break;
+ case VOLUME_OVERLAY_EXPANDABLE :
+ mMoreButton.setVisibility(View.VISIBLE);
+ mDivider.setVisibility(View.VISIBLE);
+ mShowCombinedVolumes = true;
+ mCurrentOverlayStyle = VOLUME_OVERLAY_EXPANDABLE;
+ break;
+ case VOLUME_OVERLAY_EXPANDED :
+ mMoreButton.setVisibility(View.GONE);
+ mDivider.setVisibility(View.GONE);
+ mShowCombinedVolumes = true;
+ if (mCurrentOverlayStyle == VOLUME_OVERLAY_NONE) {
+ addOtherVolumes();
+ expand();
+ }
+ mCurrentOverlayStyle = VOLUME_OVERLAY_EXPANDED;
+ break;
+ case VOLUME_OVERLAY_NONE :
+ mShowCombinedVolumes = false;
+ mCurrentOverlayStyle = VOLUME_OVERLAY_NONE;
+ break;
}
}
@@ -386,6 +439,16 @@ private void setStreamVolume(int streamType, int index, int flags) {
}
}
+ private boolean isMuted(int streamType) {
+ if (streamType == STREAM_MASTER) {
+ return mAudioManager.isMasterMute();
+ } else if (streamType == AudioService.STREAM_REMOTE_MUSIC) {
+ return (mAudioService.getRemoteStreamVolume() <= 0);
+ } else {
+ return mAudioManager.isStreamMute(streamType);
+ }
+ }
+
private void createSliders() {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@@ -394,9 +457,6 @@ private void createSliders() {
for (int i = 0; i < STREAMS.length; i++) {
StreamResources streamRes = STREAMS[i];
int streamType = streamRes.streamType;
- if (mVoiceCapable && streamRes == StreamResources.NotificationStream) {
- streamRes = StreamResources.RingerStream;
- }
StreamControl sc = new StreamControl();
sc.streamType = streamType;
sc.group = (ViewGroup) inflater.inflate(R.layout.volume_adjust_item, null);
@@ -407,6 +467,7 @@ private void createSliders() {
sc.iconRes = streamRes.iconRes;
sc.iconMuteRes = streamRes.iconMuteRes;
sc.icon.setImageResource(sc.iconRes);
+ sc.icon.setOnClickListener(this);
sc.seekbarView = (SeekBar) sc.group.findViewById(R.id.seekbar);
int plusOne = (streamType == AudioSystem.STREAM_BLUETOOTH_SCO ||
streamType == AudioSystem.STREAM_VOICE_CALL) ? 1 : 0;
@@ -443,6 +504,15 @@ private void addOtherVolumes() {
if (!STREAMS[i].show || streamType == mActiveStreamType) {
continue;
}
+ // Skip ring volume for non-phone devices
+ if (!mVoiceCapable && streamType == AudioManager.STREAM_RING) {
+ continue;
+ }
+ // Skip notification volume if linked with ring volume
+ if (mVoiceCapable && mVolumeLinkNotification &&
+ streamType == AudioManager.STREAM_NOTIFICATION) {
+ continue;
+ }
StreamControl sc = mStreamControls.get(streamType);
mSliderGroup.addView(sc.group);
updateSlider(sc);
@@ -476,10 +546,22 @@ private boolean isExpanded() {
private void expand() {
final int count = mSliderGroup.getChildCount();
for (int i = 0; i < count; i++) {
- mSliderGroup.getChildAt(i).setVisibility(View.VISIBLE);
+ if (mSliderGroup.getChildAt(i).getVisibility() != View.VISIBLE) {
+ mSliderGroup.getChildAt(i).setVisibility(View.VISIBLE);
+ }
+ }
+ mMoreButton.setVisibility(View.GONE);
+ mDivider.setVisibility(View.GONE);
+ }
+
+ private void hideSlider(int mActiveStreamType) {
+ final int count = mSliderGroup.getChildCount();
+ for (int i = 0; i < count; i++) {
+ StreamControl sc = (StreamControl) mSliderGroup.getChildAt(i).getTag();
+ if (mActiveStreamType == sc.streamType) {
+ mSliderGroup.getChildAt(i).setVisibility(View.GONE);
+ }
}
- mMoreButton.setVisibility(View.INVISIBLE);
- mDivider.setVisibility(View.INVISIBLE);
}
private void collapse() {
@@ -579,7 +661,10 @@ protected void onVolumeChanged(int streamType, int flags) {
if ((flags & AudioManager.FLAG_SHOW_UI) != 0) {
synchronized (this) {
- if (mActiveStreamType != streamType) {
+ if (streamType != mActiveStreamType) {
+ if (mCurrentOverlayStyle == VOLUME_OVERLAY_EXPANDABLE) {
+ hideSlider(mActiveStreamType);
+ }
reorderSliders(streamType);
}
onShowVolumeChanged(streamType, flags);
@@ -712,15 +797,20 @@ protected void onShowVolumeChanged(int streamType, int flags) {
}
}
- if (!mDialog.isShowing()) {
+ // Only Show if style needs it
+ if (!mDialog.isShowing() && mCurrentOverlayStyle != VOLUME_OVERLAY_NONE) {
int stream = (streamType == AudioService.STREAM_REMOTE_MUSIC) ? -1 : streamType;
// when the stream is for remote playback, use -1 to reset the stream type evaluation
mAudioManager.forceVolumeControlStream(stream);
mDialog.setContentView(mView);
// Showing dialog - use collapsed state
- if (mShowCombinedVolumes) {
+ if (mShowCombinedVolumes && mCurrentOverlayStyle != VOLUME_OVERLAY_EXPANDED) {
collapse();
}
+ // If just changed the style and we need to expand
+ if (mCurrentOverlayStyle == VOLUME_OVERLAY_EXPANDED) {
+ expand();
+ }
mDialog.show();
}
@@ -735,6 +825,11 @@ protected void onShowVolumeChanged(int streamType, int flags) {
protected void onPlaySound(int streamType, int flags) {
+ // If preference is no sound - just exit here
+ if (Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.VOLUME_ADJUST_SOUNDS_ENABLED, 1) == 0) {
+ return;
+ }
if (hasMessages(MSG_STOP_SOUNDS)) {
removeMessages(MSG_STOP_SOUNDS);
// Force stop right now
@@ -996,8 +1091,7 @@ private void forceTimeout() {
sendMessage(obtainMessage(MSG_TIMEOUT));
}
- public void onProgressChanged(SeekBar seekBar, int progress,
- boolean fromUser) {
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
final Object tag = seekBar.getTag();
if (fromUser && tag instanceof StreamControl) {
StreamControl sc = (StreamControl) tag;
@@ -1028,6 +1122,12 @@ public void onStopTrackingTouch(SeekBar seekBar) {
public void onClick(View v) {
if (v == mMoreButton) {
expand();
+ } else if (v instanceof ImageView) {
+ Intent volumeSettings = new Intent(android.provider.Settings.ACTION_SOUND_SETTINGS);
+ volumeSettings.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ forceTimeout();
+ mContext.startActivity(volumeSettings);
+ return;
}
resetTimeout();
}
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 06974d31e86..aa8aebf2756 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -152,6 +152,8 @@ public abstract class Window {
private boolean mDestroyed;
+ public boolean mIsFloatingWindow = false;
+
// The current window attributes.
private final WindowManager.LayoutParams mWindowAttributes =
new WindowManager.LayoutParams();
@@ -740,6 +742,10 @@ public void clearFlags(int flags) {
* @see #clearFlags
*/
public void setFlags(int flags, int mask) {
+ if ((flags & mask & WindowManager.LayoutParams.PREVENT_POWER_KEY) != 0){
+ mContext.enforceCallingOrSelfPermission("android.permission.PREVENT_POWER_KEY",
+ "No permission to prevent power key");
+ }
final WindowManager.LayoutParams attrs = getAttributes();
attrs.flags = (attrs.flags&~mask) | (flags&mask);
if ((mask&WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0) {
@@ -779,6 +785,10 @@ public void setDimAmount(float amount) {
* current values.
*/
public void setAttributes(WindowManager.LayoutParams a) {
+ if ((a.flags & WindowManager.LayoutParams.PREVENT_POWER_KEY) != 0) {
+ mContext.enforceCallingOrSelfPermission("android.permission.PREVENT_POWER_KEY",
+ "No permission to prevent power key");
+ }
mWindowAttributes.copyFrom(a);
if (mCallback != null) {
mCallback.onWindowAttributesChanged(mWindowAttributes);
diff --git a/core/java/android/view/WindowManager.aidl b/core/java/android/view/WindowManager.aidl
old mode 100755
new mode 100644
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 6a67d8b8acd..f6e838dc6c7 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -804,6 +804,10 @@ public static class LayoutParams extends ViewGroup.LayoutParams
* {@hide} */
public static final int FLAG_SYSTEM_ERROR = 0x40000000;
+ /** Window flag: Overrides default power key behavior
+ * {@hide} */
+ public static final int PREVENT_POWER_KEY = 0x80000000;
+
/**
* Various behavioral options/flags. Default is none.
*
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 26739b3d502..c5a9afad5a6 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -399,6 +399,8 @@ public FakeWindow addFakeWindow(Looper looper,
public void shutdown(boolean confirm);
public void rebootSafeMode(boolean confirm);
+ public void reboot();
+ public void rebootTile();
}
/**
@@ -611,6 +613,18 @@ public void adjustConfigurationLw(Configuration config, int keyboardPresence,
*/
public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation);
+ public int getWallpaperHeight(int rotation);
+
+ public int getWallpaperWidth(int rotation);
+
+ public int getWallpaperTop(int rot);
+
+ public int getWallpaperLeft(int rot);
+
+ public int getWallpaperBottom(int rot);
+
+ public int getWallpaperRight(int rot);
+
/**
* Return whether the given window should forcibly hide everything
* behind it. Typically returns true for the keyguard.
@@ -1034,6 +1048,11 @@ interface OnKeyguardExitResult {
*/
public void systemBooted();
+ /**
+ * name of package being worked on during boot time message
+ */
+ public void setPackageName(String pkgName);
+
/**
* Show boot time message to the user.
*/
diff --git a/core/java/android/view/WindowOrientationListener.java b/core/java/android/view/WindowOrientationListener.java
old mode 100755
new mode 100644
index 4c34dd4e5b8..88671abdee2
--- a/core/java/android/view/WindowOrientationListener.java
+++ b/core/java/android/view/WindowOrientationListener.java
@@ -42,8 +42,10 @@
*/
public abstract class WindowOrientationListener {
private static final String TAG = "WindowOrientationListener";
- private static final boolean LOG = SystemProperties.getBoolean(
- "debug.orientation.log", false);
+ private static final boolean LOG = SystemProperties.getBoolean( "debug.orientation.log", false);
+ private static final float MAGNITUDE_THRESHOLD = ((float)SystemProperties.getLong( "orientation.magnitude.threshold", 0))/1000.0f;
+
+
private static final boolean USE_GRAVITY_SENSOR = false;
@@ -98,6 +100,7 @@ public void enable() {
if (LOG) {
Log.d(TAG, "WindowOrientationListener enabled");
}
+ mSensorEventListener.reset();
mSensorManager.registerListener(mSensorEventListener, mSensor, mRate);
mEnabled = true;
}
@@ -421,23 +424,15 @@ public void onSensorChanged(SensorEvent event) {
mLastFilteredY = y;
mLastFilteredZ = z;
- boolean isAccelerating = false;
boolean isFlat = false;
boolean isSwinging = false;
if (!skipSample) {
// Calculate the magnitude of the acceleration vector.
final float magnitude = FloatMath.sqrt(x * x + y * y + z * z);
- if (magnitude < NEAR_ZERO_MAGNITUDE) {
- if (LOG) {
- Slog.v(TAG, "Ignoring sensor data, magnitude too close to zero.");
- }
+ if (isMagnitudeOutOfRange(magnitude) || Math.abs(magnitude - SensorManager.STANDARD_GRAVITY) < MAGNITUDE_THRESHOLD) {
+ if (LOG) { Slog.v(TAG, "Ignoring sensor data"); }
clearPredictedRotation();
} else {
- // Determine whether the device appears to be undergoing external acceleration.
- if (isAccelerating(magnitude)) {
- isAccelerating = true;
- mAccelerationTimestampNanos = now;
- }
// Calculate the tilt angle.
// This is the angle between the up vector and the x-y plane (the plane of
@@ -445,8 +440,7 @@ public void onSensorChanged(SensorEvent event) {
// -90 degrees: screen horizontal and facing the ground (overhead)
// 0 degrees: screen vertical
// 90 degrees: screen horizontal and facing the sky (on table)
- final int tiltAngle = (int) Math.round(
- Math.asin(z / magnitude) * RADIANS_TO_DEGREES);
+ final int tiltAngle = (int) Math.round( Math.asin(z / magnitude) * RADIANS_TO_DEGREES);
addTiltHistoryEntry(now, tiltAngle);
// Determine whether the device appears to be flat or swinging.
@@ -522,7 +516,6 @@ && isOrientationAngleAcceptable(nearestRotation,
+ ", proposedRotation=" + mProposedRotation
+ ", predictedRotation=" + mPredictedRotation
+ ", timeDeltaMS=" + timeDeltaMS
- + ", isAccelerating=" + isAccelerating
+ ", isFlat=" + isFlat
+ ", isSwinging=" + isSwinging
+ ", timeUntilSettledMS=" + remainingMS(now,
@@ -541,6 +534,7 @@ && isOrientationAngleAcceptable(nearestRotation,
Slog.v(TAG, "Proposed rotation changed! proposedRotation=" + mProposedRotation
+ ", oldProposedRotation=" + oldProposedRotation);
}
+ mAccelerationTimestampNanos = now;
mOrientationListener.onProposedRotationChanged(mProposedRotation);
}
}
@@ -659,7 +653,7 @@ private void updatePredictedRotation(long now, int rotation) {
}
}
- private boolean isAccelerating(float magnitude) {
+ private boolean isMagnitudeOutOfRange(float magnitude) {
return magnitude < MIN_ACCELERATION_MAGNITUDE
|| magnitude > MAX_ACCELERATION_MAGNITUDE;
}
diff --git a/core/java/android/view/animation/package.html b/core/java/android/view/animation/package.html
old mode 100755
new mode 100644
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index 51465675261..bcf6cd60bfc 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -320,6 +320,15 @@ public final void makeCompatible(int targetSdkVersion) {
}
}
}
+ public final void formalTextInput(boolean forceLong) {
+ if (forceLong) {
+ switch (inputType&(TYPE_MASK_CLASS|TYPE_MASK_VARIATION)) {
+ case TYPE_CLASS_TEXT|TYPE_TEXT_VARIATION_SHORT_MESSAGE:
+ inputType = TYPE_CLASS_TEXT|TYPE_TEXT_VARIATION_LONG_MESSAGE
+ | (inputType&TYPE_MASK_FLAGS);
+ }
+ }
+ }
/**
* Write debug output of this object.
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 4dbca23c927..35aabf71dd4 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -70,6 +70,7 @@ class BrowserFrame extends Handler {
* request's LoadListener
*/
private final static int MAX_OUTSTANDING_REQUESTS = 300;
+ private final static String SCHEME_HOST_DELIMITER = "://";
private final CallbackProxy mCallbackProxy;
private final WebSettingsClassic mSettings;
@@ -500,9 +501,14 @@ public void handleMessage(Message msg) {
.getCurrentItem();
if (item != null) {
WebAddress uri = new WebAddress(item.getUrl());
- String schemePlusHost = uri.getScheme() + uri.getHost();
+ String schemePlusHost = uri.getScheme() + SCHEME_HOST_DELIMITER +
+ uri.getHost();
String[] up = mDatabase.getUsernamePassword(
schemePlusHost);
+ if (up == null) { // no row found, try again using the legacy method
+ schemePlusHost = uri.getScheme() + uri.getHost();
+ up = mDatabase.getUsernamePassword(schemePlusHost);
+ }
if (up != null && up[0] != null) {
setUsernamePassword(up[0], up[1]);
}
@@ -817,7 +823,7 @@ private void maybeSavePassword(
}
WebAddress uri = new WebAddress(mCallbackProxy
.getBackForwardList().getCurrentItem().getUrl());
- String schemePlusHost = uri.getScheme() + uri.getHost();
+ String schemePlusHost = uri.getScheme() + SCHEME_HOST_DELIMITER + uri.getHost();
// Check to see if the username & password appear in
// the post data (there could be another form on the
// page and that was posted instead.
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index a326da2ef89..c3c51030da9 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -305,7 +305,12 @@ public void handleMessage(Message msg) {
// in the UI thread. The WebViewClient and WebChromeClient functions
// that check for a non-null callback are ok because java ensures atomic
// 32-bit reads and writes.
- if (messagesBlocked()) return;
+ if (messagesBlocked()) {
+ synchronized (this) {
+ notify();
+ }
+ return;
+ }
switch (msg.what) {
case PAGE_STARTED:
String startedUrl = msg.getData().getString("url");
diff --git a/core/java/android/webkit/DeviceMotionService.java b/core/java/android/webkit/DeviceMotionService.java
old mode 100755
new mode 100644
diff --git a/core/java/android/webkit/DeviceOrientationService.java b/core/java/android/webkit/DeviceOrientationService.java
old mode 100755
new mode 100644
diff --git a/core/java/android/webkit/FindActionModeCallback.java b/core/java/android/webkit/FindActionModeCallback.java
index 1a4ccfa9585..6a627e147a1 100644
--- a/core/java/android/webkit/FindActionModeCallback.java
+++ b/core/java/android/webkit/FindActionModeCallback.java
@@ -152,7 +152,7 @@ public void updateMatchCount(int matchIndex, int matchCount, boolean isEmptyFind
mActiveMatchIndex = matchIndex;
updateMatchesString();
} else {
- mMatches.setVisibility(View.INVISIBLE);
+ mMatches.setVisibility(View.GONE);
mNumberOfMatches = 0;
}
}
diff --git a/core/java/android/webkit/GeolocationPermissions.java b/core/java/android/webkit/GeolocationPermissions.java
old mode 100755
new mode 100644
diff --git a/core/java/android/webkit/GeolocationPermissionsClassic.java b/core/java/android/webkit/GeolocationPermissionsClassic.java
old mode 100755
new mode 100644
diff --git a/core/java/android/webkit/GeolocationService.java b/core/java/android/webkit/GeolocationService.java
old mode 100755
new mode 100644
diff --git a/core/java/android/webkit/HTML5Audio.java b/core/java/android/webkit/HTML5Audio.java
index fc5df2d5f59..684ec073ce4 100644
--- a/core/java/android/webkit/HTML5Audio.java
+++ b/core/java/android/webkit/HTML5Audio.java
@@ -54,14 +54,15 @@ class HTML5Audio extends Handler
// The private status of the view that created this player
private IsPrivateBrowsingEnabledGetter mIsPrivateBrowsingEnabledGetter;
- private static int IDLE = 0;
- private static int INITIALIZED = 1;
- private static int PREPARED = 2;
- private static int STARTED = 4;
- private static int COMPLETE = 5;
- private static int PAUSED = 6;
- private static int STOPPED = -2;
- private static int ERROR = -1;
+ private static int IDLE = 0;
+ private static int INITIALIZED = 1;
+ private static int PREPARED = 2;
+ private static int STARTED = 4;
+ private static int COMPLETE = 5;
+ private static int PAUSED = 6;
+ private static int PAUSED_TRANSITORILY = 7;
+ private static int STOPPED = -2;
+ private static int ERROR = -1;
private int mState = IDLE;
@@ -247,7 +248,7 @@ public void onAudioFocusChange(int focusChange) {
// resume playback
if (mMediaPlayer == null) {
resetMediaPlayer();
- } else if (mState != ERROR && !mMediaPlayer.isPlaying()) {
+ } else if (mState == PAUSED_TRANSITORILY && !mMediaPlayer.isPlaying()) {
mMediaPlayer.start();
mState = STARTED;
}
@@ -265,7 +266,9 @@ public void onAudioFocusChange(int focusChange) {
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
// Lost focus for a short time, but we have to stop
// playback.
- if (mState != ERROR && mMediaPlayer.isPlaying()) pause();
+ if (mState != ERROR && mMediaPlayer.isPlaying()) {
+ pause(PAUSED_TRANSITORILY);
+ }
break;
}
}
@@ -298,12 +301,16 @@ private void play() {
}
private void pause() {
+ pause(PAUSED);
+ }
+
+ private void pause(int state) {
if (mState == STARTED) {
if (mTimer != null) {
mTimer.purge();
}
mMediaPlayer.pause();
- mState = PAUSED;
+ mState = state;
}
}
diff --git a/core/java/android/webkit/HTML5WebSocket.java b/core/java/android/webkit/HTML5WebSocket.java
new file mode 100644
index 00000000000..d35676b5235
--- /dev/null
+++ b/core/java/android/webkit/HTML5WebSocket.java
@@ -0,0 +1,529 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013 Oleg Smirnov
+ *
+ * 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.webkit;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ClosedSelectorException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+
+import android.util.Log;
+/**
+ * @hide This is only used by the browser
+ *
+ * HTML5 support class for WebSockets.
+ *
+ * This class runs almost entirely on the WebCore thread.
+ */
+public final class HTML5WebSocket extends Handler {
+ // Logging tag.
+ private static final String LOG_TAG = "HTML5WebSocket";
+
+ // Message ids
+ private static final int WEB_SOCKET_SEND = 100;
+ private static final int WEB_SOCKET_CLOSE = 101;
+
+ // Message ids to be handled on the WebCore thread
+ private static final int WEB_SOCKET_CONNECTED = 200;
+ private static final int WEB_SOCKET_CLOSED = 201;
+ private static final int WEB_SOCKET_MESSAGE = 202;
+ private static final int WEB_SOCKET_ERROR = 203;
+
+ // The C++ WebSocketBridge object.
+ private int mNativePointer = 0;
+ // The handler for WebCore thread messages;
+ private Handler mWebCoreHandler = null;
+ // Helper class with internal implementation
+ private WebSocket mWebSocket = null;
+
+ /** @hide */
+ public void onConnected() {
+ Message msg = Message.obtain(mWebCoreHandler, WEB_SOCKET_CONNECTED);
+ mWebCoreHandler.sendMessage(msg);
+ }
+
+ /** @hide */
+ public void onClosed() {
+ Message msg = Message.obtain(mWebCoreHandler, WEB_SOCKET_CLOSED);
+ mWebCoreHandler.sendMessage(msg);
+ }
+
+ /** @hide */
+ public void onMessage() {
+ Message msg = Message.obtain(mWebCoreHandler, WEB_SOCKET_MESSAGE);
+ mWebCoreHandler.sendMessage(msg);
+ }
+
+ /** @hide */
+ public void onError(Throwable t) {
+ Message msg = Message.obtain(mWebCoreHandler, WEB_SOCKET_ERROR);
+ mWebCoreHandler.sendMessage(msg);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case WEB_SOCKET_SEND: {
+ mWebSocket.send();
+ break;
+ }
+ case WEB_SOCKET_CLOSE: {
+ mWebSocket.close();
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ }
+
+ /** @hide */
+ private static class WebSocket implements Runnable {
+ private static final String LOG_TAG = "WebSocket";
+
+ // Handler on HTML5WebSocket
+ private HTML5WebSocket mCurrentWebSocket;
+
+ private SocketChannel mSocketChannel;
+ private Selector mSelector;
+ private boolean mRunning = false;
+
+ private boolean mIsSecure = false;
+
+ private static final int BUFFER_SIZE = 4096;
+
+ private BlockingQueue mBufferWriteQueue;
+ private BlockingQueue mBufferReadQueue;
+
+ private String mHost = null;
+ private int mPort = 80;
+
+ private ByteBuffer mReadBuffer = null;
+
+ /** @hide */
+ public WebSocket(HTML5WebSocket webSocket) throws NoSuchAlgorithmException, KeyManagementException {
+ mCurrentWebSocket = webSocket;
+
+ mBufferWriteQueue = new LinkedBlockingQueue();
+ mBufferReadQueue = new LinkedBlockingQueue();
+ }
+
+ /** @hide */
+ public Thread connect(URI uri) throws IOException {
+ mHost = uri.getHost();
+ mPort = uri.getPort();
+
+ mIsSecure = uri.getScheme().equalsIgnoreCase("https") ? true : false;
+
+ setSocketRunning(true);
+ mSocketChannel = SocketChannel.open();
+ mSocketChannel.configureBlocking(false);
+ mSocketChannel.connect(new InetSocketAddress(mHost, mPort));
+
+ System.setProperty("java.net.preferIPv4Stack", "true");
+ System.setProperty("java.net.preferIPv6Addresses", "false");
+
+ mSelector = Selector.open();
+ mSocketChannel.register(mSelector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ);
+
+ if (mIsSecure || mHost == null) {
+ // TODO: SSL web sockets are not implemented
+ setSocketRunning(false);
+ Thread th = null;
+ return th;
+ }
+ Thread th = new Thread(this);
+ th.start();
+ return th;
+ }
+
+ @Override
+ public void run() {
+ while (isSocketRunning()) {
+ try {
+ handleRunnable();
+ } catch (IOException e) {
+ mCurrentWebSocket.onError(e);
+ } catch (InterruptedException e) {
+ mCurrentWebSocket.onError(e);
+ }
+ }
+ }
+
+ /** @hide */
+ public void close() {
+ try {
+ closeImpl();
+ } catch (IOException e) {
+ return;
+ }
+ }
+
+ /** @hide */
+ public void send() {
+ try {
+ mSocketChannel.register(mSelector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ
+ | SelectionKey.OP_WRITE);
+ } catch (ClosedChannelException e) {
+ mCurrentWebSocket.onError(e);
+ }
+ }
+
+ /** @hide */
+ public ByteBuffer getReadData() {
+ ByteBuffer sendData = null;
+ ByteBuffer readData = null;
+ do {
+ readData = getReadQueueData();
+ if (readData == null) {
+ break;
+ }
+ ByteBuffer chunk = ByteBuffer.allocate((sendData != null ? sendData.capacity() : 0) + readData.capacity());
+
+ if (sendData != null) {
+ sendData.rewind();
+ chunk.put(sendData);
+ }
+ readData.rewind();
+ chunk.put(readData.array(), 0, readData.capacity());
+ sendData = chunk;
+
+ if (sendData.capacity() > 2 * BUFFER_SIZE) {
+ break;
+ }
+ } while (readData != null);
+ return sendData;
+ }
+
+ /** @hide */
+ synchronized public ByteBuffer getReadQueueData() {
+ return mBufferReadQueue.poll();
+ }
+
+ /** @hide */
+ synchronized public ByteBuffer getWriteQueueData() {
+ return mBufferWriteQueue.poll();
+ }
+
+ /** @hide */
+ synchronized public void putReadQueueData(ByteBuffer data) throws InterruptedException {
+ data.rewind();
+ mBufferReadQueue.put(data);
+ }
+
+ /** @hide */
+ synchronized public void putWriteQueueData(ByteBuffer data) throws InterruptedException {
+ data.rewind();
+ mBufferWriteQueue.put(data);
+ }
+
+ synchronized private boolean isSocketConnected() {
+ if (mSocketChannel != null && mSocketChannel.isConnected()) {
+ return true;
+ }
+ return false;
+ }
+
+ synchronized private boolean isSocketRunning() {
+ if (mRunning && mSocketChannel != null && !mSocketChannel.socket().isClosed()) {
+ return true;
+ }
+ return false;
+ }
+
+ synchronized private void setSocketRunning(boolean running) {
+ mRunning = running;
+ }
+
+ /** @hide */
+ synchronized public boolean isSocketSecure() {
+ return mIsSecure;
+ }
+
+ private void handleRunnable() throws InterruptedException, IOException {
+ if (!isSocketRunning()) {
+ return;
+ }
+ if (!mSelector.isOpen()) {
+ return;
+ }
+
+ try {
+ if (mSelector.select() == 0) {
+ return;
+ }
+ } catch (IOException e) {
+ return;
+ } catch (ClosedSelectorException e) {
+ return;
+ } catch (IllegalArgumentException e) {
+ return;
+ }
+
+ Set keys = mSelector.selectedKeys();
+ Iterator iter = keys.iterator();
+
+ while (iter.hasNext()) {
+ SelectionKey key = iter.next();
+ iter.remove();
+
+ if (!key.isValid())
+ continue;
+
+ if (key.isConnectable()) {
+ handleConnectable(key);
+ continue;
+ }
+ if (isSocketConnected() && key.isWritable()) {
+ handleWritable(key);
+ continue;
+ }
+ if (isSocketConnected() && key.isReadable()) {
+ handleReadable(key);
+ continue;
+ }
+ }
+ }
+
+ private void handleConnectable(SelectionKey key) throws IOException {
+ if (mSocketChannel.isConnectionPending()) {
+ mSocketChannel.finishConnect();
+ }
+
+ mReadBuffer = ByteBuffer.allocate(BUFFER_SIZE);
+
+ mCurrentWebSocket.onConnected();
+ }
+
+ private void handleWritable(SelectionKey key) throws IOException {
+ try {
+ int count = 0;
+ ByteBuffer data = getWriteQueueData();
+
+ if (data != null) {
+ count = writeImpl(data);
+ }
+
+ if (count > 0) {
+ key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
+ }
+ } catch (IOException ex) {
+ mCurrentWebSocket.onError(ex);
+ key.cancel();
+ }
+ }
+
+ private void handleReadable(SelectionKey key) throws IOException, InterruptedException {
+ try {
+ int count = readImpl();
+
+ if (count < 0) {
+ mCurrentWebSocket.onMessage();
+ handleWritable(key);
+ }
+ } catch (IOException ex) {
+ mCurrentWebSocket.onError(ex);
+ key.cancel();
+ }
+ }
+
+ private int writeImpl(ByteBuffer data) throws IOException {
+ int plainDataCount = -1;
+ if (data == null) {
+ return plainDataCount;
+ }
+
+ while (data.hasRemaining()) {
+ if (!isSocketRunning()) {
+ break;
+ }
+ plainDataCount = mSocketChannel.write(data);
+ }
+
+ return plainDataCount;
+ }
+
+ private int readImpl() throws IOException, InterruptedException {
+ int plainDataCount = -1;
+ do {
+ if (!isSocketRunning()) {
+ break;
+ }
+
+ mReadBuffer.clear();
+ plainDataCount = mSocketChannel.read(mReadBuffer);
+
+ if (plainDataCount <= 0) {
+ plainDataCount = -1;
+ break;
+ }
+ ByteBuffer chunk = mReadBuffer;
+ if (plainDataCount < BUFFER_SIZE) {
+ // allocate less chunk buffer than BUFFER_SIZE
+ chunk = ByteBuffer.allocate(plainDataCount);
+ if (chunk != null) {
+ chunk.put(mReadBuffer.array(), 0, plainDataCount);
+ }
+ }
+
+ putReadQueueData(chunk);
+
+ } while (plainDataCount > 0);
+
+ return plainDataCount;
+ }
+
+ private void closeImpl() throws IOException {
+ setSocketRunning(false);
+ mCurrentWebSocket.onClosed();
+
+ if (mSocketChannel != null) {
+ mSocketChannel.close();
+ }
+ if (mSelector != null) {
+ mSelector.wakeup();
+ }
+ }
+ }
+
+ /**
+ * Private constructor.
+ * @param nativePtr is the C++ pointer to the WebSocketBridge object.
+ * @param uri is a server uri for WebSocket object.
+ */
+ private HTML5WebSocket(int nativePtr, String uri) {
+ // This handler is for the main (UI) thread.
+ super(Looper.getMainLooper());
+ mNativePointer = nativePtr;
+ // Create the message handler for this thread
+ createWebCoreHandler();
+
+ Thread th = null;
+ try {
+ mWebSocket = new WebSocket(this);
+ th = mWebSocket.connect(new URI(uri));
+ } catch (Exception e) {
+ if (th != null) {
+ th.interrupt();
+ }
+ }
+ if (th == null && mWebSocket.isSocketSecure()) {
+ onError(new Exception("SSL WebSockets aren't supported now!"));
+ }
+ }
+
+ /**
+ * Message handler
+ */
+ private void createWebCoreHandler() {
+ mWebCoreHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case WEB_SOCKET_CONNECTED: {
+ nativeOnWebSocketConnected(mNativePointer);
+ break;
+ }
+ case WEB_SOCKET_CLOSED: {
+ nativeOnWebSocketClosed(mNativePointer);
+ break;
+ }
+ case WEB_SOCKET_MESSAGE: {
+ ByteBuffer msgData = null;
+ do {
+ msgData = mWebSocket.getReadData();
+ if (msgData == null) {
+ break;
+ }
+ nativeOnWebSocketMessage(mNativePointer, msgData.array(), msgData.capacity());
+ } while (msg != null);
+ break;
+ }
+ case WEB_SOCKET_ERROR: {
+ nativeOnWebSocketError(mNativePointer);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ }
+ };
+ }
+
+ /**
+ * Send data to web socket.
+ * @param bytes is sened data.
+ */
+ public void send(byte[] bytes) {
+ if (bytes == null) {
+ return;
+ }
+ ByteBuffer data = ByteBuffer.allocate(bytes.length);
+ data.put(bytes);
+ try {
+ mWebSocket.putWriteQueueData(data);
+ } catch (InterruptedException e) {
+ onError(e);
+ }
+ Message message = obtainMessage(WEB_SOCKET_SEND);
+ sendMessage(message);
+ }
+
+ /**
+ * Close web socket.
+ */
+ public void close() {
+ Message message = obtainMessage(WEB_SOCKET_CLOSE);
+ sendMessage(message);
+ }
+
+ /**
+ * The factory for HTML5WebSocket instances.
+ * @param uri is the URL that is requesting
+ *
+ * @return a new HTML5WebSocket object.
+ * @hide
+ */
+ public static HTML5WebSocket getInstance(int nativePtr, String uri) {
+ return new HTML5WebSocket(nativePtr, uri);
+ }
+
+ private native void nativeOnWebSocketConnected(int nativePointer);
+ private native void nativeOnWebSocketClosed(int nativePointer);
+ private native void nativeOnWebSocketMessage(int nativePointer, byte[] data, int length);
+ private native void nativeOnWebSocketError(int nativePointer);
+};
+
diff --git a/core/java/android/webkit/SelectActionModeCallback.java b/core/java/android/webkit/SelectActionModeCallback.java
index f9f5b033274..215467be4e2 100644
--- a/core/java/android/webkit/SelectActionModeCallback.java
+++ b/core/java/android/webkit/SelectActionModeCallback.java
@@ -137,7 +137,7 @@ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
@Override
public void onDestroyActionMode(ActionMode mode) {
- mWebView.selectionDone();
+ mWebView.clearSelection();
}
private void setMenuVisibility(Menu menu, boolean visible, int resourceId) {
diff --git a/core/java/android/webkit/WebCoreThreadWatchdog.java b/core/java/android/webkit/WebCoreThreadWatchdog.java
index a22e6e85a45..c27bb5f3454 100644
--- a/core/java/android/webkit/WebCoreThreadWatchdog.java
+++ b/core/java/android/webkit/WebCoreThreadWatchdog.java
@@ -270,7 +270,7 @@ public void onCancel(DialogInterface dialog) {
SUBSEQUENT_TIMEOUT_PERIOD);
}
})
- .setIcon(android.R.drawable.ic_dialog_alert)
+ .setIconAttribute(android.R.attr.alertDialogIcon)
.show();
}
}
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index aa689044e51..cf529d810ed 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -1082,6 +1082,16 @@ public synchronized void setDatabaseEnabled(boolean flag) {
throw new MustOverrideException();
}
+ /**
+ * Sets whether the web sockets API is enabled. The default value is
+ * false.
+ *
+ * @param flag true if the WebView should use the web sockets API
+ */
+ public synchronized void setWebSocketsEnabled(boolean flag) {
+ throw new MustOverrideException();
+ }
+
/**
* Sets whether the DOM storage API is enabled. The default value is false.
*
@@ -1120,6 +1130,16 @@ public synchronized boolean getDatabaseEnabled() {
throw new MustOverrideException();
}
+ /**
+ * Gets whether the web sockets API is enabled.
+ *
+ * @return true if the web sockets API is enabled
+ * @see #setWebSocketsEnabled
+ */
+ public synchronized boolean getWebSocketsEnabled() {
+ throw new MustOverrideException();
+ }
+
/**
* Sets whether Geolocation is enabled. The default is true. See also
* {@link #setGeolocationDatabasePath} for how to correctly set up
diff --git a/core/java/android/webkit/WebSettingsClassic.java b/core/java/android/webkit/WebSettingsClassic.java
index 1bbe7bbad07..58a32d11d37 100644
--- a/core/java/android/webkit/WebSettingsClassic.java
+++ b/core/java/android/webkit/WebSettingsClassic.java
@@ -22,6 +22,7 @@
import android.os.Build;
import android.os.Handler;
import android.os.Message;
+import android.os.SystemProperties;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.EventLog;
@@ -89,6 +90,7 @@ public class WebSettingsClassic extends WebSettings {
// HTML5 API flags
private boolean mAppCacheEnabled = false;
private boolean mDatabaseEnabled = false;
+ private boolean mWebSocketsEnabled = false;
private boolean mDomStorageEnabled = false;
private boolean mWorkersEnabled = false; // only affects V8.
private boolean mGeolocationEnabled = true;
@@ -125,6 +127,7 @@ public class WebSettingsClassic extends WebSettings {
private boolean mEnableSmoothTransition = false;
private boolean mForceUserScalable = false;
private boolean mPasswordEchoEnabled = true;
+ private boolean mWebGLEnabled = true;
// AutoFill Profile data
public static class AutoFillProfile {
@@ -432,6 +435,9 @@ public static String getDefaultUserAgentForLocale(Context context, Locale locale
buffer.append(" Build/");
buffer.append(id);
}
+ final String carbonversion = SystemProperties.get("ro.carbon.version");
+ if (carbonversion != null && carbonversion.length() > 0)
+ buffer.append("; Carbon-" + carbonversion.replaceAll("([0-9\\.]+?)-.*","$1"));
String mobile = context.getResources().getText(
com.android.internal.R.string.web_user_agent_target_content).toString();
final String base = context.getResources().getText(
@@ -1253,7 +1259,7 @@ public synchronized void setAppCacheEnabled(boolean flag) {
@Override
public synchronized void setAppCachePath(String path) {
// We test for a valid path and for repeated setting on the native
- // side, but we can avoid syncing in some simple cases.
+ // side, but we can avoid syncing in some simple cases.
if (mAppCachePath == null && path != null && !path.isEmpty()) {
mAppCachePath = path;
postSync();
@@ -1282,6 +1288,17 @@ public synchronized void setDatabaseEnabled(boolean flag) {
}
}
+ /**
+ * @see android.webkit.WebSettings#setWebSocketsEnabled(boolean)
+ */
+ @Override
+ public synchronized void setWebSocketsEnabled(boolean flag) {
+ if (mWebSocketsEnabled != flag) {
+ mWebSocketsEnabled = flag;
+ postSync();
+ }
+ }
+
/**
* @see android.webkit.WebSettings#setDomStorageEnabled(boolean)
*/
@@ -1317,6 +1334,14 @@ public synchronized boolean getDatabaseEnabled() {
return mDatabaseEnabled;
}
+ /**
+ * @see android.webkit.WebSettings#getWebSocketsEnabled()
+ */
+ @Override
+ public synchronized boolean getWebSocketsEnabled() {
+ return mWebSocketsEnabled;
+ }
+
/**
* Tell the WebView to enable WebWorkers API.
* @param flag True if the WebView should enable WebWorkers.
@@ -1629,6 +1654,25 @@ public boolean forceUserScalable() {
return mForceUserScalable;
}
+ /**
+ * @hide
+ */
+ public synchronized boolean isWebGLAvailable() {
+ return nativeIsWebGLAvailable();
+ }
+
+ /**
+ * Sets whether WebGL is enabled.
+ * @param flag Set to true to enable WebGL.
+ * @hide
+ */
+ public synchronized void setWebGLEnabled(boolean flag) {
+ if (mWebGLEnabled != flag) {
+ mWebGLEnabled = flag;
+ postSync();
+ }
+ }
+
/**
* Sets whether viewport metatag can disable zooming.
* @param flag Whether or not to forceably enable user scalable.
@@ -1741,4 +1785,5 @@ private synchronized void postSync() {
// Synchronize the native and java settings.
private native void nativeSync(int nativeFrame);
+ private native boolean nativeIsWebGLAvailable();
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 6df78204bb4..9feb513cd97 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -595,7 +595,8 @@ public void setCertificate(SslCertificate certificate) {
* forms. Note that this is unrelated to the credentials used for HTTP
* authentication.
*
- * @param host the host that required the credentials
+ * @param host the host that required the credentials. It is recommended that
+ * the host is given using scheme://hostname format.
* @param username the username for the given host
* @param password the password for the given host
* @see WebViewDatabase#clearUsernamePassword
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index ae56e6bfde0..d546d237ca6 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -2136,6 +2136,10 @@ private void destroyJava() {
mAccessibilityInjector.destroy();
mAccessibilityInjector = null;
}
+ if (mSavePasswordDialog != null) {
+ mSavePasswordDialog.dismiss();
+ mSavePasswordDialog = null;
+ }
if (mWebViewCore != null) {
// Tell WebViewCore to destroy itself
synchronized (this) {
@@ -3813,6 +3817,7 @@ public void computeScroll() {
invalidate(); // So we draw again
if (!mScroller.isFinished()) {
+ mSendScroll.setPostpone(true);
int rangeX = computeMaxScrollX();
int rangeY = computeMaxScrollY();
int overflingDistance = mOverflingDistance;
@@ -3840,6 +3845,7 @@ public void computeScroll() {
if (mOverScrollGlow != null) {
mOverScrollGlow.absorbGlow(x, y, oldX, oldY, rangeX, rangeY);
}
+ mSendScroll.setPostpone(false);
} else {
if (mTouchMode == TOUCH_DRAG_LAYER_MODE) {
// Update the layer position instead of WebView.
@@ -3859,7 +3865,7 @@ public void computeScroll() {
}
}
if (oldX != getScrollX() || oldY != getScrollY()) {
- sendOurVisibleRect();
+ mSendScroll.send(true);
}
}
} else {
@@ -4444,6 +4450,13 @@ public boolean selectText() {
return selectText(x, y);
}
+ public void clearSelection() {
+ selectionDone();
+ if (mWebViewCore != null) {
+ mWebViewCore.sendMessage(EventHub.CLEAR_SELECT_TEXT);
+ }
+ }
+
/**
* Select the word at the indicated content coordinates.
*/
@@ -4461,7 +4474,7 @@ boolean selectText(int x, int y) {
public void onConfigurationChanged(Configuration newConfig) {
mCachedOverlappingActionModeHeight = -1;
if (mSelectingText && mOrientation != newConfig.orientation) {
- selectionDone();
+ clearSelection();
}
mOrientation = newConfig.orientation;
if (mWebViewCore != null && !mBlockWebkitViewMessages) {
@@ -4716,7 +4729,7 @@ void switchOutDrawHistory() {
if (oldScrollX != getScrollX() || oldScrollY != getScrollY()) {
mWebViewPrivate.onScrollChanged(getScrollX(), getScrollY(), oldScrollX, oldScrollY);
} else {
- sendOurVisibleRect();
+ mSendScroll.send(true);
}
}
}
@@ -5382,7 +5395,7 @@ public void pasteFromClipboard() {
ClipData clipData = cm.getPrimaryClip();
if (clipData != null) {
ClipData.Item clipItem = clipData.getItemAt(0);
- CharSequence pasteText = clipItem.getText();
+ CharSequence pasteText = clipItem.coerceToText(mContext);
if (mInputConnection != null) {
mInputConnection.replaceSelection(pasteText);
}
@@ -5674,10 +5687,31 @@ private void scrollEditIntoView() {
contentScrollTo(scrollX, scrollY, false);
}
+ private final class SendScrollToWebCore implements Runnable {
+ public void run() {
+ if (!mInOverScrollMode) {
+ sendOurVisibleRect();
+ }
+ }
+ private boolean mPostpone = false;
+ public void setPostpone(boolean set) { mPostpone = set; }
+ public void send(boolean force) {
+ mPrivateHandler.removeCallbacks(this);
+ if (!mPostpone || force) {
+ run();
+ } else {
+ mPrivateHandler.postAtFrontOfQueue(this);
+ }
+ }
+ }
+
+ SendScrollToWebCore mSendScroll = new SendScrollToWebCore();
+
@Override
public void onScrollChanged(int l, int t, int oldl, int oldt) {
+ mSendScroll.send(false);
+
if (!mInOverScrollMode) {
- sendOurVisibleRect();
// update WebKit if visible title bar height changed. The logic is same
// as getVisibleTitleHeightImpl.
int titleHeight = getTitleHeight();
@@ -8366,8 +8400,10 @@ public void onItemClick(AdapterView> parent, View v,
mListBoxDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
+ if (mWebViewCore != null) {
mWebViewCore.sendMessage(
EventHub.SINGLE_LISTBOX_CHOICE, -2, 0);
+ }
mListBoxDialog = null;
}
});
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 3fb3ec62c43..883bd896b1e 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2012-2013 Sony Mobile Communications AB.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +13,9 @@
* 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.
+ *
+ * NOTE: This file has been modified by Sony Mobile Communications AB.
+ * Modifications are licensed under the License.
*/
package android.webkit;
@@ -758,9 +762,9 @@ public void handleMessage(Message msg) {
break;
case REDUCE_PRIORITY:
- // 3 is an adjustable number.
+ // 10 is an adjustable number.
Process.setThreadPriority(
- Process.THREAD_PRIORITY_DEFAULT + 3 *
+ Process.THREAD_PRIORITY_DEFAULT + 10 *
Process.THREAD_PRIORITY_LESS_FAVORABLE);
break;
@@ -1172,6 +1176,7 @@ public class EventHub implements WebViewInputDispatcher.WebKitCallbacks {
static final int SELECT_TEXT = 213;
static final int SELECT_WORD_AT = 214;
static final int SELECT_ALL = 215;
+ static final int CLEAR_SELECT_TEXT = 216;
// for updating state on trust storage change
static final int TRUST_STORAGE_UPDATED = 220;
@@ -1278,6 +1283,7 @@ public void handleMessage(Message msg) {
mBrowserFrame = null;
mSettings.onDestroyed();
mNativeClass = 0;
+ WebCoreThreadWatchdog.unregisterWebView(mWebViewClassic);
mWebViewClassic = null;
}
break;
@@ -1693,6 +1699,10 @@ public void handleMessage(Message msg) {
case INSERT_TEXT:
nativeInsertText(mNativeClass, (String) msg.obj);
break;
+ case CLEAR_SELECT_TEXT: {
+ nativeClearTextSelection(mNativeClass);
+ break;
+ }
case SELECT_TEXT: {
int handleId = (Integer) msg.obj;
nativeSelectText(mNativeClass, handleId,
@@ -1982,7 +1992,6 @@ void destroy() {
mEventHub.sendMessageAtFrontOfQueue(
Message.obtain(null, EventHub.DESTROY));
mEventHub.blockMessages();
- WebCoreThreadWatchdog.unregisterWebView(mWebViewClassic);
}
}
diff --git a/core/java/android/webkit/WebViewDatabaseClassic.java b/core/java/android/webkit/WebViewDatabaseClassic.java
index be0102874ff..5ad4fa541b3 100644
--- a/core/java/android/webkit/WebViewDatabaseClassic.java
+++ b/core/java/android/webkit/WebViewDatabaseClassic.java
@@ -37,7 +37,7 @@ final class WebViewDatabaseClassic extends WebViewDatabase {
private static final String DATABASE_FILE = "webview.db";
private static final String CACHE_DATABASE_FILE = "webviewCache.db";
- private static final int DATABASE_VERSION = 11;
+ private static final int DATABASE_VERSION = 12;
// 2 -> 3 Modified Cache table to allow cache of redirects
// 3 -> 4 Added Oma-Downloads table
// 4 -> 5 Modified Cache table to support persistent contentLength
@@ -50,6 +50,7 @@ final class WebViewDatabaseClassic extends WebViewDatabase {
// 10 -> 11 Drop cookies and cache now managed by the chromium stack,
// and update the form data table to use the new format
// implemented for b/5265606.
+ // 11 -> 12 Add a delimiter between scheme and host when storing passwords
private static WebViewDatabaseClassic sInstance = null;
private static final Object sInstanceLock = new Object();
@@ -169,11 +170,23 @@ private void initDatabase(Context context) {
private static void upgradeDatabase() {
upgradeDatabaseToV10();
upgradeDatabaseFromV10ToV11();
+ upgradeDatabaseFromV11ToV12();
// Add future database upgrade functions here, one version at a
// time.
sDatabase.setVersion(DATABASE_VERSION);
}
+ private static void upgradeDatabaseFromV11ToV12() {
+ int oldVersion = sDatabase.getVersion();
+
+ if (oldVersion >= 12) {
+ // Nothing to do.
+ return;
+ }
+ // delete the rows in the database.
+ sDatabase.delete(mTableNames[TABLE_PASSWORD_ID], null, null);
+ }
+
private static void upgradeDatabaseFromV10ToV11() {
int oldVersion = sDatabase.getVersion();
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 33a8531194a..c9598a88b29 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -581,6 +581,7 @@ public abstract class AbsListView extends AdapterView implements Te
Runnable mPositionScrollAfterLayout;
private int mMinimumVelocity;
private int mMaximumVelocity;
+ private int mDecacheThreshold;
private float mVelocityScale = 1.0f;
final boolean[] mIsScrap = new boolean[1];
@@ -818,6 +819,7 @@ private void initAbsListView() {
mTouchSlop = configuration.getScaledTouchSlop();
mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
+ mDecacheThreshold = mMaximumVelocity / 2;
mOverscrollDistance = configuration.getScaledOverscrollDistance();
mOverflingDistance = configuration.getScaledOverflingDistance();
@@ -2637,7 +2639,7 @@ protected void onDetachedFromWindow() {
if (mTouchModeReset != null) {
removeCallbacks(mTouchModeReset);
- mTouchModeReset = null;
+ mTouchModeReset.run();
}
mIsAttached = false;
}
@@ -3416,12 +3418,14 @@ public boolean onTouchEvent(MotionEvent ev) {
mTouchModeReset = new Runnable() {
@Override
public void run() {
+ mTouchModeReset = null;
mTouchMode = TOUCH_MODE_REST;
child.setPressed(false);
setPressed(false);
if (!mDataChanged) {
performClick.run();
}
+ mTouchModeReset = null;
}
};
postDelayed(mTouchModeReset,
@@ -3921,7 +3925,7 @@ public void run() {
// Keep the fling alive a little longer
postDelayed(this, FLYWHEEL_TIMEOUT);
} else {
- endFling();
+ endFling(false); // Don't disable the scrolling cache right after it was enabled
mTouchMode = TOUCH_MODE_SCROLL;
reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
}
@@ -3935,6 +3939,11 @@ public void run() {
}
void start(int initialVelocity) {
+ if (Math.abs(initialVelocity) > mDecacheThreshold) {
+ // For long flings, scrolling cache causes stutter, so don't use it
+ clearScrollingCache();
+ }
+
int initialY = initialVelocity < 0 ? Integer.MAX_VALUE : 0;
mLastFlingY = initialY;
mScroller.setInterpolator(null);
@@ -4007,13 +4016,18 @@ void startScroll(int distance, int duration, boolean linear) {
}
void endFling() {
+ endFling(true);
+ }
+
+ void endFling(boolean clearCache) {
mTouchMode = TOUCH_MODE_REST;
removeCallbacks(this);
removeCallbacks(mCheckFlywheel);
reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
- clearScrollingCache();
+ if (clearCache)
+ clearScrollingCache();
mScroller.abortAnimation();
if (mFlingStrictSpan != null) {
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
old mode 100755
new mode 100644
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index 361eca4d339..a19c6a813fe 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -247,7 +247,7 @@ public class CalendarView extends FrameLayout {
/**
* Which month should be displayed/highlighted [0-11].
*/
- private int mCurrentMonthDisplayed;
+ private int mCurrentMonthDisplayed = -1;
/**
* Used for tracking during a scroll.
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index de8b80d45ec..3f080d6f531 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -242,7 +242,7 @@ protected void onDraw(Canvas canvas) {
right = width - mBasePadding;
left = right - mCheckMarkWidth;
}
- checkMarkDrawable.setBounds( left, top, right, bottom);
+ checkMarkDrawable.setBounds(mScrollX + left, top, mScrollX + right, bottom);
checkMarkDrawable.draw(canvas);
}
}
diff --git a/core/java/android/widget/CoverFlow.java b/core/java/android/widget/CoverFlow.java
new file mode 100644
index 00000000000..17140223157
--- /dev/null
+++ b/core/java/android/widget/CoverFlow.java
@@ -0,0 +1,1686 @@
+package android.widget;
+
+import java.util.HashMap;
+
+import com.android.internal.R;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Camera;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.GestureDetector;
+import android.view.Gravity;
+import android.view.HapticFeedbackConstants;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.SoundEffectConstants;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.animation.Transformation;
+import android.widget.AdapterView.AdapterContextMenuInfo;
+
+public class CoverFlow extends AbsSpinner implements GestureDetector.OnGestureListener {
+
+
+ private Camera mCamera = new Camera();
+ private int mCoverFlowCenter;
+ private boolean mCoverflow = false;
+ private int mRadius = 500;
+ private ViewCache mCache = new ViewCache();
+
+ private static final String TAG = "Gallery";
+
+ private static final boolean localLOGV = false;
+
+ /**
+ * Duration in milliseconds from the start of a scroll during which we're
+ * unsure whether the user is scrolling or flinging.
+ */
+ private static final int SCROLL_TO_FLING_UNCERTAINTY_TIMEOUT = 250;
+
+ /**
+ * Horizontal spacing between items.
+ */
+ private int mSpacing = 0;
+
+ /**
+ * How long the transition animation should run when a child view changes
+ * position, measured in milliseconds.
+ */
+ private int mAnimationDuration = 400;
+
+ /**
+ * The alpha of items that are not selected.
+ */
+ private float mUnselectedAlpha;
+
+ /**
+ * Left most edge of a child seen so far during layout.
+ */
+ private int mLeftMost;
+
+ /**
+ * Right most edge of a child seen so far during layout.
+ */
+ private int mRightMost;
+
+ private int mGravity;
+
+ /**
+ * Helper for detecting touch gestures.
+ */
+ private GestureDetector mGestureDetector;
+
+ /**
+ * The position of the item that received the user's down touch.
+ */
+ private int mDownTouchPosition;
+
+ /**
+ * The view of the item that received the user's down touch.
+ */
+ private View mDownTouchView;
+
+ /**
+ * Executes the delta scrolls from a fling or scroll movement.
+ */
+ private FlingRunnable mFlingRunnable = new FlingRunnable();
+
+ /**
+ * Sets mSuppressSelectionChanged = false. This is used to set it to false
+ * in the future. It will also trigger a selection changed.
+ */
+ private Runnable mDisableSuppressSelectionChangedRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mSuppressSelectionChanged = false;
+ selectionChanged();
+ }
+ };
+
+ /**
+ * When fling runnable runs, it resets this to false. Any method along the
+ * path until the end of its run() can set this to true to abort any
+ * remaining fling. For example, if we've reached either the leftmost or
+ * rightmost item, we will set this to true.
+ */
+ private boolean mShouldStopFling;
+
+ /**
+ * The currently selected item's child.
+ */
+ private View mSelectedChild;
+
+ /**
+ * Whether to continuously callback on the item selected listener during a
+ * fling.
+ */
+ private boolean mShouldCallbackDuringFling = true;
+
+ /**
+ * Whether to callback when an item that is not selected is clicked.
+ */
+ private boolean mShouldCallbackOnUnselectedItemClick = true;
+
+ /**
+ * If true, do not callback to item selected listener.
+ */
+ private boolean mSuppressSelectionChanged;
+
+ /**
+ * If true, we have received the "invoke" (center or enter buttons) key
+ * down. This is checked before we action on the "invoke" key up, and is
+ * subsequently cleared.
+ */
+ private boolean mReceivedInvokeKeyDown;
+
+ private AdapterContextMenuInfo mContextMenuInfo;
+
+ /**
+ * If true, this onScroll is the first for this user's drag (remember, a
+ * drag sends many onScrolls).
+ */
+ private boolean mIsFirstScroll;
+
+ /**
+ * If true, mFirstPosition is the position of the rightmost child, and
+ * the children are ordered right to left.
+ */
+ private boolean mIsRtl = true;
+
+ /**
+ * Offset between the center of the selected child view and the center of the Gallery.
+ * Used to reset position correctly during layout.
+ */
+ private int mSelectedCenterOffset;
+ private int mDataSetSize = 1;
+
+ public CoverFlow(Context context) {
+ this(context, null);
+ }
+
+ public CoverFlow(Context context, AttributeSet attrs) {
+ this(context, attrs, R.attr.galleryStyle);
+ }
+
+ public CoverFlow(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ mGestureDetector = new GestureDetector(context, this);
+ mGestureDetector.setIsLongpressEnabled(true);
+
+ TypedArray a = context.obtainStyledAttributes(
+ attrs, com.android.internal.R.styleable.Gallery, defStyle, 0);
+
+ int index = a.getInt(com.android.internal.R.styleable.Gallery_gravity, -1);
+ if (index >= 0) {
+ setGravity(index);
+ }
+
+ int animationDuration =
+ a.getInt(com.android.internal.R.styleable.Gallery_animationDuration, -1);
+ if (animationDuration > 0) {
+ setAnimationDuration(animationDuration);
+ }
+
+ int spacing =
+ a.getDimensionPixelOffset(com.android.internal.R.styleable.Gallery_spacing, 0);
+ setSpacing(spacing);
+
+ float unselectedAlpha = a.getFloat(
+ com.android.internal.R.styleable.Gallery_unselectedAlpha, 0.5f);
+ setUnselectedAlpha(unselectedAlpha);
+
+ a.recycle();
+
+ // We draw the selected item last (because otherwise the item to the
+ // right overlaps it)
+ mGroupFlags |= FLAG_USE_CHILD_DRAWING_ORDER;
+
+ mGroupFlags |= FLAG_SUPPORT_STATIC_TRANSFORMATIONS;
+
+ setStaticTransformationsEnabled(true);
+ }
+
+ /**
+ * Whether or not to callback on any {@link #getOnItemSelectedListener()}
+ * while the items are being flinged. If false, only the final selected item
+ * will cause the callback. If true, all items between the first and the
+ * final will cause callbacks.
+ *
+ * @param shouldCallback Whether or not to callback on the listener while
+ * the items are being flinged.
+ */
+ public void setCallbackDuringFling(boolean shouldCallback) {
+ mShouldCallbackDuringFling = shouldCallback;
+ }
+
+ /**
+ * Whether or not to callback when an item that is not selected is clicked.
+ * If false, the item will become selected (and re-centered). If true, the
+ * {@link #getOnItemClickListener()} will get the callback.
+ *
+ * @param shouldCallback Whether or not to callback on the listener when a
+ * item that is not selected is clicked.
+ * @hide
+ */
+ public void setCallbackOnUnselectedItemClick(boolean shouldCallback) {
+ mShouldCallbackOnUnselectedItemClick = shouldCallback;
+ }
+
+ /**
+ * Sets how long the transition animation should run when a child view
+ * changes position. Only relevant if animation is turned on.
+ *
+ * @param animationDurationMillis The duration of the transition, in
+ * milliseconds.
+ *
+ * @attr ref android.R.styleable#Gallery_animationDuration
+ */
+ public void setAnimationDuration(int animationDurationMillis) {
+ mAnimationDuration = animationDurationMillis;
+ }
+
+ /**
+ * Sets the spacing between items in a Gallery
+ *
+ * @param spacing The spacing in pixels between items in the Gallery
+ *
+ * @attr ref android.R.styleable#Gallery_spacing
+ */
+ public void setSpacing(int spacing) {
+ mSpacing = spacing;
+ }
+
+ /**
+ * Sets the alpha of items that are not selected in the Gallery.
+ *
+ * @param unselectedAlpha the alpha for the items that are not selected.
+ *
+ * @attr ref android.R.styleable#Gallery_unselectedAlpha
+ */
+ public void setUnselectedAlpha(float unselectedAlpha) {
+ mUnselectedAlpha = unselectedAlpha;
+ }
+
+ @Override
+ protected int computeHorizontalScrollExtent() {
+ // Only 1 item is considered to be selected
+ return 1;
+ }
+
+ @Override
+ protected int computeHorizontalScrollOffset() {
+ // Current scroll position is the same as the selected position
+ return mSelectedPosition;
+ }
+
+ @Override
+ protected int computeHorizontalScrollRange() {
+ // Scroll range is the same as the item count
+ return mItemCount;
+ }
+
+ @Override
+ protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+ return p instanceof LayoutParams;
+ }
+
+ @Override
+ protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+ return new LayoutParams(p);
+ }
+
+ @Override
+ public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
+ return new LayoutParams(getContext(), attrs);
+ }
+
+ @Override
+ protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
+ /*
+ * Gallery expects Gallery.LayoutParams.
+ */
+ return new CoverFlow.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ super.onLayout(changed, l, t, r, b);
+
+ /*
+ * Remember that we are in layout to prevent more layout request from
+ * being generated.
+ */
+ mInLayout = true;
+ layout(0, false);
+ mInLayout = false;
+ }
+
+ @Override
+ int getChildHeight(View child) {
+ return child.getMeasuredHeight();
+ }
+
+ public void release(){
+ mCache.clear();
+ resetList();
+ }
+
+ /**
+ * Tracks a motion scroll. In reality, this is used to do just about any
+ * movement to items (touch scroll, arrow-key scroll, set an item as selected).
+ *
+ * @param deltaX Change in X from the previous event.
+ */
+ void trackMotionScroll(int deltaX) {
+
+ if (getChildCount() == 0) {
+ return;
+ }
+
+ boolean toLeft = deltaX < 0;
+
+ int limitedDeltaX = getLimitedMotionScrollAmount(toLeft, deltaX);
+ if (limitedDeltaX != deltaX) {
+ // The above call returned a limited amount, so stop any scrolls/flings
+ mFlingRunnable.endFling(false);
+ onFinishedMovement();
+ }
+
+ offsetChildrenLeftAndRight(limitedDeltaX);
+
+ detachOffScreenChildren(toLeft);
+
+ if (toLeft) {
+ // If moved left, there will be empty space on the right
+ fillToGalleryRight();
+ } else {
+ // Similarly, empty space on the left
+ fillToGalleryLeft();
+ }
+
+ // Clear unused views
+// mCache.clear();
+
+ setSelectionToCenterChild();
+
+ final View selChild = mSelectedChild;
+ if (selChild != null) {
+ final int childLeft = selChild.getLeft();
+ final int childCenter = selChild.getWidth() / 2;
+ final int galleryCenter = getWidth() / 2;
+ mSelectedCenterOffset = childLeft + childCenter - galleryCenter;
+ }
+
+ onScrollChanged(0, 0, 0, 0); // dummy values, View's implementation does not use these.
+
+ invalidate();
+ }
+
+ int getLimitedMotionScrollAmount(boolean motionToLeft, int deltaX) {
+ int extremeItemPosition = motionToLeft != mIsRtl ? mItemCount - 1 : 0;
+ View extremeChild = getChildAt(extremeItemPosition - mFirstPosition);
+
+ if (extremeChild == null) {
+ return deltaX;
+ }
+
+ int extremeChildCenter = getCenterOfView(extremeChild);
+ int galleryCenter = getCenterOfGallery();
+
+ if (motionToLeft) {
+ if (extremeChildCenter <= galleryCenter) {
+
+ // The extreme child is past his boundary point!
+ return 0;
+ }
+ } else {
+ if (extremeChildCenter >= galleryCenter) {
+
+ // The extreme child is past his boundary point!
+ return 0;
+ }
+ }
+
+ int centerDifference = galleryCenter - extremeChildCenter;
+
+ return motionToLeft
+ ? Math.max(centerDifference, deltaX)
+ : Math.min(centerDifference, deltaX);
+ }
+
+ /**
+ * Offset the horizontal location of all children of this view by the
+ * specified number of pixels.
+ *
+ * @param offset the number of pixels to offset
+ */
+ private void offsetChildrenLeftAndRight(int offset) {
+ for (int i = getChildCount() - 1; i >= 0; i--) {
+ getChildAt(i).offsetLeftAndRight(offset);
+ }
+ }
+
+ /**
+ * @return The center of this Gallery.
+ */
+ private int getCenterOfGallery() {
+ return (getWidth() - mPaddingLeft - mPaddingRight) / 2 + mPaddingLeft;
+ }
+
+ /**
+ * @return The center of the given view.
+ */
+ private static int getCenterOfView(View view) {
+ return view.getLeft() + view.getWidth() / 2;
+ }
+
+ /**
+ * Detaches children that are off the screen (i.e.: Gallery bounds).
+ *
+ * @param toLeft Whether to detach children to the left of the Gallery, or
+ * to the right.
+ */
+ private void detachOffScreenChildren(boolean toLeft) {
+ int numChildren = getChildCount();
+ int firstPosition = mFirstPosition;
+ int start = 0;
+ int count = 0;
+
+ if (toLeft) {
+ final int galleryLeft = mPaddingLeft;
+ for (int i = 0; i < numChildren; i++) {
+ int n = mIsRtl ? (numChildren - 1 - i) : i;
+ final View child = getChildAt(n);
+ if (child.getRight() >= galleryLeft) {
+ break;
+ } else {
+ start = n;
+ count++;
+ if(!mCoverflow)
+ mCache.put(firstPosition + n, child);
+ }
+ }
+ if (!mIsRtl) {
+ start = 0;
+ }
+ } else {
+ final int galleryRight = getWidth() - mPaddingRight;
+ for (int i = numChildren - 1; i >= 0; i--) {
+ int n = mIsRtl ? numChildren - 1 - i : i;
+ final View child = getChildAt(n);
+ if (child.getLeft() <= galleryRight) {
+ break;
+ } else {
+ start = n;
+ count++;
+ if(!mCoverflow)
+ mCache.put(firstPosition + n, child);
+ }
+ }
+ if (mIsRtl) {
+ start = 0;
+ }
+ }
+
+ detachViewsFromParent(start, count);
+
+ if (toLeft != mIsRtl) {
+ mFirstPosition += count;
+ }
+ }
+
+ /**
+ * Scrolls the items so that the selected item is in its 'slot' (its center
+ * is the gallery's center).
+ */
+ private void scrollIntoSlots() {
+
+ if (getChildCount() == 0 || mSelectedChild == null) return;
+
+ int selectedCenter = getCenterOfView(mSelectedChild);
+ int targetCenter = getCenterOfGallery();
+
+ int scrollAmount = targetCenter - selectedCenter;
+ if (scrollAmount != 0) {
+ mFlingRunnable.startUsingDistance(scrollAmount);
+ } else {
+ onFinishedMovement();
+ }
+ }
+
+ private void onFinishedMovement() {
+ if (mSuppressSelectionChanged) {
+ mSuppressSelectionChanged = false;
+
+ // We haven't been callbacking during the fling, so do it now
+ super.selectionChanged();
+ }
+ mSelectedCenterOffset = 0;
+ invalidate();
+ }
+
+ @Override
+ void selectionChanged() {
+ if (!mSuppressSelectionChanged) {
+ super.selectionChanged();
+ }
+ }
+
+ /**
+ * Looks for the child that is closest to the center and sets it as the
+ * selected child.
+ */
+ private void setSelectionToCenterChild() {
+
+ View selView = mSelectedChild;
+ if (mSelectedChild == null) return;
+
+ int galleryCenter = getCenterOfGallery();
+
+ // Common case where the current selected position is correct
+ if (selView.getLeft() <= galleryCenter && selView.getRight() >= galleryCenter) {
+ return;
+ }
+
+ // TODO better search
+ int closestEdgeDistance = Integer.MAX_VALUE;
+ int newSelectedChildIndex = 0;
+ for (int i = getChildCount() - 1; i >= 0; i--) {
+
+ View child = getChildAt(i);
+
+ if (child.getLeft() <= galleryCenter && child.getRight() >= galleryCenter) {
+ // This child is in the center
+ newSelectedChildIndex = i;
+ break;
+ }
+
+ int childClosestEdgeDistance = Math.min(Math.abs(child.getLeft() - galleryCenter),
+ Math.abs(child.getRight() - galleryCenter));
+ if (childClosestEdgeDistance < closestEdgeDistance) {
+ closestEdgeDistance = childClosestEdgeDistance;
+ newSelectedChildIndex = i;
+ }
+ }
+
+ int newPos = mFirstPosition + newSelectedChildIndex;
+
+ if (newPos != mSelectedPosition) {
+ setSelectedPositionInt(newPos);
+ setNextSelectedPositionInt(newPos);
+ checkSelectionChanged();
+ }
+ }
+
+ /**
+ * Creates and positions all views for this Gallery.
+ *
+ * We layout rarely, most of the time {@link #trackMotionScroll(int)} takes
+ * care of repositioning, adding, and removing children.
+ *
+ * @param delta Change in the selected position. +1 means the selection is
+ * moving to the right, so views are scrolling to the left. -1
+ * means the selection is moving to the left.
+ */
+ @Override
+ void layout(int delta, boolean animate) {
+
+ mIsRtl = isLayoutRtl();
+
+ int childrenLeft = mSpinnerPadding.left;
+ int childrenWidth = mRight - mLeft - mSpinnerPadding.left - mSpinnerPadding.right;
+
+ if (mDataChanged) {
+ handleDataChanged();
+ }
+
+ // Handle an empty gallery by removing all views.
+ if (mItemCount == 0) {
+ resetList();
+ return;
+ }
+
+ // Update to the new selected position.
+ if (mNextSelectedPosition >= 0) {
+ setSelectedPositionInt(mNextSelectedPosition);
+ }
+
+ // All views go in recycler while we are in layout
+ recycleAllViews();
+
+ // Clear out old views
+ //removeAllViewsInLayout();
+ detachAllViewsFromParent();
+
+ /*
+ * These will be used to give initial positions to views entering the
+ * gallery as we scroll
+ */
+ mRightMost = 0;
+ mLeftMost = 0;
+
+ // Make selected view and center it
+
+ /*
+ * mFirstPosition will be decreased as we add views to the left later
+ * on. The 0 for x will be offset in a couple lines down.
+ */
+ mFirstPosition = mSelectedPosition;
+ View sel = makeAndAddView(mSelectedPosition, 0, 0, true);
+
+ // Put the selected child in the center
+ int selectedOffset = childrenLeft + (childrenWidth / 2) - (sel.getWidth() / 2) +
+ mSelectedCenterOffset;
+ sel.offsetLeftAndRight(selectedOffset);
+
+ fillToGalleryRight();
+ fillToGalleryLeft();
+
+ // Flush any cached views that did not get reused above
+// mCache.clear();
+
+ invalidate();
+ checkSelectionChanged();
+
+ mDataChanged = false;
+ mNeedSync = false;
+ setNextSelectedPositionInt(mSelectedPosition);
+
+ updateSelectedItemMetadata();
+ }
+
+ @Override
+ void recycleAllViews() {
+ if(mCoverflow) return;
+ final int childCount = getChildCount();
+ final int position = mFirstPosition;
+
+ // All views go in recycler
+ for (int i = 0; i < childCount; i++) {
+ View v = getChildAt(i);
+ int index = position + i;
+ mCache.put(index, v);
+ }
+ }
+
+ private void fillToGalleryLeft() {
+ if (mIsRtl) {
+ fillToGalleryLeftRtl();
+ } else {
+ fillToGalleryLeftLtr();
+ }
+ }
+
+ private void fillToGalleryLeftRtl() {
+ int itemSpacing = mSpacing;
+ int galleryLeft = mPaddingLeft;
+ int numChildren = getChildCount();
+ int numItems = mItemCount;
+
+ // Set state for initial iteration
+ View prevIterationView = getChildAt(numChildren - 1);
+ int curPosition;
+ int curRightEdge;
+
+ if (prevIterationView != null) {
+ curPosition = mFirstPosition + numChildren;
+ curRightEdge = prevIterationView.getLeft() - itemSpacing;
+ } else {
+ // No children available!
+ mFirstPosition = curPosition = mItemCount - 1;
+ curRightEdge = mRight - mLeft - mPaddingRight;
+ mShouldStopFling = true;
+ }
+
+ while (curRightEdge > galleryLeft && curPosition < mItemCount) {
+ prevIterationView = makeAndAddView(curPosition, curPosition - mSelectedPosition,
+ curRightEdge, false);
+
+ // Set state for next iteration
+ curRightEdge = prevIterationView.getLeft() - itemSpacing;
+ curPosition++;
+ }
+ }
+
+ private void fillToGalleryLeftLtr() {
+ int itemSpacing = mSpacing;
+ int galleryLeft = mPaddingLeft;
+
+ // Set state for initial iteration
+ View prevIterationView = getChildAt(0);
+ int curPosition;
+ int curRightEdge;
+
+ if (prevIterationView != null) {
+ curPosition = mFirstPosition - 1;
+ curRightEdge = prevIterationView.getLeft() - itemSpacing;
+ } else {
+ // No children available!
+ curPosition = 0;
+ curRightEdge = mRight - mLeft - mPaddingRight;
+ mShouldStopFling = true;
+ }
+
+ while (curRightEdge > galleryLeft && curPosition >= 0) {
+ prevIterationView = makeAndAddView(curPosition, curPosition - mSelectedPosition,
+ curRightEdge, false);
+
+ // Remember some state
+ mFirstPosition = curPosition;
+
+ // Set state for next iteration
+ curRightEdge = prevIterationView.getLeft() - itemSpacing;
+ curPosition--;
+ }
+ }
+
+ private void fillToGalleryRight() {
+ if (mIsRtl) {
+ fillToGalleryRightRtl();
+ } else {
+ fillToGalleryRightLtr();
+ }
+ }
+
+ private void fillToGalleryRightRtl() {
+ int itemSpacing = mSpacing;
+ int galleryRight = mRight - mLeft - mPaddingRight;
+
+ // Set state for initial iteration
+ View prevIterationView = getChildAt(0);
+ int curPosition;
+ int curLeftEdge;
+
+ if (prevIterationView != null) {
+ curPosition = mFirstPosition -1;
+ curLeftEdge = prevIterationView.getRight() + itemSpacing;
+ } else {
+ curPosition = 0;
+ curLeftEdge = mPaddingLeft;
+ mShouldStopFling = true;
+ }
+
+ while (curLeftEdge < galleryRight && curPosition >= 0) {
+ prevIterationView = makeAndAddView(curPosition, curPosition - mSelectedPosition,
+ curLeftEdge, true);
+
+ // Remember some state
+ mFirstPosition = curPosition;
+
+ // Set state for next iteration
+ curLeftEdge = prevIterationView.getRight() + itemSpacing;
+ curPosition--;
+ }
+ }
+
+ private void fillToGalleryRightLtr() {
+ int itemSpacing = mSpacing;
+ int galleryRight = mRight - mLeft - mPaddingRight;
+ int numChildren = getChildCount();
+ int numItems = mItemCount;
+
+ // Set state for initial iteration
+ View prevIterationView = getChildAt(numChildren - 1);
+ int curPosition;
+ int curLeftEdge;
+
+ if (prevIterationView != null) {
+ curPosition = mFirstPosition + numChildren;
+ curLeftEdge = prevIterationView.getRight() + itemSpacing;
+ } else {
+ mFirstPosition = curPosition = mItemCount - 1;
+ curLeftEdge = mPaddingLeft;
+ mShouldStopFling = true;
+ }
+
+ while (curLeftEdge < galleryRight && curPosition < numItems) {
+ prevIterationView = makeAndAddView(curPosition, curPosition - mSelectedPosition,
+ curLeftEdge, true);
+
+ // Set state for next iteration
+ curLeftEdge = prevIterationView.getRight() + itemSpacing;
+ curPosition++;
+ }
+ }
+
+ /**
+ * Obtain a view, either by pulling an existing view from the recycler or by
+ * getting a new one from the adapter. If we are animating, make sure there
+ * is enough information in the view's layout parameters to animate from the
+ * old to new positions.
+ *
+ * @param position Position in the gallery for the view to obtain
+ * @param offset Offset from the selected position
+ * @param x X-coordinate indicating where this view should be placed. This
+ * will either be the left or right edge of the view, depending on
+ * the fromLeft parameter
+ * @param fromLeft Are we positioning views based on the left edge? (i.e.,
+ * building from left to right)?
+ * @return A view that has been added to the gallery
+ */
+ private View makeAndAddView(int position, int offset, int x, boolean fromLeft) {
+
+ View child;
+ if (!mDataChanged) {
+ child = (mCoverflow ? null : mCache.get(position));
+ if (child != null) {
+ // Can reuse an existing view
+ int childLeft = child.getLeft();
+
+ // Remember left and right edges of where views have been placed
+ mRightMost = Math.max(mRightMost, childLeft
+ + child.getMeasuredWidth());
+ mLeftMost = Math.min(mLeftMost, childLeft);
+
+ // Position the view
+ setUpChild(child, offset, x, fromLeft);
+
+ return child;
+ }
+ }
+
+ // Nothing found in the recycler -- ask the adapter for a view
+ child = mAdapter.getView(position, null, this);
+ if(!mCoverflow)
+ mCache.put(position, child);
+ // Position the view
+ setUpChild(child, offset, x, fromLeft);
+
+ return child;
+ }
+
+ /**
+ * Helper for makeAndAddView to set the position of a view and fill out its
+ * layout parameters.
+ *
+ * @param child The view to position
+ * @param offset Offset from the selected position
+ * @param x X-coordinate indicating where this view should be placed. This
+ * will either be the left or right edge of the view, depending on
+ * the fromLeft parameter
+ * @param fromLeft Are we positioning views based on the left edge? (i.e.,
+ * building from left to right)?
+ */
+ private void setUpChild(View child, int offset, int x, boolean fromLeft) {
+
+ // Respect layout params that are already in the view. Otherwise
+ // make some up...
+ CoverFlow.LayoutParams lp = (CoverFlow.LayoutParams) child.getLayoutParams();
+ if (lp == null) {
+ lp = (CoverFlow.LayoutParams) generateDefaultLayoutParams();
+ }
+
+ addViewInLayout(child, fromLeft != mIsRtl ? -1 : 0, lp);
+
+ child.setSelected(offset == 0);
+
+ // Get measure specs
+ int childHeightSpec = ViewGroup.getChildMeasureSpec(mHeightMeasureSpec,
+ mSpinnerPadding.top + mSpinnerPadding.bottom, lp.height);
+ int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec,
+ mSpinnerPadding.left + mSpinnerPadding.right, lp.width);
+
+ // Measure child
+ child.measure(childWidthSpec, childHeightSpec);
+
+ int childLeft;
+ int childRight;
+
+ // Position vertically based on gravity setting
+ int childTop = calculateTop(child, true);
+ int childBottom = childTop + child.getMeasuredHeight();
+
+ int width = child.getMeasuredWidth();
+ if (fromLeft) {
+ childLeft = x;
+ childRight = childLeft + width;
+ } else {
+ childLeft = x - width;
+ childRight = x;
+ }
+
+ child.layout(childLeft, childTop, childRight, childBottom);
+ }
+
+ /**
+ * Figure out vertical placement based on mGravity
+ *
+ * @param child Child to place
+ * @return Where the top of the child should be
+ */
+ private int calculateTop(View child, boolean duringLayout) {
+ int myHeight = duringLayout ? getMeasuredHeight() : getHeight();
+ int childHeight = duringLayout ? child.getMeasuredHeight() : child.getHeight();
+
+ int childTop = 0;
+
+ switch (mGravity) {
+ case Gravity.TOP:
+ childTop = mSpinnerPadding.top;
+ break;
+ case Gravity.CENTER_VERTICAL:
+ int availableSpace = myHeight - mSpinnerPadding.bottom
+ - mSpinnerPadding.top - childHeight;
+ childTop = mSpinnerPadding.top + (availableSpace / 2);
+ break;
+ case Gravity.BOTTOM:
+ childTop = myHeight - mSpinnerPadding.bottom - childHeight;
+ break;
+ }
+ return childTop;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+
+ // Give everything to the gesture detector
+ boolean retValue = mGestureDetector.onTouchEvent(event);
+
+ int action = event.getAction();
+ if (action == MotionEvent.ACTION_UP) {
+ // Helper method for lifted finger
+ onUp();
+ } else if (action == MotionEvent.ACTION_CANCEL) {
+ onCancel();
+ }
+
+ return retValue;
+ }
+
+ @Override
+ public boolean onSingleTapUp(MotionEvent e) {
+
+ if (mDownTouchPosition >= 0) {
+
+ // An item tap should make it selected, so scroll to this child.
+ scrollToChild(mDownTouchPosition - mFirstPosition);
+
+ // Also pass the click so the client knows, if it wants to.
+ if (mShouldCallbackOnUnselectedItemClick || mDownTouchPosition == mSelectedPosition) {
+ performItemClick(mDownTouchView, mDownTouchPosition, mAdapter
+ .getItemId(mDownTouchPosition));
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+
+ if (!mShouldCallbackDuringFling) {
+ // We want to suppress selection changes
+
+ // Remove any future code to set mSuppressSelectionChanged = false
+ removeCallbacks(mDisableSuppressSelectionChangedRunnable);
+
+ // This will get reset once we scroll into slots
+ if (!mSuppressSelectionChanged) mSuppressSelectionChanged = true;
+ }
+
+ // Fling the gallery!
+ mFlingRunnable.startUsingVelocity((int) -velocityX);
+
+ return true;
+ }
+
+ @Override
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+
+ if (localLOGV) Log.v(TAG, String.valueOf(e2.getX() - e1.getX()));
+
+ /*
+ * Now's a good time to tell our parent to stop intercepting our events!
+ * The user has moved more than the slop amount, since GestureDetector
+ * ensures this before calling this method. Also, if a parent is more
+ * interested in this touch's events than we are, it would have
+ * intercepted them by now (for example, we can assume when a Gallery is
+ * in the ListView, a vertical scroll would not end up in this method
+ * since a ListView would have intercepted it by now).
+ */
+ mParent.requestDisallowInterceptTouchEvent(true);
+
+ // As the user scrolls, we want to callback selection changes so related-
+ // info on the screen is up-to-date with the gallery's selection
+ if (!mShouldCallbackDuringFling) {
+ if (mIsFirstScroll) {
+ /*
+ * We're not notifying the client of selection changes during
+ * the fling, and this scroll could possibly be a fling. Don't
+ * do selection changes until we're sure it is not a fling.
+ */
+ if (!mSuppressSelectionChanged) mSuppressSelectionChanged = true;
+ postDelayed(mDisableSuppressSelectionChangedRunnable, SCROLL_TO_FLING_UNCERTAINTY_TIMEOUT);
+ }
+ } else {
+ if (mSuppressSelectionChanged) mSuppressSelectionChanged = false;
+ }
+
+ // Track the motion
+ trackMotionScroll(-1 * (int) distanceX);
+
+ mIsFirstScroll = false;
+ return true;
+ }
+
+ @Override
+ public boolean onDown(MotionEvent e) {
+
+ // Kill any existing fling/scroll
+ mFlingRunnable.stop(false);
+
+ // Get the item's view that was touched
+ mDownTouchPosition = pointToPosition((int) e.getX(), (int) e.getY());
+
+ if (mDownTouchPosition >= 0) {
+ mDownTouchView = getChildAt(mDownTouchPosition - mFirstPosition);
+ mDownTouchView.setPressed(true);
+ }
+
+ // Reset the multiple-scroll tracking state
+ mIsFirstScroll = true;
+
+ // Must return true to get matching events for this down event.
+ return true;
+ }
+
+ /**
+ * Called when a touch event's action is MotionEvent.ACTION_UP.
+ */
+ void onUp() {
+
+ if (mFlingRunnable.mScroller.isFinished()) {
+ scrollIntoSlots();
+ }
+
+ dispatchUnpress();
+ }
+
+ /**
+ * Called when a touch event's action is MotionEvent.ACTION_CANCEL.
+ */
+ void onCancel() {
+ onUp();
+ }
+
+ @Override
+ public void onLongPress(MotionEvent e) {
+
+ if (mDownTouchPosition < 0) {
+ return;
+ }
+
+ performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ long id = getItemIdAtPosition(mDownTouchPosition);
+ dispatchLongPress(mDownTouchView, mDownTouchPosition, id);
+ }
+
+ // Unused methods from GestureDetector.OnGestureListener below
+
+ @Override
+ public void onShowPress(MotionEvent e) {
+ }
+
+ // Unused methods from GestureDetector.OnGestureListener above
+
+ private void dispatchPress(View child) {
+
+ if (child != null) {
+ child.setPressed(true);
+ }
+
+ setPressed(true);
+ }
+
+ private void dispatchUnpress() {
+
+ for (int i = getChildCount() - 1; i >= 0; i--) {
+ getChildAt(i).setPressed(false);
+ }
+
+ setPressed(false);
+ }
+
+ @Override
+ public void dispatchSetSelected(boolean selected) {
+ /*
+ * We don't want to pass the selected state given from its parent to its
+ * children since this widget itself has a selected state to give to its
+ * children.
+ */
+ }
+
+ @Override
+ protected void dispatchSetPressed(boolean pressed) {
+
+ // Show the pressed state on the selected child
+ if (mSelectedChild != null) {
+ mSelectedChild.setPressed(pressed);
+ }
+ }
+
+ @Override
+ protected ContextMenuInfo getContextMenuInfo() {
+ return mContextMenuInfo;
+ }
+
+ @Override
+ public boolean showContextMenuForChild(View originalView) {
+
+ final int longPressPosition = getPositionForView(originalView);
+ if (longPressPosition < 0) {
+ return false;
+ }
+
+ final long longPressId = mAdapter.getItemId(longPressPosition);
+ return dispatchLongPress(originalView, longPressPosition, longPressId);
+ }
+
+ @Override
+ public boolean showContextMenu() {
+
+ if (isPressed() && mSelectedPosition >= 0) {
+ int index = mSelectedPosition - mFirstPosition;
+ View v = getChildAt(index);
+ return dispatchLongPress(v, mSelectedPosition, mSelectedRowId);
+ }
+
+ return false;
+ }
+
+ private boolean dispatchLongPress(View view, int position, long id) {
+ boolean handled = false;
+
+ if (mOnItemLongClickListener != null) {
+ handled = mOnItemLongClickListener.onItemLongClick(this, mDownTouchView,
+ mDownTouchPosition, id);
+ }
+
+ if (!handled) {
+ mContextMenuInfo = new AdapterContextMenuInfo(view, position, id);
+ handled = super.showContextMenuForChild(this);
+ }
+
+ if (handled) {
+ performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ }
+
+ return handled;
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ // Gallery steals all key events
+ return event.dispatch(this, null, null);
+ }
+
+ /**
+ * Handles left, right, and clicking
+ * @see android.view.View#onKeyDown
+ */
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ switch (keyCode) {
+
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (movePrevious()) {
+ playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT);
+ return true;
+ }
+ break;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (moveNext()) {
+ playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT);
+ return true;
+ }
+ break;
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ case KeyEvent.KEYCODE_ENTER:
+ mReceivedInvokeKeyDown = true;
+ // fallthrough to default handling
+ }
+
+ return super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ case KeyEvent.KEYCODE_ENTER: {
+
+ if (mReceivedInvokeKeyDown) {
+ if (mItemCount > 0) {
+
+ dispatchPress(mSelectedChild);
+ postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ dispatchUnpress();
+ }
+ }, ViewConfiguration.getPressedStateDuration());
+
+ int selectedIndex = mSelectedPosition - mFirstPosition;
+ performItemClick(getChildAt(selectedIndex), mSelectedPosition, mAdapter
+ .getItemId(mSelectedPosition));
+ }
+ }
+
+ // Clear the flag
+ mReceivedInvokeKeyDown = false;
+
+ return true;
+ }
+ }
+
+ return super.onKeyUp(keyCode, event);
+ }
+
+ boolean movePrevious() {
+ if (mItemCount > 0 && mSelectedPosition > 0) {
+ scrollToChild(mSelectedPosition - mFirstPosition - 1);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ boolean moveNext() {
+ if (mItemCount > 0 && mSelectedPosition < mItemCount - 1) {
+ scrollToChild(mSelectedPosition - mFirstPosition + 1);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public void setRadius(int radius){
+ mRadius = radius;
+ }
+
+ private boolean scrollToChild(int childPosition) {
+ View child = getChildAt(childPosition);
+
+ if (child != null) {
+ int distance = getCenterOfGallery() - getCenterOfView(child);
+ mFlingRunnable.startUsingDistance(distance);
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ void setSelectedPositionInt(int position) {
+ super.setSelectedPositionInt(position);
+
+ // Updates any metadata we keep about the selected item.
+ updateSelectedItemMetadata();
+ }
+
+ private void updateSelectedItemMetadata() {
+
+ View oldSelectedChild = mSelectedChild;
+
+ View child = mSelectedChild = getChildAt(mSelectedPosition - mFirstPosition);
+ if (child == null) {
+ return;
+ }
+
+ child.setSelected(true);
+ child.setFocusable(true);
+
+ if (hasFocus()) {
+ child.requestFocus();
+ }
+
+ // We unfocus the old child down here so the above hasFocus check
+ // returns true
+ if (oldSelectedChild != null && oldSelectedChild != child) {
+
+ // Make sure its drawable state doesn't contain 'selected'
+ oldSelectedChild.setSelected(false);
+
+ // Make sure it is not focusable anymore, since otherwise arrow keys
+ // can make this one be focused
+ oldSelectedChild.setFocusable(false);
+ }
+
+ }
+
+ /**
+ * Describes how the child views are aligned.
+ * @param gravity
+ *
+ * @attr ref android.R.styleable#Gallery_gravity
+ */
+ public void setGravity(int gravity)
+ {
+ if (mGravity != gravity) {
+ mGravity = gravity;
+ requestLayout();
+ }
+ }
+
+ @Override
+ protected int getChildDrawingOrder(int childCount, int i) {
+ int selectedIndex = mSelectedPosition - mFirstPosition;
+
+ // Just to be safe
+ if (selectedIndex < 0) return i;
+
+ if (i == childCount - 1) {
+ // Draw the selected child last
+ return selectedIndex;
+ } else if (i >= selectedIndex) {
+ // Move the children after the selected child earlier one
+ return i + 1;
+ } else {
+ // Keep the children before the selected child the same
+ return i;
+ }
+ }
+
+ @Override
+ protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
+ super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
+
+ /*
+ * The gallery shows focus by focusing the selected item. So, give
+ * focus to our selected item instead. We steal keys from our
+ * selected item elsewhere.
+ */
+ if (gainFocus && mSelectedChild != null) {
+ mSelectedChild.requestFocus(direction);
+ mSelectedChild.setSelected(true);
+ }
+
+ }
+
+ @Override
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(event);
+ event.setClassName(CoverFlow.class.getName());
+ }
+
+ @Override
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(info);
+ info.setClassName(CoverFlow.class.getName());
+ info.setScrollable(mItemCount > 1);
+ if (isEnabled()) {
+ if (mItemCount > 0 && mSelectedPosition < mItemCount - 1) {
+ info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
+ }
+ if (isEnabled() && mItemCount > 0 && mSelectedPosition > 0) {
+ info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
+ }
+ }
+ }
+
+ @Override
+ public boolean performAccessibilityAction(int action, Bundle arguments) {
+ if (super.performAccessibilityAction(action, arguments)) {
+ return true;
+ }
+ switch (action) {
+ case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
+ if (isEnabled() && mItemCount > 0 && mSelectedPosition < mItemCount - 1) {
+ final int currentChildIndex = mSelectedPosition - mFirstPosition;
+ return scrollToChild(currentChildIndex + 1);
+ }
+ } return false;
+ case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
+ if (isEnabled() && mItemCount > 0 && mSelectedPosition > 0) {
+ final int currentChildIndex = mSelectedPosition - mFirstPosition;
+ return scrollToChild(currentChildIndex - 1);
+ }
+ } return false;
+ }
+ return false;
+ }
+
+ /**
+ * Responsible for fling behavior. Use {@link #startUsingVelocity(int)} to
+ * initiate a fling. Each frame of the fling is handled in {@link #run()}.
+ * A FlingRunnable will keep re-posting itself until the fling is done.
+ */
+ private class FlingRunnable implements Runnable {
+ /**
+ * Tracks the decay of a fling scroll
+ */
+ private Scroller mScroller;
+
+ /**
+ * X value reported by mScroller on the previous fling
+ */
+ private int mLastFlingX;
+
+ public FlingRunnable() {
+ mScroller = new Scroller(getContext());
+ }
+
+ private void startCommon() {
+ // Remove any pending flings
+ removeCallbacks(this);
+ }
+
+ public void startUsingVelocity(int initialVelocity) {
+ if (initialVelocity == 0) return;
+
+ startCommon();
+
+ int initialX = initialVelocity < 0 ? Integer.MAX_VALUE : 0;
+ mLastFlingX = initialX;
+ mScroller.fling(initialX, 0, initialVelocity, 0,
+ 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE);
+ post(this);
+ }
+
+ public void startUsingDistance(int distance) {
+ if (distance == 0) return;
+
+ startCommon();
+
+ mLastFlingX = 0;
+ mScroller.startScroll(0, 0, -distance, 0, mAnimationDuration);
+ post(this);
+ }
+
+ public void stop(boolean scrollIntoSlots) {
+ removeCallbacks(this);
+ endFling(scrollIntoSlots);
+ }
+
+ private void endFling(boolean scrollIntoSlots) {
+ /*
+ * Force the scroller's status to finished (without setting its
+ * position to the end)
+ */
+ mScroller.forceFinished(true);
+
+ if (scrollIntoSlots) scrollIntoSlots();
+ }
+
+ @Override
+ public void run() {
+
+ if (mItemCount == 0) {
+ endFling(true);
+ return;
+ }
+
+ mShouldStopFling = false;
+
+ final Scroller scroller = mScroller;
+ boolean more = scroller.computeScrollOffset();
+ final int x = scroller.getCurrX();
+
+ // Flip sign to convert finger direction to list items direction
+ // (e.g. finger moving down means list is moving towards the top)
+ int delta = mLastFlingX - x;
+
+ // Pretend that each frame of a fling scroll is a touch scroll
+ if (delta > 0) {
+ // Moving towards the left. Use leftmost view as mDownTouchPosition
+ mDownTouchPosition = mIsRtl ? (mFirstPosition + getChildCount() - 1) :
+ mFirstPosition;
+
+ // Don't fling more than 1 screen
+ delta = Math.min(getWidth() - mPaddingLeft - mPaddingRight - 1, delta);
+ } else {
+ // Moving towards the right. Use rightmost view as mDownTouchPosition
+ int offsetToLast = getChildCount() - 1;
+ mDownTouchPosition = mIsRtl ? mFirstPosition :
+ (mFirstPosition + getChildCount() - 1);
+
+ // Don't fling more than 1 screen
+ delta = Math.max(-(getWidth() - mPaddingRight - mPaddingLeft - 1), delta);
+ }
+
+ trackMotionScroll(delta);
+
+ if (more && !mShouldStopFling) {
+ mLastFlingX = x;
+ post(this);
+ } else {
+ endFling(true);
+ }
+ }
+
+ }
+
+ /**
+ * Gallery extends LayoutParams to provide a place to hold current
+ * Transformation information along with previous position/transformation
+ * info.
+ */
+ public static class LayoutParams extends ViewGroup.LayoutParams {
+ public LayoutParams(Context c, AttributeSet attrs) {
+ super(c, attrs);
+ }
+
+ public LayoutParams(int w, int h) {
+ super(w, h);
+ }
+
+ public LayoutParams(ViewGroup.LayoutParams source) {
+ super(source);
+ }
+ }
+
+ public void setCoverflowStyle(boolean coverflow){
+ mCoverflow = coverflow;
+ }
+
+ public boolean getCoverFlowStyle() {
+ return mCoverflow;
+ }
+
+ private int getCenterOfCoverFlow() {
+ return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2
+ + getPaddingLeft();
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ mCoverFlowCenter = getCenterOfCoverFlow();
+ super.onSizeChanged(w, h, oldw, oldh);
+ }
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ for (int i = 0; i < getChildCount(); i++) {
+ getChildAt(i).invalidate();
+ }
+ super.dispatchDraw(canvas);
+ }
+
+ @Override
+ protected boolean getChildStaticTransformation(View child, Transformation t) {
+
+ final int childCenter = getCenterOfView(child);
+
+ t.clear();
+ t.setTransformationType(Transformation.TYPE_BOTH);
+
+ float offset = mCoverFlowCenter - childCenter;
+
+ double angle = Math.toDegrees(Math.atan(offset/mRadius));
+
+ transformImageBitmap((ImageView) child, t, angle,offset);
+
+ t.setAlpha(offset == 0 ? 1.0f : 1- Math.abs((offset/mCoverFlowCenter)*(float).9));
+
+ return true;
+ }
+
+ private void transformImageBitmap(ImageView child, Transformation t,
+ double rotationAngle,float offset) {
+
+ mCamera.save();
+ final Matrix imageMatrix = t.getMatrix();
+
+ final int imageHeight = child.getLayoutParams().height;
+
+ final int imageWidth = child.getLayoutParams().width;
+
+ final double rotation = Math.abs(rotationAngle);
+ int compAng = (int) (180-(((180-rotation)/2)+90));
+ double zoom = Math.tan(Math.toRadians(compAng))*offset;
+
+ if(!mCoverflow){
+ mCamera.translate(0.0f, 0.0f, (float) Math.abs(zoom));
+ }
+ mCamera.rotateY((float) (mCoverflow ? rotationAngle : -rotationAngle));
+ mCamera.getMatrix(imageMatrix);
+ imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2));
+ imageMatrix.postTranslate((imageWidth / 2), (imageHeight / 2));
+ mCamera.restore();
+ }
+
+ public void setDataSize(int size) {
+ mDataSetSize = size;
+ }
+
+ class ViewCache {
+ private final SparseArray mScrapHeap = new SparseArray();
+ private final SparseArray mUsedHeap = new SparseArray();
+ private final static String TAG = "Recycler";
+ private final static boolean DEBUG = false;
+
+ public void put(int position, View v) {
+ if(DEBUG)Log.d(TAG, "Attempting Adding View to caches at postion: "+position+ "/"+position % mDataSetSize);
+ if(mScrapHeap.get(position % mDataSetSize) == null || mUsedHeap.get(position % mDataSetSize) == null){
+ mScrapHeap.put(position % mDataSetSize, v);
+ View clone = mAdapter.getView(position, null, (ViewGroup) v.getParent());
+ mUsedHeap.put(position % mDataSetSize,clone );
+ }else if(DEBUG){
+ Log.e(TAG,"View already existed");
+ }
+ }
+
+ View get(int position) {
+ if(DEBUG)Log.d(TAG,"Looking for " + position+ "/"+position % mDataSetSize);
+ View result = mScrapHeap.get(position % mDataSetSize);
+ if (result != null) {
+ // System.out.println(" HIT");
+ if(result.getParent() == null){
+ if(DEBUG)Log.w(TAG," Hit Scrap");
+ return result;
+ }
+ //mScrapHeap.delete(position);
+ }
+ result = mUsedHeap.get(position % mDataSetSize);
+ if (result != null) {
+ // System.out.println(" HIT");
+ if(result.getParent() == null){
+ if(DEBUG)Log.w(TAG," Hit Used");
+ return result;
+ }
+ //mScrapHeap.delete(position);
+ }
+ if(DEBUG)Log.e(TAG," Miss");
+ return null;
+ }
+
+ void clear() {
+ final SparseArray scrapHeap = mScrapHeap;
+ int count = scrapHeap.size();
+ for (int i = 0; i < count; i++) {
+ final View view = scrapHeap.valueAt(i);
+ if (view != null) {
+ removeDetachedView(view, true);
+ }
+ }
+ scrapHeap.clear();
+ final SparseArray usedHeap = mUsedHeap;
+ count = usedHeap.size();
+ for (int i = 0; i < count; i++) {
+ final View view = usedHeap.valueAt(i);
+ if (view != null) {
+ removeDetachedView(view, true);
+ }
+ }
+ usedHeap.clear();
+ }
+ }
+
+
+
+}
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 07d3a7a7553..a875d0ab97b 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -23,6 +23,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
+import android.text.InputType;
import android.text.format.DateFormat;
import android.text.format.DateUtils;
import android.util.AttributeSet;
@@ -660,6 +661,10 @@ private void updateSpinners() {
mYearSpinner.setValue(mCurrentDate.get(Calendar.YEAR));
mMonthSpinner.setValue(mCurrentDate.get(Calendar.MONTH));
mDaySpinner.setValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
+
+ if (Character.isDigit(displayedValues[0].charAt(0))) {
+ mMonthSpinnerInput.setRawInputType(InputType.TYPE_CLASS_NUMBER);
+ }
}
/**
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 30d022ca39e..aee283e6ac1 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -124,7 +124,6 @@ public class Editor {
InputMethodState mInputMethodState;
DisplayList[] mTextDisplayLists;
- int mLastLayoutHeight;
boolean mFrozenWithFocus;
boolean mSelectionMoved;
@@ -1289,20 +1288,11 @@ private void drawHardwareAccelerated(Canvas canvas, Layout layout, Path highligh
mTextDisplayLists = new DisplayList[ArrayUtils.idealObjectArraySize(0)];
}
- // If the height of the layout changes (usually when inserting or deleting a line,
- // but could be changes within a span), invalidate everything. We could optimize
- // more aggressively (for example, adding offsets to blocks) but it would be more
- // complex and we would only get the benefit in some cases.
- int layoutHeight = layout.getHeight();
- if (mLastLayoutHeight != layoutHeight) {
- invalidateTextDisplayList();
- mLastLayoutHeight = layoutHeight;
- }
-
DynamicLayout dynamicLayout = (DynamicLayout) layout;
int[] blockEndLines = dynamicLayout.getBlockEndLines();
int[] blockIndices = dynamicLayout.getBlockIndices();
final int numberOfBlocks = dynamicLayout.getNumberOfBlocks();
+ final int indexFirstChangedBlock = dynamicLayout.getIndexFirstChangedBlock();
int endOfPreviousBlock = -1;
int searchStartIndex = 0;
@@ -1327,7 +1317,8 @@ private void drawHardwareAccelerated(Canvas canvas, Layout layout, Path highligh
if (blockIsInvalid) blockDisplayList.invalidate();
}
- if (!blockDisplayList.isValid()) {
+ final boolean blockDisplayListIsInvalid = !blockDisplayList.isValid();
+ if (i >= indexFirstChangedBlock || blockDisplayListIsInvalid) {
final int blockBeginLine = endOfPreviousBlock + 1;
final int top = layout.getLineTop(blockBeginLine);
final int bottom = layout.getLineBottom(blockEndLine);
@@ -1344,24 +1335,30 @@ private void drawHardwareAccelerated(Canvas canvas, Layout layout, Path highligh
right = (int) (max + 0.5f);
}
- final HardwareCanvas hardwareCanvas = blockDisplayList.start();
- try {
- // Tighten the bounds of the viewport to the actual text size
- hardwareCanvas.setViewport(right - left, bottom - top);
- // The dirty rect should always be null for a display list
- hardwareCanvas.onPreDraw(null);
- // drawText is always relative to TextView's origin, this translation brings
- // this range of text back to the top left corner of the viewport
- hardwareCanvas.translate(-left, -top);
- layout.drawText(hardwareCanvas, blockBeginLine, blockEndLine);
- // No need to untranslate, previous context is popped after drawDisplayList
- } finally {
- hardwareCanvas.onPostDraw();
- blockDisplayList.end();
- blockDisplayList.setLeftTopRightBottom(left, top, right, bottom);
- // Same as drawDisplayList below, handled by our TextView's parent
- blockDisplayList.setClipChildren(false);
+ // Rebuild display list if it is invalid
+ if (blockDisplayListIsInvalid) {
+ final HardwareCanvas hardwareCanvas = blockDisplayList.start();
+ try {
+ // Tighten the bounds of the viewport to the actual text size
+ hardwareCanvas.setViewport(right - left, bottom - top);
+ // The dirty rect should always be null for a display list
+ hardwareCanvas.onPreDraw(null);
+ // drawText is always relative to TextView's origin, this translation brings
+ // this range of text back to the top left corner of the viewport
+ hardwareCanvas.translate(-left, -top);
+ layout.drawText(hardwareCanvas, blockBeginLine, blockEndLine);
+ // No need to untranslate, previous context is popped after drawDisplayList
+ } finally {
+ hardwareCanvas.onPostDraw();
+ blockDisplayList.end();
+ // Same as drawDisplayList below, handled by our TextView's parent
+ blockDisplayList.setClipChildren(false);
+ }
}
+
+ // Valid disply list whose index is >= indexFirstChangedBlock
+ // only needs to update its drawing location.
+ blockDisplayList.setLeftTopRightBottom(left, top, right, bottom);
}
((HardwareCanvas) canvas).drawDisplayList(blockDisplayList, null,
@@ -1369,6 +1366,8 @@ private void drawHardwareAccelerated(Canvas canvas, Layout layout, Path highligh
endOfPreviousBlock = blockEndLine;
}
+
+ dynamicLayout.setIndexFirstChangedBlock(numberOfBlocks);
} else {
// Boring layout is used for empty and hint text
layout.drawText(canvas, firstLine, lastLine);
@@ -2696,23 +2695,14 @@ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
TypedArray styledAttributes = mTextView.getContext().obtainStyledAttributes(
com.android.internal.R.styleable.SelectionModeDrawables);
- boolean allowText = mTextView.getContext().getResources().getBoolean(
- com.android.internal.R.bool.config_allowActionMenuItemTextWithIcon);
-
mode.setTitle(mTextView.getContext().getString(
com.android.internal.R.string.textSelectionCABTitle));
mode.setSubtitle(null);
mode.setTitleOptionalHint(true);
- int selectAllIconId = 0; // No icon by default
- if (!allowText) {
- // Provide an icon, text will not be displayed on smaller screens.
- selectAllIconId = styledAttributes.getResourceId(
- R.styleable.SelectionModeDrawables_actionModeSelectAllDrawable, 0);
- }
-
menu.add(0, TextView.ID_SELECT_ALL, 0, com.android.internal.R.string.selectAll).
- setIcon(selectAllIconId).
+ setIcon(styledAttributes.getResourceId(
+ R.styleable.SelectionModeDrawables_actionModeSelectAllDrawable, 0)).
setAlphabeticShortcut('a').
setShowAsAction(
MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index d2139af22ea..2dac2c46878 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -646,8 +646,13 @@ private int getThumbPositionForListPosition(int firstVisibleItem, int visibleIte
final int section = mSectionIndexer.getSectionForPosition(firstVisibleItem);
final int sectionPos = mSectionIndexer.getPositionForSection(section);
- final int nextSectionPos = mSectionIndexer.getPositionForSection(section + 1);
+ final int nextSectionPos;
final int sectionCount = mSections.length;
+ if (section + 1 < sectionCount) {
+ nextSectionPos = mSectionIndexer.getPositionForSection(section + 1);
+ } else {
+ nextSectionPos = totalItemCount - 1;
+ }
final int positionsInSection = nextSectionPos - sectionPos;
final View child = mList.getChildAt(0);
diff --git a/core/java/android/widget/HeaderViewListAdapter.java b/core/java/android/widget/HeaderViewListAdapter.java
index e2a269ea13e..0685e613c07 100644
--- a/core/java/android/widget/HeaderViewListAdapter.java
+++ b/core/java/android/widget/HeaderViewListAdapter.java
@@ -79,7 +79,8 @@ public int getFootersCount() {
}
public boolean isEmpty() {
- return mAdapter == null || mAdapter.isEmpty();
+ return (mAdapter == null || mAdapter.isEmpty())
+ && getFootersCount() + getHeadersCount() == 0;
}
private boolean areAllListInfosSelectable(ArrayList infos) {
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 03507b5ffd8..93179ad3c02 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -2429,7 +2429,9 @@ private boolean arrowScrollImpl(int direction) {
View selectedView = getSelectedView();
int selectedPos = mSelectedPosition;
- int nextSelectedPosition = lookForSelectablePositionOnScreen(direction);
+ int nextSelectedPosition = (direction == View.FOCUS_DOWN) ?
+ lookForSelectablePosition(selectedPos + 1, true) :
+ lookForSelectablePosition(selectedPos - 1, false);
int amountToScroll = amountToScroll(direction, nextSelectedPosition);
// if we are moving focus, we may OVERRIDE the default behavior
@@ -2641,14 +2643,18 @@ private int amountToScroll(int direction, int nextSelectedPosition) {
final int listBottom = getHeight() - mListPadding.bottom;
final int listTop = mListPadding.top;
- final int numChildren = getChildCount();
+ int numChildren = getChildCount();
if (direction == View.FOCUS_DOWN) {
int indexToMakeVisible = numChildren - 1;
if (nextSelectedPosition != INVALID_POSITION) {
indexToMakeVisible = nextSelectedPosition - mFirstPosition;
}
-
+ while (numChildren <= indexToMakeVisible) {
+ // Child to view is not attached yet.
+ addViewBelow(getChildAt(numChildren - 1), mFirstPosition + numChildren - 1);
+ numChildren++;
+ }
final int positionToMakeVisible = mFirstPosition + indexToMakeVisible;
final View viewToMakeVisible = getChildAt(indexToMakeVisible);
@@ -2682,6 +2688,12 @@ private int amountToScroll(int direction, int nextSelectedPosition) {
if (nextSelectedPosition != INVALID_POSITION) {
indexToMakeVisible = nextSelectedPosition - mFirstPosition;
}
+ while (indexToMakeVisible < 0) {
+ // Child to view is not attached yet.
+ addViewAbove(getChildAt(0), mFirstPosition);
+ mFirstPosition--;
+ indexToMakeVisible = nextSelectedPosition - mFirstPosition;
+ }
final int positionToMakeVisible = mFirstPosition + indexToMakeVisible;
final View viewToMakeVisible = getChildAt(indexToMakeVisible);
int goalTop = listTop;
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index ac216717202..9323f454c04 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -1939,8 +1939,10 @@ public CharSequence filter(
* Ensure the user can't type in a value greater than the max
* allowed. We have to allow less than min as the user might
* want to delete some numbers and then type a new number.
+ * And prevent multiple-"0" that exceeds the length of upper
+ * bound number.
*/
- if (val > mMaxValue) {
+ if (val > mMaxValue || result.length() > String.valueOf(mMaxValue).length()) {
return "";
} else {
return filtered;
diff --git a/core/java/android/widget/OverScroller.java b/core/java/android/widget/OverScroller.java
index f2181991b4c..47f3a30f86a 100644
--- a/core/java/android/widget/OverScroller.java
+++ b/core/java/android/widget/OverScroller.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.hardware.SensorManager;
+import android.os.PowerManager;
import android.util.FloatMath;
import android.util.Log;
import android.view.ViewConfiguration;
@@ -43,6 +44,8 @@ public class OverScroller {
private static final int SCROLL_MODE = 0;
private static final int FLING_MODE = 1;
+ private final PowerManager mPm;
+
/**
* Creates an OverScroller with a viscous fluid scroll interpolator and flywheel.
* @param context
@@ -72,8 +75,11 @@ public OverScroller(Context context, Interpolator interpolator) {
public OverScroller(Context context, Interpolator interpolator, boolean flywheel) {
mInterpolator = interpolator;
mFlywheel = flywheel;
+
mScrollerX = new SplineOverScroller(context);
mScrollerY = new SplineOverScroller(context);
+
+ mPm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
}
/**
@@ -373,6 +379,7 @@ public void startScroll(int startX, int startY, int dx, int dy) {
*/
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
mMode = SCROLL_MODE;
+ mPm.cpuBoost(1500000);
mScrollerX.startScroll(startX, dx, duration);
mScrollerY.startScroll(startY, dy, duration);
}
@@ -443,6 +450,7 @@ public void fling(int startX, int startY, int velocityX, int velocityY,
}
}
+ mPm.cpuBoost(1500000);
mMode = FLING_MODE;
mScrollerX.fling(startX, velocityX, minX, maxX, overX);
mScrollerY.fling(startY, velocityY, minY, maxY, overY);
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index ea50e2e438e..e7da5ac9d95 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -990,11 +990,9 @@ public void invalidateDrawable(Drawable dr) {
if (!mInDrawing) {
if (verifyDrawable(dr)) {
final Rect dirty = dr.getBounds();
- final int scrollX = mScrollX + mPaddingLeft;
- final int scrollY = mScrollY + mPaddingTop;
- invalidate(dirty.left + scrollX, dirty.top + scrollY,
- dirty.right + scrollX, dirty.bottom + scrollY);
+ invalidate(dirty.left + mScrollX, dirty.top + mScrollY,
+ dirty.right + mScrollX, dirty.bottom + mScrollY);
} else {
super.invalidateDrawable(dr);
}
diff --git a/core/java/android/widget/Scroller.java b/core/java/android/widget/Scroller.java
index 3bfd39d80ba..2a690bdf414 100644
--- a/core/java/android/widget/Scroller.java
+++ b/core/java/android/widget/Scroller.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.hardware.SensorManager;
import android.os.Build;
+import android.os.PowerManager;
import android.util.FloatMath;
import android.view.ViewConfiguration;
import android.view.animation.AnimationUtils;
@@ -111,6 +112,8 @@ public class Scroller {
// A context-specific coefficient adjusted to physical values.
private float mPhysicalCoeff;
+ private final PowerManager mPm;
+
static {
float x_min = 0.0f;
float y_min = 0.0f;
@@ -184,6 +187,7 @@ public Scroller(Context context, Interpolator interpolator, boolean flywheel) {
mFlywheel = flywheel;
mPhysicalCoeff = computeDeceleration(0.84f); // look and feel tuning
+ mPm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
}
/**
@@ -396,6 +400,7 @@ public void startScroll(int startX, int startY, int dx, int dy) {
* @param duration Duration of the scroll in milliseconds.
*/
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
+ mPm.cpuBoost(1500000);
mMode = SCROLL_MODE;
mFinished = false;
mDuration = duration;
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
index 6bced1c6977..579593ecd66 100644
--- a/core/java/android/widget/TabWidget.java
+++ b/core/java/android/widget/TabWidget.java
@@ -330,28 +330,30 @@ public void dispatchDraw(Canvas canvas) {
return;
}
- final View selectedChild = getChildTabViewAt(mSelectedTab);
-
- final Drawable leftStrip = mLeftStrip;
- final Drawable rightStrip = mRightStrip;
-
- leftStrip.setState(selectedChild.getDrawableState());
- rightStrip.setState(selectedChild.getDrawableState());
-
- if (mStripMoved) {
- final Rect bounds = mBounds;
- bounds.left = selectedChild.getLeft();
- bounds.right = selectedChild.getRight();
- final int myHeight = getHeight();
- leftStrip.setBounds(Math.min(0, bounds.left - leftStrip.getIntrinsicWidth()),
- myHeight - leftStrip.getIntrinsicHeight(), bounds.left, myHeight);
- rightStrip.setBounds(bounds.right, myHeight - rightStrip.getIntrinsicHeight(),
- Math.max(getWidth(), bounds.right + rightStrip.getIntrinsicWidth()), myHeight);
- mStripMoved = false;
+ if(mSelectedTab != -1) {
+ final View selectedChild = getChildTabViewAt(mSelectedTab);
+
+ final Drawable leftStrip = mLeftStrip;
+ final Drawable rightStrip = mRightStrip;
+
+ leftStrip.setState(selectedChild.getDrawableState());
+ rightStrip.setState(selectedChild.getDrawableState());
+
+ if (mStripMoved) {
+ final Rect bounds = mBounds;
+ bounds.left = selectedChild.getLeft();
+ bounds.right = selectedChild.getRight();
+ final int myHeight = getHeight();
+ leftStrip.setBounds(Math.min(0, bounds.left - leftStrip.getIntrinsicWidth()),
+ myHeight - leftStrip.getIntrinsicHeight(), bounds.left, myHeight);
+ rightStrip.setBounds(bounds.right, myHeight - rightStrip.getIntrinsicHeight(),
+ Math.max(getWidth(), bounds.right + rightStrip.getIntrinsicWidth()), myHeight);
+ mStripMoved = false;
+ }
+
+ leftStrip.draw(canvas);
+ rightStrip.draw(canvas);
}
-
- leftStrip.draw(canvas);
- rightStrip.draw(canvas);
}
/**
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 22bfadb3811..5cb0274f03b 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1009,6 +1009,11 @@ public TextView(Context context, AttributeSet attrs, int defStyle) {
}
a.recycle();
+ // if the TextView is from Talk and autoLink is set to 'all' then make the text selectable
+ if(getContext().getPackageName().equals("com.google.android.talk") && mAutoLinkMask==0x0f){
+ setTextIsSelectable(true);
+ }
+
BufferType bufferType = BufferType.EDITABLE;
final int variation =
@@ -6462,7 +6467,6 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto
mDeferScroll = -1;
bringPointIntoView(Math.min(curs, mText.length()));
}
- if (changed && mEditor != null) mEditor.invalidateTextDisplayList();
}
private boolean isShowingHint() {
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index e6796cb343d..e33c4d4da7a 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -237,6 +237,7 @@ public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
// update controls to initial state
updateHourControl();
+ updateMinuteControl();
updateAmPmControl();
setOnTimeChangedListener(NO_OP_CHANGE_LISTENER);
@@ -428,6 +429,7 @@ public void setIs24HourView(Boolean is24HourView) {
updateHourControl();
// set value after spinner range is updated
setCurrentHour(currentHour);
+ updateMinuteControl();
updateAmPmControl();
}
@@ -508,6 +510,14 @@ private void updateHourControl() {
}
}
+ private void updateMinuteControl() {
+ if (is24HourView()) {
+ mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE);
+ } else {
+ mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
+ }
+ }
+
private void updateAmPmControl() {
if (is24HourView()) {
if (mAmPmSpinner != null) {
diff --git a/core/java/com/android/internal/app/ActivityTrigger.java b/core/java/com/android/internal/app/ActivityTrigger.java
new file mode 100644
index 00000000000..71aeff3c770
--- /dev/null
+++ b/core/java/com/android/internal/app/ActivityTrigger.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Code Aurora nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.internal.app;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.util.Log;
+
+public class ActivityTrigger
+{
+ private static final String TAG = "ActivityTrigger";
+
+ /** &hide */
+ public ActivityTrigger() {
+ //Log.d(TAG, "ActivityTrigger initialized");
+ }
+
+ /** &hide */
+ protected void finalize() {
+ native_at_deinit();
+ }
+
+ /** &hide */
+ public void activityStartTrigger(Intent intent) {
+ ComponentName cn = intent.getComponent();
+ String activity = null;
+
+ if (cn != null)
+ activity = cn.flattenToString();
+ native_at_startActivity(activity);
+ }
+
+ /** &hide */
+ public void activityResumeTrigger(Intent intent) {
+ ComponentName cn = intent.getComponent();
+ String activity = null;
+
+ if (cn != null)
+ activity = cn.flattenToString();
+ native_at_resumeActivity(activity);
+ }
+
+ private native void native_at_startActivity(String activity);
+ private native void native_at_resumeActivity(String activity);
+ private native void native_at_deinit();
+}
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index 43a02cf27b3..fe532b0ebc8 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -572,7 +572,7 @@ private boolean setupButtons() {
if (whichButtons == BIT_BUTTON_POSITIVE) {
centerButton(mButtonPositive);
} else if (whichButtons == BIT_BUTTON_NEGATIVE) {
- centerButton(mButtonNeutral);
+ centerButton(mButtonNegative);
} else if (whichButtons == BIT_BUTTON_NEUTRAL) {
centerButton(mButtonNeutral);
}
diff --git a/core/java/com/android/internal/app/ExternalMediaFormatActivity.java b/core/java/com/android/internal/app/ExternalMediaFormatActivity.java
index 5ab9217b6b1..b1f9d466730 100644
--- a/core/java/com/android/internal/app/ExternalMediaFormatActivity.java
+++ b/core/java/com/android/internal/app/ExternalMediaFormatActivity.java
@@ -26,6 +26,8 @@
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
+import android.os.storage.StorageManager;
+import android.os.storage.StorageVolume;
/**
* This activity is shown to the user to confirm formatting of external media.
@@ -34,6 +36,10 @@
public class ExternalMediaFormatActivity extends AlertActivity implements DialogInterface.OnClickListener {
private static final int POSITIVE_BUTTON = AlertDialog.BUTTON_POSITIVE;
+ public static final String FORMAT_PATH = "format_path";
+
+ private StorageManager mStorageManager;
+ private StorageVolume mStorageVolume = null;
/** Used to detect when the media state changes, in case we need to call finish() */
private BroadcastReceiver mStorageReceiver = new BroadcastReceiver() {
@@ -50,17 +56,38 @@ public void onReceive(Context context, Intent intent) {
}
}
};
-
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ // This is necessary because this class's caller,
+ // packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java,
+ // supplies the path to be erased/formatted as a String, instead of a
+ // StorageVolume. This for-loop gets the correct StorageVolume from the
+ // given path.
+ mStorageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
+ String path = getIntent().getStringExtra(FORMAT_PATH);
+ StorageVolume[] volumes = mStorageManager.getVolumeList();
+
+ for (StorageVolume sv : volumes) {
+ if (path.equals(sv.getPath())) {
+ mStorageVolume = sv;
+ break;
+ }
+ }
+
Log.d("ExternalMediaFormatActivity", "onCreate!");
+ Log.d("ExternalMediaFormatActivity", "The storage volume to be formatted is : "
+ + mStorageVolume.getPath());
+
// Set up the "dialog"
final AlertController.AlertParams p = mAlertParams;
p.mIconId = com.android.internal.R.drawable.stat_sys_warning;
p.mTitle = getString(com.android.internal.R.string.extmedia_format_title);
- p.mMessage = getString(com.android.internal.R.string.extmedia_format_message);
+ p.mMessage = String.format(
+ getString(com.android.internal.R.string.extmedia_format_message),
+ mStorageVolume.getPath());
p.mPositiveButtonText = getString(com.android.internal.R.string.extmedia_format_button_format);
p.mPositiveButtonListener = this;
p.mNegativeButtonText = getString(com.android.internal.R.string.cancel);
@@ -83,7 +110,7 @@ protected void onResume() {
@Override
protected void onPause() {
super.onPause();
-
+
unregisterReceiver(mStorageReceiver);
}
@@ -95,10 +122,11 @@ public void onClick(DialogInterface dialog, int which) {
if (which == POSITIVE_BUTTON) {
Intent intent = new Intent(ExternalStorageFormatter.FORMAT_ONLY);
intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME);
+ intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, mStorageVolume);
startService(intent);
}
// No matter what, finish the activity
finish();
}
-}
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/app/IAssetRedirectionManager.aidl b/core/java/com/android/internal/app/IAssetRedirectionManager.aidl
new file mode 100644
index 00000000000..8b47f0b31c2
--- /dev/null
+++ b/core/java/com/android/internal/app/IAssetRedirectionManager.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2011, T-Mobile USA, Inc.
+ *
+ * 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.internal.app;
+
+import android.content.res.PackageRedirectionMap;
+
+/**
+ * Interface used to interact with the AssetRedirectionManagerService.
+ */
+interface IAssetRedirectionManager {
+ /**
+ * Access the package redirection map for the supplied package name given a
+ * particular theme.
+ */
+ PackageRedirectionMap getPackageRedirectionMap(in String themePackageName,
+ String themeId, in String targetPackageName);
+
+ /**
+ * Clear all redirection maps for the given theme.
+ */
+ void clearRedirectionMapsByTheme(in String themePackageName,
+ in String themeId);
+
+ /**
+ * Clear all redirection maps for the given target package.
+ */
+ void clearPackageRedirectionMap(in String targetPackageName);
+}
diff --git a/core/java/com/android/internal/app/IMediaContainerService.aidl b/core/java/com/android/internal/app/IMediaContainerService.aidl
old mode 100755
new mode 100644
index 03d3b226425..83eb352cd79
--- a/core/java/com/android/internal/app/IMediaContainerService.aidl
+++ b/core/java/com/android/internal/app/IMediaContainerService.aidl
@@ -33,8 +33,10 @@ interface IMediaContainerService {
boolean checkExternalFreeStorage(in Uri fileUri, boolean isForwardLocked);
ObbInfo getObbInfo(in String filename);
long calculateDirectorySize(in String directory);
+ byte[] listDirectory(in String directory);
/** Return file system stats: [0] is total bytes, [1] is available bytes */
long[] getFileSystemStats(in String path);
void clearDirectory(in String directory);
+ void deleteFile(in String file);
long calculateInstalledSize(in String packagePath, boolean isForwardLocked);
}
diff --git a/core/java/com/android/internal/app/IUsageStats.aidl b/core/java/com/android/internal/app/IUsageStats.aidl
old mode 100755
new mode 100644
diff --git a/core/java/com/android/internal/app/NetInitiatedActivity.java b/core/java/com/android/internal/app/NetInitiatedActivity.java
old mode 100755
new mode 100644
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index e63c57f47d8..edb2c12dbfc 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -30,14 +30,15 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.PatternMatcher;
-import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.provider.Settings;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -45,6 +46,7 @@
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
+import android.widget.CheckBox;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ListView;
@@ -64,6 +66,7 @@
*/
public class ResolverActivity extends AlertActivity implements AdapterView.OnItemClickListener {
private static final String TAG = "ResolverActivity";
+ private static final boolean DEBUG = false;
private int mLaunchedFromUid;
private ResolveListAdapter mAdapter;
@@ -73,12 +76,14 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
private GridView mGrid;
private Button mAlwaysButton;
private Button mOnceButton;
+ private CheckBox mAlwaysCheckBox;
private int mIconDpi;
private int mIconSize;
private int mMaxColumns;
private int mLastSelected = GridView.INVALID_POSITION;
private boolean mRegistered;
+ private boolean mUseAltGrid;
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@Override public void onSomePackagesChanged() {
mAdapter.handlePackagesChanged();
@@ -106,7 +111,12 @@ protected void onCreate(Bundle savedInstanceState) {
protected void onCreate(Bundle savedInstanceState, Intent intent,
CharSequence title, Intent[] initialIntents, List rList,
boolean alwaysUseOption) {
- setTheme(R.style.Theme_DeviceDefault_Light_Dialog_Alert);
+ if (getResources().getConfiguration().uiInvertedMode
+ == Configuration.UI_INVERTED_MODE_YES) {
+ setTheme(R.style.Theme_DeviceDefault_Dialog_Alert);
+ } else {
+ setTheme(R.style.Theme_DeviceDefault_Light_Dialog_Alert);
+ }
super.onCreate(savedInstanceState);
try {
mLaunchedFromUid = ActivityManagerNative.getDefault().getLaunchedFromUid(
@@ -114,6 +124,7 @@ protected void onCreate(Bundle savedInstanceState, Intent intent,
} catch (RemoteException e) {
mLaunchedFromUid = -1;
}
+ mUseAltGrid = Settings.System.getBoolean(getContentResolver(), Settings.System.ACTIVITY_RESOLVER_USE_ALT, false);
mPm = getPackageManager();
mAlwaysUseOption = alwaysUseOption;
mMaxColumns = getResources().getInteger(R.integer.config_maxResolverActivityColumns);
@@ -138,7 +149,11 @@ protected void onCreate(Bundle savedInstanceState, Intent intent,
finish();
return;
} else if (count > 1) {
- ap.mView = getLayoutInflater().inflate(R.layout.resolver_grid, null);
+ if (mUseAltGrid) {
+ ap.mView = getLayoutInflater().inflate(R.layout.resolver_grid_alt, null);
+ } else {
+ ap.mView = getLayoutInflater().inflate(R.layout.resolver_grid, null);
+ }
mGrid = (GridView) ap.mView.findViewById(R.id.resolver_grid);
mGrid.setAdapter(mAdapter);
mGrid.setOnItemClickListener(this);
@@ -165,8 +180,12 @@ protected void onCreate(Bundle savedInstanceState, Intent intent,
final ViewGroup buttonLayout = (ViewGroup) findViewById(R.id.button_bar);
if (buttonLayout != null) {
buttonLayout.setVisibility(View.VISIBLE);
- mAlwaysButton = (Button) buttonLayout.findViewById(R.id.button_always);
- mOnceButton = (Button) buttonLayout.findViewById(R.id.button_once);
+ if (mUseAltGrid) {
+ mAlwaysCheckBox = (CheckBox) buttonLayout.findViewById(R.id.checkbox_always);
+ } else {
+ mAlwaysButton = (Button) buttonLayout.findViewById(R.id.button_always);
+ mOnceButton = (Button) buttonLayout.findViewById(R.id.button_once);
+ }
} else {
mAlwaysUseOption = false;
}
@@ -249,8 +268,10 @@ protected void onRestoreInstanceState(Bundle savedInstanceState) {
final int checkedPos = mGrid.getCheckedItemPosition();
final boolean enabled = checkedPos != GridView.INVALID_POSITION;
mLastSelected = checkedPos;
- mAlwaysButton.setEnabled(enabled);
- mOnceButton.setEnabled(enabled);
+ if (!mUseAltGrid) {
+ mAlwaysButton.setEnabled(enabled);
+ mOnceButton.setEnabled(enabled);
+ }
if (enabled) {
mGrid.setSelection(checkedPos);
}
@@ -262,10 +283,16 @@ public void onItemClick(AdapterView> parent, View view, int position, long id)
final int checkedPos = mGrid.getCheckedItemPosition();
final boolean hasValidSelection = checkedPos != GridView.INVALID_POSITION;
if (mAlwaysUseOption && (!hasValidSelection || mLastSelected != checkedPos)) {
- mAlwaysButton.setEnabled(hasValidSelection);
- mOnceButton.setEnabled(hasValidSelection);
+ if (!mUseAltGrid) {
+ mAlwaysButton.setEnabled(hasValidSelection);
+ mOnceButton.setEnabled(hasValidSelection);
+ }
if (hasValidSelection) {
- mGrid.smoothScrollToPosition(checkedPos);
+ if (mUseAltGrid) {
+ startSelected(position,mAlwaysCheckBox.isChecked());
+ } else {
+ mGrid.smoothScrollToPosition(checkedPos);
+ }
}
mLastSelected = checkedPos;
} else {
@@ -323,7 +350,7 @@ protected void onIntentSelected(ResolveInfo ri, Intent intent, boolean alwaysChe
|| (!"file".equals(data.getScheme())
&& !"content".equals(data.getScheme()))) {
filter.addDataScheme(data.getScheme());
-
+
// Look through the resolved filter to determine which part
// of it matched the original Intent.
Iterator aIt = ri.filter.authoritiesIterator();
@@ -402,7 +429,6 @@ private final class ResolveListAdapter extends BaseAdapter {
private final int mLaunchedFromUid;
private final LayoutInflater mInflater;
- private List mCurrentResolveList;
private List mList;
public ResolveListAdapter(Context context, Intent intent,
@@ -413,6 +439,7 @@ public ResolveListAdapter(Context context, Intent intent,
mBaseResolveList = rList;
mLaunchedFromUid = launchedFromUid;
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ mList = new ArrayList();
rebuildList();
}
@@ -420,22 +447,23 @@ public void handlePackagesChanged() {
final int oldItemCount = getCount();
rebuildList();
notifyDataSetChanged();
- if (mList.size() <= 0) {
+ final int newItemCount = getCount();
+ if (newItemCount == 0) {
// We no longer have any items... just finish the activity.
finish();
- }
-
- final int newItemCount = getCount();
- if (newItemCount != oldItemCount) {
+ } else if (newItemCount != oldItemCount) {
resizeGrid();
}
}
private void rebuildList() {
+ List currentResolveList;
+
+ mList.clear();
if (mBaseResolveList != null) {
- mCurrentResolveList = mBaseResolveList;
+ currentResolveList = mBaseResolveList;
} else {
- mCurrentResolveList = mPm.queryIntentActivities(
+ currentResolveList = mPm.queryIntentActivities(
mIntent, PackageManager.MATCH_DEFAULT_ONLY
| (mAlwaysUseOption ? PackageManager.GET_RESOLVED_FILTER : 0));
// Filter out any activities that the launched uid does not
@@ -443,36 +471,36 @@ private void rebuildList() {
// list of resolved activities, because that only happens when
// we are being subclassed, so we can safely launch whatever
// they gave us.
- if (mCurrentResolveList != null) {
- for (int i=mCurrentResolveList.size()-1; i >= 0; i--) {
- ActivityInfo ai = mCurrentResolveList.get(i).activityInfo;
+ if (currentResolveList != null) {
+ for (int i=currentResolveList.size()-1; i >= 0; i--) {
+ ActivityInfo ai = currentResolveList.get(i).activityInfo;
int granted = ActivityManager.checkComponentPermission(
ai.permission, mLaunchedFromUid,
ai.applicationInfo.uid, ai.exported);
if (granted != PackageManager.PERMISSION_GRANTED) {
// Access not allowed!
- mCurrentResolveList.remove(i);
+ currentResolveList.remove(i);
}
}
}
}
int N;
- if ((mCurrentResolveList != null) && ((N = mCurrentResolveList.size()) > 0)) {
+ if ((currentResolveList != null) && ((N = currentResolveList.size()) > 0)) {
// Only display the first matches that are either of equal
// priority or have asked to be default options.
- ResolveInfo r0 = mCurrentResolveList.get(0);
+ ResolveInfo r0 = currentResolveList.get(0);
for (int i=1; i 1) {
ResolveInfo.DisplayNameComparator rComparator =
new ResolveInfo.DisplayNameComparator(mPm);
- Collections.sort(mCurrentResolveList, rComparator);
+ Collections.sort(currentResolveList, rComparator);
}
-
- mList = new ArrayList();
-
// First put the initial items at the top.
if (mInitialIntents != null) {
for (int i=0; i rList, int start, int end, ResolveIn
}
public ResolveInfo resolveInfoForPosition(int position) {
- if (mList == null) {
- return null;
- }
-
return mList.get(position).ri;
}
public Intent intentForPosition(int position) {
- if (mList == null) {
- return null;
- }
-
DisplayResolveInfo dri = mList.get(position);
Intent intent = new Intent(dri.origIntent != null
@@ -614,11 +631,11 @@ public Intent intentForPosition(int position) {
}
public int getCount() {
- return mList != null ? mList.size() : 0;
+ return mList.size();
}
public Object getItem(int position) {
- return position;
+ return mList.get(position);
}
public long getItemId(int position) {
diff --git a/core/java/com/android/internal/app/ThemeUtils.java b/core/java/com/android/internal/app/ThemeUtils.java
new file mode 100644
index 00000000000..2eda7fd6c03
--- /dev/null
+++ b/core/java/com/android/internal/app/ThemeUtils.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2012 The CyanogenMod 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.internal.app;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.BroadcastReceiver;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+
+public class ThemeUtils {
+ private static final String TAG = "ThemeUtils";
+ private static final String DATA_TYPE_TMOBILE_STYLE = "vnd.tmobile.cursor.item/style";
+ private static final String DATA_TYPE_TMOBILE_THEME = "vnd.tmobile.cursor.item/theme";
+ private static final String ACTION_TMOBILE_THEME_CHANGED = "com.tmobile.intent.action.THEME_CHANGED";
+
+ private static class ThemedUiContext extends ContextWrapper {
+ private String mPackageName;
+
+ public ThemedUiContext(Context context, String packageName) {
+ super(context);
+ mPackageName = packageName;
+ }
+
+ @Override
+ public String getPackageName() {
+ return mPackageName;
+ }
+ }
+
+ public static Context createUiContext(final Context context) {
+ try {
+ Context uiContext = context.createPackageContext("com.android.systemui",
+ Context.CONTEXT_RESTRICTED);
+ return new ThemedUiContext(uiContext, context.getPackageName());
+ } catch (PackageManager.NameNotFoundException e) {
+ }
+
+ return null;
+ }
+
+ public static void registerThemeChangeReceiver(final Context context, final BroadcastReceiver receiver) {
+ IntentFilter filter = new IntentFilter(ACTION_TMOBILE_THEME_CHANGED);
+ try {
+ filter.addDataType(DATA_TYPE_TMOBILE_THEME);
+ filter.addDataType(DATA_TYPE_TMOBILE_STYLE);
+ } catch (IntentFilter.MalformedMimeTypeException e) {
+ Log.e(TAG, "Could not add MIME types to filter", e);
+ }
+
+ context.registerReceiver(receiver, filter);
+ }
+}
+
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 94e7a068c7f..210d7d92251 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -2015,6 +2015,12 @@ public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) {
case TelephonyManager.NETWORK_TYPE_EHRPD:
bin = DATA_CONNECTION_EHRPD;
break;
+ case TelephonyManager.NETWORK_TYPE_HSPAP:
+ bin = DATA_CONNECTION_HSPAP;
+ break;
+ case TelephonyManager.NETWORK_TYPE_DCHSPAP:
+ bin = DATA_CONNECTION_DCHSPAP;
+ break;
default:
bin = DATA_CONNECTION_OTHER;
break;
diff --git a/core/java/com/android/internal/os/DeviceKeyHandler.java b/core/java/com/android/internal/os/DeviceKeyHandler.java
new file mode 100644
index 00000000000..e7d103dd6be
--- /dev/null
+++ b/core/java/com/android/internal/os/DeviceKeyHandler.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2012 The CyanogenMod 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.internal.os;
+
+import android.view.KeyEvent;
+
+public interface DeviceKeyHandler {
+
+ /**
+ * Invoked when an unknown key was detected by the system, letting the device handle
+ * this special keys prior to pass the key to the active app.
+ *
+ * @param event The key event to be handled
+ * @return If the event is consume
+ */
+ public boolean handleKeyEvent(KeyEvent event);
+}
diff --git a/core/java/com/android/internal/os/PkgUsageStats.aidl b/core/java/com/android/internal/os/PkgUsageStats.aidl
old mode 100755
new mode 100644
diff --git a/core/java/com/android/internal/os/PkgUsageStats.java b/core/java/com/android/internal/os/PkgUsageStats.java
old mode 100755
new mode 100644
diff --git a/core/java/com/android/internal/os/ProcessStats.java b/core/java/com/android/internal/os/ProcessStats.java
index b1bb8c173a6..fc28a8ca755 100644
--- a/core/java/com/android/internal/os/ProcessStats.java
+++ b/core/java/com/android/internal/os/ProcessStats.java
@@ -702,7 +702,9 @@ final public String printCurrentState(long now) {
long sampleTime = mCurrentSampleTime - mLastSampleTime;
long sampleRealTime = mCurrentSampleRealTime - mLastSampleRealTime;
- long percAwake = sampleRealTime > 0 ? ((sampleTime*100) / sampleRealTime) : 0;
+ long percAwake = ((sampleRealTime > 0)
+ ? (sampleTime*100) / sampleRealTime
+ : 100);
if (percAwake != 100) {
pw.print(" with ");
pw.print(percAwake);
diff --git a/core/java/com/android/internal/os/SamplingProfilerIntegration.java b/core/java/com/android/internal/os/SamplingProfilerIntegration.java
index df0fcd97787..6429aa420fd 100644
--- a/core/java/com/android/internal/os/SamplingProfilerIntegration.java
+++ b/core/java/com/android/internal/os/SamplingProfilerIntegration.java
@@ -106,7 +106,7 @@ public static void start() {
}
ThreadGroup group = Thread.currentThread().getThreadGroup();
- SamplingProfiler.ThreadSet threadSet = SamplingProfiler.newThreadGroupTheadSet(group);
+ SamplingProfiler.ThreadSet threadSet = SamplingProfiler.newThreadGroupThreadSet(group);
samplingProfiler = new SamplingProfiler(samplingProfilerDepth, threadSet);
samplingProfiler.start(samplingProfilerMilliseconds);
startMillis = System.currentTimeMillis();
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index d24513a3035..e7447afe953 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -825,7 +825,7 @@ private static void applyInvokeWithSecurityPolicy(Arguments args, Credentials pe
}
/**
- * Applies zygote security policy for SEAndroid information.
+ * Applies zygote security policy for SELinux information.
*
* @param args non-null; zygote spawner arguments
* @param peer non-null; peer credentials
@@ -844,7 +844,7 @@ private static void applyseInfoSecurityPolicy(
if (!(peerUid == 0 || peerUid == Process.SYSTEM_UID)) {
// All peers with UID other than root or SYSTEM_UID
throw new ZygoteSecurityException(
- "This UID may not specify SEAndroid info.");
+ "This UID may not specify SELinux info.");
}
boolean allowed = SELinux.checkSELinuxAccess(peerSecurityContext,
@@ -853,7 +853,7 @@ private static void applyseInfoSecurityPolicy(
"specifyseinfo");
if (!allowed) {
throw new ZygoteSecurityException(
- "Peer may not specify SEAndroid info");
+ "Peer may not specify SELinux info");
}
return;
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 9e43749d61f..13a8972febb 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -99,7 +99,7 @@ public class ZygoteInit {
private static final String PRELOADED_CLASSES = "preloaded-classes";
/** Controls whether we should preload resources during zygote init. */
- private static final boolean PRELOAD_RESOURCES = true;
+ private static final boolean PRELOAD_RESOURCES = false;
/**
* Invokes a static "main(argv[]) method on class "className".
@@ -361,6 +361,8 @@ private static void preloadResources() {
ar.recycle();
Log.i(TAG, "...preloaded " + N + " resources in "
+ (SystemClock.uptimeMillis()-startTime) + "ms.");
+ } else {
+ Log.i(TAG, "Preload resources disabled, skipped.");
}
mResources.finishPreloading();
} catch (RuntimeException e) {
@@ -483,7 +485,7 @@ private static boolean startSystemServer()
String args[] = {
"--setuid=1000",
"--setgid=1000",
- "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003,3006,3007",
+ "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,3001,3002,3003,3004,3006,3007,3009",
"--capabilities=130104352,130104352",
"--runtime-init",
"--nice-name=system_server",
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 780f5b3504d..5bce2eff49b 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -29,12 +29,14 @@ oneway interface IStatusBar
void removeNotification(IBinder key);
void disable(int state);
void animateExpandNotificationsPanel();
- void animateExpandSettingsPanel();
+ void animateExpandSettingsPanel(boolean flip);
void animateCollapsePanels();
void setSystemUiVisibility(int vis, int mask);
void topAppWindowChanged(boolean menuVisible);
void setImeWindowStatus(in IBinder token, int vis, int backDisposition);
void setHardKeyboardStatus(boolean available, boolean enabled);
+ void toggleNotificationShade();
+ void toggleQSShade();
void toggleRecentApps();
void preloadRecentApps();
void cancelPreloadRecentApps();
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 04e5bc97d39..5c43edca9d1 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -48,6 +48,8 @@ interface IStatusBarService
void onNotificationClear(String pkg, String tag, int id);
void setSystemUiVisibility(int vis, int mask);
void setHardKeyboardEnabled(boolean enabled);
+ void toggleNotificationShade();
+ void toggleQSShade();
void toggleRecentApps();
void preloadRecentApps();
void cancelPreloadRecentApps();
diff --git a/core/java/com/android/internal/util/carbon/AokpRibbonHelper.java b/core/java/com/android/internal/util/carbon/AokpRibbonHelper.java
new file mode 100644
index 00000000000..c4416859aa5
--- /dev/null
+++ b/core/java/com/android/internal/util/carbon/AokpRibbonHelper.java
@@ -0,0 +1,164 @@
+package com.android.internal.util.carbon;
+
+import java.util.ArrayList;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.view.Gravity;
+import android.view.View;
+import android.util.DisplayMetrics;
+import android.view.WindowManager;
+import android.widget.ArrayAdapter;
+import android.widget.HorizontalScrollView;
+import android.widget.ScrollView;
+import android.widget.LinearLayout;
+import android.widget.LinearLayout.LayoutParams;
+import android.widget.RelativeLayout;
+
+public class AokpRibbonHelper {
+
+ private static final String TAG = "Aokp Ribbon";
+
+ private static final String TARGET_DELIMITER = "|";
+ public static final int LOCKSCREEN = 0;
+ public static final int NOTIFICATIONS = 1;
+ public static final int SWIPE_RIBBON_LEFT = 2;
+ public static final int QUICK_SETTINGS = 3;
+ public static final int SWIPE_RIBBON_RIGHT = 4;
+ public static final int SWIPE_RIBBON_BOTTOM = 5;
+
+ public static final LinearLayout.LayoutParams PARAMS_TARGET = new LinearLayout.LayoutParams(
+ LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, 1f);
+
+ public static final LinearLayout.LayoutParams PARAMS_TARGET_VERTICAL = new LinearLayout.LayoutParams(
+ LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT, 1f);
+
+ public static final LinearLayout.LayoutParams PARAMS_TARGET_SCROLL = new LinearLayout.LayoutParams(
+ LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 1f);
+
+ public static final LinearLayout.LayoutParams PARAMS_GRID = new LinearLayout.LayoutParams(
+ 0, LayoutParams.WRAP_CONTENT, 1f);
+
+ public static HorizontalScrollView getRibbon(Context mContext, ArrayList shortTargets, ArrayList longTargets,
+ ArrayList customIcons, boolean text, int color, int size, int pad, boolean vib, boolean colorize, int dismiss) {
+ DisplayMetrics metrics = new DisplayMetrics();
+ WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+ wm.getDefaultDisplay().getMetrics(metrics);
+ int padding = (int) (pad * metrics.density);
+ int top = (int) (1 * metrics.density);
+ int length = shortTargets.size();
+ HorizontalScrollView targetScrollView = new HorizontalScrollView(mContext);
+ if (length > 0 && (shortTargets.size() == customIcons.size())) {
+
+ ArrayList targets = new ArrayList();
+ for (int i = 0; i < length; i++) {
+ if (!TextUtils.isEmpty(shortTargets.get(i))) {
+ RibbonTarget newTarget = null;
+ newTarget = new RibbonTarget(mContext, shortTargets.get(i), longTargets.get(i),
+ customIcons.get(i), text, color, size, vib, colorize, dismiss);
+ if (newTarget != null) {
+ if (i < length -1) {
+ newTarget.setPadding(padding, top);
+ }
+ targets.add(newTarget);
+ }
+ }
+ }
+ LinearLayout targetsLayout = new LinearLayout(mContext);
+ targetsLayout.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
+ targetScrollView.setHorizontalFadingEdgeEnabled(true);
+ for (int i = 0; i < targets.size(); i++) {
+ targetsLayout.addView(targets.get(i).getView(), PARAMS_TARGET_SCROLL);
+ }
+ targetScrollView.addView(targetsLayout, PARAMS_TARGET);
+ }
+ return targetScrollView;
+ }
+
+ public static ScrollView getVerticalRibbon(Context mContext, ArrayList shortTargets, ArrayList longTargets,
+ ArrayList customIcons, boolean text, int color, int size, int pad, boolean vib, boolean colorize, int dismiss) {
+ DisplayMetrics metrics = new DisplayMetrics();
+ WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+ wm.getDefaultDisplay().getMetrics(metrics);
+ int padding = (int) (pad * metrics.density);
+ int sides = (int) (5 * metrics.density);
+ int length = shortTargets.size();
+ ScrollView targetScrollView = new ScrollView(mContext);
+ if (length > 0 && (shortTargets.size() == customIcons.size())) {
+
+ ArrayList targets = new ArrayList();
+ for (int i = 0; i < length; i++) {
+ if (!TextUtils.isEmpty(shortTargets.get(i))) {
+ RibbonTarget newTarget = null;
+ newTarget = new RibbonTarget(mContext, shortTargets.get(i), longTargets.get(i),
+ customIcons.get(i), text, color, size, vib, colorize, dismiss);
+ if (newTarget != null) {
+ if (i < length -1) {
+ newTarget.setVerticalPadding(padding, sides);
+ }
+ targets.add(newTarget);
+ }
+ }
+ }
+ LinearLayout targetsLayout = new LinearLayout(mContext);
+ targetsLayout.setOrientation(LinearLayout.VERTICAL);
+ targetsLayout.setGravity(Gravity.CENTER);
+ targetScrollView.setOverScrollMode(View.OVER_SCROLL_IF_CONTENT_SCROLLS);
+ for (int i = 0; i < targets.size(); i++) {
+ targetsLayout.addView(targets.get(i).getView(), PARAMS_TARGET_SCROLL);
+ }
+ targetScrollView.addView(targetsLayout, PARAMS_TARGET_SCROLL);
+ }
+ return targetScrollView;
+ }
+
+ public static ScrollView getGridView(Context mContext, ArrayList apps, ArrayList appInfo,
+ int color, int columns, int pad) {
+ DisplayMetrics metrics = new DisplayMetrics();
+ WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+ wm.getDefaultDisplay().getMetrics(metrics);
+ int padding = (int) (pad * metrics.density);
+ int length = apps.size();
+ ScrollView appGridView = new ScrollView(mContext);
+ ArrayList targets = new ArrayList();
+ for (int i = 0; i < length; i++) {
+ if (!TextUtils.isEmpty(apps.get(i))) {
+ RibbonTarget newApp = null;
+ newApp = new RibbonTarget(mContext, apps.get(i), appInfo.get(i), "**null**", true, color, 0, true, false, 0);
+ if (newApp != null) {
+ targets.add(newApp);
+ }
+ }
+ }
+ LinearLayout table = new LinearLayout(mContext);
+ table.setOrientation(LinearLayout.VERTICAL);
+ length = targets.size();
+ int intDiv = length / columns;
+ for (int i = 0; i < intDiv; i++) {
+ LinearLayout row = new LinearLayout(mContext);
+ row.setOrientation(LinearLayout.HORIZONTAL);
+ for (int j = 0; j < columns; j++) {
+ row.addView(targets.get(0).getView(), PARAMS_GRID);
+ targets.remove(0);
+ }
+ if (targets.size() < 1) {
+ table.addView(row, PARAMS_TARGET);
+ } else {
+ LinearLayout.LayoutParams PARAMS_ROW = new LinearLayout.LayoutParams(
+ LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, 1f);
+ PARAMS_ROW.setMargins(0, 0, 0, padding);
+ table.addView(row, PARAMS_ROW);
+ }
+ }
+ length = targets.size();
+ LinearLayout newRow = new LinearLayout(mContext);
+ newRow.setOrientation(LinearLayout.HORIZONTAL);
+ for (int i = 0; i < length; i++) {
+ newRow.addView(targets.get(i).getView(), PARAMS_GRID);
+ }
+ newRow.setGravity(Gravity.CENTER);
+ table.addView(newRow, PARAMS_TARGET);
+ appGridView.addView(table, PARAMS_TARGET);
+ return appGridView;
+ }
+}
diff --git a/core/java/com/android/internal/util/carbon/AwesomeAnimationHelper.java b/core/java/com/android/internal/util/carbon/AwesomeAnimationHelper.java
new file mode 100755
index 00000000000..798d7ed8c03
--- /dev/null
+++ b/core/java/com/android/internal/util/carbon/AwesomeAnimationHelper.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2013 AOKP by Steve Spear - Stevespear426
+ *
+ * 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.internal.util.carbon;
+
+import android.content.Context;
+import android.content.res.Resources;
+
+import java.util.ArrayList;
+
+public class AwesomeAnimationHelper {
+
+ public final static int ANIMATION_DEFAULT = 0;
+ public final static int ANIMATION_FADE = 1;
+ public final static int ANIMATION_SLIDE_RIGHT = 2;
+ public final static int ANIMATION_SLIDE_LEFT = 3;
+ public final static int ANIMATION_SLIDE_RIGHT_NO_FADE = 4;
+ public final static int ANIMATION_SLIDE_LEFT_NO_FADE = 5;
+ public final static int ANIMATION_SLIDE_UP = 6;
+ public final static int ANIMATION_SLIDE_DOWN = 7;
+ public final static int ANIMATION_TRANSLUCENT = 8;
+ public final static int ANIMATION_GROW_SHRINK = 9;
+ public final static int ANIMATION_GROW_SHRINK_CENTER = 10;
+ public final static int ANIMATION_GROW_SHRINK_BOTTOM = 11;
+ public final static int ANIMATION_GROW_SHRINK_LEFT = 12;
+ public final static int ANIMATION_GROW_SHRINK_RIGHT = 13;
+
+ public static int[] getAnimationsList() {
+ ArrayList animList = new ArrayList();
+ animList.add(ANIMATION_DEFAULT);
+ animList.add(ANIMATION_FADE);
+ animList.add(ANIMATION_SLIDE_RIGHT);
+ animList.add(ANIMATION_SLIDE_LEFT);
+ animList.add(ANIMATION_SLIDE_RIGHT_NO_FADE);
+ animList.add(ANIMATION_SLIDE_LEFT_NO_FADE);
+ animList.add(ANIMATION_SLIDE_UP);
+ animList.add(ANIMATION_SLIDE_DOWN);
+ animList.add(ANIMATION_TRANSLUCENT);
+ animList.add(ANIMATION_GROW_SHRINK);
+ animList.add(ANIMATION_GROW_SHRINK_CENTER);
+ animList.add(ANIMATION_GROW_SHRINK_BOTTOM);
+ animList.add(ANIMATION_GROW_SHRINK_LEFT);
+ animList.add(ANIMATION_GROW_SHRINK_RIGHT);
+ int length = animList.size();
+ int[] anim = new int[length];
+ for (int i = 0; i < length; i++) {
+ anim[i] = animList.get(i);
+ }
+ return anim;
+ }
+
+ public static int[] getAnimations(int mAnim) {
+ int[] anim = new int[2];
+ switch (mAnim) {
+ case ANIMATION_FADE:
+ anim[0] = com.android.internal.R.anim.slow_fade_out;
+ anim[1] = com.android.internal.R.anim.slow_fade_in;
+ break;
+ case ANIMATION_SLIDE_RIGHT:
+ anim[0] = com.android.internal.R.anim.slide_out_right_ribbon;
+ anim[1] = com.android.internal.R.anim.slide_in_right_ribbon;
+ break;
+ case ANIMATION_SLIDE_LEFT:
+ anim[0] = com.android.internal.R.anim.slide_out_left_ribbon;
+ anim[1] = com.android.internal.R.anim.slide_in_left_ribbon;
+ break;
+ case ANIMATION_SLIDE_UP:
+ anim[0] = com.android.internal.R.anim.slide_out_down_ribbon;
+ anim[1] = com.android.internal.R.anim.slide_in_up_ribbon;
+ break;
+ case ANIMATION_SLIDE_DOWN:
+ anim[0] = com.android.internal.R.anim.slide_out_up;
+ anim[1] = com.android.internal.R.anim.slide_in_down;
+ break;
+ case ANIMATION_SLIDE_RIGHT_NO_FADE:
+ anim[0] = com.android.internal.R.anim.slide_out_right_no_fade;
+ anim[1] = com.android.internal.R.anim.slide_in_right_no_fade;
+ break;
+ case ANIMATION_SLIDE_LEFT_NO_FADE:
+ anim[0] = com.android.internal.R.anim.slide_out_left_no_fade;
+ anim[1] = com.android.internal.R.anim.slide_in_left_no_fade;
+ break;
+ case ANIMATION_TRANSLUCENT:
+ anim[0] = com.android.internal.R.anim.translucent_exit_ribbon;
+ anim[1] = com.android.internal.R.anim.translucent_enter_ribbon;
+ break;
+ case ANIMATION_GROW_SHRINK:
+ anim[0] = com.android.internal.R.anim.shrink_fade_out_ribbon;
+ anim[1] = com.android.internal.R.anim.grow_fade_in_ribbon;
+ break;
+ case ANIMATION_GROW_SHRINK_CENTER:
+ anim[0] = com.android.internal.R.anim.shrink_fade_out_center_ribbon;
+ anim[1] = com.android.internal.R.anim.grow_fade_in_center_ribbon;
+ break;
+ case ANIMATION_GROW_SHRINK_LEFT:
+ anim[0] = com.android.internal.R.anim.shrink_fade_out_left_ribbon;
+ anim[1] = com.android.internal.R.anim.grow_fade_in_left_ribbon;
+ break;
+ case ANIMATION_GROW_SHRINK_RIGHT:
+ anim[0] = com.android.internal.R.anim.shrink_fade_out_right_ribbon;
+ anim[1] = com.android.internal.R.anim.grow_fade_in_right_ribbon;
+ break;
+ case ANIMATION_GROW_SHRINK_BOTTOM:
+ anim[0] = com.android.internal.R.anim.shrink_fade_out_from_bottom_ribbon;
+ anim[1] = com.android.internal.R.anim.grow_fade_in_from_bottom_ribbon;
+ break;
+ }
+ return anim;
+ }
+
+ public static String getProperName(Context context, int mAnim) {
+ Resources res = context.getResources();
+ String value = "";
+ switch (mAnim) {
+ case ANIMATION_DEFAULT:
+ value = res.getString(com.android.internal.R.string.animation_default);
+ break;
+ case ANIMATION_FADE:
+ value = res.getString(com.android.internal.R.string.animation_fade);
+ break;
+ case ANIMATION_SLIDE_RIGHT:
+ value = res.getString(com.android.internal.R.string.animation_slide_right);
+ break;
+ case ANIMATION_SLIDE_RIGHT_NO_FADE:
+ value = res.getString(com.android.internal.R.string.animation_slide_right_no_fade);
+ break;
+ case ANIMATION_SLIDE_LEFT:
+ value = res.getString(com.android.internal.R.string.animation_slide_left);
+ break;
+ case ANIMATION_SLIDE_UP:
+ value = res.getString(com.android.internal.R.string.animation_slide_up);
+ break;
+ case ANIMATION_SLIDE_DOWN:
+ value = res.getString(com.android.internal.R.string.animation_slide_down);
+ break;
+ case ANIMATION_SLIDE_LEFT_NO_FADE:
+ value = res.getString(com.android.internal.R.string.animation_slide_left_no_fade);
+ break;
+ case ANIMATION_TRANSLUCENT:
+ value = res.getString(com.android.internal.R.string.animation_translucent);
+ break;
+ case ANIMATION_GROW_SHRINK_BOTTOM:
+ value = res.getString(com.android.internal.R.string.animation_grow_shrink_bottom);
+ break;
+ case ANIMATION_GROW_SHRINK_CENTER:
+ value = res.getString(com.android.internal.R.string.animation_grow_shrink_center);
+ break;
+ case ANIMATION_GROW_SHRINK_LEFT:
+ value = res.getString(com.android.internal.R.string.animation_grow_shrink_left);
+ break;
+ case ANIMATION_GROW_SHRINK_RIGHT:
+ value = res.getString(com.android.internal.R.string.animation_grow_shrink_right);
+ break;
+ case ANIMATION_GROW_SHRINK:
+ value = res.getString(com.android.internal.R.string.animation_grow_shrink);
+ break;
+ default:
+ value = res.getString(com.android.internal.R.string.action_null);
+ break;
+
+ }
+ return value;
+ }
+}
diff --git a/core/java/com/android/internal/util/carbon/AwesomeConstants.java b/core/java/com/android/internal/util/carbon/AwesomeConstants.java
new file mode 100755
index 00000000000..6c8a48d342c
--- /dev/null
+++ b/core/java/com/android/internal/util/carbon/AwesomeConstants.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2013 AOKP by Mike Wilson - Zaphod-Beeblebrox && Steve Spear - Stevespear426
+ *
+ * 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.internal.util.carbon;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+
+public class AwesomeConstants {
+
+ public static final String ASSIST_ICON_METADATA_NAME = "com.android.systemui.action_assist_icon";
+
+ public final static int SWIPE_LEFT = 0;
+ public final static int SWIPE_RIGHT = 1;
+ public final static int SWIPE_DOWN = 2;
+ public final static int SWIPE_UP = 3;
+ public final static int TAP_DOUBLE = 4;
+ public final static int PRESS_LONG = 5;
+ public final static int SPEN_REMOVE = 6;
+ public final static int SPEN_INSERT = 7;
+
+ /* Adding Actions here will automatically add them to NavBar actions in ROMControl.
+ * **app** must remain the last action. Add other actions before that final action.
+ * For clarity, **null** should probably also be just before APP. New actions
+ * should be added prior to **null**
+ */
+ public static enum AwesomeConstant {
+ ACTION_HOME { @Override public String value() { return "**home**";}},
+ ACTION_BACK { @Override public String value() { return "**back**";}},
+ ACTION_MENU { @Override public String value() { return "**menu**";}},
+ ACTION_SEARCH { @Override public String value() { return "**search**";}},
+ ACTION_RECENTS { @Override public String value() { return "**recents**";}},
+ ACTION_ASSIST { @Override public String value() { return "**assist**";}},
+ ACTION_POWER { @Override public String value() { return "**power**";}},
+ ACTION_WIDGETS { @Override public String value() { return "**widgets**";}},
+ ACTION_APP_WINDOW { @Override public String value() { return "**app_window**";}},
+ ACTION_NOTIFICATIONS { @Override public String value() { return "**notifications**";}},
+ ACTION_QUICKSETTINGS { @Override public String value() { return "**quicksettings**";}},
+ ACTION_CLOCKOPTIONS { @Override public String value() { return "**clockoptions**";}},
+ ACTION_VOICEASSIST { @Override public String value() { return "**voiceassist**";}},
+ ACTION_LAST_APP { @Override public String value() { return "**lastapp**";}},
+ ACTION_TORCH { @Override public String value() { return "**torch**";}},
+ ACTION_IME { @Override public String value() { return "**ime**";}},
+ ACTION_KILL { @Override public String value() { return "**kill**";}},
+ ACTION_SILENT { @Override public String value() { return "**ring_silent**";}},
+ ACTION_VIB { @Override public String value() { return "**ring_vib**";}},
+ ACTION_SILENT_VIB { @Override public String value() { return "**ring_vib_silent**";}},
+ ACTION_EVENT { @Override public String value() { return "**event**";}},
+ ACTION_TODAY { @Override public String value() { return "**today**";}},
+ ACTION_ALARM { @Override public String value() { return "**alarm**";}},
+ ACTION_UNLOCK { @Override public String value() { return "**unlock**";}},
+ ACTION_CAMERA { @Override public String value() { return "**camera**";}},
+ ACTION_NULL { @Override public String value() { return "**null**";}},
+ ACTION_APP { @Override public String value() { return "**app**";}};
+ public String value() { return this.value(); }
+ }
+
+ public static AwesomeConstant fromString(String string) {
+ if (!TextUtils.isEmpty(string)) {
+ AwesomeConstant[] allTargs = AwesomeConstant.values();
+ for (int i=0; i < allTargs.length; i++) {
+ if (string.equals(allTargs[i].value())) {
+ return allTargs[i];
+ }
+ }
+ }
+ // not in ENUM must be custom
+ return AwesomeConstant.ACTION_APP;
+ }
+
+ public static String[] AwesomeActions() {
+ return fromAwesomeActionArray(AwesomeConstant.values());
+ }
+
+ public static String[] fromAwesomeActionArray(AwesomeConstant[] allTargs) {
+ int actions = allTargs.length;
+ String[] values = new String [actions];
+ for (int i = 0; i < actions; i++) {
+ values [i] = allTargs[i].value();
+ }
+ return values;
+ }
+
+ public static Drawable getSystemUIDrawable(Context mContext, String DrawableID) {
+ Resources res = mContext.getResources();
+ PackageManager pm = mContext.getPackageManager();
+ int resId = 0;
+ Drawable d = res.getDrawable(com.android.internal.R.drawable.ic_action_empty);
+ if (pm != null) {
+ Resources mSystemUiResources = null;
+ try {
+ mSystemUiResources = pm.getResourcesForApplication("com.android.systemui");
+ } catch (Exception e) {
+ }
+
+ if (mSystemUiResources != null && DrawableID != null) {
+ resId = mSystemUiResources.getIdentifier(DrawableID, null, null);
+ }
+ if (resId > 0) {
+ try {
+ d = mSystemUiResources.getDrawable(resId);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return d;
+ }
+
+ public static String getProperName(Context context, String actionstring) {
+ // Will return a string for the associated action, but will need the caller's context to get resources.
+ Resources res = context.getResources();
+ String value = "";
+ if (TextUtils.isEmpty(actionstring)) {
+ actionstring = AwesomeConstant.ACTION_NULL.value();
+ }
+ AwesomeConstant action = fromString(actionstring);
+ switch (action) {
+ case ACTION_HOME :
+ value = res.getString(com.android.internal.R.string.action_home);
+ break;
+ case ACTION_BACK:
+ value = res.getString(com.android.internal.R.string.action_back);
+ break;
+ case ACTION_RECENTS:
+ value = res.getString(com.android.internal.R.string.action_recents);
+ break;
+ case ACTION_SEARCH:
+ value = res.getString(com.android.internal.R.string.action_search);
+ break;
+ /*case ACTION_SCREENSHOT:
+ value = res.getString(com.android.internal.R.string.action_screenshot);
+ break;*/
+ case ACTION_MENU:
+ value = res.getString(com.android.internal.R.string.action_menu);
+ break;
+ case ACTION_IME:
+ value = res.getString(com.android.internal.R.string.action_ime);
+ break;
+ case ACTION_KILL:
+ value = res.getString(com.android.internal.R.string.action_kill);
+ break;
+ case ACTION_LAST_APP:
+ value = res.getString(com.android.internal.R.string.action_lastapp);
+ break;
+ case ACTION_POWER:
+ value = res.getString(com.android.internal.R.string.action_power);
+ break;
+ case ACTION_WIDGETS:
+ value = res.getString(com.android.internal.R.string.action_widgets);
+ break;
+ case ACTION_APP_WINDOW:
+ value = res.getString(com.android.internal.R.string.action_app_window);
+ break;
+ case ACTION_NOTIFICATIONS:
+ value = res.getString(com.android.internal.R.string.action_notifications);
+ break;
+ case ACTION_QUICKSETTINGS:
+ value = res.getString(com.android.internal.R.string.action_quicksettings);
+ break;
+ case ACTION_ASSIST:
+ value = res.getString(com.android.internal.R.string.action_assist);
+ break;
+ case ACTION_CLOCKOPTIONS:
+ value = res.getString(com.android.internal.R.string.action_clockoptions);
+ break;
+ case ACTION_VOICEASSIST:
+ value = res.getString(com.android.internal.R.string.action_voiceassist);
+ break;
+ case ACTION_TORCH:
+ value = res.getString(com.android.internal.R.string.action_torch);
+ break;
+ case ACTION_SILENT:
+ value = res.getString(com.android.internal.R.string.action_silent);
+ break;
+ case ACTION_VIB:
+ value = res.getString(com.android.internal.R.string.action_vib);
+ break;
+ case ACTION_SILENT_VIB:
+ value = res.getString(com.android.internal.R.string.action_silent_vib);
+ break;
+ case ACTION_EVENT:
+ value = res.getString(com.android.internal.R.string.action_event);
+ break;
+ case ACTION_TODAY:
+ value = res.getString(com.android.internal.R.string.action_today);
+ break;
+ case ACTION_ALARM:
+ value = res.getString(com.android.internal.R.string.action_alarm);
+ break;
+ case ACTION_UNLOCK:
+ value = res.getString(com.android.internal.R.string.action_unlock);
+ break;
+ case ACTION_CAMERA:
+ value = res.getString(com.android.internal.R.string.action_camera);
+ break;
+ case ACTION_APP:
+ value = res.getString(com.android.internal.R.string.action_app);
+ break;
+ case ACTION_NULL:
+ default:
+ value = res.getString(com.android.internal.R.string.action_null);
+ break;
+
+ }
+ return value;
+ }
+ public static Drawable getActionIcon(Context context,String actionstring) {
+ // Will return a Drawable for the associated action, but will need the caller's context to get resources.
+ Resources res = context.getResources();
+ Drawable value = null;
+ AwesomeConstant action = fromString(actionstring);
+ switch (action) {
+ case ACTION_HOME :
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_home");
+ break;
+ case ACTION_BACK:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_back");
+ break;
+ case ACTION_RECENTS:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_recent");
+ break;
+ case ACTION_SEARCH:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_search");
+ break;
+ /*case ACTION_SCREENSHOT:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_screenshot");
+ break;*/
+ case ACTION_MENU:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_menu_big");
+ break;
+ case ACTION_IME:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_ime_switcher");
+ break;
+ case ACTION_KILL:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_killtask");
+ break;
+ case ACTION_LAST_APP:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_lastapp");
+ break;
+ case ACTION_POWER:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_power");
+ break;
+ case ACTION_WIDGETS:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_widget");
+ break;
+ case ACTION_APP_WINDOW:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_widget");
+ break;
+ case ACTION_NOTIFICATIONS:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_notifications");
+ break;
+ case ACTION_QUICKSETTINGS:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_quicksettings");
+ break;
+ case ACTION_ASSIST:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_assist");
+ break;
+ case ACTION_CLOCKOPTIONS:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_clockoptions");
+ break;
+ case ACTION_VOICEASSIST:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_voiceassist");
+ break;
+ case ACTION_TORCH:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_torch");
+ break;
+ case ACTION_SILENT:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_silent");
+ break;
+ case ACTION_VIB:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_vib");
+ break;
+ case ACTION_SILENT_VIB:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_silent_vib");
+ break;
+ case ACTION_EVENT:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_event");
+ break;
+ case ACTION_TODAY:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_today");
+ break;
+ case ACTION_ALARM:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_alarm");
+ break;
+ case ACTION_UNLOCK:
+ value = res.getDrawable(com.android.internal.R.drawable.ic_lockscreen_unlock);
+ break;
+ case ACTION_CAMERA:
+ value = res.getDrawable(com.android.internal.R.drawable.ic_lockscreen_camera);
+ break;
+ case ACTION_APP: // APP doesn't really have an icon - it should look up
+ //the package icon - we'll return the 'null' on just in case
+ case ACTION_NULL:
+ default:
+ value = getSystemUIDrawable(context, "com.android.systemui:drawable/ic_sysbar_null");
+ break;
+
+ }
+ return value;
+ }
+}
diff --git a/core/java/com/android/internal/util/carbon/BackgroundAlphaColorDrawable.java b/core/java/com/android/internal/util/carbon/BackgroundAlphaColorDrawable.java
new file mode 100644
index 00000000000..57e1cf3e758
--- /dev/null
+++ b/core/java/com/android/internal/util/carbon/BackgroundAlphaColorDrawable.java
@@ -0,0 +1,94 @@
+
+package com.android.internal.util.carbon;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.drawable.ColorDrawable;
+
+public class BackgroundAlphaColorDrawable extends ColorDrawable {
+ int mBgColor;
+ int mAlpha = 255;
+ int mComputedDrawColor = 0;
+
+ public BackgroundAlphaColorDrawable(int bgColor) {
+ setBgColor(mBgColor = bgColor);
+ updateColor();
+ }
+
+ public void setBgColor(int color) {
+ if (color < 0) {
+ color = Color.BLACK;
+ }
+ mBgColor = color;
+ updateColor();
+ }
+
+ @Override
+ public void setColor(int color) {
+ mComputedDrawColor = mBgColor = color;
+ invalidateSelf();
+ }
+
+ @Override
+ public int getColor() {
+ return mComputedDrawColor;
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ if (alpha > 255) {
+ alpha = 255;
+ } else if (alpha < 0) {
+ alpha = 0;
+ }
+ mAlpha = alpha;
+ updateColor();
+ }
+
+ public int getBgColor() {
+ return mBgColor;
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ canvas.drawColor(mComputedDrawColor, Mode.SRC);
+ }
+
+ private void updateColor() {
+ mComputedDrawColor = applyAlphaToColor(mBgColor, mAlpha);
+ invalidateSelf();
+ }
+
+ @Override
+ public int getAlpha() {
+ return mAlpha;
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter cf) {
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ public static int floatAlphaToInt(float alpha) {
+ return Math.round(alpha * 255);
+ }
+
+ public static int applyAlphaToColor(int color, float alpha) {
+ int a = floatAlphaToInt(alpha);
+ return applyAlphaToColor(color, a);
+ }
+
+ public static int applyAlphaToColor(int color, int alpha) {
+ int r = Color.red(color);
+ int g = Color.green(color);
+ int b = Color.blue(color);
+ return Color.argb(alpha, r, g, b);
+ }
+}
diff --git a/core/java/com/android/internal/util/carbon/GlowPadTorchHelper.java b/core/java/com/android/internal/util/carbon/GlowPadTorchHelper.java
new file mode 100755
index 00000000000..b66371657a2
--- /dev/null
+++ b/core/java/com/android/internal/util/carbon/GlowPadTorchHelper.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod 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.internal.util.carbon;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Message;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.ViewConfiguration;
+
+public class GlowPadTorchHelper {
+
+ private static final String TAG = "GlowPadTorchHelper";
+
+ public final static int TORCH_TIMEOUT = ViewConfiguration.getLongPressTimeout(); //longpress glowpad torch
+ public final static int TORCH_CHECK = 2000; //make sure torch turned off
+
+
+ private GlowPadTorchHelper() {
+ }
+
+ public static boolean torchActive(Context mContext) {
+ boolean torchActive = Settings.System.getBoolean(mContext.getContentResolver(),
+ Settings.System.TORCH_STATE, false);
+ return torchActive;
+ }
+
+ public static void killTorch(Context mContext) {
+ vibrate(mContext);
+ torchOff(mContext, false);
+ }
+
+ public static boolean startTorch(Context mContext) {
+ if (!torchActive(mContext)) {
+ vibrate(mContext);
+ Intent intent = new Intent("net.cactii.flash2.TOGGLE_FLASHLIGHT");
+ intent.putExtra("bright", false);
+ mContext.sendBroadcast(intent);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public static void torchOff(Context mContext, boolean logIt) {
+ if (logIt) {
+ Log.w(TAG, "Second Torch Temination Required");
+ }
+ Intent intent = new Intent("net.cactii.flash2.TOGGLE_FLASHLIGHT");
+ intent.putExtra("bright", false);
+ mContext.sendBroadcast(intent);
+ }
+
+ public static void vibrate(Context mContext) {
+ if (Settings.System.getIntForUser(mContext.getContentResolver(),
+ Settings.System.HAPTIC_FEEDBACK_ENABLED, 1, UserHandle.USER_CURRENT) != 0) {
+ android.os.Vibrator vib = (android.os.Vibrator)mContext.getSystemService(
+ Context.VIBRATOR_SERVICE);
+ if (vib != null) {
+ vib.vibrate(25);
+ }
+ }
+ }
+}
diff --git a/core/java/com/android/internal/util/carbon/LockScreenHelpers.java b/core/java/com/android/internal/util/carbon/LockScreenHelpers.java
new file mode 100755
index 00000000000..6b8e446a30e
--- /dev/null
+++ b/core/java/com/android/internal/util/carbon/LockScreenHelpers.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2013 Android Open Kang 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.internal.util.carbon;
+
+import android.app.SearchManager;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap.Config;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Xfermode;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.graphics.drawable.InsetDrawable;
+import android.graphics.drawable.StateListDrawable;
+import android.net.Uri;
+import android.media.AudioManager;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.TextUtils;
+
+import static com.android.internal.util.carbon.AwesomeConstants.*;
+import com.android.internal.widget.multiwaveview.GlowPadView;
+import com.android.internal.widget.multiwaveview.TargetDrawable;
+
+import java.io.File;
+import java.net.URISyntaxException;
+
+public class LockScreenHelpers {
+
+ private LockScreenHelpers() {
+ }
+
+ public static TargetDrawable getTargetDrawable(Context context, String action) {
+ int resourceId = -1;
+ final Resources res = context.getResources();
+
+ if (TextUtils.isEmpty(action) || action.equals(AwesomeConstant.ACTION_NULL.value())) {
+ TargetDrawable drawable = new TargetDrawable(res, stateDrawable(res.getDrawable(com.android.internal.R.drawable.ic_empty), context));
+ drawable.setEnabled(false);
+ return drawable;
+ }
+
+ AwesomeConstant IconEnum = fromString(action);
+ switch (IconEnum) {
+ case ACTION_UNLOCK:
+ resourceId = com.android.internal.R.drawable.ic_lockscreen_unlock;
+ break;
+ case ACTION_ASSIST:
+ resourceId = com.android.internal.R.drawable.ic_action_assist_generic;
+ break;
+ case ACTION_CAMERA:
+ resourceId = com.android.internal.R.drawable.ic_lockscreen_camera;
+ break;
+ case ACTION_APP:
+ // no pre-defined action, try to resolve URI
+ try {
+ Intent intent = Intent.parseUri(action, 0);
+ PackageManager pm = context.getPackageManager();
+ ActivityInfo info = intent.resolveActivityInfo(pm, PackageManager.GET_ACTIVITIES);
+ if (info == null) {
+ TargetDrawable drawable = new TargetDrawable(res, stateDrawable(res.getDrawable(com.android.internal.R.drawable.ic_empty), context));
+ drawable.setEnabled(false);
+ return drawable;
+ }
+ Drawable front = info.loadIcon(pm);
+ return new TargetDrawable(res, stateDrawable(front, context));
+ } catch (URISyntaxException e) {
+ resourceId = com.android.internal.R.drawable.ic_empty;
+ }
+ break;
+ }
+ TargetDrawable drawable = new TargetDrawable(res, resourceId);
+ if (resourceId == com.android.internal.R.drawable.ic_empty) {
+ drawable.setEnabled(false);
+ }
+ return drawable;
+ }
+
+ public static StateListDrawable stateDrawable(Drawable front, Context context) {
+ final Resources res = context.getResources();
+ Drawable iconBg = res.getDrawable(
+ com.android.internal.R.drawable.ic_navbar_blank_activated);
+ int inset = (int)(iconBg.getIntrinsicHeight() / 3);
+ final Drawable blankActiveDrawable = res.getDrawable(
+ com.android.internal.R.drawable.ic_lockscreen_target_activated);
+ final InsetDrawable activeBack = new InsetDrawable(blankActiveDrawable, 0, 0, 0, 0);
+ Drawable back = activeBack;
+ InsetDrawable[] inactivelayer = new InsetDrawable[2];
+ InsetDrawable[] activelayer = new InsetDrawable[2];
+ inactivelayer[0] = new InsetDrawable(
+ res.getDrawable(com.android.internal.R.drawable.ic_lockscreen_lock_pressed), 0, 0,0, 0);
+ inactivelayer[1] = new InsetDrawable(front, inset, inset, inset, inset);
+ activelayer[0] = new InsetDrawable(back, 0, 0, 0, 0);
+ activelayer[1] = new InsetDrawable(front, inset, inset, inset, inset);
+ StateListDrawable states = new StateListDrawable();
+ LayerDrawable inactiveLayerDrawable = new LayerDrawable(inactivelayer);
+ inactiveLayerDrawable.setId(0, 0);
+ inactiveLayerDrawable.setId(1, 1);
+ LayerDrawable activeLayerDrawable = new LayerDrawable(activelayer);
+ activeLayerDrawable.setId(0, 0);
+ activeLayerDrawable.setId(1, 1);
+ states.addState(TargetDrawable.STATE_INACTIVE, inactiveLayerDrawable);
+ states.addState(TargetDrawable.STATE_ACTIVE, activeLayerDrawable);
+ states.addState(TargetDrawable.STATE_FOCUSED, activeLayerDrawable);
+ return states;
+ }
+
+ public static TargetDrawable getCustomDrawable(Context context, String action) {
+ final Resources res = context.getResources();
+
+ File f = new File(Uri.parse(action).getPath());
+ Drawable front = new BitmapDrawable(res,
+ getRoundedCornerBitmap(BitmapFactory.decodeFile(f.getAbsolutePath())));
+ final Drawable blankActiveDrawable = res.getDrawable(
+ com.android.internal.R.drawable.ic_lockscreen_target_activated);
+ final InsetDrawable activeBack = new InsetDrawable(blankActiveDrawable, 0, 0, 0, 0);
+ Drawable back = activeBack;
+ Drawable iconBg = res.getDrawable(
+ com.android.internal.R.drawable.ic_navbar_blank_activated);
+ int inset = (int)(iconBg.getIntrinsicHeight() / 3);
+ InsetDrawable[] inactivelayer = new InsetDrawable[2];
+ InsetDrawable[] activelayer = new InsetDrawable[2];
+ inactivelayer[0] = new InsetDrawable(
+ res.getDrawable(com.android.internal.R.drawable.ic_lockscreen_lock_pressed), 0, 0,0, 0);
+ inactivelayer[1] = new InsetDrawable(front, inset, inset, inset, inset);
+ activelayer[0] = new InsetDrawable(back, 0, 0, 0, 0);
+ activelayer[1] = new InsetDrawable(front, inset, inset, inset, inset);
+ StateListDrawable states = new StateListDrawable();
+ LayerDrawable inactiveLayerDrawable = new LayerDrawable(inactivelayer);
+ inactiveLayerDrawable.setId(0, 0);
+ inactiveLayerDrawable.setId(1, 1);
+ LayerDrawable activeLayerDrawable = new LayerDrawable(activelayer);
+ activeLayerDrawable.setId(0, 0);
+ activeLayerDrawable.setId(1, 1);
+ states.addState(TargetDrawable.STATE_INACTIVE, inactiveLayerDrawable);
+ states.addState(TargetDrawable.STATE_ACTIVE, activeLayerDrawable);
+ states.addState(TargetDrawable.STATE_FOCUSED, activeLayerDrawable);
+ return new TargetDrawable(res, states);
+ }
+
+ public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
+ Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
+ bitmap.getHeight(), Config.ARGB_8888);
+ Canvas canvas = new Canvas(output);
+
+ final int color = 0xff424242;
+ final Paint paint = new Paint();
+ final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
+ final RectF rectF = new RectF(rect);
+ final float roundPx = 24;
+ paint.setAntiAlias(true);
+ canvas.drawARGB(0, 0, 0, 0);
+ paint.setColor(color);
+ canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
+ paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
+ canvas.drawBitmap(bitmap, rect, rect, paint);
+ return output;
+ }
+}
diff --git a/core/java/com/android/internal/util/carbon/NavBarHelpers.java b/core/java/com/android/internal/util/carbon/NavBarHelpers.java
new file mode 100755
index 00000000000..ef7d23f419c
--- /dev/null
+++ b/core/java/com/android/internal/util/carbon/NavBarHelpers.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod 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.internal.util.carbon;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+
+import static com.android.internal.util.carbon.AwesomeConstants.*;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class NavBarHelpers {
+
+ // These items will be subtracted from NavBar Actions when RC requests list of
+ // Available Actions
+ private static final AwesomeConstant[] EXCLUDED_FROM_NAVBAR = {
+ AwesomeConstant.ACTION_UNLOCK,
+ AwesomeConstant.ACTION_CAMERA,
+ AwesomeConstant.ACTION_CLOCKOPTIONS,
+ AwesomeConstant.ACTION_SILENT,
+ AwesomeConstant.ACTION_VIB,
+ AwesomeConstant.ACTION_SILENT_VIB,
+ AwesomeConstant.ACTION_EVENT,
+ AwesomeConstant.ACTION_TODAY,
+ AwesomeConstant.ACTION_ALARM
+ };
+
+ private NavBarHelpers() {
+ }
+
+ public static Drawable getIconImage(Context mContext, String uri) {
+ Drawable actionIcon;
+ if (TextUtils.isEmpty(uri)) {
+ uri = AwesomeConstants.AwesomeConstant.ACTION_NULL.value();
+ }
+ if (uri.startsWith("**")) {
+ return AwesomeConstants.getActionIcon(mContext, uri);
+ } else { // This must be an app
+ try {
+ actionIcon = mContext.getPackageManager().getActivityIcon(Intent.parseUri(uri, 0));
+ } catch (NameNotFoundException e) {
+ e.printStackTrace();
+ actionIcon = AwesomeConstants.getActionIcon(mContext,
+ AwesomeConstants.AwesomeConstant.ACTION_NULL.value());
+ } catch (URISyntaxException e) {
+ e.printStackTrace();
+ actionIcon = AwesomeConstants.getActionIcon(mContext,
+ AwesomeConstants.AwesomeConstant.ACTION_NULL.value());
+ }
+ }
+ return actionIcon;
+ }
+
+ public static String[] getNavBarActions() {
+ boolean itemFound;
+ String[] mActions;
+ ArrayList mActionList = new ArrayList();
+ String[] mActionStart = AwesomeConstants.AwesomeActions();
+ int startLength = mActionStart.length;
+ int excludeLength = EXCLUDED_FROM_NAVBAR.length;
+ for (int i = 0; i < startLength; i++) {
+ itemFound = false;
+ for (int j = 0; j < excludeLength; j++) {
+ if (mActionStart[i].equals(EXCLUDED_FROM_NAVBAR[j].value())) {
+ itemFound = true;
+ }
+ }
+ if (!itemFound) {
+ mActionList.add(mActionStart[i]);
+ }
+ }
+ int actionSize = mActionList.size();
+ mActions = new String[actionSize];
+ for (int i = 0; i < actionSize; i++) {
+ mActions[i] = mActionList.get(i);
+ }
+ return mActions;
+ }
+
+ public static String getProperSummary(Context mContext, String uri) {
+ if (TextUtils.isEmpty(uri)) {
+ uri = AwesomeConstants.AwesomeConstant.ACTION_NULL.value();
+ }
+ if (uri.startsWith("**")) {
+ return AwesomeConstants.getProperName(mContext, uri);
+ } else { // This must be an app
+ try {
+ Intent intent = Intent.parseUri(uri, 0);
+ if (Intent.ACTION_MAIN.equals(intent.getAction())) {
+ return getFriendlyActivityName(mContext, intent);
+ }
+ return getFriendlyShortcutName(mContext, intent);
+ } catch (URISyntaxException e) {
+ return AwesomeConstants.getProperName(mContext, AwesomeConstants.AwesomeConstant.ACTION_NULL.value());
+ }
+ }
+ }
+
+ private static String getFriendlyActivityName(Context mContext, Intent intent) {
+ PackageManager pm = mContext.getPackageManager();
+ ActivityInfo ai = intent.resolveActivityInfo(pm, PackageManager.GET_ACTIVITIES);
+ String friendlyName = null;
+
+ if (ai != null) {
+ friendlyName = ai.loadLabel(pm).toString();
+ if (friendlyName == null) {
+ friendlyName = ai.name;
+ }
+ }
+
+ return (friendlyName != null) ? friendlyName : intent.toUri(0);
+ }
+
+ private static String getFriendlyShortcutName(Context mContext, Intent intent) {
+ String activityName = getFriendlyActivityName(mContext, intent);
+ String name = intent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
+
+ if (activityName != null && name != null) {
+ return activityName + ": " + name;
+ }
+ return name != null ? name : intent.toUri(0);
+ }
+}
diff --git a/core/java/com/android/internal/util/carbon/NavRingHelpers.java b/core/java/com/android/internal/util/carbon/NavRingHelpers.java
new file mode 100755
index 00000000000..aa7c5163d23
--- /dev/null
+++ b/core/java/com/android/internal/util/carbon/NavRingHelpers.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod 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.internal.util.carbon;
+
+import android.app.SearchManager;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap.Config;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Xfermode;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.graphics.drawable.StateListDrawable;
+import android.net.Uri;
+import android.media.AudioManager;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.WindowManager;
+
+import static com.android.internal.util.carbon.AwesomeConstants.*;
+import com.android.internal.widget.multiwaveview.GlowPadView;
+import com.android.internal.widget.multiwaveview.TargetDrawable;
+
+import java.io.File;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class NavRingHelpers {
+
+ // These items will be subtracted from NavRing Actions when RC requests list of
+ // Available Actions
+ private static final AwesomeConstant[] EXCLUDED_FROM_NAVRING = {
+ AwesomeConstant.ACTION_UNLOCK,
+ AwesomeConstant.ACTION_CAMERA,
+ AwesomeConstant.ACTION_CLOCKOPTIONS,
+ AwesomeConstant.ACTION_EVENT,
+ AwesomeConstant.ACTION_TODAY,
+ AwesomeConstant.ACTION_ALARM
+ };
+
+ private NavRingHelpers() {
+ }
+
+ public static String[] getNavRingActions() {
+ boolean itemFound;
+ String[] mActions;
+ ArrayList mActionList = new ArrayList();
+ String[] mActionStart = AwesomeConstants.AwesomeActions();
+ int startLength = mActionStart.length;
+ int excludeLength = EXCLUDED_FROM_NAVRING.length;
+ for (int i = 0; i < startLength; i++) {
+ itemFound = false;
+ for (int j = 0; j < excludeLength; j++) {
+ if (mActionStart[i].equals(EXCLUDED_FROM_NAVRING[j].value())) {
+ itemFound = true;
+ }
+ }
+ if (!itemFound) {
+ mActionList.add(mActionStart[i]);
+ }
+ }
+ int actionSize = mActionList.size();
+ mActions = new String[actionSize];
+ for (int i = 0; i < actionSize; i++) {
+ mActions[i] = mActionList.get(i);
+ }
+ return mActions;
+ }
+
+ public static TargetDrawable getTargetDrawable(Context context, String action) {
+ int resourceId = -1;
+ final Resources res = context.getResources();
+ Drawable activityIcon;
+ DisplayMetrics metrics = new DisplayMetrics();
+ WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ wm.getDefaultDisplay().getMetrics(metrics);
+
+ if (TextUtils.isEmpty(action)) {
+ TargetDrawable drawable = new TargetDrawable(res,
+ com.android.internal.R.drawable.ic_action_empty);
+ drawable.setEnabled(false);
+ return drawable;
+ }
+
+ AwesomeConstant IconEnum = fromString(action);
+ if (IconEnum.equals(AwesomeConstant.ACTION_NULL)) {
+ TargetDrawable drawable = new TargetDrawable(res,
+ com.android.internal.R.drawable.ic_action_empty);
+ drawable.setEnabled(false);
+ return drawable;
+ } else if (IconEnum.equals(AwesomeConstant.ACTION_ASSIST)) {
+ TargetDrawable drawable = new TargetDrawable(res,
+ com.android.internal.R.drawable.ic_action_assist_generic);
+ return drawable;
+ } else if (IconEnum.equals(AwesomeConstant.ACTION_APP)) {
+ // no pre-defined action, try to resolve URI
+ try {
+ Intent intent = Intent.parseUri(action, 0);
+ PackageManager pm = context.getPackageManager();
+ ActivityInfo info = intent.resolveActivityInfo(pm, PackageManager.GET_ACTIVITIES);
+
+ if (info == null) {
+ TargetDrawable drawable = new TargetDrawable(res,
+ com.android.internal.R.drawable.ic_action_empty);
+ drawable.setEnabled(false);
+ return drawable;
+ }
+
+ activityIcon = info.loadIcon(pm);
+
+ int desiredSize = (int) (48 * metrics.density);
+ int width = activityIcon.getIntrinsicWidth();
+
+ if (width > desiredSize)
+ {
+ Bitmap bm = ((BitmapDrawable) activityIcon).getBitmap();
+ if (bm != null) {
+ Bitmap bitmapOrig = Bitmap.createScaledBitmap(bm, desiredSize, desiredSize,
+ false);
+ activityIcon = new BitmapDrawable(res, bitmapOrig);
+ }
+ }
+
+ } catch (URISyntaxException e) {
+ TargetDrawable drawable = new TargetDrawable(res,
+ com.android.internal.R.drawable.ic_action_empty);
+ drawable.setEnabled(false);
+ return drawable;
+ }
+ } else {
+ activityIcon = AwesomeConstants.getActionIcon(context, action);
+ }
+
+ Drawable iconBg = res.getDrawable(com.android.internal.R.drawable.ic_navbar_blank);
+ Drawable iconBgActivated = res
+ .getDrawable(com.android.internal.R.drawable.ic_navbar_blank_activated);
+ int margin = (int) (iconBg.getIntrinsicHeight() / 3);
+ LayerDrawable icon = new LayerDrawable(new Drawable[] {
+ iconBg, activityIcon
+ });
+ LayerDrawable iconActivated = new LayerDrawable(new Drawable[] {
+ iconBgActivated, activityIcon
+ });
+
+ icon.setLayerInset(1, margin, margin, margin, margin);
+ iconActivated.setLayerInset(1, margin, margin, margin, margin);
+
+ StateListDrawable selector = new StateListDrawable();
+ selector.addState(new int[] {
+ android.R.attr.state_enabled,
+ -android.R.attr.state_active,
+ -android.R.attr.state_focused
+ }, icon);
+ selector.addState(new int[] {
+ android.R.attr.state_enabled,
+ android.R.attr.state_active,
+ -android.R.attr.state_focused
+ }, iconActivated);
+ selector.addState(new int[] {
+ android.R.attr.state_enabled,
+ -android.R.attr.state_active,
+ android.R.attr.state_focused
+ }, iconActivated);
+ return new TargetDrawable(res, selector);
+ }
+
+ public static TargetDrawable getCustomDrawable(Context context, String action) {
+ final Resources res = context.getResources();
+
+ File f = new File(Uri.parse(action).getPath());
+ Drawable activityIcon = new BitmapDrawable(res,
+ getRoundedCornerBitmap(BitmapFactory.decodeFile(f.getAbsolutePath())));
+
+ Drawable iconBg = res.getDrawable(
+ com.android.internal.R.drawable.ic_navbar_blank);
+ Drawable iconBgActivated = res.getDrawable(
+ com.android.internal.R.drawable.ic_navbar_blank_activated);
+
+ int margin = (int) (iconBg.getIntrinsicHeight() / 3);
+ LayerDrawable icon = new LayerDrawable(new Drawable[] {
+ iconBg, activityIcon
+ });
+ LayerDrawable iconActivated = new LayerDrawable(new Drawable[] {
+ iconBgActivated, activityIcon
+ });
+
+ icon.setLayerInset(1, margin, margin, margin, margin);
+ iconActivated.setLayerInset(1, margin, margin, margin, margin);
+
+ StateListDrawable selector = new StateListDrawable();
+ selector.addState(new int[] {
+ android.R.attr.state_enabled,
+ -android.R.attr.state_active,
+ -android.R.attr.state_focused
+ }, icon);
+ selector.addState(new int[] {
+ android.R.attr.state_enabled,
+ android.R.attr.state_active,
+ -android.R.attr.state_focused
+ }, iconActivated);
+ selector.addState(new int[] {
+ android.R.attr.state_enabled,
+ -android.R.attr.state_active,
+ android.R.attr.state_focused
+ }, iconActivated);
+ return new TargetDrawable(res, selector);
+ }
+
+ public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
+ Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
+ bitmap.getHeight(), Config.ARGB_8888);
+ Canvas canvas = new Canvas(output);
+
+ final int color = 0xff424242;
+ final Paint paint = new Paint();
+ final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
+ final RectF rectF = new RectF(rect);
+ final float roundPx = 24;
+ paint.setAntiAlias(true);
+ canvas.drawARGB(0, 0, 0, 0);
+ paint.setColor(color);
+ canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
+ paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
+ canvas.drawBitmap(bitmap, rect, rect, paint);
+ return output;
+ }
+}
diff --git a/core/java/com/android/internal/util/carbon/RibbonTarget.java b/core/java/com/android/internal/util/carbon/RibbonTarget.java
new file mode 100644
index 00000000000..21cc5a15a46
--- /dev/null
+++ b/core/java/com/android/internal/util/carbon/RibbonTarget.java
@@ -0,0 +1,369 @@
+/*
+ * Copyright (C) 2013 The Android Open Kang 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.internal.util.carbon;
+
+import android.app.ActivityManagerNative;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap.Config;
+import android.graphics.BlurMaskFilter;
+import android.graphics.BlurMaskFilter.Blur;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Xfermode;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.os.Vibrator;
+import android.provider.Settings;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.IWindowManager;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnLongClickListener;
+import android.widget.ImageView;
+import android.widget.Button;
+import android.widget.TextView;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.WindowManager;
+import android.widget.LinearLayout;
+
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.R;
+
+import java.io.File;
+
+public class RibbonTarget {
+
+ private static final String TAG = "Ribbon Target";
+
+ private View mView;
+ private LinearLayout mContainer;
+ private Context mContext;
+ private IWindowManager mWm;
+ private ImageView mIcon;
+ private Drawable mIconBase;
+ private Drawable mIconGlow;
+ private Button mBackground;
+ private TextView mText;
+ private Vibrator vib;
+ private Intent u;
+ private Intent b;
+ private Intent a;
+ private boolean mDismiss;
+
+
+ /*
+ * sClick = short click send the uri for the short click action also this will be the icon used
+ * lClick = long click send the uri for the long click action
+ * cIcon = custom icon
+ * text = a boolean for weither to show the app text label
+ * color = text color
+ * touchVib = vibrate on touch
+ * size = size used to resize icons 0 is default and will not resize the icons at all.
+ * dismiss = weither or not to dismiss a swipe ribbon, 0 == never, 1 == always, 2 == dont dismiss navbar actions
+ */
+
+ public RibbonTarget(Context context, final String sClick, final String lClick,
+ final String cIcon, final boolean text, final int color, final int size, final boolean touchVib, final boolean colorize, final int dismiss) {
+ mContext = context;
+ u = new Intent();
+ u.setAction("com.android.lockscreen.ACTION_UNLOCK_RECEIVER");
+ b = new Intent();
+ b.setAction("com.android.systemui.ACTION_HIDE_RIBBON");
+ a = new Intent();
+ a.setAction("com.android.systemui.ACTION_HIDE_APP_WINDOW");
+ mWm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
+ DisplayMetrics metrics = new DisplayMetrics();
+ WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+ wm.getDefaultDisplay().getMetrics(metrics);
+ mDismiss = ((dismiss == 1) || ((dismiss == 2) && (sClick.equals("**null**") ? !lClick.startsWith("**") : !sClick.startsWith("**"))));
+ vib = (Vibrator) mContext.getSystemService(mContext.VIBRATOR_SERVICE);
+ mView = View.inflate(mContext, R.layout.target_button, null);
+ mView.setDrawingCacheEnabled(true);
+ mContainer = (LinearLayout) mView.findViewById(R.id.container);
+ mBackground = (Button) mView.findViewById(R.id.background);
+ mBackground.setBackgroundColor(Color.TRANSPARENT);
+ mBackground.setClickable(false);
+ mText = (TextView) mView.findViewById(R.id.label);
+ mText.setDrawingCacheEnabled(true);
+ if (!text) {
+ mText.setVisibility(View.GONE);
+ }
+ mText.setText(NavBarHelpers.getProperSummary(mContext, sClick.equals("**null**") ? lClick : sClick));
+ if (color != -1) {
+ mText.setTextColor(color);
+ }
+ mText.setOnClickListener(new OnClickListener() {
+ @Override
+ public final void onClick(View v) {
+ if(vib != null && touchVib) {
+ vib.vibrate(10);
+ }
+ collapseStatusBar();
+ sendIt(sClick.equals("**null**") ? lClick : sClick);
+ }
+ });
+ if (!lClick.equals("**null**")) {
+ mText.setOnLongClickListener(new OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ collapseStatusBar();
+ sendIt(lClick);
+ return true;
+ }
+ });
+ }
+ mText.setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ int action = event.getAction();
+ switch (action) {
+ case MotionEvent.ACTION_DOWN :
+ mIcon.setImageDrawable(mIconGlow);
+ break;
+ case MotionEvent.ACTION_CANCEL :
+ case MotionEvent.ACTION_UP:
+ mIcon.setImageDrawable(mIconBase);
+ break;
+ }
+ return false;
+ }
+ });
+ mIcon = (ImageView) mView.findViewById(R.id.icon);
+ mIcon.setDrawingCacheEnabled(true);
+ mIconBase = NavBarHelpers.getIconImage(mContext, "**null**");
+ if (!cIcon.equals("**null**")) {
+ if (size > 0) {
+ mIconBase = resize(getCustomDrawable(mContext, cIcon), mapChosenDpToPixels(size));
+ } else {
+ mIconBase = getCustomDrawable(mContext, cIcon);
+ }
+ } else {
+ if (size > 0) {
+ mIconBase = resize(NavBarHelpers.getIconImage(mContext, sClick.equals("**null**") ? lClick : sClick), mapChosenDpToPixels(size));
+ } else {
+ mIconBase = NavBarHelpers.getIconImage(mContext, sClick.equals("**null**") ? lClick : sClick);
+ int desiredSize = (int) (48 * metrics.density);
+ int width = mIconBase.getIntrinsicWidth();
+ if (width > desiredSize) {
+ Bitmap bm = ((BitmapDrawable) mIconBase).getBitmap();
+ if (bm != null) {
+ Bitmap bitmapOrig = Bitmap.createScaledBitmap(bm, desiredSize, desiredSize, true);
+ mIconBase = new BitmapDrawable(mContext.getResources(), bitmapOrig);
+ }
+ }
+ }
+ }
+ if ((sClick.equals("**null**") ? lClick.startsWith("**") : sClick.startsWith("**")) && colorize) {
+ mIcon.setColorFilter(color);
+ }
+ mIconGlow = getGlowDrawable(mContext, mIconBase, (color != -1) ? color : Color.CYAN);
+ mIcon.setImageDrawable(mIconBase);
+ if (!sClick.equals("**null**")) {
+ mIcon.setOnClickListener(new OnClickListener() {
+ @Override
+ public final void onClick(View v) {
+ if(vib != null && touchVib) {
+ vib.vibrate(10);
+ }
+ collapseStatusBar();
+ sendIt(sClick);
+ }
+ });
+ }
+ if (!lClick.equals("**null**")) {
+ mIcon.setOnLongClickListener(new OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ collapseStatusBar();
+ sendIt(lClick);
+ return true;
+ }
+ });
+ }
+ mIcon.setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ int action = event.getAction();
+ switch (action) {
+ case MotionEvent.ACTION_DOWN :
+ mIcon.setImageDrawable(mIconGlow);
+ break;
+ case MotionEvent.ACTION_CANCEL :
+ case MotionEvent.ACTION_UP:
+ mIcon.setImageDrawable(mIconBase);
+ break;
+ }
+ return false;
+ }
+ });
+ }
+
+ private Drawable resize(Drawable image, int size) {
+ int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, size,
+ mContext.getResources().getDisplayMetrics());
+
+ Bitmap d = ((BitmapDrawable) image).getBitmap();
+ if (d == null) {
+ return AwesomeConstants.getSystemUIDrawable(mContext, "**null**");
+ } else {
+ Bitmap bitmapOrig = Bitmap.createScaledBitmap(d, px, px, true);
+ return new BitmapDrawable(mContext.getResources(), bitmapOrig);
+ }
+ }
+
+ private void sendIt(String action) {
+ mContext.sendBroadcastAsUser(a, UserHandle.ALL);
+ if (shouldUnlock(action)) {
+ mContext.sendBroadcastAsUser(u, UserHandle.ALL);
+ }
+ Intent i = new Intent();
+ i.setAction("com.android.systemui.carbon.LAUNCH_ACTION");
+ i.putExtra("action", action);
+ mContext.sendBroadcastAsUser(i, UserHandle.ALL);
+ if (mDismiss) {
+ mContext.sendBroadcastAsUser(b, UserHandle.ALL);
+ }
+ }
+
+ private boolean shouldUnlock(String action) {
+ if (action.equals(AwesomeConstants.AwesomeConstant.ACTION_TORCH.value()) ||
+ action.equals(AwesomeConstants.AwesomeConstant.ACTION_NOTIFICATIONS.value()) ||
+ action.equals(AwesomeConstants.AwesomeConstant.ACTION_QUICKSETTINGS.value()) ||
+ action.equals(AwesomeConstants.AwesomeConstant.ACTION_POWER.value())) {
+ return false;
+ }
+
+ return true;
+ }
+
+ private int mapChosenDpToPixels(int dp) {
+ switch (dp) {
+ case 0:
+ return 0;
+ case 20:
+ return mContext.getResources().getDimensionPixelSize(R.dimen.icon_size_20);
+ case 15:
+ return mContext.getResources().getDimensionPixelSize(R.dimen.icon_size_15);
+ }
+ return -1;
+ }
+
+ private void collapseStatusBar() {
+ try {
+ IStatusBarService sb = IStatusBarService.Stub
+ .asInterface(ServiceManager
+ .getService(Context.STATUS_BAR_SERVICE));
+ sb.collapsePanels();
+ } catch (RemoteException e) {
+ }
+ }
+
+ public View getView() {
+ return mView;
+ }
+
+ public void setVerticalPadding(int pad, int side) {
+ mContainer.setPadding(side, 0, side, pad);
+ }
+
+ public void setPadding(int pad, int top) {
+ mContainer.setPadding(pad, top, pad, top);
+ }
+
+ private static Drawable getCustomDrawable(Context context, String action) {
+ final Resources res = context.getResources();
+
+ File f = new File(Uri.parse(action).getPath());
+ Drawable front = new BitmapDrawable(res,
+ getRoundedCornerBitmap(BitmapFactory.decodeFile(f.getAbsolutePath())));
+ return front;
+ }
+
+ private static Drawable getGlowDrawable(Context context, Drawable icon, int color) {
+
+ // the glow radius
+ int glowRadius = 10;
+
+ // the glow color
+ int glowColor = color;
+
+ // The original image to use
+ Bitmap src = ((BitmapDrawable) icon).getBitmap();
+
+ // extract the alpha from the source image
+ Bitmap alpha = src.extractAlpha();
+
+ // The output bitmap (same size as icon)
+ Bitmap bmp = Bitmap.createBitmap(src.getWidth(),
+ src.getHeight(), Bitmap.Config.ARGB_8888);
+
+ // The canvas to paint on the image
+ Canvas canvas = new Canvas(bmp);
+
+ Paint paint = new Paint();
+ paint.setColor(glowColor);
+
+ // outer glow
+ paint.setMaskFilter(new BlurMaskFilter(glowRadius, Blur.OUTER));
+ canvas.drawBitmap(alpha, 0, 0, paint);
+
+ // original icon
+ canvas.drawBitmap(src, 0, 0, null);
+ Drawable d = new BitmapDrawable(context.getResources(), bmp);
+ return d;
+ }
+
+
+ private static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
+ Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
+ bitmap.getHeight(), Config.ARGB_8888);
+ Canvas canvas = new Canvas(output);
+
+ final int color = 0xff424242;
+ final Paint paint = new Paint();
+ final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
+ final RectF rectF = new RectF(rect);
+ final float roundPx = 24;
+ paint.setAntiAlias(true);
+ canvas.drawARGB(0, 0, 0, 0);
+ paint.setColor(color);
+ canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
+ paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
+ canvas.drawBitmap(bitmap, rect, rect, paint);
+ return output;
+ }
+}
diff --git a/core/java/com/android/internal/util/carbon/SysHelpers.java b/core/java/com/android/internal/util/carbon/SysHelpers.java
new file mode 100644
index 00000000000..c6502cac1d0
--- /dev/null
+++ b/core/java/com/android/internal/util/carbon/SysHelpers.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2013 AOKP
+ *
+ * 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.internal.util.carbon;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.InputStream;
+
+import android.util.Log;
+
+public class SysHelpers {
+
+ private static final String TAG = "System UI Helper";
+ private Boolean can_su;
+ public SH sh;
+ public SH su;
+
+ public SysHelpers() {
+ sh = new SH("sh");
+ su = new SH("su");
+ }
+
+ public SH suOrSH() {
+ return canSU() ? su : sh;
+ }
+
+ public boolean canSU() {
+ return canSU(false);
+ }
+
+ public class CommandResult {
+ public final String stdout;
+ public final String stderr;
+ public final Integer exit_value;
+
+ CommandResult(final Integer exit_value_in) {
+ this(exit_value_in, null, null);
+ }
+
+ CommandResult(final Integer exit_value_in, final String stdout_in,
+ final String stderr_in) {
+ exit_value = exit_value_in;
+ stdout = stdout_in;
+ stderr = stderr_in;
+ }
+
+ public boolean success() {
+ return exit_value != null && exit_value == 0;
+ }
+ }
+
+ public class SH {
+ private String SHELL = "sh";
+
+ public SH(final String SHELL_in) {
+ SHELL = SHELL_in;
+ }
+
+ private String getStreamLines(final InputStream is) {
+ String out = null;
+ StringBuffer buffer = null;
+ final DataInputStream dis = new DataInputStream(is);
+
+ try {
+ if (dis.available() > 0) {
+ buffer = new StringBuffer(dis.readLine());
+ while (dis.available() > 0) {
+ buffer.append("\n").append(dis.readLine());
+ }
+ }
+ dis.close();
+ } catch (final Exception ex) {
+ Log.e(TAG, ex.getMessage());
+ }
+ if (buffer != null) {
+ out = buffer.toString();
+ }
+ return out;
+ }
+
+ public Process run(final String s) {
+ Process process = null;
+ try {
+ process = Runtime.getRuntime().exec(SHELL);
+ final DataOutputStream toProcess = new DataOutputStream(
+ process.getOutputStream());
+ toProcess.writeBytes("exec " + s + "\n");
+ toProcess.flush();
+ } catch (final Exception e) {
+ Log.e(TAG, "Exception while trying to run: '" + s + "' "
+ + e.getMessage());
+ process = null;
+ }
+ return process;
+ }
+
+ public CommandResult runWaitFor(final String s) {
+ final Process process = run(s);
+ Integer exit_value = null;
+ String stdout = null;
+ String stderr = null;
+ if (process != null) {
+ try {
+ exit_value = process.waitFor();
+
+ stdout = getStreamLines(process.getInputStream());
+ stderr = getStreamLines(process.getErrorStream());
+
+ } catch (final InterruptedException e) {
+ Log.e(TAG, "runWaitFor " + e.toString());
+ } catch (final NullPointerException e) {
+ Log.e(TAG, "runWaitFor " + e.toString());
+ }
+ }
+ return new CommandResult(exit_value, stdout, stderr);
+ }
+ }
+
+ public boolean canSU(final boolean force_check) {
+ if (can_su == null || force_check) {
+ final CommandResult r = su.runWaitFor("id");
+ final StringBuilder out = new StringBuilder();
+
+ if (r.stdout != null) {
+ out.append(r.stdout).append(" ; ");
+ }
+ if (r.stderr != null) {
+ out.append(r.stderr);
+ }
+
+ Log.d(TAG, "canSU() su[" + r.exit_value + "]: " + out);
+ can_su = r.success();
+ }
+ return can_su;
+ }
+
+ public static void restartSystemUI() {
+ new SysHelpers().su.run("pkill -TERM -f com.android.systemui");
+ }
+}
diff --git a/core/java/com/android/internal/util/cm/TorchConstants.java b/core/java/com/android/internal/util/cm/TorchConstants.java
new file mode 100644
index 00000000000..eea8eea894a
--- /dev/null
+++ b/core/java/com/android/internal/util/cm/TorchConstants.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod 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.internal.util.cm;
+
+import android.content.Intent;
+
+public class TorchConstants {
+ /**
+ * Package name of the torch app
+ */
+ public static final String APP_PACKAGE_NAME = "net.cactii.flash2";
+
+ /**
+ * Intent broadcast action for toggling the torch state
+ */
+ public static final String ACTION_TOGGLE_STATE = APP_PACKAGE_NAME + ".TOGGLE_FLASHLIGHT";
+
+ /**
+ * Extra for {@link ACTION_TOGGLE_STATE}:
+ * When toggling to on, use the bright brightness setting
+ * Type: boolean
+ */
+ public static final String EXTRA_BRIGHT_MODE = "bright";
+
+ /**
+ * Intent action for 'torch state changed' broadcast
+ */
+ public static final String ACTION_STATE_CHANGED = APP_PACKAGE_NAME + ".TORCH_STATE_CHANGED";
+
+ /**
+ * Extra for {@link ACTION_STATE_CHANGED}:
+ * Current torch state
+ * Type: integer (0/1)
+ */
+ public static final String EXTRA_CURRENT_STATE = "state";
+
+ /**
+ * Intent for launching the torch application
+ */
+ public static Intent INTENT_LAUNCH_APP = new Intent(Intent.ACTION_MAIN)
+ .setClassName(APP_PACKAGE_NAME, APP_PACKAGE_NAME + ".MainActivity");
+}
diff --git a/core/java/com/android/internal/view/RotationPolicy.java b/core/java/com/android/internal/view/RotationPolicy.java
index 95130c8c958..a86c3234f39 100644
--- a/core/java/com/android/internal/view/RotationPolicy.java
+++ b/core/java/com/android/internal/view/RotationPolicy.java
@@ -58,7 +58,9 @@ public static boolean isRotationLockToggleVisible(Context context) {
return isRotationLockToggleSupported(context) &&
Settings.System.getIntForUser(context.getContentResolver(),
Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0,
- UserHandle.USER_CURRENT) == 0;
+ UserHandle.USER_CURRENT) == 0 &&
+ !context.getResources().getBoolean(com.android
+ .internal.R.bool.config_hasRotationLockSwitch);
}
/**
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index 238a9c03379..98f635cd7ff 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
@@ -240,7 +240,7 @@ public boolean onLongClick(View v) {
Toast cheatSheet = Toast.makeText(context, mItemData.getTitle(), Toast.LENGTH_SHORT);
if (midy < displayFrame.height()) {
// Show along the top; follow action buttons
- cheatSheet.setGravity(Gravity.TOP | Gravity.END,
+ cheatSheet.setGravity(Gravity.TOP | Gravity.RIGHT,
screenWidth - screenPos[0] - width / 2, height);
} else {
// Show along the bottom center
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index 4bb6d0694b3..0267db3bf34 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -34,6 +34,8 @@
import android.widget.ImageButton;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
/**
* MenuPresenter for building action menus as seen in the action bar and action modes.
@@ -351,7 +353,27 @@ public boolean isOverflowReserved() {
}
public boolean flagActionItems() {
- final ArrayList visibleItems = mMenu.getVisibleItems();
+ // Items must be sorted always in base to his showAsAction type
+ // always -> ifRoom -> Others
+ // Create an internal sorted array based in this priority (items must keep
+ // his original order)
+ final ArrayList visibleItems =
+ new ArrayList(mMenu.getVisibleItems());
+ Collections.sort(visibleItems, new Comparator() {
+ @Override
+ public int compare(MenuItemImpl lhs, MenuItemImpl rhs) {
+ boolean lhsRequires = lhs.requiresActionButton();
+ boolean lhsRequest = lhs.requestsActionButton();
+ boolean rhsRequires = rhs.requiresActionButton();
+ boolean rhsRequest = rhs.requestsActionButton();
+ if (lhsRequires && rhsRequires) return 0;
+ if (lhsRequires) return -1;
+ if (rhsRequires) return 1;
+ if (lhsRequest && rhsRequest) return 0;
+ if (lhsRequest) return -1;
+ return 1;
+ }
+ });
final int itemsSize = visibleItems.size();
int maxActions = mMaxItems;
int widthLimit = mActionItemWidthLimit;
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 0f964b9a280..856a8eed6af 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -903,19 +903,8 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
mIsCollapsed = false;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- if (widthMode != MeasureSpec.EXACTLY) {
- throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
- "with android:layout_width=\"match_parent\" (or fill_parent)");
- }
-
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- if (heightMode != MeasureSpec.AT_MOST) {
- throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
- "with android:layout_height=\"wrap_content\"");
- }
-
int contentWidth = MeasureSpec.getSize(widthMeasureSpec);
-
int maxHeight = mContentHeight >= 0 ?
mContentHeight : MeasureSpec.getSize(heightMeasureSpec);
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index c72c7709741..f2fdde3a3f4 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -16,6 +16,8 @@
package com.android.internal.widget;
+import android.gesture.Gesture;
+
/** {@hide} */
interface ILockSettings {
void setBoolean(in String key, in boolean value, in int userId);
@@ -24,11 +26,15 @@ interface ILockSettings {
boolean getBoolean(in String key, in boolean defaultValue, in int userId);
long getLong(in String key, in long defaultValue, in int userId);
String getString(in String key, in String defaultValue, in int userId);
+ byte getLockPatternSize(int userId);
void setLockPattern(in byte[] hash, int userId);
boolean checkPattern(in byte[] hash, int userId);
+ void setLockGesture(in Gesture gesture, int userId);
+ boolean checkGesture(in Gesture gesture, int userId);
void setLockPassword(in byte[] hash, int userId);
boolean checkPassword(in byte[] hash, int userId);
boolean havePattern(int userId);
+ boolean haveGesture(int userId);
boolean havePassword(int userId);
void removeUser(int userId);
}
diff --git a/core/java/com/android/internal/widget/LockGestureView.java b/core/java/com/android/internal/widget/LockGestureView.java
new file mode 100644
index 00000000000..8e0895e3c58
--- /dev/null
+++ b/core/java/com/android/internal/widget/LockGestureView.java
@@ -0,0 +1,176 @@
+package com.android.internal.widget;
+
+import android.content.Context;
+import android.gesture.Gesture;
+import android.gesture.GestureOverlayView;
+import android.graphics.Color;
+import android.util.AttributeSet;
+
+public class LockGestureView extends GestureOverlayView implements GestureOverlayView.OnGesturingListener,
+ GestureOverlayView.OnGesturePerformedListener {
+ private static final int CORRECT_COLOR = Color.GREEN;
+ private static final int WRONG_COLOR = Color.RED;
+
+ private DisplayMode mGestureDisplayMode = DisplayMode.Correct;
+ private boolean mInStealthMode = false;
+
+ private OnLockGestureListener mOnGestureListener;
+
+ @Override
+ public void onGesturePerformed(GestureOverlayView gestureOverlayView, Gesture gesture) {
+ notifyGestureDetected(gesture);
+ }
+
+ @Override
+ public void onGesturingStarted(GestureOverlayView gestureOverlayView) {
+ notifyGestureStart();
+ }
+
+ @Override
+ public void onGesturingEnded(GestureOverlayView gestureOverlayView) {
+ }
+
+ /**
+ * The call back interface for detecting gestures entered by the user.
+ */
+ public static interface OnLockGestureListener {
+
+ /**
+ * A new gesture has begun.
+ */
+ void onGestureStart();
+
+ /**
+ * The gesture was cleared.
+ */
+ void onGestureCleared();
+
+ /**
+ * A gesture was detected from the user.
+ * @param gesture The gesture.
+ */
+ void onGestureDetected(Gesture gesture);
+ }
+
+ /**
+ * How to display the current pattern.
+ */
+ public enum DisplayMode {
+
+ /**
+ * The pattern drawn is correct (i.e draw it in a friendly color)
+ */
+ Correct,
+
+ /**
+ * The pattern is wrong (i.e draw a foreboding color)
+ */
+ Wrong
+ }
+
+ public LockGestureView(Context context) {
+ this(context, null);
+ }
+
+ public LockGestureView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setGestureVisible(true);
+ addOnGesturingListener(this);
+ addOnGesturePerformedListener(this);
+ setGestureColor(CORRECT_COLOR);
+ mClearPerformedGesture = false;
+ }
+
+ /**
+ * @return Whether the view is in stealth mode.
+ */
+ public boolean isInStealthMode() {
+ return mInStealthMode;
+ }
+
+ /**
+ * Set whether the view is in stealth mode. If true, there will be no
+ * visible feedback as the user enters the gesture.
+ *
+ * @param inStealthMode Whether in stealth mode.
+ */
+ public void setInStealthMode(boolean inStealthMode) {
+ mInStealthMode = inStealthMode;
+ setGestureVisible(!inStealthMode);
+ }
+
+ /**
+ * Set the display mode of the current pattern. This can be useful, for
+ * instance, after detecting a pattern to tell this view whether change the
+ * in progress result to correct or wrong.
+ * @param displayMode The display mode.
+ */
+ public void setDisplayMode(DisplayMode displayMode) {
+ mGestureDisplayMode = displayMode;
+ switch (displayMode) {
+ case Correct:
+ setGestureColor(CORRECT_COLOR);
+ break;
+ case Wrong:
+ setGestureColor(WRONG_COLOR);
+ break;
+ }
+
+ invalidate();
+ }
+
+ /**
+ * Disable input (for instance when displaying a message that will
+ * timeout so user doesn't get view into messy state).
+ */
+ public void disableInput() {
+ mInputEnabled = false;
+ }
+
+ /**
+ * Enable input.
+ */
+ public void enableInput() {
+ mInputEnabled = true;
+ }
+
+ /**
+ * Clear the gesture.
+ */
+ public void clearGesture() {
+ resetGesture();
+ }
+
+ /**
+ * Reset all pattern state.
+ */
+ private void resetGesture() {
+ mGestureDisplayMode = DisplayMode.Correct;
+ clear(false);
+ invalidate();
+ }
+
+ /**
+ * Set the call back for gesture detection.
+ * @param onGestureListener The call back.
+ */
+ public void setOnGestureListener(
+ OnLockGestureListener onGestureListener) {
+ mOnGestureListener = onGestureListener;
+ }
+
+ private void notifyGestureStart() {
+ if (mOnGestureListener != null)
+ mOnGestureListener.onGestureStart();
+ }
+
+ private void notifyGestureCleared() {
+ if (mOnGestureListener != null)
+ mOnGestureListener.onGestureCleared();
+ }
+
+ private void notifyGestureDetected(Gesture gesture) {
+ if (mOnGestureListener != null)
+ mOnGestureListener.onGestureDetected(gesture);
+ }
+}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 907b52aa7ef..95cddf8ebf2 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2012 The CyanogenMod Project (Calendar)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,12 +18,17 @@
package com.android.internal.widget;
import android.app.ActivityManagerNative;
+import android.app.Profile;
+import android.app.ProfileManager;
import android.app.admin.DevicePolicyManager;
import android.appwidget.AppWidgetManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.gesture.Gesture;
+import android.database.Cursor;
+import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -30,10 +36,13 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.storage.IMountService;
+import android.provider.CalendarContract;
import android.provider.Settings;
import android.security.KeyStore;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import android.text.format.DateFormat;
+import android.text.format.Time;
import android.util.Log;
import android.view.IWindowManager;
import android.view.View;
@@ -46,7 +55,10 @@
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
+import java.text.SimpleDateFormat;
+import java.util.Date;
import java.util.List;
+import java.util.TimeZone;
/**
* Utilities for the lock pattern and its settings.
@@ -90,6 +102,11 @@ public class LockPatternUtils {
*/
public static final int MIN_LOCK_PATTERN_SIZE = 4;
+ /**
+ * The default size of the pattern lockscreen. Ex: 3x3
+ */
+ public static final byte PATTERN_SIZE_DEFAULT = 3;
+
/**
* The minimum number of dots the user must include in a wrong pattern
* attempt for it to be counted against the counts that affect
@@ -126,6 +143,7 @@ public class LockPatternUtils {
protected final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently";
protected final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline";
protected final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen";
+ protected final static String GESTURE_EVER_CHOSEN_KEY = "lockscreen.gestureeverchosen";
public final static String PASSWORD_TYPE_KEY = "lockscreen.password_type";
public static final String PASSWORD_TYPE_ALTERNATE_KEY = "lockscreen.password_type_alternate";
protected final static String LOCK_PASSWORD_SALT_KEY = "lockscreen.password_salt";
@@ -144,6 +162,7 @@ public class LockPatternUtils {
private final ContentResolver mContentResolver;
private DevicePolicyManager mDevicePolicyManager;
private ILockSettings mLockSettingsService;
+ private ProfileManager mProfileManager;
// The current user is set by KeyguardViewMediator and shared by all LockPatternUtils.
private static volatile int sCurrentUserId = UserHandle.USER_NULL;
@@ -166,6 +185,7 @@ public DevicePolicyManager getDevicePolicyManager() {
public LockPatternUtils(Context context) {
mContext = context;
mContentResolver = context.getContentResolver();
+ mProfileManager = (ProfileManager) context.getSystemService(Context.PROFILE_SERVICE);
}
private ILockSettings getLockSettings() {
@@ -289,6 +309,24 @@ public boolean checkPattern(List pattern) {
}
}
+ /**
+ * Check to see if a gesture matches the saved gesture. If no gesture exists,
+ * always returns true.
+ * @param gesture The gesture to check.
+ * @return Whether the gesture matches the stored one.
+ */
+ public boolean checkGesture(Gesture gesture) {
+ final int userId = getCurrentOrCallingUserId();
+ try {
+ final boolean matched = getLockSettings().checkGesture(gesture, userId);
+ if (matched && (userId == UserHandle.USER_OWNER)) {
+ }
+ return matched;
+ } catch (RemoteException re) {
+ return true;
+ }
+ }
+
/**
* Check to see if a password matches the saved password. If no password exists,
* always returns true.
@@ -336,6 +374,18 @@ public boolean checkPasswordHistory(String password) {
return passwordHistory.contains(passwordHashString);
}
+ /**
+ * Check to see if the user has stored a lock gesture.
+ * @return Whether a saved gesture exists.
+ */
+ public boolean savedGestureExists() {
+ try {
+ return getLockSettings().haveGesture(getCurrentOrCallingUserId());
+ } catch (RemoteException re) {
+ return false;
+ }
+ }
+
/**
* Check to see if the user has stored a lock pattern.
* @return Whether a saved pattern exists.
@@ -370,6 +420,16 @@ public boolean isPatternEverChosen() {
return getBoolean(PATTERN_EVER_CHOSEN_KEY, false);
}
+ /**
+ * Return true if the user has ever chosen a gesture. This is true even if the gesture is
+ * currently cleared.
+ *
+ * @return True if the user has ever chosen a pattern.
+ */
+ public boolean isGestureEverChosen() {
+ return getBoolean(GESTURE_EVER_CHOSEN_KEY, false);
+ }
+
/**
* Return true if the user has ever chosen biometric weak. This is true even if biometric
* weak is not current set.
@@ -421,6 +481,11 @@ public int getActivePasswordQuality() {
activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
}
break;
+ case DevicePolicyManager.PASSWORD_QUALITY_GESTURE_WEAK:
+ if (isLockGestureEnabled()) {
+ activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_GESTURE_WEAK;
+ }
+ break;
}
return activePasswordQuality;
@@ -434,6 +499,8 @@ public void clearLock(boolean isFallback) {
saveLockPassword(null, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
setLockPatternEnabled(false);
saveLockPattern(null);
+ saveLockGesture(null);
+ setLockGestureEnabled(false);
setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
setLong(PASSWORD_TYPE_ALTERNATE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
}
@@ -493,7 +560,7 @@ public void saveLockPattern(List pattern) {
*/
public void saveLockPattern(List pattern, boolean isFallback) {
// Compute the hash
- final byte[] hash = LockPatternUtils.patternToHash(pattern);
+ final byte[] hash = patternToHash(pattern);
try {
getLockSettings().setLockPattern(hash, getCurrentOrCallingUserId());
DevicePolicyManager dpm = getDevicePolicyManager();
@@ -526,6 +593,51 @@ public void saveLockPattern(List pattern, boolean isFallba
}
}
+ /**
+ * Save a lock pattern.
+ * @param pattern The new pattern to save.
+ */
+ public void saveLockGesture(Gesture gesture) {
+ this.saveLockGesture(gesture, false);
+ }
+
+ /**
+ * Save a lock pattern.
+ * @param pattern The new pattern to save.
+ * @param isFallback Specifies if this is a fallback to biometric weak
+ */
+ public void saveLockGesture(Gesture gesture, boolean isFallback) {
+ try {
+ getLockSettings().setLockGesture(gesture, getCurrentOrCallingUserId());
+ DevicePolicyManager dpm = getDevicePolicyManager();
+ KeyStore keyStore = KeyStore.getInstance();
+ if (gesture != null) {
+ setBoolean(GESTURE_EVER_CHOSEN_KEY, true);
+ if (!isFallback) {
+ deleteGallery();
+ setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_GESTURE_WEAK);
+ dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_GESTURE_WEAK,
+ 0, 0, 0, 0, 0, 0, 0, getCurrentOrCallingUserId());
+ } else {
+ setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK);
+ setLong(PASSWORD_TYPE_ALTERNATE_KEY,
+ DevicePolicyManager.PASSWORD_QUALITY_GESTURE_WEAK);
+ finishBiometricWeak();
+ dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK,
+ 0, 0, 0, 0, 0, 0, 0, getCurrentOrCallingUserId());
+ }
+ } else {
+ if (keyStore.isEmpty()) {
+ keyStore.reset();
+ }
+ dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0,
+ 0, 0, 0, 0, 0, getCurrentOrCallingUserId());
+ }
+ } catch (RemoteException re) {
+ Log.e(TAG, "Couldn't save lock gesture " + re);
+ }
+ }
+
/**
* Compute the password quality from the given password string.
*/
@@ -737,13 +849,16 @@ public boolean usingBiometricWeak() {
* @param string The pattern serialized with {@link #patternToString}
* @return The pattern.
*/
- public static List stringToPattern(String string) {
+ public List stringToPattern(String string) {
List result = Lists.newArrayList();
+ final byte size = getLockPatternSize();
+ LockPatternView.Cell.updateSize(size);
+
final byte[] bytes = string.getBytes();
for (int i = 0; i < bytes.length; i++) {
byte b = bytes[i];
- result.add(LockPatternView.Cell.of(b / 3, b % 3));
+ result.add(LockPatternView.Cell.of(b / size, b % size, size));
}
return result;
}
@@ -753,7 +868,7 @@ public static List stringToPattern(String string) {
* @param pattern The pattern.
* @return The pattern in string form.
*/
- public static String patternToString(List pattern) {
+ public String patternToString(List pattern) {
if (pattern == null) {
return "";
}
@@ -762,7 +877,7 @@ public static String patternToString(List pattern) {
byte[] res = new byte[patternSize];
for (int i = 0; i < patternSize; i++) {
LockPatternView.Cell cell = pattern.get(i);
- res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
+ res[i] = (byte) (cell.getRow() * getLockPatternSize() + cell.getColumn());
}
return new String(res);
}
@@ -774,7 +889,7 @@ public static String patternToString(List pattern) {
* @param pattern the gesture pattern.
* @return the hash of the pattern in a byte array.
*/
- private static byte[] patternToHash(List pattern) {
+ private byte[] patternToHash(List pattern) {
if (pattern == null) {
return null;
}
@@ -783,7 +898,7 @@ private static byte[] patternToHash(List pattern) {
byte[] res = new byte[patternSize];
for (int i = 0; i < patternSize; i++) {
LockPatternView.Cell cell = pattern.get(i);
- res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
+ res[i] = (byte) (cell.getRow() * getLockPatternSize() + cell.getColumn());
}
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
@@ -876,6 +991,20 @@ public boolean isLockPatternEnabled() {
(usingBiometricWeak() && backupEnabled));
}
+ /**
+ * @return Whether the lock gesture is enabled, or if it is set as a backup for biometric weak
+ */
+ public boolean isLockGestureEnabled() {
+ final boolean backupEnabled =
+ getLong(PASSWORD_TYPE_ALTERNATE_KEY, DevicePolicyManager.PASSWORD_QUALITY_GESTURE_WEAK)
+ == DevicePolicyManager.PASSWORD_QUALITY_GESTURE_WEAK;
+
+ return getBoolean(Settings.Secure.LOCK_GESTURE_ENABLED, false)
+ && (getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_GESTURE_WEAK)
+ == DevicePolicyManager.PASSWORD_QUALITY_GESTURE_WEAK ||
+ (usingBiometricWeak() && backupEnabled));
+ }
+
/**
* @return Whether biometric weak lock is installed and that the front facing camera exists
*/
@@ -951,6 +1080,61 @@ public boolean isTactileFeedbackEnabled() {
Settings.System.HAPTIC_FEEDBACK_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
}
+ /**
+ * @return the pattern lockscreen size
+ */
+ public byte getLockPatternSize() {
+ try {
+ return getLockSettings().getLockPatternSize(getCurrentOrCallingUserId());
+ } catch (RemoteException re) {
+ return PATTERN_SIZE_DEFAULT;
+ }
+ }
+
+ /**
+ * Set the pattern lockscreen size
+ */
+ public void setLockPatternSize(long size) {
+ setLong(Settings.Secure.LOCK_PATTERN_SIZE, size);
+ }
+
+ public void setVisibleDotsEnabled(boolean enabled) {
+ setBoolean(Settings.Secure.LOCK_DOTS_VISIBLE, enabled);
+ }
+
+ public boolean isVisibleDotsEnabled() {
+ return getBoolean(Settings.Secure.LOCK_DOTS_VISIBLE, true);
+ }
+
+ public void setShowErrorPath(boolean enabled) {
+ setBoolean(Settings.Secure.LOCK_SHOW_ERROR_PATH, enabled);
+ }
+
+ public boolean isShowErrorPath() {
+ return getBoolean(Settings.Secure.LOCK_SHOW_ERROR_PATH, true);
+ }
+
+ /**
+ * Set whether the lock gesture is enabled.
+ */
+ public void setLockGestureEnabled(boolean enabled) {
+ setBoolean(Settings.Secure.LOCK_GESTURE_ENABLED, enabled);
+ }
+
+ /**
+ * @return Whether the visible gesture is enabled.
+ */
+ public boolean isVisibleGestureEnabled() {
+ return getBoolean(Settings.Secure.LOCK_GESTURE_VISIBLE, true);
+ }
+
+ /**
+ * Set whether the visible gesture is enabled.
+ */
+ public void setVisibleGestureEnabled(boolean enabled) {
+ setBoolean(Settings.Secure.LOCK_GESTURE_VISIBLE, enabled);
+ }
+
/**
* Set and store the lockout deadline, meaning the user can't attempt his/her unlock
* pattern until the deadline has passed.
@@ -1220,12 +1404,15 @@ private void setString(String secureSettingKey, String value, int userHandle) {
public boolean isSecure() {
long mode = getKeyguardStoredPasswordQuality();
final boolean isPattern = mode == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
+ final boolean isGesture = mode == DevicePolicyManager.PASSWORD_QUALITY_GESTURE_WEAK;
final boolean isPassword = mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
|| mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
|| mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
|| mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
- final boolean secure = isPattern && isLockPatternEnabled() && savedPatternExists()
- || isPassword && savedPasswordExists();
+ final boolean isProfileSecure = mProfileManager.getActiveProfile().getScreenLockModeWithDPM(mContext) == Profile.LockMode.DEFAULT;
+ final boolean secure = (isPattern && isLockPatternEnabled() && savedPatternExists()
+ || isPassword && savedPasswordExists()) && isProfileSecure
+ || isGesture && isLockGestureEnabled() && savedGestureExists();
return secure;
}
@@ -1333,4 +1520,13 @@ public static boolean isSafeModeEnabled() {
return false;
}
+ /**
+ * @hide
+ * Set the lock-before-unlock option (show widgets before the secure
+ * unlock screen). See config_enableLockBeforeUnlockScreen
+ */
+ public void setLockBeforeUnlock(boolean enabled) {
+ setBoolean(Settings.Secure.LOCK_BEFORE_UNLOCK, enabled);
+ }
+
}
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 7a76ab01b8c..3a1bc92c335 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -38,13 +38,14 @@
import android.view.accessibility.AccessibilityManager;
import com.android.internal.R;
+import com.android.internal.widget.LockPatternUtils;
import java.util.ArrayList;
import java.util.List;
/**
* Displays and detects the user's unlock attempt, which is a drag of a finger
- * across 9 regions of the screen.
+ * across regions of the screen.
*
* Is also capable of displaying a static pattern in "in progress", "wrong" or
* "correct" states.
@@ -72,8 +73,10 @@ public class LockPatternView extends View {
*/
private static final int MILLIS_PER_CIRCLE_ANIMATING = 700;
+ private byte mPatternSize = LockPatternUtils.PATTERN_SIZE_DEFAULT;
+
private OnPatternListener mOnPatternListener;
- private ArrayList mPattern = new ArrayList(9);
+ private ArrayList mPattern = new ArrayList(mPatternSize * mPatternSize);
/**
* Lookup table for the circles of the pattern we are currently drawing.
@@ -81,7 +84,7 @@ public class LockPatternView extends View {
* in which case we use this to hold the cells we are drawing for the in
* progress animation.
*/
- private boolean[][] mPatternDrawLookup = new boolean[3][3];
+ private boolean[][] mPatternDrawLookup = new boolean[mPatternSize][mPatternSize];
/**
* the in progress point:
@@ -98,6 +101,8 @@ public class LockPatternView extends View {
private boolean mInStealthMode = false;
private boolean mEnableHapticFeedback = true;
private boolean mPatternInProgress = false;
+ private boolean mVisibleDots = true;
+ private boolean mShowErrorPath = true;
private float mDiameterFactor = 0.10f; // TODO: move to attrs
private final int mStrokeAlpha = 128;
@@ -125,30 +130,27 @@ public class LockPatternView extends View {
private final Matrix mArrowMatrix = new Matrix();
private final Matrix mCircleMatrix = new Matrix();
+ private LockPatternUtils mLockPatternUtils;
/**
- * Represents a cell in the 3 X 3 matrix of the unlock pattern view.
+ * Represents a cell in the matrix of the unlock pattern view.
*/
public static class Cell {
int row;
int column;
- // keep # objects limited to 9
- static Cell[][] sCells = new Cell[3][3];
+ // keep # objects limited
+ static Cell[][] sCells;
static {
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++) {
- sCells[i][j] = new Cell(i, j);
- }
- }
+ updateSize(LockPatternUtils.PATTERN_SIZE_DEFAULT);
}
/**
* @param row The row of the cell.
* @param column The column of the cell.
*/
- private Cell(int row, int column) {
- checkRange(row, column);
+ private Cell(int row, int column, byte size) {
+ checkRange(row, column, size);
this.row = row;
this.column = column;
}
@@ -165,17 +167,26 @@ public int getColumn() {
* @param row The row of the cell.
* @param column The column of the cell.
*/
- public static synchronized Cell of(int row, int column) {
- checkRange(row, column);
+ public static synchronized Cell of(int row, int column, byte size) {
+ checkRange(row, column, size);
return sCells[row][column];
}
- private static void checkRange(int row, int column) {
- if (row < 0 || row > 2) {
- throw new IllegalArgumentException("row must be in range 0-2");
+ public static void updateSize(byte size) {
+ sCells = new Cell[size][size];
+ for (int i = 0; i < size; i++) {
+ for (int j = 0; j < size; j++) {
+ sCells[i][j] = new Cell(i, j, size);
+ }
}
- if (column < 0 || column > 2) {
- throw new IllegalArgumentException("column must be in range 0-2");
+ }
+
+ private static void checkRange(int row, int column, byte size) {
+ if (row < 0 || row > size - 1) {
+ throw new IllegalArgumentException("row must be in range 0-" + (size - 1));
+ }
+ if (column < 0 || column > size - 1) {
+ throw new IllegalArgumentException("column must be in range 0-" + (size - 1));
}
}
@@ -303,6 +314,13 @@ public boolean isTactileFeedbackEnabled() {
return mEnableHapticFeedback;
}
+ /**
+ * @return the current pattern lockscreen size.
+ */
+ public int getLockPatternSize() {
+ return mPatternSize;
+ }
+
/**
* Set whether the view is in stealth mode. If true, there will be no
* visible feedback as the user enters the pattern.
@@ -313,6 +331,22 @@ public void setInStealthMode(boolean inStealthMode) {
mInStealthMode = inStealthMode;
}
+ public void setVisibleDots(boolean visibleDots) {
+ mVisibleDots = visibleDots;
+ }
+
+ public boolean isVisibleDots() {
+ return mVisibleDots;
+ }
+
+ public void setShowErrorPath(boolean showErrorPath) {
+ mShowErrorPath = showErrorPath;
+ }
+
+ public boolean isShowErrorPath() {
+ return mShowErrorPath;
+ }
+
/**
* Set whether the view will use tactile feedback. If true, there will be
* tactile feedback as the user enters the pattern.
@@ -323,6 +357,26 @@ public void setTactileFeedbackEnabled(boolean tactileFeedbackEnabled) {
mEnableHapticFeedback = tactileFeedbackEnabled;
}
+ /**
+ * Set the pattern size of the lockscreen
+ *
+ * @param size The pattern size.
+ */
+ public void setLockPatternSize(byte size) {
+ mPatternSize = size;
+ Cell.updateSize(size);
+ mPattern = new ArrayList(size * size);
+ mPatternDrawLookup = new boolean[size][size];
+ }
+
+ /**
+ * Set the LockPatternUtil instance used to encode a pattern to a string
+ * @param utils The instance.
+ */
+ public void setLockPatternUtils(LockPatternUtils utils) {
+ mLockPatternUtils = utils;
+ }
+
/**
* Set the call back for pattern detection.
* @param onPatternListener The call back.
@@ -420,8 +474,8 @@ private void resetPattern() {
* Clear the pattern lookup table.
*/
private void clearPatternDrawLookup() {
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++) {
+ for (int i = 0; i < mPatternSize; i++) {
+ for (int j = 0; j < mPatternSize; j++) {
mPatternDrawLookup[i][j] = false;
}
}
@@ -445,10 +499,10 @@ public void enableInput() {
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
final int width = w - mPaddingLeft - mPaddingRight;
- mSquareWidth = width / 3.0f;
+ mSquareWidth = width / (float) mPatternSize;
final int height = h - mPaddingTop - mPaddingBottom;
- mSquareHeight = height / 3.0f;
+ mSquareHeight = height / (float) mPatternSize;
}
private int resolveMeasured(int measureSpec, int desired)
@@ -471,14 +525,14 @@ private int resolveMeasured(int measureSpec, int desired)
@Override
protected int getSuggestedMinimumWidth() {
- // View should be large enough to contain 3 side-by-side target bitmaps
- return 3 * mBitmapWidth;
+ // View should be large enough to contain side-by-side target bitmaps
+ return mPatternSize * mBitmapWidth;
}
@Override
protected int getSuggestedMinimumHeight() {
- // View should be large enough to contain 3 side-by-side target bitmaps
- return 3 * mBitmapWidth;
+ // View should be large enough to contain side-by-side target bitmaps
+ return mPatternSize * mBitmapWidth;
}
@Override
@@ -515,7 +569,6 @@ private Cell detectAndAddHit(float x, float y) {
if (cell != null) {
// check for gaps in existing pattern
- Cell fillInGapCell = null;
final ArrayList| pattern = mPattern;
if (!pattern.isEmpty()) {
final Cell lastCell = pattern.get(pattern.size() - 1);
@@ -525,21 +578,19 @@ private Cell detectAndAddHit(float x, float y) {
int fillInRow = lastCell.row;
int fillInColumn = lastCell.column;
- if (Math.abs(dRow) == 2 && Math.abs(dColumn) != 1) {
- fillInRow = lastCell.row + ((dRow > 0) ? 1 : -1);
- }
-
- if (Math.abs(dColumn) == 2 && Math.abs(dRow) != 1) {
- fillInColumn = lastCell.column + ((dColumn > 0) ? 1 : -1);
+ if (dRow == 0 || dColumn == 0 || Math.abs(dRow) == Math.abs(dColumn)) {
+ while (true) {
+ fillInRow += Integer.signum(dRow);
+ fillInColumn += Integer.signum(dColumn);
+ if (fillInRow == cell.row && fillInColumn == cell.column) break;
+ Cell fillInGapCell = Cell.of(fillInRow, fillInColumn, mPatternSize);
+ if (!mPatternDrawLookup[fillInGapCell.row][fillInGapCell.column]) {
+ addCellToPattern(fillInGapCell);
+ }
+ }
}
-
- fillInGapCell = Cell.of(fillInRow, fillInColumn);
}
- if (fillInGapCell != null &&
- !mPatternDrawLookup[fillInGapCell.row][fillInGapCell.column]) {
- addCellToPattern(fillInGapCell);
- }
addCellToPattern(cell);
if (mEnableHapticFeedback) {
performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
@@ -572,7 +623,7 @@ private Cell checkForNewHit(float x, float y) {
if (mPatternDrawLookup[rowHit][columnHit]) {
return null;
}
- return Cell.of(rowHit, columnHit);
+ return Cell.of(rowHit, columnHit, mPatternSize);
}
/**
@@ -586,7 +637,7 @@ private int getRowHit(float y) {
float hitSize = squareHeight * mHitFactor;
float offset = mPaddingTop + (squareHeight - hitSize) / 2f;
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < mPatternSize; i++) {
final float hitTop = offset + squareHeight * i;
if (y >= hitTop && y <= hitTop + hitSize) {
@@ -606,7 +657,7 @@ private int getColumnHit(float x) {
float hitSize = squareWidth * mHitFactor;
float offset = mPaddingLeft + (squareWidth - hitSize) / 2f;
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < mPatternSize; i++) {
final float hitLeft = offset + squareWidth * i;
if (x >= hitLeft && x <= hitLeft + hitSize) {
@@ -918,10 +969,10 @@ protected void onDraw(Canvas canvas) {
final int paddingTop = mPaddingTop;
final int paddingLeft = mPaddingLeft;
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < mPatternSize; i++) {
float topY = paddingTop + i * squareHeight;
//float centerY = mPaddingTop + i * mSquareHeight + (mSquareHeight / 2);
- for (int j = 0; j < 3; j++) {
+ for (int j = 0; j < mPatternSize; j++) {
float leftX = paddingLeft + j * squareWidth;
drawCircle(canvas, (int) leftX, (int) topY, drawLookup[i][j]);
}
@@ -931,7 +982,8 @@ protected void onDraw(Canvas canvas) {
// only the last segment of the path should be computed here
// draw the path of the pattern (unless the user is in progress, and
// we are in stealth mode)
- final boolean drawPath = (!mInStealthMode || mPatternDisplayMode == DisplayMode.Wrong);
+ final boolean drawPath = ((!mInStealthMode && mPatternDisplayMode != DisplayMode.Wrong)
+ || (mPatternDisplayMode == DisplayMode.Wrong && mShowErrorPath));
// draw the arrows associated with the path (unless the user is in progress, and
// we are in stealth mode)
@@ -1034,8 +1086,11 @@ private void drawArrow(Canvas canvas, float leftX, float topY, Cell start, Cell
private void drawCircle(Canvas canvas, int leftX, int topY, boolean partOfPattern) {
Bitmap outerCircle;
Bitmap innerCircle;
-
- if (!partOfPattern || (mInStealthMode && mPatternDisplayMode != DisplayMode.Wrong)) {
+ if (!partOfPattern || (mInStealthMode && mPatternDisplayMode != DisplayMode.Wrong)
+ || (mPatternDisplayMode == DisplayMode.Wrong && !mShowErrorPath)) {
+ if (!mVisibleDots) {
+ return;
+ }
// unselected circle
outerCircle = mBitmapCircleDefault;
innerCircle = mBitmapBtnDefault;
@@ -1082,9 +1137,9 @@ private void drawCircle(Canvas canvas, int leftX, int topY, boolean partOfPatter
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
return new SavedState(superState,
- LockPatternUtils.patternToString(mPattern),
- mPatternDisplayMode.ordinal(),
- mInputEnabled, mInStealthMode, mEnableHapticFeedback);
+ mLockPatternUtils.patternToString(mPattern),
+ mPatternDisplayMode.ordinal(), mPatternSize,
+ mInputEnabled, mInStealthMode, mEnableHapticFeedback, mVisibleDots, mShowErrorPath);
}
@Override
@@ -1093,11 +1148,14 @@ protected void onRestoreInstanceState(Parcelable state) {
super.onRestoreInstanceState(ss.getSuperState());
setPattern(
DisplayMode.Correct,
- LockPatternUtils.stringToPattern(ss.getSerializedPattern()));
+ mLockPatternUtils.stringToPattern(ss.getSerializedPattern()));
mPatternDisplayMode = DisplayMode.values()[ss.getDisplayMode()];
+ mPatternSize = ss.getPatternSize();
mInputEnabled = ss.isInputEnabled();
mInStealthMode = ss.isInStealthMode();
mEnableHapticFeedback = ss.isTactileFeedbackEnabled();
+ mVisibleDots = ss.isVisibleDots();
+ mShowErrorPath = ss.isShowErrorPath();
}
/**
@@ -1107,21 +1165,28 @@ private static class SavedState extends BaseSavedState {
private final String mSerializedPattern;
private final int mDisplayMode;
+ private final byte mPatternSize;
private final boolean mInputEnabled;
private final boolean mInStealthMode;
private final boolean mTactileFeedbackEnabled;
+ private final boolean mVisibleDots;
+ private final boolean mShowErrorPath;
/**
* Constructor called from {@link LockPatternView#onSaveInstanceState()}
*/
private SavedState(Parcelable superState, String serializedPattern, int displayMode,
- boolean inputEnabled, boolean inStealthMode, boolean tactileFeedbackEnabled) {
+ byte patternSize, boolean inputEnabled, boolean inStealthMode,
+ boolean tactileFeedbackEnabled, boolean visibleDots, boolean showErrorPath) {
super(superState);
mSerializedPattern = serializedPattern;
mDisplayMode = displayMode;
+ mPatternSize = patternSize;
mInputEnabled = inputEnabled;
mInStealthMode = inStealthMode;
mTactileFeedbackEnabled = tactileFeedbackEnabled;
+ mVisibleDots = visibleDots;
+ mShowErrorPath = showErrorPath;
}
/**
@@ -1131,9 +1196,12 @@ private SavedState(Parcel in) {
super(in);
mSerializedPattern = in.readString();
mDisplayMode = in.readInt();
+ mPatternSize = (byte) in.readByte();
mInputEnabled = (Boolean) in.readValue(null);
mInStealthMode = (Boolean) in.readValue(null);
mTactileFeedbackEnabled = (Boolean) in.readValue(null);
+ mVisibleDots = (Boolean) in.readValue(null);
+ mShowErrorPath = (Boolean) in.readValue(null);
}
public String getSerializedPattern() {
@@ -1144,6 +1212,10 @@ public int getDisplayMode() {
return mDisplayMode;
}
+ public byte getPatternSize() {
+ return mPatternSize;
+ }
+
public boolean isInputEnabled() {
return mInputEnabled;
}
@@ -1156,14 +1228,25 @@ public boolean isTactileFeedbackEnabled(){
return mTactileFeedbackEnabled;
}
+ public boolean isVisibleDots() {
+ return mVisibleDots;
+ }
+
+ public boolean isShowErrorPath() {
+ return mShowErrorPath;
+ }
+
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString(mSerializedPattern);
dest.writeInt(mDisplayMode);
+ dest.writeByte(mPatternSize);
dest.writeValue(mInputEnabled);
dest.writeValue(mInStealthMode);
dest.writeValue(mTactileFeedbackEnabled);
+ dest.writeValue(mVisibleDots);
+ dest.writeValue(mShowErrorPath);
}
public static final Parcelable.Creator CREATOR =
diff --git a/core/java/com/android/internal/widget/LockSettingsService.java b/core/java/com/android/internal/widget/LockSettingsService.java
index 4ecbd1609e7..37936abbf5e 100644
--- a/core/java/com/android/internal/widget/LockSettingsService.java
+++ b/core/java/com/android/internal/widget/LockSettingsService.java
@@ -22,6 +22,11 @@
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
+import android.gesture.Gesture;
+import android.gesture.GestureLibraries;
+import android.gesture.GestureLibrary;
+import android.gesture.Prediction;
+import android.gesture.GestureStore;
import android.os.Binder;
import android.os.Environment;
import android.os.RemoteException;
@@ -32,11 +37,14 @@
import android.text.TextUtils;
import android.util.Slog;
+import com.android.internal.widget.LockPatternUtils;
+
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;
+import java.util.ArrayList;
/**
* Keeps the lock pattern/password data and related settings for each user.
@@ -61,6 +69,9 @@ public class LockSettingsService extends ILockSettings.Stub {
private static final String SYSTEM_DIRECTORY = "/system/";
private static final String LOCK_PATTERN_FILE = "gesture.key";
private static final String LOCK_PASSWORD_FILE = "password.key";
+ private static final String LOCK_GESTURE_FILE = "lock_gesture.key";
+
+ private static final String LOCK_GESTURE_NAME = "lock_gesture";
private final Context mContext;
@@ -166,15 +177,57 @@ public String getString(String key, String defaultValue, int userId) throws Remo
return readFromDb(key, defaultValue, userId);
}
+ @Override
+ public byte getLockPatternSize(int userId) {
+ try {
+ long size = getLong(Settings.Secure.LOCK_PATTERN_SIZE, -1, userId);
+ if (size > 0 && size < 128) {
+ return (byte) size;
+ }
+ } catch (RemoteException re) {
+ //Any invalid size handled below
+ }
+ return LockPatternUtils.PATTERN_SIZE_DEFAULT;
+ }
+
+ private boolean isDefaultSize(int userId) {
+ return getLockPatternSize(userId) == LockPatternUtils.PATTERN_SIZE_DEFAULT;
+ }
+
private String getLockPatternFilename(int userId) {
+ return getLockPatternFilename(userId, isDefaultSize(userId));
+ }
+
+ private String getLockPatternFilename(int userId, boolean defaultSize) {
+ String dataSystemDirectory =
+ android.os.Environment.getDataDirectory().getAbsolutePath() +
+ SYSTEM_DIRECTORY;
+ String patternFile = (defaultSize ? "" : "cm_") + LOCK_PATTERN_FILE;
+
+ if (userId == 0) {
+ // Leave it in the same place for user 0
+ return dataSystemDirectory + patternFile;
+ } else {
+ return new File(Environment.getUserSystemDirectory(userId), patternFile)
+ .getAbsolutePath();
+ }
+ }
+
+ private String getLockGestureFilename(int userId) {
+ return getLockGestureFilename(userId, isDefaultSize(userId));
+ }
+
+ private String getLockGestureFilename(int userId, boolean defaultSize) {
String dataSystemDirectory =
android.os.Environment.getDataDirectory().getAbsolutePath() +
SYSTEM_DIRECTORY;
+ String patternFile = LOCK_GESTURE_FILE;
+
if (userId == 0) {
// Leave it in the same place for user 0
- return dataSystemDirectory + LOCK_PATTERN_FILE;
+ return dataSystemDirectory + patternFile;
} else {
- return new File(Environment.getUserSystemDirectory(userId), LOCK_PATTERN_FILE)
+ return new File(Environment.getUserSystemDirectory(userId), patternFile)
.getAbsolutePath();
}
}
@@ -206,11 +259,20 @@ public boolean havePattern(int userId) throws RemoteException {
return new File(getLockPatternFilename(userId)).length() > 0;
}
+ @Override
+ public boolean haveGesture(int userId) throws RemoteException {
+ // Do we need a permissions check here?
+
+ return new File(getLockGestureFilename(userId)).length() > 0;
+ }
+
@Override
public void setLockPattern(byte[] hash, int userId) throws RemoteException {
checkWritePermission(userId);
- writeFile(getLockPatternFilename(userId), hash);
+ boolean defaultSize = isDefaultSize(userId);
+ writeFile(getLockPatternFilename(userId, defaultSize), hash);
+ writeFile(getLockPatternFilename(userId, !defaultSize), null);
}
@Override
@@ -236,6 +298,46 @@ public boolean checkPattern(byte[] hash, int userId) throws RemoteException {
}
}
+ @Override
+ public void setLockGesture(Gesture gesture, int userId) throws RemoteException {
+ checkWritePermission(userId);
+ if (gesture == null)
+ return;
+
+ File storeFile = new File(getLockGestureFilename(userId));
+ GestureLibrary store = GestureLibraries.fromFile(storeFile);
+
+ store.load();
+ if (store.getGestures(LOCK_GESTURE_NAME) != null) {
+ store.removeEntry(LOCK_GESTURE_NAME);
+ }
+
+ store.addGesture(LOCK_GESTURE_NAME, gesture);
+ store.save();
+ }
+
+ @Override
+ public boolean checkGesture(Gesture gesture, int userId) throws RemoteException {
+ checkPasswordReadPermission(userId);
+
+ File storeFile = new File(getLockGestureFilename(userId));
+ GestureLibrary store = GestureLibraries.fromFile(storeFile);
+ int minPredictionScore = mContext.getResources().getInteger(
+ com.android.internal.R.integer.min_gesture_prediction_score);
+ store.setOrientationStyle(GestureStore.ORIENTATION_SENSITIVE);
+ store.load();
+ ArrayList predictions = store.recognize(gesture);
+ if (predictions.size() > 0) {
+ Prediction prediction = predictions.get(0);
+ if (prediction.score > minPredictionScore) {
+ if (prediction.name.equals(LOCK_GESTURE_NAME)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
@Override
public void setLockPassword(byte[] hash, int userId) throws RemoteException {
checkWritePermission(userId);
@@ -400,6 +502,8 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) {
Secure.LOCK_PATTERN_ENABLED,
Secure.LOCK_BIOMETRIC_WEAK_FLAGS,
Secure.LOCK_PATTERN_VISIBLE,
- Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED
+ Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED,
+ Secure.LOCK_SHOW_ERROR_PATH,
+ Secure.LOCK_DOTS_VISIBLE
};
}
diff --git a/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java b/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java
index aad285ac2f8..0730541284c 100644
--- a/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java
@@ -62,6 +62,28 @@ public class GlowPadView extends View {
private static final int STATE_SNAP = 4;
private static final int STATE_FINISH = 5;
+
+ /**
+ * @hide
+ */
+ public final static String ICON_RESOURCE = "icon_resource";
+
+ /**
+ * @hide
+ */
+ public final static String ICON_PACKAGE = "icon_package";
+
+ /**
+ * @hide
+ */
+ public final static String ICON_FILE = "icon_file";
+
+ /**
+ *
+ * @hide
+ */
+ public final static String EMPTY_TARGET = "empty";
+
// Animation properties.
private static final float SNAP_MARGIN_DEFAULT = 20.0f; // distance to ring before we snap to it
@@ -71,6 +93,7 @@ public interface OnTriggerListener {
public void onGrabbed(View v, int handle);
public void onReleased(View v, int handle);
public void onTrigger(View v, int target);
+ public void onTargetChange(View v, int target);
public void onGrabbedStateChange(View v, int handle);
public void onFinishFinalAnimation();
}
@@ -122,6 +145,7 @@ public interface OnTriggerListener {
private boolean mMagneticTargets = false;
private boolean mDragging;
private int mNewTargetResources;
+ private ArrayList mNewTargetDrawables;
private class AnimationBundle extends ArrayList {
private static final long serialVersionUID = 0xA84D78726F127468L;
@@ -187,6 +211,10 @@ public void onAnimationEnd(Animator animator) {
internalSetTargetResources(mNewTargetResources);
mNewTargetResources = 0;
hideTargets(false, false);
+ } else if (mNewTargetDrawables != null) {
+ internalSetTargetResources(mNewTargetDrawables);
+ mNewTargetDrawables = null;
+ hideTargets(false, false);
}
mAnimatingTargets = false;
}
@@ -243,6 +271,7 @@ public GlowPadView(Context context, AttributeSet attrs) {
if (a.getValue(R.styleable.GlowPadView_targetDrawables, outValue)) {
internalSetTargetResources(outValue.resourceId);
}
+
if (mTargetDrawables == null || mTargetDrawables.size() == 0) {
throw new IllegalStateException("Must specify at least one target drawable");
}
@@ -431,6 +460,9 @@ private void deactivateTargets() {
target.setState(TargetDrawable.STATE_INACTIVE);
}
mActiveTarget = -1;
+ if (mOnTriggerListener != null) {
+ mOnTriggerListener.onTargetChange(this, mActiveTarget);
+ }
}
/**
@@ -466,6 +498,7 @@ private void doFinish() {
// Force ring and targets to finish animation to final expanded state
mTargetAnimations.stop();
}
+ hideTargets(false, false);
} else {
// Animate handle back to the center based on current state.
hideGlow(HIDE_ANIMATION_DURATION, 0, 0.0f, mResetListenerWithPing);
@@ -605,6 +638,14 @@ private void internalSetTargetResources(int resourceId) {
}
}
+ private void internalSetTargetResources(ArrayList drawList) {
+ mTargetResourceId = 0;
+ mTargetDrawables = drawList;
+ updateTargetPositions(mWaveCenterX, mWaveCenterY);
+ updatePointCloudPosition(mWaveCenterX, mWaveCenterY);
+ hideTargets(false, false);
+ }
+
/**
* Loads an array of drawables from the given resourceId.
*
@@ -619,10 +660,31 @@ public void setTargetResources(int resourceId) {
}
}
+ public void setMagneticTargets(boolean active) {
+ mMagneticTargets = active;
+ }
+
+ public void setOffset(float offset) {
+ mFirstItemOffset = (float) Math.toRadians(offset);
+ }
+
+ public void setTargetResources(ArrayList drawList) {
+ if (mAnimatingTargets) {
+ // postpone this change until we return to the initial state
+ mNewTargetDrawables = drawList;
+ } else {
+ internalSetTargetResources(drawList);
+ }
+ }
+
public int getTargetResourceId() {
return mTargetResourceId;
}
+ public ArrayList getTargetDrawables() {
+ return mTargetDrawables;
+ }
+
/**
* Sets the resource id specifying the target descriptions for accessibility.
*
@@ -923,6 +985,7 @@ private void handleMove(MotionEvent event) {
TargetDrawable target = targets.get(activeTarget);
if (target.hasState(TargetDrawable.STATE_FOCUSED)) {
target.setState(TargetDrawable.STATE_FOCUSED);
+ vibrate();
}
if (mMagneticTargets) {
updateTargetPosition(activeTarget, mWaveCenterX, mWaveCenterY, activeAngle);
@@ -934,6 +997,9 @@ private void handleMove(MotionEvent event) {
}
}
mActiveTarget = activeTarget;
+ if (mOnTriggerListener !=null) {
+ mOnTriggerListener.onTargetChange(this, mActiveTarget);
+ }
}
@Override
@@ -1110,17 +1176,13 @@ private float getRingHeight() {
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
- final int width = right - left;
- final int height = bottom - top;
// Target placement width/height. This puts the targets on the greater of the ring
// width or the specified outer radius.
final float placementWidth = getRingWidth();
final float placementHeight = getRingHeight();
- float newWaveCenterX = mHorizontalInset
- + Math.max(width, mMaxTargetWidth + placementWidth) / 2;
- float newWaveCenterY = mVerticalInset
- + Math.max(height, + mMaxTargetHeight + placementHeight) / 2;
+ float newWaveCenterX = mHorizontalInset + (mMaxTargetWidth + placementWidth) / 2;
+ float newWaveCenterY = mVerticalInset + (mMaxTargetHeight + placementHeight) / 2;
if (mInitialLayout) {
stopAndHideWaveAnimation();
@@ -1245,7 +1307,7 @@ private void announceTargets() {
}
private String getTargetDescription(int index) {
- if (mTargetDescriptions == null || mTargetDescriptions.isEmpty()) {
+ if (mTargetDescriptions == null || mTargetDescriptions.isEmpty() || index >= mTargetDescriptions.size()) {
mTargetDescriptions = loadDescriptions(mTargetDescriptionsResourceId);
if (mTargetDrawables.size() != mTargetDescriptions.size()) {
Log.w(TAG, "The number of target drawables must be"
@@ -1257,7 +1319,7 @@ private String getTargetDescription(int index) {
}
private String getDirectionDescription(int index) {
- if (mDirectionDescriptions == null || mDirectionDescriptions.isEmpty()) {
+ if (mDirectionDescriptions == null || mDirectionDescriptions.isEmpty() || index >= mDirectionDescriptions.size()) {
mDirectionDescriptions = loadDescriptions(mDirectionDescriptionsResourceId);
if (mTargetDrawables.size() != mDirectionDescriptions.size()) {
Log.w(TAG, "The number of target drawables must be"
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
index e22d1e8d43b..5c3858bf0d8 100644
--- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
@@ -1006,17 +1006,13 @@ private void computeInsets(int dx, int dy) {
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
- final int width = right - left;
- final int height = bottom - top;
// Target placement width/height. This puts the targets on the greater of the ring
// width or the specified outer radius.
final float placementWidth = Math.max(mOuterRing.getWidth(), 2 * mOuterRadius);
final float placementHeight = Math.max(mOuterRing.getHeight(), 2 * mOuterRadius);
- float newWaveCenterX = mHorizontalInset
- + Math.max(width, mMaxTargetWidth + placementWidth) / 2;
- float newWaveCenterY = mVerticalInset
- + Math.max(height, + mMaxTargetHeight + placementHeight) / 2;
+ float newWaveCenterX = mHorizontalInset + (mMaxTargetWidth + placementWidth) / 2;
+ float newWaveCenterY = mVerticalInset + (mMaxTargetHeight + placementHeight) / 2;
if (mInitialLayout) {
hideChevrons();
diff --git a/core/java/com/android/internal/widget/multiwaveview/TargetDrawable.java b/core/java/com/android/internal/widget/multiwaveview/TargetDrawable.java
index 30f5f2f2dde..1b70a9e8cae 100644
--- a/core/java/com/android/internal/widget/multiwaveview/TargetDrawable.java
+++ b/core/java/com/android/internal/widget/multiwaveview/TargetDrawable.java
@@ -28,9 +28,9 @@ public class TargetDrawable {
private static final boolean DEBUG = false;
public static final int[] STATE_ACTIVE =
- { android.R.attr.state_enabled, android.R.attr.state_active };
+ { android.R.attr.state_enabled, android.R.attr.state_active, -android.R.attr.state_focused };
public static final int[] STATE_INACTIVE =
- { android.R.attr.state_enabled, -android.R.attr.state_active };
+ { android.R.attr.state_enabled, -android.R.attr.state_active , -android.R.attr.state_focused };
public static final int[] STATE_FOCUSED =
{ android.R.attr.state_enabled, -android.R.attr.state_active,
android.R.attr.state_focused };
@@ -91,6 +91,14 @@ public void setDrawable(Resources res, int resId) {
setState(STATE_INACTIVE);
}
+ public TargetDrawable(Resources res, Drawable drawable) {
+ mResourceId = 0;
+ // Mutate the drawable so we can animate shared drawable properties.
+ mDrawable = drawable != null ? drawable.mutate() : null;
+ resizeDrawables();
+ setState(STATE_INACTIVE);
+ }
+
public TargetDrawable(TargetDrawable other) {
mResourceId = other.mResourceId;
// Mutate the drawable so we can animate shared drawable properties.
@@ -257,4 +265,4 @@ public void setEnabled(boolean enabled) {
public int getResourceId() {
return mResourceId;
}
-}
+}
\ No newline at end of file
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 3ca085b8ebd..e8aa9496a9b 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -4,6 +4,7 @@ include $(CLEAR_VARS)
LOCAL_CFLAGS += -DHAVE_CONFIG_H -DKHTML_NO_EXCEPTIONS -DGKWQ_NO_JAVA
LOCAL_CFLAGS += -DNO_SUPPORT_JS_BINDING -DQT_NO_WHEELEVENT -DKHTML_NO_XBL
LOCAL_CFLAGS += -U__APPLE__
+LOCAL_CFLAGS += -fno-strict-aliasing
ifeq ($(TARGET_ARCH), arm)
LOCAL_CFLAGS += -DPACKED="__attribute__ ((packed))"
@@ -86,8 +87,8 @@ LOCAL_SRC_FILES:= \
android_util_Process.cpp \
android_util_StringBlock.cpp \
android_util_XmlBlock.cpp \
+ android_util_PackageRedirectionMap.cpp \
android/graphics/AutoDecodeCancel.cpp \
- android/graphics/Bitmap.cpp \
android/graphics/BitmapFactory.cpp \
android/graphics/Camera.cpp \
android/graphics/Canvas.cpp \
@@ -151,6 +152,12 @@ LOCAL_SRC_FILES:= \
android_content_res_Configuration.cpp \
android_animation_PropertyValuesHolder.cpp
+ifeq ($(BOARD_USES_QCOM_HARDWARE),true)
+ LOCAL_CFLAGS += -DQCOM_HARDWARE
+ LOCAL_SRC_FILES += \
+ com_android_internal_app_ActivityTrigger.cpp
+endif
+
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE) \
$(LOCAL_PATH)/android/graphics \
@@ -159,7 +166,8 @@ LOCAL_C_INCLUDES += \
$(call include-path-for, bluedroid) \
$(call include-path-for, libhardware)/hardware \
$(call include-path-for, libhardware_legacy)/hardware_legacy \
- $(TOP)/frameworks/av/include \
+ $(TOP)/frameworks/av/include \
+ external/e2fsprogs/lib \
external/skia/include/core \
external/skia/include/effects \
external/skia/include/images \
@@ -183,6 +191,7 @@ LOCAL_C_INCLUDES += \
LOCAL_SHARED_LIBRARIES := \
libandroidfw \
libexpat \
+ libext2_blkid \
libnativehelper \
libcutils \
libutils \
@@ -219,6 +228,26 @@ LOCAL_SHARED_LIBRARIES += libselinux
LOCAL_CFLAGS += -DHAVE_SELINUX
endif # HAVE_SELINUX
+ifeq ($(TARGET_ARCH), arm)
+ ifeq ($(TARGET_USE_KRAIT_BIONIC_OPTIMIZATION), true)
+ TARGET_arm_CFLAGS += -DUSE_NEON_BITMAP_OPTS -mvectorize-with-neon-quad
+ LOCAL_SRC_FILES+= \
+ android/graphics/Bitmap.cpp.arm
+ else
+ ifeq ($(TARGET_ARCH_VARIANT_CPU), cortex-a15)
+ TARGET_arm_CFLAGS += -DUSE_NEON_BITMAP_OPTS -mvectorize-with-neon-quad
+ LOCAL_SRC_FILES+= \
+ android/graphics/Bitmap.cpp.arm
+ else
+ LOCAL_SRC_FILES+= \
+ android/graphics/Bitmap.cpp
+ endif
+ endif
+else
+ LOCAL_SRC_FILES+= \
+ android/graphics/Bitmap.cpp
+endif
+
ifeq ($(USE_OPENGL_RENDERER),true)
LOCAL_SHARED_LIBRARIES += libhwui
endif
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 9820e60545d..01ad2f0e65e 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -173,6 +173,10 @@ extern int register_android_content_res_ObbScanner(JNIEnv* env);
extern int register_android_content_res_Configuration(JNIEnv* env);
extern int register_android_animation_PropertyValuesHolder(JNIEnv *env);
extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env);
+extern int register_android_content_res_PackageRedirectionMap(JNIEnv* env);
+#ifdef QCOM_HARDWARE
+extern int register_com_android_internal_app_ActivityTrigger(JNIEnv *env);
+#endif
static AndroidRuntime* gCurRuntime = NULL;
@@ -1212,6 +1216,12 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_animation_PropertyValuesHolder),
REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
+ REG_JNI(register_android_content_res_PackageRedirectionMap),
+
+#ifdef QCOM_HARDWARE
+ REG_JNI(register_com_android_internal_app_ActivityTrigger),
+#endif
+
};
/*
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 63683b4f495..7c5da262d08 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -22,6 +22,12 @@
#define TRACE_BITMAP(code)
#endif
+#ifdef USE_NEON_BITMAP_OPTS
+ #define __BITMAP_OPTS __attribute__((optimize("-ftree-vectorize", "-fprefetch-loop-arrays")))
+#else
+ #define __BITMAP_OPTS
+#endif
+
///////////////////////////////////////////////////////////////////////////////
// Conversions to/from SkColor, for get/setPixels, and the create method, which
// is basically like setPixels
@@ -29,7 +35,7 @@
typedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
int x, int y);
-static void FromColor_D32(void* dst, const SkColor src[], int width,
+static void __BITMAP_OPTS FromColor_D32(void* dst, const SkColor src[], int width,
int, int) {
SkPMColor* d = (SkPMColor*)dst;
@@ -38,7 +44,7 @@ static void FromColor_D32(void* dst, const SkColor src[], int width,
}
}
-static void FromColor_D565(void* dst, const SkColor src[], int width,
+static void __BITMAP_OPTS FromColor_D565(void* dst, const SkColor src[], int width,
int x, int y) {
uint16_t* d = (uint16_t*)dst;
@@ -50,7 +56,7 @@ static void FromColor_D565(void* dst, const SkColor src[], int width,
}
}
-static void FromColor_D4444(void* dst, const SkColor src[], int width,
+static void __BITMAP_OPTS FromColor_D4444(void* dst, const SkColor src[], int width,
int x, int y) {
SkPMColor16* d = (SkPMColor16*)dst;
@@ -113,7 +119,7 @@ bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors,
typedef void (*ToColorProc)(SkColor dst[], const void* src, int width,
SkColorTable*);
-static void ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
+static void __BITMAP_OPTS ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
SkColorTable*) {
SkASSERT(width > 0);
const SkPMColor* s = (const SkPMColor*)src;
@@ -122,7 +128,7 @@ static void ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
} while (--width != 0);
}
-static void ToColor_S32_Opaque(SkColor dst[], const void* src, int width,
+static void __BITMAP_OPTS ToColor_S32_Opaque(SkColor dst[], const void* src, int width,
SkColorTable*) {
SkASSERT(width > 0);
const SkPMColor* s = (const SkPMColor*)src;
@@ -133,7 +139,7 @@ static void ToColor_S32_Opaque(SkColor dst[], const void* src, int width,
} while (--width != 0);
}
-static void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width,
+static void __BITMAP_OPTS ToColor_S4444_Alpha(SkColor dst[], const void* src, int width,
SkColorTable*) {
SkASSERT(width > 0);
const SkPMColor16* s = (const SkPMColor16*)src;
@@ -142,7 +148,7 @@ static void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width,
} while (--width != 0);
}
-static void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,
+static void __BITMAP_OPTS ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,
SkColorTable*) {
SkASSERT(width > 0);
const SkPMColor16* s = (const SkPMColor16*)src;
@@ -153,7 +159,7 @@ static void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,
} while (--width != 0);
}
-static void ToColor_S565(SkColor dst[], const void* src, int width,
+static void __BITMAP_OPTS ToColor_S565(SkColor dst[], const void* src, int width,
SkColorTable*) {
SkASSERT(width > 0);
const uint16_t* s = (const uint16_t*)src;
@@ -164,7 +170,7 @@ static void ToColor_S565(SkColor dst[], const void* src, int width,
} while (--width != 0);
}
-static void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width,
+static void __BITMAP_OPTS ToColor_SI8_Alpha(SkColor dst[], const void* src, int width,
SkColorTable* ctable) {
SkASSERT(width > 0);
const uint8_t* s = (const uint8_t*)src;
@@ -175,7 +181,7 @@ static void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width,
ctable->unlockColors(false);
}
-static void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
+static void __BITMAP_OPTS ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
SkColorTable* ctable) {
SkASSERT(width > 0);
const uint8_t* s = (const uint8_t*)src;
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 88233286e68..bfb06f15d33 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -15,6 +15,7 @@
#include "JNIHelp.h"
#include
+#include
#include
#include
#include
@@ -45,6 +46,8 @@ jfieldID gBitmap_layoutBoundsFieldID;
using namespace android;
+bool mPurgeableAssets;
+
static inline int32_t validOrNeg1(bool isValid, int32_t value) {
// return isValid ? value : -1;
SkASSERT((int)isValid == 0 || (int)isValid == 1);
@@ -351,6 +354,17 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding,
SkCanvas canvas(*bitmap);
canvas.scale(sx, sy);
canvas.drawBitmap(*decoded, 0.0f, 0.0f, &paint);
+
+ // Save off the unscaled version of bitmap to be used in later
+ // transformations if it would reduce memory pressure. Only do
+ // so if it is being upscaled more than 50%, is bigger than
+ // 256x256, and not too big to be keeping a copy of (<1MB).
+ const int numUnscaledPixels = decoded->width() * decoded->height();
+ if (sx > 1.5 && numUnscaledPixels > 65536 && numUnscaledPixels < 262144) {
+ bitmap->setUnscaledBitmap(decoded);
+ adb2.detach(); //responsibility for freeing decoded's memory is
+ //transferred to bitmap's destructor
+ }
}
if (padding) {
@@ -491,8 +505,8 @@ static jobject nativeDecodeAssetScaled(JNIEnv* env, jobject clazz, jint native_a
SkStream* stream;
Asset* asset = reinterpret_cast(native_asset);
- bool forcePurgeable = optionsPurgeable(env, options);
- if (forcePurgeable) {
+ bool forcePurgeable = mPurgeableAssets;
+ if (forcePurgeable || optionsPurgeable(env, options)) {
// if we could "ref/reopen" the asset, we may not need to copy it here
// and we could assume optionsShareable, since assets are always RO
stream = copyAssetToStream(asset);
@@ -616,6 +630,11 @@ int register_android_graphics_BitmapFactory(JNIEnv* env) {
SkASSERT(bitmap_class);
gBitmap_nativeBitmapFieldID = getFieldIDCheck(env, bitmap_class, "mNativeBitmap", "I");
gBitmap_layoutBoundsFieldID = getFieldIDCheck(env, bitmap_class, "mLayoutBounds", "[I");
+
+ char value[PROPERTY_VALUE_MAX];
+ property_get("persist.sys.purgeable_assets", value, "0");
+ mPurgeableAssets = atoi(value) == 1;
+
int ret = AndroidRuntime::registerNativeMethods(env,
"android/graphics/BitmapFactory$Options",
gOptionsMethods,
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 5d6f73849b8..82422dfa051 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -493,19 +493,36 @@ class SkCanvasGlue {
jobject srcIRect, const SkRect& dst, SkPaint* paint,
jint screenDensity, jint bitmapDensity) {
SkIRect src, *srcPtr = NULL;
+ SkPaint filteredPaint;
if (NULL != srcIRect) {
GraphicsJNI::jrect_to_irect(env, srcIRect, &src);
srcPtr = &src;
}
-
+
if (screenDensity != 0 && screenDensity != bitmapDensity) {
- SkPaint filteredPaint;
if (paint) {
filteredPaint = *paint;
}
filteredPaint.setFilterBitmap(true);
- canvas->drawBitmapRect(*bitmap, srcPtr, dst, &filteredPaint);
+ paint = &filteredPaint;
+ }
+
+ //If we're doing downscaling and we have an unscaled bitmap, convert
+ //this to an upscaling operation, or at least less of a downscale
+ SkBitmap* unscaled = bitmap->unscaledBitmap();
+ if (NULL != srcPtr && NULL != unscaled) {
+ //use new bitmap and adapt the coordinates of the src rect to this new bitmap
+ SkScalar dx, dy;
+ SkRect srcF;
+ dx = SkScalarDiv(SkIntToScalar(unscaled->width()), SkIntToScalar(bitmap->width()));
+ dy = SkScalarDiv(SkIntToScalar(unscaled->height()), SkIntToScalar(bitmap->height()));
+ srcF.set(SkScalarMul(SkIntToScalar(src.left()), dx),
+ SkScalarMul(SkIntToScalar(src.top()), dy),
+ SkScalarMul(SkIntToScalar(src.right()), dx),
+ SkScalarMul(SkIntToScalar(src.bottom()), dy));
+
+ canvas->drawBitmapScalarRect(*unscaled, &srcF, dst, paint);
} else {
canvas->drawBitmapRect(*bitmap, srcPtr, dst, paint);
}
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 150caf3c5a9..067bd941909 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -740,7 +740,23 @@ class SkPaintGlue {
jfloat* array = autoMeasured.ptr();
array[0] = SkScalarToFloat(measured);
}
- return bytes >> 1;
+
+ //we've got the number of glyphs processed, but we need the number of characters
+ int measuredCount = bytes >> 1;
+ int charCount = 0;
+ int advanceCount = value->getAdvancesCount();
+ const jfloat* advances = value->getAdvances();
+ for (; charCount < advanceCount; charCount ++) {
+ //0 length means ZWSP, which is added in case a glyphs is for more than 1 chars
+ if (advances[charCount] > 0) {
+ measuredCount --;
+ if (measuredCount < 0) {
+ break;
+ }
+ }
+ }
+
+ return charCount;
}
static int breakTextC(JNIEnv* env, jobject jpaint, jcharArray jtext,
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 4669c378365..e4d794f1153 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -144,7 +144,7 @@ sp TextLayoutCache::getValue(const SkPaint* paint,
"This indicates that the cache already has an entry with the "
"same key but it should not since we checked earlier!"
" - start = %d, count = %d, contextCount = %d - Text = '%s'",
- start, count, contextCount, String8(key.getText() + start, count).string());
+ start, count, contextCount, String8(reinterpret_cast(key.getText() + start), count).string());
if (mDebugEnabled) {
nsecs_t totalTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime;
@@ -155,7 +155,8 @@ sp TextLayoutCache::getValue(const SkPaint* paint,
value.get(), start, count, contextCount, size, mMaxSize - mSize,
value->getElapsedTime() * 0.000001f,
(totalTime - value->getElapsedTime()) * 0.000001f,
- String8(key.getText() + start, count).string());
+ String8(reinterpret_cast(key.getText() + start), count).string());
+
}
} else {
if (mDebugEnabled) {
@@ -165,7 +166,8 @@ sp TextLayoutCache::getValue(const SkPaint* paint,
" - Compute time %0.6f ms - Text = '%s'",
start, count, contextCount, size, mMaxSize - mSize,
value->getElapsedTime() * 0.000001f,
- String8(key.getText() + start, count).string());
+ String8(reinterpret_cast(key.getText() + start), count).string());
+
}
}
} else {
@@ -185,7 +187,8 @@ sp TextLayoutCache::getValue(const SkPaint* paint,
value->getElapsedTime() * 0.000001f,
elapsedTimeThruCacheGet * 0.000001f,
deltaPercent,
- String8(key.getText() + start, count).string());
+ String8(reinterpret_cast(key.getText() + start), count).string());
+
}
if (mCacheHitCount % DEFAULT_DUMP_STATS_CACHE_HIT_INTERVAL == 0) {
dumpCacheStats();
@@ -231,7 +234,7 @@ TextLayoutCacheKey::TextLayoutCacheKey(const SkPaint* paint, const UChar* text,
size_t start, size_t count, size_t contextCount, int dirFlags) :
start(start), count(count), contextCount(contextCount),
dirFlags(dirFlags) {
- textCopy.setTo(text, contextCount);
+ textCopy.setTo(reinterpret_cast(text), contextCount);
typeface = paint->getTypeface();
textSize = paint->getTextSize();
textSkewX = paint->getTextSkewX();
@@ -256,6 +259,7 @@ TextLayoutCacheKey::TextLayoutCacheKey(const TextLayoutCacheKey& other) :
hinting(other.hinting),
variant(other.variant),
language(other.language) {
+
}
int TextLayoutCacheKey::compare(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) {
@@ -296,6 +300,7 @@ int TextLayoutCacheKey::compare(const TextLayoutCacheKey& lhs, const TextLayoutC
if (lhs.language > rhs.language) return +1;
return memcmp(lhs.getText(), rhs.getText(), lhs.contextCount * sizeof(UChar));
+
}
size_t TextLayoutCacheKey::getSize() const {
@@ -420,7 +425,7 @@ void TextLayoutShaper::computeValues(const SkPaint* paint, const UChar* chars,
} else if (!U_SUCCESS(status) || rc < 1) {
ALOGW("Need to force to single run -- string = '%s',"
" status = %d, rc = %d",
- String8(chars + start, count).string(), status, int(rc));
+ String8((const char16_t*)chars + start, count).string(), status, int(rc));
isRTL = (paraDir == 1);
useSingleRun = true;
} else {
@@ -945,7 +950,7 @@ sp TextLayoutEngine::getValue(const SkPaint* paint, const jchar
contextCount, dirFlags);
if (value == NULL) {
ALOGE("Cannot get TextLayoutCache value for text = '%s'",
- String8(text + start, count).string());
+ String8((const char16_t*)text + start, count).string());
}
#else
value = new TextLayoutValue(count);
diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h
index 9994393a091..c6de95fdabf 100644
--- a/core/jni/android/graphics/TextLayoutCache.h
+++ b/core/jni/android/graphics/TextLayoutCache.h
@@ -83,7 +83,7 @@ class TextLayoutCacheKey {
static int compare(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs);
- inline const UChar* getText() const { return textCopy.string(); }
+ inline const UChar* getText() const { return (UChar*)textCopy.string(); }
private:
String16 textCopy;
@@ -99,7 +99,6 @@ class TextLayoutCacheKey {
SkPaint::Hinting hinting;
SkPaint::FontVariant variant;
SkLanguage language;
-
}; // TextLayoutCacheKey
inline int strictly_order_type(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) {
diff --git a/core/jni/android_content_res_Configuration.cpp b/core/jni/android_content_res_Configuration.cpp
index 246e3bd229a..f98948373b9 100644
--- a/core/jni/android_content_res_Configuration.cpp
+++ b/core/jni/android_content_res_Configuration.cpp
@@ -37,6 +37,7 @@ static struct {
jfieldID navigation;
jfieldID navigationHidden;
jfieldID orientation;
+ jfieldID uiInvertedMode;
jfieldID uiMode;
jfieldID screenWidthDp;
jfieldID screenHeightDp;
@@ -62,6 +63,7 @@ void android_Configuration_getFromJava(
<< ResTable_config::SHIFT_NAVHIDDEN;
out->orientation = env->GetIntField(clazz, gConfigurationClassInfo.orientation);
+ out->uiInvertedMode = env->GetIntField(clazz, gConfigurationClassInfo.uiInvertedMode);
out->uiMode = env->GetIntField(clazz, gConfigurationClassInfo.uiMode);
out->screenWidthDp = env->GetIntField(clazz, gConfigurationClassInfo.screenWidthDp);
@@ -114,6 +116,8 @@ int register_android_content_res_Configuration(JNIEnv* env)
"navigationHidden", "I");
GET_FIELD_ID(gConfigurationClassInfo.orientation, clazz,
"orientation", "I");
+ GET_FIELD_ID(gConfigurationClassInfo.uiInvertedMode, clazz,
+ "uiInvertedMode", "I");
GET_FIELD_ID(gConfigurationClassInfo.uiMode, clazz,
"uiMode", "I");
GET_FIELD_ID(gConfigurationClassInfo.screenWidthDp, clazz,
diff --git a/core/jni/android_database_SQLiteConnection.cpp b/core/jni/android_database_SQLiteConnection.cpp
index c9cf2fa9c28..f70f0d1900c 100644
--- a/core/jni/android_database_SQLiteConnection.cpp
+++ b/core/jni/android_database_SQLiteConnection.cpp
@@ -706,7 +706,7 @@ static jlong nativeExecuteForCursorWindow(JNIEnv* env, jclass clazz,
}
CopyRowResult cpr = copyRow(env, window, statement, numColumns, startPos, addedRows);
- if (cpr == CPR_FULL && addedRows && startPos + addedRows < requiredPos) {
+ if (cpr == CPR_FULL && addedRows && startPos + addedRows <= requiredPos) {
// We filled the window before we got to the one row that we really wanted.
// Clear the window and start filling it again from here.
// TODO: Would be nicer if we could progressively replace earlier rows.
diff --git a/core/jni/android_ddm_DdmHandleNativeHeap.cpp b/core/jni/android_ddm_DdmHandleNativeHeap.cpp
index 42d408d23ce..f5eaf94b15d 100644
--- a/core/jni/android_ddm_DdmHandleNativeHeap.cpp
+++ b/core/jni/android_ddm_DdmHandleNativeHeap.cpp
@@ -2,16 +2,16 @@
**
** Copyright 2006, 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
+** 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
+** 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
+** 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.
*/
@@ -23,20 +23,17 @@
#include
#include
+#include
#include
#include
#include
#include
-#if defined(__arm__)
-extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
- size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
-
-extern "C" void free_malloc_leak_info(uint8_t* info);
-#endif
+extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
+ size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
-#define MAPS_FILE_SIZE 65 * 1024
+extern "C" void free_malloc_leak_info(uint8_t* info);
struct Header {
size_t mapSize;
@@ -48,96 +45,57 @@ struct Header {
namespace android {
+static void ReadFile(const char* path, String8& s) {
+ int fd = open(path, O_RDONLY);
+ if (fd != -1) {
+ char bytes[1024];
+ ssize_t byteCount;
+ while ((byteCount = TEMP_FAILURE_RETRY(read(fd, bytes, sizeof(bytes)))) > 0) {
+ s.append(bytes, byteCount);
+ }
+ close(fd);
+ }
+}
+
/*
- * Retrieve the native heap information and the info from /proc//maps,
+ * Retrieve the native heap information and the info from /proc/self/maps,
* copy them into a byte[] with a "struct Header" that holds data offsets,
* and return the array.
*/
-static jbyteArray getLeakInfo(JNIEnv *env, jobject clazz)
-{
-#if defined(__arm__)
- // get the info in /proc/[pid]/map
+static jbyteArray DdmHandleNativeHeap_getLeakInfo(JNIEnv* env, jobject) {
Header header;
memset(&header, 0, sizeof(header));
- pid_t pid = getpid();
-
- char path[FILENAME_MAX];
- sprintf(path, "/proc/%d/maps", pid);
-
- struct stat sb;
- int ret = stat(path, &sb);
-
- uint8_t* mapsFile = NULL;
- if (ret == 0) {
- mapsFile = (uint8_t*)malloc(MAPS_FILE_SIZE);
- int fd = open(path, O_RDONLY);
-
- if (mapsFile != NULL && fd != -1) {
- int amount = 0;
- do {
- uint8_t* ptr = mapsFile + header.mapSize;
- amount = read(fd, ptr, MAPS_FILE_SIZE);
- if (amount <= 0) {
- if (errno != EINTR)
- break;
- else
- continue;
- }
- header.mapSize += amount;
- } while (header.mapSize < MAPS_FILE_SIZE);
-
- ALOGD("**** read %d bytes from '%s'", (int) header.mapSize, path);
- }
- }
+ String8 maps;
+ ReadFile("/proc/self/maps", maps);
+ header.mapSize = maps.size();
uint8_t* allocBytes;
- get_malloc_leak_info(&allocBytes, &header.allocSize, &header.allocInfoSize,
- &header.totalMemory, &header.backtraceSize);
+ get_malloc_leak_info(&allocBytes, &header.allocSize, &header.allocInfoSize,
+ &header.totalMemory, &header.backtraceSize);
- jbyte* bytes = NULL;
- jbyte* ptr = NULL;
- jbyteArray array = env->NewByteArray(sizeof(Header) + header.mapSize + header.allocSize);
- if (array == NULL) {
- goto done;
- }
-
- bytes = env->GetByteArrayElements(array, NULL);
- ptr = bytes;
-
-// ALOGD("*** mapSize: %d allocSize: %d allocInfoSize: %d totalMemory: %d",
-// header.mapSize, header.allocSize, header.allocInfoSize, header.totalMemory);
+ ALOGD("*** mapSize: %d allocSize: %d allocInfoSize: %d totalMemory: %d",
+ header.mapSize, header.allocSize, header.allocInfoSize, header.totalMemory);
- memcpy(ptr, &header, sizeof(header));
- ptr += sizeof(header);
-
- if (header.mapSize > 0 && mapsFile != NULL) {
- memcpy(ptr, mapsFile, header.mapSize);
- ptr += header.mapSize;
+ jbyteArray array = env->NewByteArray(sizeof(Header) + header.mapSize + header.allocSize);
+ if (array != NULL) {
+ env->SetByteArrayRegion(array, 0,
+ sizeof(header), reinterpret_cast(&header));
+ env->SetByteArrayRegion(array, sizeof(header),
+ maps.size(), reinterpret_cast(maps.string()));
+ env->SetByteArrayRegion(array, sizeof(header) + maps.size(),
+ header.allocSize, reinterpret_cast(allocBytes));
}
-
- memcpy(ptr, allocBytes, header.allocSize);
- env->ReleaseByteArrayElements(array, bytes, 0);
-done:
- if (mapsFile != NULL) {
- free(mapsFile);
- }
- // free the info up!
free_malloc_leak_info(allocBytes);
-
return array;
-#else
- return NULL;
-#endif
}
static JNINativeMethod method_table[] = {
- { "getLeakInfo", "()[B", (void*)getLeakInfo },
+ { "getLeakInfo", "()[B", (void*) DdmHandleNativeHeap_getLeakInfo },
};
-int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env)
-{
+int register_android_ddm_DdmHandleNativeHeap(JNIEnv* env) {
return AndroidRuntime::registerNativeMethods(env, "android/ddm/DdmHandleNativeHeap", method_table, NELEM(method_table));
}
diff --git a/core/jni/android_emoji_EmojiFactory.cpp b/core/jni/android_emoji_EmojiFactory.cpp
index a658561b059..43839972227 100644
--- a/core/jni/android_emoji_EmojiFactory.cpp
+++ b/core/jni/android_emoji_EmojiFactory.cpp
@@ -3,8 +3,7 @@
#define LOG_TAG "EmojiFactory_jni"
#include
-#include
-#include
+#include
#include "EmojiFactory.h"
#include | | | | | |