Merge "Made QuickContacts on tablet a little smaller"
diff --git a/res/layout/date_picker.xml b/res/layout/date_picker.xml
index 4fb2318..4be95c0 100644
--- a/res/layout/date_picker.xml
+++ b/res/layout/date_picker.xml
@@ -19,12 +19,13 @@
<!-- Layout of date picker-->
-<!-- Warning: everything within the parent is removed and re-ordered depending
- on the date format selected by the user. -->
+<!-- The width of this container is manually set a little bigger than the one of the children
+ contained in it. This helps to prevent rounding errors when toggling the "Show year" option -->
+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_gravity="center_horizontal"
- android:layout_width="wrap_content"
+ android:layout_width="270dip"
android:layout_height="wrap_content">
<CheckBox
@@ -33,8 +34,11 @@
android:paddingTop="5dip"
android:paddingBottom="5dip"
android:textAppearance="?android:attr/textAppearanceLarge"
+ android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
+ <!-- Warning: everything within the parent is removed and re-ordered depending
+ on the date format selected by the user. -->
<LinearLayout
android:id="@+id/parent"
android:orientation="horizontal"
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index ec797e7..830fc00 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -220,7 +220,7 @@
<string name="searching_vcard_message" product="default" msgid="3962269894118092049">"Menelusuri data vCard pada kartu SD..."</string>
<string name="scanning_sdcard_failed_message" product="nosdcard" msgid="7221682312959229201">"Penyimpanan tidak dapat dipindai. (Alasan: \"<xliff:g id="FAIL_REASON">%s</xliff:g>\")"</string>
<string name="scanning_sdcard_failed_message" product="default" msgid="189023067829510792">"Kartu SD tidak dapat dipindai. (Alasan: \"<xliff:g id="FAIL_REASON">%s</xliff:g>\")"</string>
- <string name="fail_reason_io_error" msgid="6748358842976073255">"Galat I/O"</string>
+ <string name="fail_reason_io_error" msgid="6748358842976073255">"Kesalahan I/O"</string>
<string name="fail_reason_low_memory_during_import" msgid="875222757734882898">"Memori tidak cukup. File mungkin terlalu besar."</string>
<string name="fail_reason_vcard_parse_error" msgid="888263542360355784">"Tidak dapat mengurai vCard karena alasan yang tak terduga."</string>
<string name="fail_reason_not_supported" msgid="8219562769267148825">"Format tidak didukung."</string>
@@ -229,7 +229,7 @@
<string name="import_failure_no_vcard_file" product="default" msgid="1754014167874286173">"Tidak ditemukan file vCard pada kartu SD."</string>
<string name="fail_reason_failed_to_collect_vcard_meta_info" msgid="6427931733267328564">"Tidak dapat mengumpulkan informasi meta dari file vCard yang diberikan."</string>
<string name="fail_reason_failed_to_read_files" msgid="5823434810622484922">"Satu file atau lebih tidak dapat diimpor (%s)."</string>
- <string name="fail_reason_unknown" msgid="1714092345030570863">"Galat tidak dikenal."</string>
+ <string name="fail_reason_unknown" msgid="1714092345030570863">"Kesalahan tidak dikenal."</string>
<string name="select_vcard_title" msgid="7791371083694672861">"Pilih file vCard"</string>
<string name="caching_vcard_title" msgid="1226272312940516605">"Menyimpan ke tembolok"</string>
<string name="caching_vcard_message" msgid="4926308675041506756">"Menyimpan vCard ke tembolok untuk penyimpanan lokal sementara. Impor yang sebenarnya akan segera dimulai."</string>
@@ -259,7 +259,7 @@
<string name="exporting_contact_list_title" msgid="9072240631534457415">"Mengekspor data kenalan"</string>
<string name="exporting_contact_list_message" msgid="7181663157672374569">"Data kenalan Anda sedang diekspor ke: <xliff:g id="FILE_NAME">%s</xliff:g>."</string>
<string name="fail_reason_could_not_initialize_exporter" msgid="707260459259688510">"Tidak dapat memulai pengeskpor: \"<xliff:g id="EXACT_REASON">%s</xliff:g>\"."</string>
- <string name="fail_reason_error_occurred_during_export" msgid="3018855323913649063">"Terjadi galat saat ekspor: \"<xliff:g id="EXACT_REASON">%s</xliff:g>\"."</string>
+ <string name="fail_reason_error_occurred_during_export" msgid="3018855323913649063">"Terjadi kesalahan saat ekspor: \"<xliff:g id="EXACT_REASON">%s</xliff:g>\"."</string>
<string name="composer_failed_to_get_database_infomation" msgid="1765944280846236723">"Tidak dapat memperoleh informasi basis data."</string>
<string name="composer_has_no_exportable_contact" product="tablet" msgid="6991449891825077743">"Tidak ada data kenalan yang dapat diekspor. Jika Anda menyimpan data kenalan di tablet, beberapa penyedia data mungkin tidak mengizinkan data kenalan untuk diekspor dari tablet."</string>
<string name="composer_has_no_exportable_contact" product="default" msgid="3296493229040294335">"Tidak ada data kenalan yang dapat diekspor. Jika Anda menyimpan data kenalan pada ponsel, beberapa penyedia data tidak mengizinkan data kenalan diekspor dari ponsel."</string>
diff --git a/src/com/android/contacts/ContactSaveService.java b/src/com/android/contacts/ContactSaveService.java
index 6de361d..3fbca54 100644
--- a/src/com/android/contacts/ContactSaveService.java
+++ b/src/com/android/contacts/ContactSaveService.java
@@ -21,6 +21,7 @@
import com.android.contacts.model.EntityDelta;
import com.android.contacts.model.EntityDeltaList;
import com.android.contacts.model.EntityModifier;
+import com.android.contacts.util.CallerInfoCacheUtils;
import com.google.android.collect.Lists;
import com.google.android.collect.Sets;
@@ -177,11 +178,15 @@
@Override
protected void onHandleIntent(Intent intent) {
+ // Call an appropriate method. If we're sure it affects how incoming phone calls are
+ // handled, then notify the fact to in-call screen.
String action = intent.getAction();
if (ACTION_NEW_RAW_CONTACT.equals(action)) {
createRawContact(intent);
+ CallerInfoCacheUtils.sendUpdateCallerInfoCacheIntent(this);
} else if (ACTION_SAVE_CONTACT.equals(action)) {
saveContact(intent);
+ CallerInfoCacheUtils.sendUpdateCallerInfoCacheIntent(this);
} else if (ACTION_CREATE_GROUP.equals(action)) {
createGroup(intent);
} else if (ACTION_RENAME_GROUP.equals(action)) {
@@ -198,12 +203,16 @@
clearPrimary(intent);
} else if (ACTION_DELETE_CONTACT.equals(action)) {
deleteContact(intent);
+ CallerInfoCacheUtils.sendUpdateCallerInfoCacheIntent(this);
} else if (ACTION_JOIN_CONTACTS.equals(action)) {
joinContacts(intent);
+ CallerInfoCacheUtils.sendUpdateCallerInfoCacheIntent(this);
} else if (ACTION_SET_SEND_TO_VOICEMAIL.equals(action)) {
setSendToVoicemail(intent);
+ CallerInfoCacheUtils.sendUpdateCallerInfoCacheIntent(this);
} else if (ACTION_SET_RINGTONE.equals(action)) {
setRingtone(intent);
+ CallerInfoCacheUtils.sendUpdateCallerInfoCacheIntent(this);
}
}
diff --git a/src/com/android/contacts/datepicker/DatePicker.java b/src/com/android/contacts/datepicker/DatePicker.java
index 7ea9641..268243d 100644
--- a/src/com/android/contacts/datepicker/DatePicker.java
+++ b/src/com/android/contacts/datepicker/DatePicker.java
@@ -108,6 +108,7 @@
mDayPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
mDayPicker.setOnLongPressUpdateInterval(100);
mDayPicker.setOnValueChangedListener(new OnValueChangeListener() {
+ @Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
mDay = newVal;
notifyDateChanged();
@@ -137,6 +138,7 @@
mMonthPicker.setOnLongPressUpdateInterval(200);
mMonthPicker.setOnValueChangedListener(new OnValueChangeListener() {
+ @Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
/* We display the month 1-12 but store it 0-11 so always
@@ -152,6 +154,7 @@
mYearPicker = (NumberPicker) findViewById(R.id.year);
mYearPicker.setOnLongPressUpdateInterval(100);
mYearPicker.setOnValueChangedListener(new OnValueChangeListener() {
+ @Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
mYear = newVal;
// Adjust max day for leap years if needed
@@ -353,10 +356,12 @@
public static final Parcelable.Creator<SavedState> CREATOR =
new Creator<SavedState>() {
+ @Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
+ @Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
diff --git a/src/com/android/contacts/datepicker/DatePickerDialog.java b/src/com/android/contacts/datepicker/DatePickerDialog.java
index 112b96e..b0c4ed6 100644
--- a/src/com/android/contacts/datepicker/DatePickerDialog.java
+++ b/src/com/android/contacts/datepicker/DatePickerDialog.java
@@ -19,6 +19,10 @@
// This is a fork of the standard Android DatePicker that additionally allows toggling the year
// on/off. It uses some private API so that not everything has to be copied.
+import com.android.contacts.R;
+import com.android.contacts.datepicker.DatePicker.OnDateChangedListener;
+import com.android.contacts.util.DateUtils;
+
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
@@ -30,10 +34,8 @@
import android.view.View;
import android.widget.TextView;
-import com.android.contacts.R;
-import com.android.contacts.datepicker.DatePicker.OnDateChangedListener;
-
-import java.text.DateFormatSymbols;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
import java.util.Calendar;
/**
@@ -53,8 +55,8 @@
private final DatePicker mDatePicker;
private final OnDateSetListener mCallBack;
private final Calendar mCalendar;
- private final java.text.DateFormat mTitleDateFormat;
- private final String[] mWeekDays;
+ private final DateFormat mTitleDateFormat;
+ private final DateFormat mTitleNoYearDateFormat;
private int mInitialYear;
private int mInitialMonth;
@@ -148,11 +150,10 @@
mInitialYear = year;
mInitialMonth = monthOfYear;
mInitialDay = dayOfMonth;
- DateFormatSymbols symbols = new DateFormatSymbols();
- mWeekDays = symbols.getShortWeekdays();
- mTitleDateFormat = java.text.DateFormat.
- getDateInstance(java.text.DateFormat.FULL);
+ mTitleDateFormat = DateFormat.getDateInstance(DateFormat.FULL);
+ mTitleNoYearDateFormat = new SimpleDateFormat(
+ DateUtils.isMonthBeforeDay(getContext()) ? "MMMM dd" : "dd MMMM");
mCalendar = Calendar.getInstance();
updateTitle(mInitialYear, mInitialMonth, mInitialDay);
@@ -182,6 +183,7 @@
title.setEllipsize(TruncateAt.END);
}
+ @Override
public void onClick(DialogInterface dialog, int which) {
if (mCallBack != null) {
mDatePicker.clearFocus();
@@ -190,8 +192,8 @@
}
}
- public void onDateChanged(DatePicker view, int year,
- int month, int day) {
+ @Override
+ public void onDateChanged(DatePicker view, int year, int month, int day) {
updateTitle(year, month, day);
}
@@ -206,7 +208,9 @@
mCalendar.set(Calendar.YEAR, year);
mCalendar.set(Calendar.MONTH, month);
mCalendar.set(Calendar.DAY_OF_MONTH, day);
- setTitle(mTitleDateFormat.format(mCalendar.getTime()));
+ final DateFormat dateFormat =
+ year == 0 ? mTitleNoYearDateFormat : mTitleDateFormat;
+ setTitle(dateFormat.format(mCalendar.getTime()));
}
@Override
diff --git a/src/com/android/contacts/editor/EventFieldEditorView.java b/src/com/android/contacts/editor/EventFieldEditorView.java
index 08cbaef..538d4dc 100644
--- a/src/com/android/contacts/editor/EventFieldEditorView.java
+++ b/src/com/android/contacts/editor/EventFieldEditorView.java
@@ -29,7 +29,6 @@
import android.app.Dialog;
import android.content.Context;
-import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.os.Bundle;
import android.text.TextUtils;
@@ -238,10 +237,11 @@
final Calendar outCalendar =
Calendar.getInstance(DateUtils.UTC_TIMEZONE, Locale.US);
- // If no year specified, set it to 1900. The format string will ignore that year
+ // If no year specified, set it to 2000 (we could pick any leap year here).
+ // The format string will ignore that year.
// For formats other than Exchange, the time of the day is ignored
outCalendar.clear();
- outCalendar.set(year == 0 ? 1900 : year, monthOfYear, dayOfMonth,
+ outCalendar.set(year == 0 ? 2000 : year, monthOfYear, dayOfMonth,
DEFAULT_HOUR, 0, 0);
final String resultString;
diff --git a/src/com/android/contacts/util/CallerInfoCacheUtils.java b/src/com/android/contacts/util/CallerInfoCacheUtils.java
new file mode 100644
index 0000000..9e53159
--- /dev/null
+++ b/src/com/android/contacts/util/CallerInfoCacheUtils.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.util;
+
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * Utilities for managing CallerInfoCache.
+ *
+ * The cache lives in Phone package and is used as fallback storage when database lookup is slower
+ * than expected. It remembers some information necessary for responding to incoming calls
+ * (e.g. custom ringtone settings, send-to-voicemail).
+ *
+ * Even though the cache will be updated periodically, Contacts app can request the cache update
+ * via broadcast Intent. This class provides that mechanism, and possibly other misc utilities
+ * for the update mechanism.
+ */
+public final class CallerInfoCacheUtils {
+ private static final String UPDATE_CALLER_INFO_CACHE =
+ "com.android.phone.UPDATE_CALLER_INFO_CACHE";
+
+ private CallerInfoCacheUtils() {
+ }
+
+ /**
+ * Sends an Intent, notifying CallerInfo cache should be updated.
+ *
+ * Note: CallerInfo is *not* part of public API, and no guarantee is available around its
+ * specific behavior. In practice this will only be used by Phone package, but may change
+ * in the future.
+ *
+ * See also CallerInfoCache in Phone package for more information.
+ */
+ public static void sendUpdateCallerInfoCacheIntent(Context context) {
+ context.sendBroadcast(new Intent(UPDATE_CALLER_INFO_CACHE));
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/contacts/util/DateUtils.java b/src/com/android/contacts/util/DateUtils.java
index 1ea84a1..d0bb68f 100644
--- a/src/com/android/contacts/util/DateUtils.java
+++ b/src/com/android/contacts/util/DateUtils.java
@@ -56,7 +56,7 @@
private static final java.text.DateFormat FORMAT_WITHOUT_YEAR_MONTH_FIRST =
new SimpleDateFormat("MMMM dd");
- private static final java.text.DateFormat FORMAT_WITHOUT_YEAR_DATE_FIRST =
+ private static final java.text.DateFormat FORMAT_WITHOUT_YEAR_DAY_FIRST =
new SimpleDateFormat("dd MMMM");
static {
@@ -66,7 +66,7 @@
}
NO_YEAR_DATE_FORMAT.setTimeZone(UTC_TIMEZONE);
FORMAT_WITHOUT_YEAR_MONTH_FIRST.setTimeZone(UTC_TIMEZONE);
- FORMAT_WITHOUT_YEAR_DATE_FIRST.setTimeZone(UTC_TIMEZONE);
+ FORMAT_WITHOUT_YEAR_DAY_FIRST.setTimeZone(UTC_TIMEZONE);
}
/**
@@ -112,9 +112,9 @@
}
if (parsePosition.getIndex() == string.length()) {
- java.text.DateFormat outFormat = isMonthBeforeDate(context)
+ java.text.DateFormat outFormat = isMonthBeforeDay(context)
? FORMAT_WITHOUT_YEAR_MONTH_FIRST
- : FORMAT_WITHOUT_YEAR_DATE_FIRST;
+ : FORMAT_WITHOUT_YEAR_DAY_FIRST;
synchronized (outFormat) {
return outFormat.format(date);
}
@@ -135,7 +135,7 @@
return string;
}
- private static boolean isMonthBeforeDate(Context context) {
+ public static boolean isMonthBeforeDay(Context context) {
char[] dateFormatOrder = DateFormat.getDateFormatOrder(context);
for (int i = 0; i < dateFormatOrder.length; i++) {
if (dateFormatOrder[i] == DateFormat.DATE) {
diff --git a/src/com/android/contacts/util/MoreMath.java b/src/com/android/contacts/util/MoreMath.java
index 6f28ccd..db76fe4 100644
--- a/src/com/android/contacts/util/MoreMath.java
+++ b/src/com/android/contacts/util/MoreMath.java
@@ -24,6 +24,16 @@
* If the input value lies outside of the specified range, return the nearer
* bound. Otherwise, return the input value, unchanged.
*/
+ public static int clamp(int input, int lowerBound, int upperBound) {
+ if (input < lowerBound) return lowerBound;
+ if (input > upperBound) return upperBound;
+ return input;
+ }
+
+ /**
+ * If the input value lies outside of the specified range, return the nearer
+ * bound. Otherwise, return the input value, unchanged.
+ */
public static float clamp(float input, float lowerBound, float upperBound) {
if (input < lowerBound) return lowerBound;
if (input > upperBound) return upperBound;