summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/accounts/AccountManagerService.java55
-rw-r--r--core/java/android/pim/vcard/ContactStruct.java4
-rw-r--r--core/java/android/pim/vcard/VCardComposer.java578
-rw-r--r--core/java/android/pim/vcard/VCardUtils.java28
-rw-r--r--core/java/android/widget/FasttrackBadgeWidget.java7
-rwxr-xr-xcore/res/res/drawable-hdpi/contact_header_bg.9.pngbin0 -> 219 bytes
-rwxr-xr-xcore/res/res/drawable-hdpi/ic_contact_picture_2.pngbin0 -> 1845 bytes
-rwxr-xr-xcore/res/res/drawable-hdpi/ic_contact_picture_3.pngbin0 -> 1105 bytes
-rwxr-xr-xcore/res/res/drawable-hdpi/stat_sys_data_connected_h.pngbin0 -> 1165 bytes
-rwxr-xr-xcore/res/res/drawable-hdpi/stat_sys_data_in_h.pngbin0 -> 1148 bytes
-rwxr-xr-xcore/res/res/drawable-hdpi/stat_sys_data_inandout_h.pngbin0 -> 1103 bytes
-rwxr-xr-xcore/res/res/drawable-hdpi/stat_sys_data_out_h.pngbin0 -> 1135 bytes
-rwxr-xr-xcore/res/res/drawable-land-hdpi/bottombar_565.pngbin0 -> 1040 bytes
-rw-r--r--core/res/res/drawable-land-mdpi/bottombar_565.png (renamed from core/res/res/drawable-land/bottombar_565.png)bin3214 -> 3214 bytes
-rw-r--r--core/res/res/drawable-mdpi/contact_header_bg.9.png (renamed from core/res/res/drawable/contact_header_bg.9.png)bin231 -> 231 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_contact_picture_2.png (renamed from core/res/res/drawable/ic_contact_picture_2.png)bin1894 -> 1894 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_contact_picture_3.png (renamed from core/res/res/drawable/ic_contact_picture_3.png)bin1364 -> 1364 bytes
-rw-r--r--core/res/res/drawable-mdpi/stat_sys_data_connected_h.png (renamed from core/res/res/drawable/stat_sys_data_connected_h.png)bin642 -> 642 bytes
-rw-r--r--core/res/res/drawable-mdpi/stat_sys_data_in_h.png (renamed from core/res/res/drawable/stat_sys_data_in_h.png)bin669 -> 669 bytes
-rw-r--r--core/res/res/drawable-mdpi/stat_sys_data_inandout_h.png (renamed from core/res/res/drawable/stat_sys_data_inandout_h.png)bin655 -> 655 bytes
-rw-r--r--core/res/res/drawable-mdpi/stat_sys_data_out_h.png (renamed from core/res/res/drawable/stat_sys_data_out_h.png)bin654 -> 654 bytes
-rw-r--r--core/res/res/drawable/fasttrack_nobadge.xml26
-rw-r--r--core/res/res/drawable/fasttrack_nobadge_highlight.9.pngbin0 -> 675 bytes
-rw-r--r--core/res/res/drawable/fasttrack_nobadge_normal.9.pngbin0 -> 390 bytes
-rw-r--r--core/res/res/drawable/fasttrack_nobadge_pressed.9.pngbin0 -> 675 bytes
25 files changed, 455 insertions, 243 deletions
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 2d2e75f..3b39ae4 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -102,6 +102,7 @@ public class AccountManagerService
private static final String ACCOUNTS_ID = "_id";
private static final String ACCOUNTS_NAME = "name";
private static final String ACCOUNTS_TYPE = "type";
+ private static final String ACCOUNTS_TYPE_COUNT = "count(type)";
private static final String ACCOUNTS_PASSWORD = "password";
private static final String TABLE_AUTHTOKENS = "authtokens";
@@ -127,6 +128,8 @@ public class AccountManagerService
private static final String[] ACCOUNT_NAME_TYPE_PROJECTION =
new String[]{ACCOUNTS_ID, ACCOUNTS_NAME, ACCOUNTS_TYPE};
+ private static final String[] ACCOUNT_TYPE_COUNT_PROJECTION =
+ new String[] { ACCOUNTS_TYPE, ACCOUNTS_TYPE_COUNT};
private static final Intent ACCOUNTS_CHANGED_INTENT;
private static final String COUNT_OF_MATCHING_GRANTS = ""
@@ -1455,18 +1458,54 @@ public class AccountManagerService
return asBinder();
}
- protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
- synchronized (mSessions) {
- final long now = SystemClock.elapsedRealtime();
- fout.println("AccountManagerService: " + mSessions.size() + " sessions");
- for (Session session : mSessions.values()) {
- fout.println(" " + session.toDebugString(now));
+ /**
+ * Searches array of arguments for the specified string
+ * @param args array of argument strings
+ * @param value value to search for
+ * @return true if the value is contained in the array
+ */
+ private static boolean scanArgs(String[] args, String value) {
+ if (args != null) {
+ for (String arg : args) {
+ if (value.equals(arg)) {
+ return true;
+ }
}
}
+ return false;
+ }
- fout.println();
+ protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
+ final boolean isCheckinRequest = scanArgs(args, "--checkin") || scanArgs(args, "-c");
- mAuthenticatorCache.dump(fd, fout, args);
+ if (isCheckinRequest) {
+ // This is a checkin request. *Only* upload the account types and the count of each.
+ SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+
+ Cursor cursor = db.query(TABLE_ACCOUNTS, ACCOUNT_TYPE_COUNT_PROJECTION,
+ null, null, ACCOUNTS_TYPE, null, null);
+ try {
+ while (cursor.moveToNext()) {
+ // print type,count
+ fout.println(cursor.getString(0) + "," + cursor.getString(1));
+ }
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ } else {
+ synchronized (mSessions) {
+ final long now = SystemClock.elapsedRealtime();
+ fout.println("AccountManagerService: " + mSessions.size() + " sessions");
+ for (Session session : mSessions.values()) {
+ fout.println(" " + session.toDebugString(now));
+ }
+ }
+
+ fout.println();
+ mAuthenticatorCache.dump(fd, fout, args);
+ }
}
private void doNotification(Account account, CharSequence message, Intent intent) {
diff --git a/core/java/android/pim/vcard/ContactStruct.java b/core/java/android/pim/vcard/ContactStruct.java
index 35224c7..915f09e 100644
--- a/core/java/android/pim/vcard/ContactStruct.java
+++ b/core/java/android/pim/vcard/ContactStruct.java
@@ -1051,8 +1051,8 @@ public class ContactStruct {
List<String> nameList;
switch (VCardConfig.getNameOrderType(mVCardType)) {
case VCardConfig.NAME_ORDER_JAPANESE:
- if (VCardUtils.containsOnlyAscii(mFamilyName) &&
- VCardUtils.containsOnlyAscii(mGivenName)) {
+ if (VCardUtils.containsOnlyPrintableAscii(mFamilyName) &&
+ VCardUtils.containsOnlyPrintableAscii(mGivenName)) {
nameList = Arrays.asList(mPrefix, mGivenName, mMiddleName, mFamilyName, mSuffix);
} else {
nameList = Arrays.asList(mPrefix, mFamilyName, mMiddleName, mGivenName, mSuffix);
diff --git a/core/java/android/pim/vcard/VCardComposer.java b/core/java/android/pim/vcard/VCardComposer.java
index 40b4fc4..b0376c4 100644
--- a/core/java/android/pim/vcard/VCardComposer.java
+++ b/core/java/android/pim/vcard/VCardComposer.java
@@ -56,8 +56,10 @@ import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* <p>
@@ -234,9 +236,8 @@ public class VCardComposer {
private static final String VCARD_PROPERTY_X_PHONETIC_LAST_NAME = "X-PHONETIC-LAST-NAME";
// Android specific properties
- private static final String VCARD_PROPERTY_X_PHONETIC_NAME = "X-PHONETIC-NAME";
+ // TODO: ues extra MIME-TYPE instead of adding this kind of inflexible fields
private static final String VCARD_PROPERTY_X_NICKNAME = "X-NICKNAME";
- // TODO: add properties like X-LATITUDE
// Property for call log entry
private static final String VCARD_PROPERTY_X_TIMESTAMP = "X-IRMC-CALL-DATETIME";
@@ -396,7 +397,7 @@ public class VCardComposer {
}
boolean needCharset = false;
- if (!(VCardUtils.containsOnlyAscii(phoneName))) {
+ if (!(VCardUtils.containsOnlyPrintableAscii(phoneName))) {
needCharset = true;
}
appendVCardLine(builder, VCARD_PROPERTY_FULL_NAME, phoneName, needCharset, false);
@@ -596,7 +597,7 @@ public class VCardComposer {
if (TextUtils.isEmpty(name)) {
name = mCursor.getString(NUMBER_COLUMN_INDEX);
}
- final boolean needCharset = !(VCardUtils.containsOnlyAscii(name));
+ final boolean needCharset = !(VCardUtils.containsOnlyPrintableAscii(name));
appendVCardLine(builder, VCARD_PROPERTY_FULL_NAME, name, needCharset, false);
appendVCardLine(builder, VCARD_PROPERTY_NAME, name, needCharset, false);
@@ -740,213 +741,220 @@ public class VCardComposer {
final Map<String, List<ContentValues>> contentValuesListMap) {
final List<ContentValues> contentValuesList = contentValuesListMap
.get(StructuredName.CONTENT_ITEM_TYPE);
- if (contentValuesList != null) {
+ if (contentValuesList != null && contentValuesList.size() > 0) {
appendStructuredNamesInternal(builder, contentValuesList);
} else if (mIsDoCoMo) {
appendVCardLine(builder, VCARD_PROPERTY_NAME, "");
+ } else if (mIsV30) {
+ // vCard 3.0 requires "N" and "FN" properties.
+ appendVCardLine(builder, VCARD_PROPERTY_NAME, "");
+ appendVCardLine(builder, VCARD_PROPERTY_FULL_NAME, "");
}
}
private void appendStructuredNamesInternal(final StringBuilder builder,
final List<ContentValues> contentValuesList) {
+ // For safety, we'll emit just one value around StructuredName, as external importers
+ // may get confused with multiple "N", "FN", etc. properties, though it is valid in
+ // vCard spec.
+ ContentValues primaryContentValues = null;
for (ContentValues contentValues : contentValuesList) {
- final String familyName = contentValues
- .getAsString(StructuredName.FAMILY_NAME);
- final String middleName = contentValues
- .getAsString(StructuredName.MIDDLE_NAME);
- final String givenName = contentValues
- .getAsString(StructuredName.GIVEN_NAME);
- final String prefix = contentValues
- .getAsString(StructuredName.PREFIX);
- final String suffix = contentValues
- .getAsString(StructuredName.SUFFIX);
- final String displayName = contentValues
- .getAsString(StructuredName.DISPLAY_NAME);
-
- // For now, some primary element is not encoded into Quoted-Printable, which is not
- // valid in vCard spec strictly. In the future, we may have to have some flag to
- // enable composer to encode these primary field into Quoted-Printable.
- if (!TextUtils.isEmpty(familyName) || !TextUtils.isEmpty(givenName)) {
- final String encodedFamily = escapeCharacters(familyName);
- final String encodedGiven = escapeCharacters(givenName);
- final String encodedMiddle = escapeCharacters(middleName);
- final String encodedPrefix = escapeCharacters(prefix);
- final String encodedSuffix = escapeCharacters(suffix);
-
- // N property. This order is specified by vCard spec and does not depend on countries.
- builder.append(VCARD_PROPERTY_NAME);
- if (!(VCardUtils.containsOnlyAscii(familyName) &&
- VCardUtils.containsOnlyAscii(givenName) &&
- VCardUtils.containsOnlyAscii(middleName) &&
- VCardUtils.containsOnlyAscii(prefix) &&
- VCardUtils.containsOnlyAscii(suffix))) {
- builder.append(VCARD_ATTR_SEPARATOR);
- builder.append(mVCardAttributeCharset);
- }
-
- builder.append(VCARD_DATA_SEPARATOR);
- builder.append(encodedFamily);
- builder.append(VCARD_ITEM_SEPARATOR);
- builder.append(encodedGiven);
- builder.append(VCARD_ITEM_SEPARATOR);
- builder.append(encodedMiddle);
- builder.append(VCARD_ITEM_SEPARATOR);
- builder.append(encodedPrefix);
- builder.append(VCARD_ITEM_SEPARATOR);
- builder.append(encodedSuffix);
- builder.append(VCARD_COL_SEPARATOR);
-
- final String encodedFullname = VCardUtils.constructNameFromElements(
- VCardConfig.getNameOrderType(mVCardType),
- encodedFamily, encodedMiddle, encodedGiven, encodedPrefix, encodedSuffix);
+ Integer isSuperPrimary = contentValues.getAsInteger(StructuredName.IS_SUPER_PRIMARY);
+ if (isSuperPrimary != null && isSuperPrimary != 0) {
+ // We choose "super primary" ContentValues.
+ primaryContentValues = contentValues;
+ break;
+ } else if (primaryContentValues == null && contentValues != null) {
+ // We choose the first ContentValues if "super primary" ContentValues does not exist.
+ primaryContentValues = contentValues;
+ }
+ }
- // FN property
- builder.append(VCARD_PROPERTY_FULL_NAME);
- if (!VCardUtils.containsOnlyAscii(encodedFullname)) {
- builder.append(VCARD_ATTR_SEPARATOR);
- builder.append(mVCardAttributeCharset);
- }
- builder.append(VCARD_DATA_SEPARATOR);
- builder.append(encodedFullname);
- builder.append(VCARD_COL_SEPARATOR);
- } else if (!TextUtils.isEmpty(displayName)) {
- builder.append(VCARD_PROPERTY_NAME);
+ if (primaryContentValues == null) {
+ Log.e(LOG_TAG, "All ContentValues given from database is empty.");
+ primaryContentValues = new ContentValues();
+ }
+
+ final String familyName = primaryContentValues
+ .getAsString(StructuredName.FAMILY_NAME);
+ final String middleName = primaryContentValues
+ .getAsString(StructuredName.MIDDLE_NAME);
+ final String givenName = primaryContentValues
+ .getAsString(StructuredName.GIVEN_NAME);
+ final String prefix = primaryContentValues
+ .getAsString(StructuredName.PREFIX);
+ final String suffix = primaryContentValues
+ .getAsString(StructuredName.SUFFIX);
+ final String displayName = primaryContentValues
+ .getAsString(StructuredName.DISPLAY_NAME);
+
+ // For now, some primary element is not encoded into Quoted-Printable, which is not
+ // valid in vCard spec strictly. In the future, we may have to have some flag to
+ // enable composer to encode these primary field into Quoted-Printable.
+ if (!TextUtils.isEmpty(familyName) || !TextUtils.isEmpty(givenName)) {
+ final String encodedFamily = escapeCharacters(familyName);
+ final String encodedGiven = escapeCharacters(givenName);
+ final String encodedMiddle = escapeCharacters(middleName);
+ final String encodedPrefix = escapeCharacters(prefix);
+ final String encodedSuffix = escapeCharacters(suffix);
+
+ // N property. This order is specified by vCard spec and does not depend on countries.
+ builder.append(VCARD_PROPERTY_NAME);
+ if (!(VCardUtils.containsOnlyPrintableAscii(familyName) &&
+ VCardUtils.containsOnlyPrintableAscii(givenName) &&
+ VCardUtils.containsOnlyPrintableAscii(middleName) &&
+ VCardUtils.containsOnlyPrintableAscii(prefix) &&
+ VCardUtils.containsOnlyPrintableAscii(suffix))) {
builder.append(VCARD_ATTR_SEPARATOR);
builder.append(mVCardAttributeCharset);
- builder.append(VCARD_DATA_SEPARATOR);
- builder.append(escapeCharacters(displayName));
- builder.append(VCARD_ITEM_SEPARATOR);
- builder.append(VCARD_ITEM_SEPARATOR);
- builder.append(VCARD_ITEM_SEPARATOR);
- builder.append(VCARD_ITEM_SEPARATOR);
- builder.append(VCARD_COL_SEPARATOR);
- } else if (mIsDoCoMo) {
- appendVCardLine(builder, VCARD_PROPERTY_NAME, "");
}
- String phoneticFamilyName = contentValues
- .getAsString(StructuredName.PHONETIC_FAMILY_NAME);
- String phoneticMiddleName = contentValues
- .getAsString(StructuredName.PHONETIC_MIDDLE_NAME);
- String phoneticGivenName = contentValues
- .getAsString(StructuredName.PHONETIC_GIVEN_NAME);
- if (!(TextUtils.isEmpty(phoneticFamilyName)
- && TextUtils.isEmpty(phoneticMiddleName) && TextUtils
- .isEmpty(phoneticGivenName))) { // if not empty
- if (mIsJapaneseMobilePhone) {
- phoneticFamilyName = VCardUtils
- .toHalfWidthString(phoneticFamilyName);
- phoneticMiddleName = VCardUtils
- .toHalfWidthString(phoneticMiddleName);
- phoneticGivenName = VCardUtils
- .toHalfWidthString(phoneticGivenName);
- }
+ builder.append(VCARD_DATA_SEPARATOR);
+ builder.append(encodedFamily);
+ builder.append(VCARD_ITEM_SEPARATOR);
+ builder.append(encodedGiven);
+ builder.append(VCARD_ITEM_SEPARATOR);
+ builder.append(encodedMiddle);
+ builder.append(VCARD_ITEM_SEPARATOR);
+ builder.append(encodedPrefix);
+ builder.append(VCARD_ITEM_SEPARATOR);
+ builder.append(encodedSuffix);
+ builder.append(VCARD_COL_SEPARATOR);
- if (mIsV30) {
- final String sortString = VCardUtils
- .constructNameFromElements(mVCardType,
- phoneticFamilyName, phoneticMiddleName,
- phoneticGivenName);
- builder.append(VCARD_PROPERTY_SORT_STRING);
-
- if (!VCardUtils.containsOnlyAscii(sortString)) {
- // Strictly, adding charset information is NOT valid in
- // VCard 3.0,
- // but we'll add this info since parser side may be able to
- // use the charset via
- // this attribute field.
- //
- // e.g. Japanese mobile phones use Shift_Jis while RFC 2426
- // recommends
- // UTF-8. By adding this field, parsers may be able to know
- // this text
- // is NOT UTF-8 but Shift_Jis.
- builder.append(VCARD_ATTR_SEPARATOR);
- builder.append(mVCardAttributeCharset);
- }
+ final String encodedFullname = VCardUtils.constructNameFromElements(
+ VCardConfig.getNameOrderType(mVCardType),
+ encodedFamily, encodedMiddle, encodedGiven, encodedPrefix, encodedSuffix);
- builder.append(VCARD_DATA_SEPARATOR);
- builder.append(sortString);
- builder.append(VCARD_COL_SEPARATOR);
- } else {
- // Note: There is no appropriate property for expressing
- // phonetic name in
- // VCard 2.1, while there is in VCard 3.0 (SORT-STRING).
- // We chose to use DoCoMo's way since it is supported by a
- // lot of
- // Japanese mobile phones.
+ // FN property
+ builder.append(VCARD_PROPERTY_FULL_NAME);
+ if (!VCardUtils.containsOnlyPrintableAscii(encodedFullname)) {
+ builder.append(VCARD_ATTR_SEPARATOR);
+ builder.append(mVCardAttributeCharset);
+ }
+ builder.append(VCARD_DATA_SEPARATOR);
+ builder.append(encodedFullname);
+ builder.append(VCARD_COL_SEPARATOR);
+ } else if (!TextUtils.isEmpty(displayName)) {
+ builder.append(VCARD_PROPERTY_NAME);
+ builder.append(VCARD_ATTR_SEPARATOR);
+ builder.append(mVCardAttributeCharset);
+ builder.append(VCARD_DATA_SEPARATOR);
+ builder.append(escapeCharacters(displayName));
+ builder.append(VCARD_ITEM_SEPARATOR);
+ builder.append(VCARD_ITEM_SEPARATOR);
+ builder.append(VCARD_ITEM_SEPARATOR);
+ builder.append(VCARD_ITEM_SEPARATOR);
+ builder.append(VCARD_COL_SEPARATOR);
+ } else if (mIsDoCoMo) {
+ appendVCardLine(builder, VCARD_PROPERTY_NAME, "");
+ } else if (mIsV30) {
+ appendVCardLine(builder, VCARD_PROPERTY_NAME, "");
+ appendVCardLine(builder, VCARD_PROPERTY_FULL_NAME, "");
+ }
+
+ String phoneticFamilyName = primaryContentValues
+ .getAsString(StructuredName.PHONETIC_FAMILY_NAME);
+ String phoneticMiddleName = primaryContentValues
+ .getAsString(StructuredName.PHONETIC_MIDDLE_NAME);
+ String phoneticGivenName = primaryContentValues
+ .getAsString(StructuredName.PHONETIC_GIVEN_NAME);
+ if (!(TextUtils.isEmpty(phoneticFamilyName)
+ && TextUtils.isEmpty(phoneticMiddleName) &&
+ TextUtils.isEmpty(phoneticGivenName))) { // if not empty
+ if (mIsJapaneseMobilePhone) {
+ phoneticFamilyName = VCardUtils
+ .toHalfWidthString(phoneticFamilyName);
+ phoneticMiddleName = VCardUtils
+ .toHalfWidthString(phoneticMiddleName);
+ phoneticGivenName = VCardUtils
+ .toHalfWidthString(phoneticGivenName);
+ }
+
+ if (mIsV30) {
+ final String sortString = VCardUtils
+ .constructNameFromElements(mVCardType,
+ phoneticFamilyName, phoneticMiddleName,
+ phoneticGivenName);
+ builder.append(VCARD_PROPERTY_SORT_STRING);
+
+ if (!VCardUtils.containsOnlyPrintableAscii(sortString)) {
+ // Strictly, adding charset information is NOT valid in
+ // VCard 3.0,
+ // but we'll add this info since parser side may be able to
+ // use the charset via
+ // this attribute field.
//
- // TODO: should use Quoted-Pritable?
- builder.append(VCARD_PROPERTY_SOUND);
- builder.append(VCARD_ATTR_SEPARATOR);
- builder.append(Constants.ATTR_TYPE_X_IRMC_N);
+ // e.g. Japanese mobile phones use Shift_Jis while RFC 2426
+ // recommends
+ // UTF-8. By adding this field, parsers may be able to know
+ // this text
+ // is NOT UTF-8 but Shift_Jis.
builder.append(VCARD_ATTR_SEPARATOR);
-
- if (!(VCardUtils.containsOnlyAscii(phoneticFamilyName) &&
- VCardUtils.containsOnlyAscii(phoneticMiddleName) &&
- VCardUtils.containsOnlyAscii(phoneticGivenName))) {
- builder.append(mVCardAttributeCharset);
- builder.append(VCARD_DATA_SEPARATOR);
- }
-
- builder.append(escapeCharacters(phoneticFamilyName));
- builder.append(VCARD_ITEM_SEPARATOR);
- builder.append(escapeCharacters(phoneticMiddleName));
- builder.append(VCARD_ITEM_SEPARATOR);
- builder.append(escapeCharacters(phoneticGivenName));
- builder.append(VCARD_ITEM_SEPARATOR);
- builder.append(VCARD_ITEM_SEPARATOR);
- builder.append(VCARD_COL_SEPARATOR);
-
- if (mUsesAndroidProperty) {
- final String phoneticName = VCardUtils
- .constructNameFromElements(mVCardType,
- phoneticFamilyName, phoneticMiddleName,
- phoneticGivenName);
- builder.append(VCARD_PROPERTY_X_PHONETIC_NAME);
-
- if (!VCardUtils.containsOnlyAscii(phoneticName)) {
- builder.append(VCARD_ATTR_SEPARATOR);
- builder.append(mVCardAttributeCharset);
- }
-
- builder.append(VCARD_DATA_SEPARATOR);
- // TODO: may need to make the text quoted-printable.
- builder.append(phoneticName);
- builder.append(VCARD_COL_SEPARATOR);
- }
+ builder.append(mVCardAttributeCharset);
}
- } else if (mIsDoCoMo) {
+
+ builder.append(VCARD_DATA_SEPARATOR);
+ builder.append(sortString);
+ builder.append(VCARD_COL_SEPARATOR);
+ } else {
+ // Note: There is no appropriate property for expressing
+ // phonetic name in
+ // VCard 2.1, while there is in VCard 3.0 (SORT-STRING).
+ // We chose to use DoCoMo's way since it is supported by a
+ // lot of Japanese mobile phones.
+ //
+ // TODO: should use Quoted-Pritable?
builder.append(VCARD_PROPERTY_SOUND);
builder.append(VCARD_ATTR_SEPARATOR);
builder.append(Constants.ATTR_TYPE_X_IRMC_N);
- builder.append(VCARD_DATA_SEPARATOR);
+ builder.append(VCARD_ATTR_SEPARATOR);
+
+ if (!(VCardUtils.containsOnlyPrintableAscii(phoneticFamilyName) &&
+ VCardUtils.containsOnlyPrintableAscii(phoneticMiddleName) &&
+ VCardUtils.containsOnlyPrintableAscii(phoneticGivenName))) {
+ builder.append(mVCardAttributeCharset);
+ builder.append(VCARD_DATA_SEPARATOR);
+ }
+
+ builder.append(escapeCharacters(phoneticFamilyName));
builder.append(VCARD_ITEM_SEPARATOR);
+ builder.append(escapeCharacters(phoneticMiddleName));
builder.append(VCARD_ITEM_SEPARATOR);
+ builder.append(escapeCharacters(phoneticGivenName));
builder.append(VCARD_ITEM_SEPARATOR);
builder.append(VCARD_ITEM_SEPARATOR);
builder.append(VCARD_COL_SEPARATOR);
}
+ } else if (mIsDoCoMo) {
+ builder.append(VCARD_PROPERTY_SOUND);
+ builder.append(VCARD_ATTR_SEPARATOR);
+ builder.append(Constants.ATTR_TYPE_X_IRMC_N);
+ builder.append(VCARD_DATA_SEPARATOR);
+ builder.append(VCARD_ITEM_SEPARATOR);
+ builder.append(VCARD_ITEM_SEPARATOR);
+ builder.append(VCARD_ITEM_SEPARATOR);
+ builder.append(VCARD_ITEM_SEPARATOR);
+ builder.append(VCARD_COL_SEPARATOR);
+ }
- if (mUsesDefactProperty) {
- if (!TextUtils.isEmpty(phoneticGivenName)) {
- builder.append(VCARD_PROPERTY_X_PHONETIC_FIRST_NAME);
- builder.append(VCARD_DATA_SEPARATOR);
- builder.append(phoneticGivenName);
- builder.append(VCARD_COL_SEPARATOR);
- }
- if (!TextUtils.isEmpty(phoneticMiddleName)) {
- builder.append(VCARD_PROPERTY_X_PHONETIC_MIDDLE_NAME);
- builder.append(VCARD_DATA_SEPARATOR);
- builder.append(phoneticMiddleName);
- builder.append(VCARD_COL_SEPARATOR);
- }
- if (!TextUtils.isEmpty(phoneticFamilyName)) {
- builder.append(VCARD_PROPERTY_X_PHONETIC_LAST_NAME);
- builder.append(VCARD_DATA_SEPARATOR);
- builder.append(phoneticFamilyName);
- builder.append(VCARD_COL_SEPARATOR);
- }
+ if (mUsesDefactProperty) {
+ if (!TextUtils.isEmpty(phoneticGivenName)) {
+ builder.append(VCARD_PROPERTY_X_PHONETIC_FIRST_NAME);
+ builder.append(VCARD_DATA_SEPARATOR);
+ builder.append(phoneticGivenName);
+ builder.append(VCARD_COL_SEPARATOR);
+ }
+ if (!TextUtils.isEmpty(phoneticMiddleName)) {
+ builder.append(VCARD_PROPERTY_X_PHONETIC_MIDDLE_NAME);
+ builder.append(VCARD_DATA_SEPARATOR);
+ builder.append(phoneticMiddleName);
+ builder.append(VCARD_COL_SEPARATOR);
+ }
+ if (!TextUtils.isEmpty(phoneticFamilyName)) {
+ builder.append(VCARD_PROPERTY_X_PHONETIC_LAST_NAME);
+ builder.append(VCARD_DATA_SEPARATOR);
+ builder.append(phoneticFamilyName);
+ builder.append(VCARD_COL_SEPARATOR);
}
}
}
@@ -974,7 +982,7 @@ public class VCardComposer {
}
builder.append(propertyNickname);
- if (!VCardUtils.containsOnlyAscii(propertyNickname)) {
+ if (!VCardUtils.containsOnlyPrintableAscii(propertyNickname)) {
// Strictly, this is not valid in vCard 3.0. See above.
builder.append(VCARD_ATTR_SEPARATOR);
builder.append(mVCardAttributeCharset);
@@ -991,16 +999,31 @@ public class VCardComposer {
final Map<String, List<ContentValues>> contentValuesListMap) {
final List<ContentValues> contentValuesList = contentValuesListMap
.get(Phone.CONTENT_ITEM_TYPE);
+ boolean phoneLineExists = false;
if (contentValuesList != null) {
+ Set<String> phoneSet = new HashSet<String>();
for (ContentValues contentValues : contentValuesList) {
- Integer phoneType = contentValues.getAsInteger(Phone.TYPE);
- int phoneTypeAsPrimitive =
- (phoneType == null ? Phone.TYPE_HOME : phoneType);
- appendVCardTelephoneLine(builder, phoneTypeAsPrimitive,
- contentValues.getAsString(Phone.LABEL),
- contentValues.getAsString(Phone.NUMBER));
+ final Integer typeAsObject = contentValues.getAsInteger(Phone.TYPE);
+ final String label = contentValues.getAsString(Phone.LABEL);
+ String phoneNumber = contentValues.getAsString(Phone.NUMBER);
+ if (phoneNumber != null) {
+ phoneNumber = phoneNumber.trim();
+ }
+ if (TextUtils.isEmpty(phoneNumber)) {
+ continue;
+ }
+ phoneLineExists = true;
+ int type = (typeAsObject != null ? typeAsObject : Phone.TYPE_HOME);
+ // TODO: Premature, since this allows two phone numbers which are
+ // same from the view of phone number format (e.g. "100" v.s. "1-0-0")
+ if (!phoneSet.contains(phoneNumber)) {
+ phoneSet.add(phoneNumber);
+ appendVCardTelephoneLine(builder, type, label, phoneNumber);
+ }
}
- } else if (mIsDoCoMo) {
+ }
+
+ if (!phoneLineExists && mIsDoCoMo) {
appendVCardTelephoneLine(builder, Phone.TYPE_HOME, "", "");
}
}
@@ -1009,14 +1032,31 @@ public class VCardComposer {
final Map<String, List<ContentValues>> contentValuesListMap) {
final List<ContentValues> contentValuesList = contentValuesListMap
.get(Email.CONTENT_ITEM_TYPE);
+ boolean emailAddressExists = false;
if (contentValuesList != null) {
+ Set<String> addressSet = new HashSet<String>();
for (ContentValues contentValues : contentValuesList) {
- appendVCardEmailLine(builder, contentValues
- .getAsInteger(Email.TYPE), contentValues
- .getAsString(Email.LABEL), contentValues
- .getAsString(Email.DATA));
+ Integer typeAsObject = contentValues.getAsInteger(Email.TYPE);
+ final int type = (typeAsObject != null ?
+ typeAsObject : Email.TYPE_OTHER);
+ final String label = contentValues.getAsString(Email.LABEL);
+ String emailAddress = contentValues.getAsString(Email.DATA);
+ if (emailAddress != null) {
+ emailAddress = emailAddress.trim();
+ }
+ if (TextUtils.isEmpty(emailAddress)) {
+ continue;
+ }
+ emailAddressExists = true;
+ // Do not allow completely same email address line emitted into each file.
+ if (!addressSet.contains(emailAddress)) {
+ addressSet.add(emailAddress);
+ appendVCardEmailLine(builder, type, label, emailAddress);
+ }
}
- } else if (mIsDoCoMo) {
+ }
+
+ if (!emailAddressExists && mIsDoCoMo) {
appendVCardEmailLine(builder, Email.TYPE_HOME, "", "");
}
}
@@ -1087,7 +1127,9 @@ public class VCardComposer {
for (ContentValues contentValues : contentValuesList) {
final Integer type = contentValues.getAsInteger(StructuredPostal.TYPE);
final String label = contentValues.getAsString(StructuredPostal.LABEL);
- appendVCardPostalLine(builder, type, label, contentValues);
+ if (type != null) {
+ appendVCardPostalLine(builder, type, label, contentValues);
+ }
}
}
@@ -1099,6 +1141,12 @@ public class VCardComposer {
for (ContentValues contentValues : contentValuesList) {
Integer protocol = contentValues.getAsInteger(Im.PROTOCOL);
String data = contentValues.getAsString(Im.DATA);
+ if (data != null) {
+ data = data.trim();
+ }
+ if (TextUtils.isEmpty(data)) {
+ continue;
+ }
if (protocol != null && protocol == Im.PROTOCOL_GOOGLE_TALK) {
if (VCardConfig.usesAndroidSpecificProperty(mVCardType)) {
@@ -1116,8 +1164,13 @@ public class VCardComposer {
.get(Website.CONTENT_ITEM_TYPE);
if (contentValuesList != null) {
for (ContentValues contentValues : contentValuesList) {
- final String website = contentValues.getAsString(Website.URL);
- appendVCardLine(builder, VCARD_PROPERTY_URL, website);
+ String website = contentValues.getAsString(Website.URL);
+ if (website != null) {
+ website = website.trim();
+ }
+ if (!TextUtils.isEmpty(website)) {
+ appendVCardLine(builder, VCARD_PROPERTY_URL, website);
+ }
}
}
}
@@ -1130,8 +1183,13 @@ public class VCardComposer {
// Theoretically, there must be only one birthday for each vCard data and
// we are afraid of some parse error occuring in some devices, so
// we emit only one birthday entry for now.
- final String birthday = contentValuesList.get(0).getAsString(Birthday.BIRTHDAY);
- appendVCardLine(builder, VCARD_PROPERTY_BIRTHDAY, birthday);
+ String birthday = contentValuesList.get(0).getAsString(Birthday.BIRTHDAY);
+ if (birthday != null) {
+ birthday = birthday.trim();
+ }
+ if (!TextUtils.isEmpty(birthday)) {
+ appendVCardLine(builder, VCARD_PROPERTY_BIRTHDAY, birthday);
+ }
}
}
@@ -1141,14 +1199,29 @@ public class VCardComposer {
.get(Organization.CONTENT_ITEM_TYPE);
if (contentValuesList != null) {
for (ContentValues contentValues : contentValuesList) {
- final String company = contentValues
+ String company = contentValues
.getAsString(Organization.COMPANY);
- final String title = contentValues
+ if (company != null) {
+ company = company.trim();
+ }
+ String title = contentValues
.getAsString(Organization.TITLE);
- appendVCardLine(builder, VCARD_PROPERTY_ORG, company, true,
- mUsesQuotedPrintable);
- appendVCardLine(builder, VCARD_PROPERTY_TITLE, title, true,
- mUsesQuotedPrintable);
+ if (title != null) {
+ title = title.trim();
+ }
+
+ if (!TextUtils.isEmpty(company)) {
+ appendVCardLine(builder, VCARD_PROPERTY_ORG, company,
+ !VCardUtils.containsOnlyPrintableAscii(company),
+ (mUsesQuotedPrintable &&
+ !VCardUtils.containsOnlyNonCrLfPrintableAscii(company)));
+ }
+ if (!TextUtils.isEmpty(title)) {
+ appendVCardLine(builder, VCARD_PROPERTY_TITLE, title,
+ !VCardUtils.containsOnlyPrintableAscii(title),
+ (mUsesQuotedPrintable &&
+ !VCardUtils.containsOnlyNonCrLfPrintableAscii(title)));
+ }
}
}
}
@@ -1201,7 +1274,10 @@ public class VCardComposer {
StringBuilder noteBuilder = new StringBuilder();
boolean first = true;
for (ContentValues contentValues : contentValuesList) {
- final String note = contentValues.getAsString(Note.NOTE);
+ String note = contentValues.getAsString(Note.NOTE);
+ if (note == null) {
+ note = "";
+ }
if (note.length() > 0) {
if (first) {
first = false;
@@ -1211,14 +1287,27 @@ public class VCardComposer {
noteBuilder.append(note);
}
}
- appendVCardLine(builder, VCARD_PROPERTY_NOTE, noteBuilder.toString(),
- true, mUsesQuotedPrintable);
+ final String noteStr = noteBuilder.toString();
+ // This means we scan noteStr completely twice, which is redundant.
+ // But for now, we assume this is not so time-consuming..
+ final boolean shouldAppendCharsetInfo =
+ !VCardUtils.containsOnlyPrintableAscii(noteStr);
+ final boolean reallyUseQuotedPrintable =
+ (mUsesQuotedPrintable &&
+ !VCardUtils.containsOnlyNonCrLfPrintableAscii(noteStr));
+ appendVCardLine(builder, VCARD_PROPERTY_NOTE, noteStr,
+ shouldAppendCharsetInfo, reallyUseQuotedPrintable);
} else {
for (ContentValues contentValues : contentValuesList) {
- final String note = contentValues.getAsString(Note.NOTE);
- if (!TextUtils.isEmpty(note)) {
- appendVCardLine(builder, VCARD_PROPERTY_NOTE, note, true,
- mUsesQuotedPrintable);
+ final String noteStr = contentValues.getAsString(Note.NOTE);
+ if (!TextUtils.isEmpty(noteStr)) {
+ final boolean shouldAppendCharsetInfo =
+ !VCardUtils.containsOnlyPrintableAscii(noteStr);
+ final boolean reallyUseQuotedPrintable =
+ (mUsesQuotedPrintable &&
+ !VCardUtils.containsOnlyNonCrLfPrintableAscii(noteStr));
+ appendVCardLine(builder, VCARD_PROPERTY_NOTE, noteStr,
+ shouldAppendCharsetInfo, reallyUseQuotedPrintable);
}
}
}
@@ -1339,15 +1428,31 @@ public class VCardComposer {
builder.append(VCARD_PROPERTY_ADR);
builder.append(VCARD_ATTR_SEPARATOR);
+ // Note: Not sure why we need to emit "empty" line even when actual data does not exist.
+ // There may be some reason or may not be any. We keep safer side.
+ // TODO: investigate this.
boolean dataExists = false;
String[] dataArray = VCardUtils.getVCardPostalElements(contentValues);
+ boolean actuallyUseQuotedPrintable = false;
+ boolean shouldAppendCharset = false;
+ for (String data : dataArray) {
+ if (!TextUtils.isEmpty(data)) {
+ dataExists = true;
+ if (!shouldAppendCharset && !VCardUtils.containsOnlyPrintableAscii(data)) {
+ shouldAppendCharset = true;
+ }
+ if (mUsesQuotedPrintable && !VCardUtils.containsOnlyNonCrLfPrintableAscii(data)) {
+ actuallyUseQuotedPrintable = true;
+ break;
+ }
+ }
+ }
+
int length = dataArray.length;
- final boolean useQuotedPrintable = mUsesQuotedPrintable;
for (int i = 0; i < length; i++) {
String data = dataArray[i];
if (!TextUtils.isEmpty(data)) {
- dataExists = true;
- if (useQuotedPrintable) {
+ if (actuallyUseQuotedPrintable) {
dataArray[i] = encodeQuotedPrintable(data);
} else {
dataArray[i] = escapeCharacters(data);
@@ -1394,25 +1499,40 @@ public class VCardComposer {
}
}
- if (typeAsString != null) {
- appendTypeAttribute(builder, typeAsString);
- }
+ // Attribute(s).
- if (dataExists) {
- // Strictly, vCard 3.0 does not allow exporters to emit charset information,
- // but we will add it since the information should be useful for importers,
- //
- // Assume no parser does not emit error with this attribute in vCard 3.0.
+ {
+ boolean shouldAppendAttrSeparator = false;
if (typeAsString != null) {
- builder.append(VCARD_ATTR_SEPARATOR);
+ appendTypeAttribute(builder, typeAsString);
+ shouldAppendAttrSeparator = true;
}
- builder.append(mVCardAttributeCharset);
- if (useQuotedPrintable) {
- builder.append(VCARD_ATTR_SEPARATOR);
- builder.append(VCARD_ATTR_ENCODING_QP);
+ if (dataExists) {
+ if (shouldAppendCharset) {
+ // Strictly, vCard 3.0 does not allow exporters to emit charset information,
+ // but we will add it since the information should be useful for importers,
+ //
+ // Assume no parser does not emit error with this attribute in vCard 3.0.
+ if (shouldAppendAttrSeparator) {
+ builder.append(VCARD_ATTR_SEPARATOR);
+ }
+ builder.append(mVCardAttributeCharset);
+ shouldAppendAttrSeparator = true;
+ }
+
+ if (actuallyUseQuotedPrintable) {
+ if (shouldAppendAttrSeparator) {
+ builder.append(VCARD_ATTR_SEPARATOR);
+ }
+ builder.append(VCARD_ATTR_ENCODING_QP);
+ shouldAppendAttrSeparator = true;
+ }
}
}
+
+ // Property values.
+
builder.append(VCARD_DATA_SEPARATOR);
if (dataExists) {
// The elements in dataArray are already encoded to quoted printable
diff --git a/core/java/android/pim/vcard/VCardUtils.java b/core/java/android/pim/vcard/VCardUtils.java
index ffceade..4f50103 100644
--- a/core/java/android/pim/vcard/VCardUtils.java
+++ b/core/java/android/pim/vcard/VCardUtils.java
@@ -283,7 +283,7 @@ public class VCardUtils {
return builder.toString();
}
- public static boolean containsOnlyAscii(String str) {
+ public static boolean containsOnlyPrintableAscii(String str) {
if (TextUtils.isEmpty(str)) {
return true;
}
@@ -299,13 +299,35 @@ public class VCardUtils {
}
return true;
}
-
+
+ /**
+ * This is useful when checking the string should be encoded into quoted-printable
+ * or not, which is required by vCard 2.1.
+ * See the definition of "7bit" in vCard 2.1 spec for more information.
+ */
+ public static boolean containsOnlyNonCrLfPrintableAscii(String str) {
+ if (TextUtils.isEmpty(str)) {
+ return true;
+ }
+
+ final int length = str.length();
+ final int asciiFirst = 0x20;
+ final int asciiLast = 0x126;
+ for (int i = 0; i < length; i = str.offsetByCodePoints(i, 1)) {
+ int c = str.codePointAt(i);
+ if (c < asciiFirst || asciiLast < c || c == '\n' || c == '\r') {
+ return false;
+ }
+ }
+ return true;
+ }
+
/**
* This is useful since vCard 3.0 often requires the ("X-") properties and groups
* should contain only alphabets, digits, and hyphen.
*
* Note: It is already known some devices (wrongly) outputs properties with characters
- * which should not be in the field. One example is "X-GOOGLE TALK". We appreciate
+ * which should not be in the field. One example is "X-GOOGLE TALK". We accept
* such kind of input but must never output it unless the target is very specific
* to the device which is able to parse the malformed input.
*/
diff --git a/core/java/android/widget/FasttrackBadgeWidget.java b/core/java/android/widget/FasttrackBadgeWidget.java
index 8c8e054..ba8539f 100644
--- a/core/java/android/widget/FasttrackBadgeWidget.java
+++ b/core/java/android/widget/FasttrackBadgeWidget.java
@@ -33,6 +33,7 @@ import android.provider.ContactsContract.CommonDataKinds.Email;
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
+import com.android.internal.R;
/**
* Widget used to show an image with the standard fasttrack badge
@@ -48,6 +49,7 @@ public class FasttrackBadgeWidget extends ImageView implements OnClickListener {
private int mMode;
private QueryHandler mQueryHandler;
private Drawable mBadgeBackground;
+ private Drawable mNoBadgeBackground;
protected String[] mExcludeMimes = null;
@@ -119,7 +121,10 @@ public class FasttrackBadgeWidget extends ImageView implements OnClickListener {
private void onContactUriChanged() {
if (mContactUri == null && mContactEmail == null && mContactPhone == null) {
- setBackgroundDrawable(null);
+ if (mNoBadgeBackground == null) {
+ mNoBadgeBackground = getResources().getDrawable(R.drawable.fasttrack_nobadge);
+ }
+ setBackgroundDrawable(mNoBadgeBackground);
} else {
setBackgroundDrawable(mBadgeBackground);
}
diff --git a/core/res/res/drawable-hdpi/contact_header_bg.9.png b/core/res/res/drawable-hdpi/contact_header_bg.9.png
new file mode 100755
index 0000000..981b2e9
--- /dev/null
+++ b/core/res/res/drawable-hdpi/contact_header_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_contact_picture_2.png b/core/res/res/drawable-hdpi/ic_contact_picture_2.png
new file mode 100755
index 0000000..5e65276
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_contact_picture_2.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_contact_picture_3.png b/core/res/res/drawable-hdpi/ic_contact_picture_3.png
new file mode 100755
index 0000000..a8ec1e1
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_contact_picture_3.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_data_connected_h.png b/core/res/res/drawable-hdpi/stat_sys_data_connected_h.png
new file mode 100755
index 0000000..24e07ab
--- /dev/null
+++ b/core/res/res/drawable-hdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_data_in_h.png b/core/res/res/drawable-hdpi/stat_sys_data_in_h.png
new file mode 100755
index 0000000..f2f6daa
--- /dev/null
+++ b/core/res/res/drawable-hdpi/stat_sys_data_in_h.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_data_inandout_h.png b/core/res/res/drawable-hdpi/stat_sys_data_inandout_h.png
new file mode 100755
index 0000000..5d6ef05
--- /dev/null
+++ b/core/res/res/drawable-hdpi/stat_sys_data_inandout_h.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_data_out_h.png b/core/res/res/drawable-hdpi/stat_sys_data_out_h.png
new file mode 100755
index 0000000..5e3122d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/stat_sys_data_out_h.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/bottombar_565.png b/core/res/res/drawable-land-hdpi/bottombar_565.png
new file mode 100755
index 0000000..9df56ca
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/bottombar_565.png
Binary files differ
diff --git a/core/res/res/drawable-land/bottombar_565.png b/core/res/res/drawable-land-mdpi/bottombar_565.png
index 6121856..6121856 100644
--- a/core/res/res/drawable-land/bottombar_565.png
+++ b/core/res/res/drawable-land-mdpi/bottombar_565.png
Binary files differ
diff --git a/core/res/res/drawable/contact_header_bg.9.png b/core/res/res/drawable-mdpi/contact_header_bg.9.png
index 7f9a5a3..7f9a5a3 100644
--- a/core/res/res/drawable/contact_header_bg.9.png
+++ b/core/res/res/drawable-mdpi/contact_header_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable/ic_contact_picture_2.png b/core/res/res/drawable-mdpi/ic_contact_picture_2.png
index 8b184af..8b184af 100644
--- a/core/res/res/drawable/ic_contact_picture_2.png
+++ b/core/res/res/drawable-mdpi/ic_contact_picture_2.png
Binary files differ
diff --git a/core/res/res/drawable/ic_contact_picture_3.png b/core/res/res/drawable-mdpi/ic_contact_picture_3.png
index a2d08b5..a2d08b5 100644
--- a/core/res/res/drawable/ic_contact_picture_3.png
+++ b/core/res/res/drawable-mdpi/ic_contact_picture_3.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_connected_h.png b/core/res/res/drawable-mdpi/stat_sys_data_connected_h.png
index 7d5413a..7d5413a 100644
--- a/core/res/res/drawable/stat_sys_data_connected_h.png
+++ b/core/res/res/drawable-mdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_in_h.png b/core/res/res/drawable-mdpi/stat_sys_data_in_h.png
index 695b80c..695b80c 100644
--- a/core/res/res/drawable/stat_sys_data_in_h.png
+++ b/core/res/res/drawable-mdpi/stat_sys_data_in_h.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_inandout_h.png b/core/res/res/drawable-mdpi/stat_sys_data_inandout_h.png
index 467acd1..467acd1 100644
--- a/core/res/res/drawable/stat_sys_data_inandout_h.png
+++ b/core/res/res/drawable-mdpi/stat_sys_data_inandout_h.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_out_h.png b/core/res/res/drawable-mdpi/stat_sys_data_out_h.png
index da50305..da50305 100644
--- a/core/res/res/drawable/stat_sys_data_out_h.png
+++ b/core/res/res/drawable-mdpi/stat_sys_data_out_h.png
Binary files differ
diff --git a/core/res/res/drawable/fasttrack_nobadge.xml b/core/res/res/drawable/fasttrack_nobadge.xml
new file mode 100644
index 0000000..538e165
--- /dev/null
+++ b/core/res/res/drawable/fasttrack_nobadge.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* bubble_with_chats.xml
+**
+** Copyright 2009, Google 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.
+*/
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true" android:drawable="@drawable/fasttrack_nobadge_pressed" />
+ <item android:state_selected="true" android:drawable="@drawable/fasttrack_nobadge_highlight" />
+ <item android:state_focused="true" android:drawable="@drawable/fasttrack_nobadge_highlight" />
+ <item android:state_enabled="false" android:drawable="@drawable/fasttrack_nobadge_normal" />
+ <item android:drawable="@drawable/fasttrack_nobadge_normal" />
+</selector>
diff --git a/core/res/res/drawable/fasttrack_nobadge_highlight.9.png b/core/res/res/drawable/fasttrack_nobadge_highlight.9.png
new file mode 100644
index 0000000..f0f50b3
--- /dev/null
+++ b/core/res/res/drawable/fasttrack_nobadge_highlight.9.png
Binary files differ
diff --git a/core/res/res/drawable/fasttrack_nobadge_normal.9.png b/core/res/res/drawable/fasttrack_nobadge_normal.9.png
new file mode 100644
index 0000000..01cc9dc
--- /dev/null
+++ b/core/res/res/drawable/fasttrack_nobadge_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable/fasttrack_nobadge_pressed.9.png b/core/res/res/drawable/fasttrack_nobadge_pressed.9.png
new file mode 100644
index 0000000..6e22c87
--- /dev/null
+++ b/core/res/res/drawable/fasttrack_nobadge_pressed.9.png
Binary files differ