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);
+    }
+}