Move dependencies in prep for PhoneNumberInteraction move.
Committing this change first which is a pre-factor to moving
PhoneNumberInteraction into Dialer completely.
Bug: 6993891
Change-Id: Iceca505f6cd0dcbc1ebb39b98ab63a13bb263eda
diff --git a/src/com/android/contacts/common/Collapser.java b/src/com/android/contacts/common/Collapser.java
new file mode 100644
index 0000000..d586add
--- /dev/null
+++ b/src/com/android/contacts/common/Collapser.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2009 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.common;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Class used for collapsing data items into groups of similar items. The data items that should be
+ * collapsible should implement the Collapsible interface. The class also contains a utility
+ * function that takes an ArrayList of items and returns a list of the same items collapsed into
+ * groups.
+ */
+public final class Collapser {
+
+ /*
+ * This utility class cannot be instantiated.
+ */
+ private Collapser() {}
+
+ /*
+ * Interface implemented by data types that can be collapsed into groups of similar data. This
+ * can be used for example to collapse similar contact data items into a single item.
+ */
+ public interface Collapsible<T> {
+ public boolean collapseWith(T t);
+ public boolean shouldCollapseWith(T t);
+ }
+
+ /**
+ * Collapses a list of Collapsible items into a list of collapsed items. Items are collapsed
+ * if {@link Collapsible#shouldCollapseWith(Object)} returns true, and are collapsed
+ * through the {@Link Collapsible#collapseWith(Object)} function implemented by the data item.
+ *
+ * @param list List of Objects of type <T extends Collapsible<T>> to be collapsed.
+ */
+ public static <T extends Collapsible<T>> void collapseList(List<T> list) {
+
+ int listSize = list.size();
+
+ for (int i = 0; i < listSize; i++) {
+ T iItem = list.get(i);
+ if (iItem != null) {
+ for (int j = i + 1; j < listSize; j++) {
+ T jItem = list.get(j);
+ if (jItem != null) {
+ if (iItem.shouldCollapseWith(jItem)) {
+ iItem.collapseWith(jItem);
+ list.set(j, null);
+ }
+ }
+ }
+ }
+ }
+
+ // Remove the null items
+ Iterator<T> itr = list.iterator();
+ while (itr.hasNext()) {
+ if (itr.next() == null) {
+ itr.remove();
+ }
+ }
+
+ }
+}
diff --git a/src/com/android/contacts/common/MoreContactUtils.java b/src/com/android/contacts/common/MoreContactUtils.java
new file mode 100644
index 0000000..cceea6a
--- /dev/null
+++ b/src/com/android/contacts/common/MoreContactUtils.java
@@ -0,0 +1,88 @@
+/*
+ * 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.common;
+
+import android.provider.ContactsContract;
+import android.telephony.PhoneNumberUtils;
+import android.text.TextUtils;
+
+/**
+ * Shared static contact utility methods.
+ */
+public class MoreContactUtils {
+
+ /**
+ * Returns true if two data with mimetypes which represent values in contact entries are
+ * considered equal for collapsing in the GUI. For caller-id, use
+ * {@link android.telephony.PhoneNumberUtils#compare(android.content.Context, String, String)}
+ * instead
+ */
+ public static boolean shouldCollapse(CharSequence mimetype1, CharSequence data1,
+ CharSequence mimetype2, CharSequence data2) {
+ // different mimetypes? don't collapse
+ if (!TextUtils.equals(mimetype1, mimetype2)) return false;
+
+ // exact same string? good, bail out early
+ if (TextUtils.equals(data1, data2)) return true;
+
+ // so if either is null, these two must be different
+ if (data1 == null || data2 == null) return false;
+
+ // if this is not about phone numbers, we know this is not a match (of course, some
+ // mimetypes could have more sophisticated matching is the future, e.g. addresses)
+ if (!TextUtils.equals(ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,
+ mimetype1)) {
+ return false;
+ }
+
+ return shouldCollapsePhoneNumbers(data1.toString(), data2.toString());
+ }
+
+ private static boolean shouldCollapsePhoneNumbers(
+ String number1WithLetters, String number2WithLetters) {
+ final String number1 = PhoneNumberUtils.convertKeypadLettersToDigits(number1WithLetters);
+ final String number2 = PhoneNumberUtils.convertKeypadLettersToDigits(number2WithLetters);
+
+ int index1 = 0;
+ int index2 = 0;
+ for (;;) {
+ // Skip formatting characters.
+ while (index1 < number1.length() &&
+ !PhoneNumberUtils.isNonSeparator(number1.charAt(index1))) {
+ index1++;
+ }
+ while (index2 < number2.length() &&
+ !PhoneNumberUtils.isNonSeparator(number2.charAt(index2))) {
+ index2++;
+ }
+ // If both have finished, match. If only one has finished, not match.
+ final boolean number1End = (index1 == number1.length());
+ final boolean number2End = (index2 == number2.length());
+ if (number1End) {
+ return number2End;
+ }
+ if (number2End) return false;
+
+ // If the non-formatting characters are different, not match.
+ if (number1.charAt(index1) != number2.charAt(index2)) return false;
+
+ // Go to the next characters.
+ index1++;
+ index2++;
+ }
+ }
+}
diff --git a/src/com/android/contacts/common/activity/TransactionSafeActivity.java b/src/com/android/contacts/common/activity/TransactionSafeActivity.java
new file mode 100644
index 0000000..6c2e4fe
--- /dev/null
+++ b/src/com/android/contacts/common/activity/TransactionSafeActivity.java
@@ -0,0 +1,65 @@
+/*
+ * 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 com.android.contacts.common.activity;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * A common superclass that keeps track of whether an {@link Activity} has saved its state yet or
+ * not.
+ */
+public abstract class TransactionSafeActivity extends Activity {
+
+ private boolean mIsSafeToCommitTransactions;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mIsSafeToCommitTransactions = true;
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mIsSafeToCommitTransactions = true;
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mIsSafeToCommitTransactions = true;
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mIsSafeToCommitTransactions = false;
+ }
+
+ /**
+ * Returns true if it is safe to commit {@link FragmentTransaction}s at this time, based on
+ * whether {@link Activity#onSaveInstanceState} has been called or not.
+ *
+ * Make sure that the current activity calls into
+ * {@link super.onSaveInstanceState(Bundle outState)} (if that method is overridden),
+ * so the flag is properly set.
+ */
+ public boolean isSafeToCommitTransactions() {
+ return mIsSafeToCommitTransactions;
+ }
+}
diff --git a/src/com/android/contacts/common/database/ContactUpdateUtils.java b/src/com/android/contacts/common/database/ContactUpdateUtils.java
new file mode 100644
index 0000000..1bd08aa
--- /dev/null
+++ b/src/com/android/contacts/common/database/ContactUpdateUtils.java
@@ -0,0 +1,47 @@
+/*
+ * 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.common.database;
+
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.provider.ContactsContract;
+import android.util.Log;
+
+/**
+ * Static methods to update contact information.
+ */
+public class ContactUpdateUtils {
+
+ private static final String TAG = ContactUpdateUtils.class.getSimpleName();
+
+ public static void setSuperPrimary(Context context, long dataId) {
+ if (dataId == -1) {
+ Log.e(TAG, "Invalid arguments for setSuperPrimary request");
+ return;
+ }
+
+ // Update the primary values in the data record.
+ ContentValues values = new ContentValues(2);
+ values.put(ContactsContract.Data.IS_SUPER_PRIMARY, 1);
+ values.put(ContactsContract.Data.IS_PRIMARY, 1);
+
+ context.getContentResolver().update(
+ ContentUris.withAppendedId(ContactsContract.Data.CONTENT_URI, dataId),
+ values, null, null);
+ }
+}