aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin/ContactsManager.java
diff options
context:
space:
mode:
authorAmin Bandali <bandali@kelar.org>2024-12-16 21:45:41 -0500
committerAmin Bandali <bandali@kelar.org>2025-01-11 14:17:35 -0500
commite9a0e66716dab4dd3184d009d8920de1961efdfa (patch)
tree02dcc096643d74645bf28459c2834c3d4a2ad7f2 /java/src/com/android/inputmethod/latin/ContactsManager.java
parentfb3b9360d70596d7e921de8bf7d3ca99564a077e (diff)
downloadlatinime-e9a0e66716dab4dd3184d009d8920de1961efdfa.tar.gz
latinime-e9a0e66716dab4dd3184d009d8920de1961efdfa.tar.xz
latinime-e9a0e66716dab4dd3184d009d8920de1961efdfa.zip
Rename to Kelar Keyboard (org.kelar.inputmethod.latin)
Diffstat (limited to 'java/src/com/android/inputmethod/latin/ContactsManager.java')
-rw-r--r--java/src/com/android/inputmethod/latin/ContactsManager.java245
1 files changed, 0 insertions, 245 deletions
diff --git a/java/src/com/android/inputmethod/latin/ContactsManager.java b/java/src/com/android/inputmethod/latin/ContactsManager.java
deleted file mode 100644
index 13503ff45..000000000
--- a/java/src/com/android/inputmethod/latin/ContactsManager.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (C) 2014 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.inputmethod.latin;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteException;
-import android.net.Uri;
-import android.provider.ContactsContract.Contacts;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.inputmethod.latin.common.Constants;
-import com.android.inputmethod.latin.common.StringUtils;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * Manages all interactions with Contacts DB.
- *
- * The manager provides an API for listening to meaning full updates by keeping a
- * measure of the current state of the content provider.
- */
-public class ContactsManager {
- private static final String TAG = "ContactsManager";
-
- /**
- * Use at most this many of the highest affinity contacts.
- */
- public static final int MAX_CONTACT_NAMES = 200;
-
- protected static class RankedContact {
- public final String mName;
- public final long mLastContactedTime;
- public final int mTimesContacted;
- public final boolean mInVisibleGroup;
-
- private float mAffinity = 0.0f;
-
- RankedContact(final Cursor cursor) {
- mName = cursor.getString(
- ContactsDictionaryConstants.NAME_INDEX);
- mTimesContacted = cursor.getInt(
- ContactsDictionaryConstants.TIMES_CONTACTED_INDEX);
- mLastContactedTime = cursor.getLong(
- ContactsDictionaryConstants.LAST_TIME_CONTACTED_INDEX);
- mInVisibleGroup = cursor.getInt(
- ContactsDictionaryConstants.IN_VISIBLE_GROUP_INDEX) == 1;
- }
-
- float getAffinity() {
- return mAffinity;
- }
-
- /**
- * Calculates the affinity with the contact based on:
- * - How many times it has been contacted
- * - How long since the last contact.
- * - Whether the contact is in the visible group (i.e., Contacts list).
- *
- * Note: This affinity is limited by the fact that some apps currently do not update the
- * LAST_TIME_CONTACTED or TIMES_CONTACTED counters. As a result, a frequently messaged
- * contact may still have 0 affinity.
- */
- void computeAffinity(final int maxTimesContacted, final long currentTime) {
- final float timesWeight = ((float) mTimesContacted + 1) / (maxTimesContacted + 1);
- final long timeSinceLastContact = Math.min(
- Math.max(0, currentTime - mLastContactedTime),
- TimeUnit.MILLISECONDS.convert(180, TimeUnit.DAYS));
- final float lastTimeWeight = (float) Math.pow(0.5,
- timeSinceLastContact / (TimeUnit.MILLISECONDS.convert(10, TimeUnit.DAYS)));
- final float visibleWeight = mInVisibleGroup ? 1.0f : 0.0f;
- mAffinity = (timesWeight + lastTimeWeight + visibleWeight) / 3;
- }
- }
-
- private static class AffinityComparator implements Comparator<RankedContact> {
- @Override
- public int compare(RankedContact contact1, RankedContact contact2) {
- return Float.compare(contact2.getAffinity(), contact1.getAffinity());
- }
- }
-
- /**
- * Interface to implement for classes interested in getting notified for updates
- * to Contacts content provider.
- */
- public static interface ContactsChangedListener {
- public void onContactsChange();
- }
-
- /**
- * The number of contacts observed in the most recent instance of
- * contacts content provider.
- */
- private AtomicInteger mContactCountAtLastRebuild = new AtomicInteger(0);
-
- /**
- * The hash code of list of valid contacts names in the most recent dictionary
- * rebuild.
- */
- private AtomicInteger mHashCodeAtLastRebuild = new AtomicInteger(0);
-
- private final Context mContext;
- private final ContactsContentObserver mObserver;
-
- public ContactsManager(final Context context) {
- mContext = context;
- mObserver = new ContactsContentObserver(this /* ContactsManager */, context);
- }
-
- // TODO: This was synchronized in previous version. Why?
- public void registerForUpdates(final ContactsChangedListener listener) {
- mObserver.registerObserver(listener);
- }
-
- public int getContactCountAtLastRebuild() {
- return mContactCountAtLastRebuild.get();
- }
-
- public int getHashCodeAtLastRebuild() {
- return mHashCodeAtLastRebuild.get();
- }
-
- /**
- * Returns all the valid names in the Contacts DB. Callers should also
- * call {@link #updateLocalState(ArrayList)} after they are done with result
- * so that the manager can cache local state for determining updates.
- *
- * These names are sorted by their affinity to the user, with favorite
- * contacts appearing first.
- */
- public ArrayList<String> getValidNames(final Uri uri) {
- // Check all contacts since it's not possible to find out which names have changed.
- // This is needed because it's possible to receive extraneous onChange events even when no
- // name has changed.
- final Cursor cursor = mContext.getContentResolver().query(uri,
- ContactsDictionaryConstants.PROJECTION, null, null, null);
- final ArrayList<RankedContact> contacts = new ArrayList<>();
- int maxTimesContacted = 0;
- if (cursor != null) {
- try {
- if (cursor.moveToFirst()) {
- while (!cursor.isAfterLast()) {
- final String name = cursor.getString(
- ContactsDictionaryConstants.NAME_INDEX);
- if (isValidName(name)) {
- final int timesContacted = cursor.getInt(
- ContactsDictionaryConstants.TIMES_CONTACTED_INDEX);
- if (timesContacted > maxTimesContacted) {
- maxTimesContacted = timesContacted;
- }
- contacts.add(new RankedContact(cursor));
- }
- cursor.moveToNext();
- }
- }
- } finally {
- cursor.close();
- }
- }
- final long currentTime = System.currentTimeMillis();
- for (RankedContact contact : contacts) {
- contact.computeAffinity(maxTimesContacted, currentTime);
- }
- Collections.sort(contacts, new AffinityComparator());
- final HashSet<String> names = new HashSet<>();
- for (int i = 0; i < contacts.size() && names.size() < MAX_CONTACT_NAMES; ++i) {
- names.add(contacts.get(i).mName);
- }
- return new ArrayList<>(names);
- }
-
- /**
- * Returns the number of contacts in contacts content provider.
- */
- public int getContactCount() {
- // TODO: consider switching to a rawQuery("select count(*)...") on the database if
- // performance is a bottleneck.
- Cursor cursor = null;
- try {
- cursor = mContext.getContentResolver().query(Contacts.CONTENT_URI,
- ContactsDictionaryConstants.PROJECTION_ID_ONLY, null, null, null);
- if (null == cursor) {
- return 0;
- }
- return cursor.getCount();
- } catch (final SQLiteException e) {
- Log.e(TAG, "SQLiteException in the remote Contacts process.", e);
- } finally {
- if (null != cursor) {
- cursor.close();
- }
- }
- return 0;
- }
-
- private static boolean isValidName(final String name) {
- if (TextUtils.isEmpty(name) || name.indexOf(Constants.CODE_COMMERCIAL_AT) != -1) {
- return false;
- }
- final boolean hasSpace = name.indexOf(Constants.CODE_SPACE) != -1;
- if (!hasSpace) {
- // Only allow an isolated word if it does not contain a hyphen.
- // This helps to filter out mailing lists.
- return name.indexOf(Constants.CODE_DASH) == -1;
- }
- return true;
- }
-
- /**
- * Updates the local state of the manager. This should be called when the callers
- * are done with all the updates of the content provider successfully.
- */
- public void updateLocalState(final ArrayList<String> names) {
- mContactCountAtLastRebuild.set(getContactCount());
- mHashCodeAtLastRebuild.set(names.hashCode());
- }
-
- /**
- * Performs any necessary cleanup.
- */
- public void close() {
- mObserver.unregister();
- }
-}