diff options
Diffstat (limited to 'java/com/android/dialer/lookup/LookupCache.java')
-rw-r--r-- | java/com/android/dialer/lookup/LookupCache.java | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/java/com/android/dialer/lookup/LookupCache.java b/java/com/android/dialer/lookup/LookupCache.java new file mode 100644 index 000000000..e6d5cc697 --- /dev/null +++ b/java/com/android/dialer/lookup/LookupCache.java @@ -0,0 +1,303 @@ +/* + * Copyright (C) 2014 Xiao-Long Chen <chenxiaolong@cxl.epac.to> + * + * 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.dialer.lookup; + +import com.android.dialer.phonenumbercache.ContactInfo; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.provider.ContactsContract.Contacts; +import android.telephony.PhoneNumberUtils; +import android.telephony.TelephonyManager; +import android.util.JsonReader; +import android.util.JsonWriter; +import android.util.Log; + +import com.android.dialer.util.DialerUtils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStreamReader; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.util.ArrayList; +import java.util.List; + +import org.json.JSONException; +import org.json.JSONObject; + +public class LookupCache { + private static final String TAG = LookupCache.class.getSimpleName(); + + public static final String NAME = "Name"; + public static final String TYPE = "Type"; + public static final String LABEL = "Label"; + public static final String NUMBER = "Number"; + public static final String FORMATTED_NUMBER = "FormattedNumber"; + public static final String NORMALIZED_NUMBER = "NormalizedNumber"; + public static final String PHOTO_ID = "PhotoID"; + //public static final String PHOTO_URI = "PhotoURI"; + public static final String LOOKUP_URI = "LookupURI"; + + public static boolean hasCachedContact(Context context, String number) { + String normalizedNumber = formatE164(context, number); + + if (normalizedNumber == null) { + return false; + } + + File file = getFilePath(context, normalizedNumber); + return file.exists(); + } + + public static void cacheContact(Context context, ContactInfo info) { + File file = getFilePath(context, info.normalizedNumber); + + if (file.exists()) { + file.delete(); + } + + FileOutputStream out = null; + JsonWriter writer = null; + + try { + out = new FileOutputStream(file); + writer = new JsonWriter(new OutputStreamWriter(out, "UTF-8")); + writer.setIndent(" "); + List messages = new ArrayList(); + + writer.beginObject(); + if (info.name != null) writer.name(NAME).value(info.name); + writer.name(TYPE).value(info.type); + if (info.label != null) writer.name(LABEL).value(info.label); + if (info.number != null) writer.name(NUMBER).value(info.number); + if (info.formattedNumber != null) { + writer.name(FORMATTED_NUMBER).value(info.formattedNumber); + } + if (info.normalizedNumber != null) { + writer.name(NORMALIZED_NUMBER).value(info.normalizedNumber); + } + writer.name(PHOTO_ID).value(info.photoId); + + if (info.lookupUri != null) { + writer.name(LOOKUP_URI).value(info.lookupUri.toString()); + } + + // We do not save the photo URI. If there's a cached image, that + // will be used when the contact is retrieved. Otherwise, photoUri + // will be set to null. + + writer.endObject(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + DialerUtils.closeQuietly(writer); + DialerUtils.closeQuietly(out); + } + } + + public static ContactInfo getCachedContact(Context context, String number) { + String normalizedNumber = formatE164(context, number); + + if (normalizedNumber == null) { + return null; + } + + File file = getFilePath(context, normalizedNumber); + if (!file.exists()) { + // Whatever is calling this should probably check anyway + return null; + } + + ContactInfo info = new ContactInfo(); + + FileInputStream in = null; + JsonReader reader = null; + + try { + in = new FileInputStream(file); + reader = new JsonReader(new InputStreamReader(in, "UTF-8")); + + reader.beginObject(); + while (reader.hasNext()) { + String name = reader.nextName(); + + if (NAME.equals(name)) { + info.name = reader.nextString(); + } else if (TYPE.equals(name)) { + info.type = reader.nextInt(); + } else if (LABEL.equals(name)) { + info.label = reader.nextString(); + } else if (NUMBER.equals(name)) { + info.number = reader.nextString(); + } else if (FORMATTED_NUMBER.equals(name)) { + info.formattedNumber = reader.nextString(); + } else if (NORMALIZED_NUMBER.equals(name)) { + info.normalizedNumber = reader.nextString(); + } else if (PHOTO_ID.equals(name)) { + info.photoId = reader.nextInt(); + } else if (LOOKUP_URI.equals(name)) { + Uri lookupUri = Uri.parse(reader.nextString()); + + if (hasCachedImage(context, normalizedNumber)) { + // Insert cached photo URI + Uri image = Uri.withAppendedPath( + LookupProvider.IMAGE_CACHE_URI, + Uri.encode(normalizedNumber)); + + String json = lookupUri.getEncodedFragment(); + if (json != null) { + try { + JSONObject jsonObj = new JSONObject(json); + jsonObj.putOpt(Contacts.PHOTO_URI, image.toString()); + lookupUri = lookupUri.buildUpon() + .encodedFragment(jsonObj.toString()) + .build(); + } catch (JSONException e) { + Log.e(TAG, "Failed to add image URI to json", e); + } + } + + info.photoUri = image; + } + + info.lookupUri = lookupUri; + } + } + reader.endObject(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + DialerUtils.closeQuietly(reader); + DialerUtils.closeQuietly(in); + } + + return info; + } + + public static void deleteCachedContacts(Context context) { + File dir = new File(context.getCacheDir() + + File.separator + "lookup"); + + if (!dir.exists()) { + Log.v(TAG, "Lookup cache directory does not exist. Not clearing it."); + return; + } + + if (!dir.isDirectory()) { + Log.e(TAG, "Path " + dir + " is not a directory"); + return; + } + + File[] files = dir.listFiles(); + if (files != null) { + for (File file : files) { + if (file.isFile()) { + file.delete(); + } + } + } + } + + public static void deleteCachedContact( + Context context, String normalizedNumber) { + File f = getFilePath(context, normalizedNumber); + if (f.exists()) { + f.delete(); + } + + f = getImagePath(context, normalizedNumber); + if (f.exists()) { + f.delete(); + } + } + + public static boolean hasCachedImage(Context context, String number) { + String normalizedNumber = formatE164(context, number); + + if (normalizedNumber == null) { + return false; + } + + File file = getImagePath(context, normalizedNumber); + return file.exists(); + } + + public static void cacheImage(Context context, + String normalizedNumber, Bitmap bmp) { + // Compress the cached images to save space + if (bmp == null) { + Log.e(TAG, "Failed to cache image"); + return; + } + + File image = getImagePath(context, normalizedNumber); + + FileOutputStream out = null; + + try { + out = new FileOutputStream(image); + bmp.compress(Bitmap.CompressFormat.WEBP, 100, out); + } catch (Exception e) { + e.printStackTrace(); + } finally { + DialerUtils.closeQuietly(out); + } + } + + public static Bitmap getCachedImage(Context context, String normalizedNumber) { + File image = getImagePath(context, normalizedNumber); + if (!image.exists()) { + return null; + } + + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inPreferredConfig = Bitmap.Config.ARGB_8888; + return BitmapFactory.decodeFile(image.getPath(), options); + } + + private static String formatE164(Context context, String number) { + String countryIso = ((TelephonyManager) context.getSystemService( + Context.TELEPHONY_SERVICE)).getSimCountryIso().toUpperCase(); + return PhoneNumberUtils.formatNumberToE164(number, countryIso); + } + + private static File getFilePath(Context context, String normalizedNumber) { + File dir = new File(context.getCacheDir() + + File.separator + "lookup"); + + if (!dir.exists()) { + dir.mkdirs(); + } + + return new File(dir, normalizedNumber + ".json"); + } + + public static File getImagePath(Context context, String normalizedNumber) { + File dir = new File(context.getCacheDir() + + File.separator + "lookup"); + + if (!dir.exists()) { + dir.mkdirs(); + } + + return new File(dir, normalizedNumber + ".webp"); + } +} |