Home | History | Annotate | Download | only in emergency
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.emergency;
     17 
     18 import android.content.ContentUris;
     19 import android.content.Context;
     20 import android.database.Cursor;
     21 import android.graphics.Bitmap;
     22 import android.graphics.BitmapFactory;
     23 import com.android.internal.logging.MetricsLogger;
     24 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
     25 import android.net.Uri;
     26 import android.provider.ContactsContract;
     27 import android.util.Log;
     28 
     29 import java.io.ByteArrayInputStream;
     30 
     31 /**
     32  * Provides methods to read name, phone number, photo, etc. from contacts.
     33  */
     34 public class EmergencyContactManager {
     35     private static final String TAG = "EmergencyContactManager";
     36 
     37     /**
     38      * Returns a {@link Contact} that contains all the relevant information of the contact indexed
     39      * by {@code @phoneUri}.
     40      */
     41     public static Contact getContact(Context context, Uri phoneUri) {
     42         String phoneNumber = null;
     43         String phoneType = null;
     44         String name = null;
     45         Bitmap photo = null;
     46         final Uri contactLookupUri =
     47                 ContactsContract.Contacts.getLookupUri(context.getContentResolver(),
     48                         phoneUri);
     49         Cursor cursor = context.getContentResolver().query(
     50                 phoneUri,
     51                 new String[]{ContactsContract.Contacts.DISPLAY_NAME,
     52                         ContactsContract.CommonDataKinds.Phone.NUMBER,
     53                         ContactsContract.CommonDataKinds.Phone.TYPE,
     54                         ContactsContract.CommonDataKinds.Phone.LABEL,
     55                         ContactsContract.CommonDataKinds.Photo.PHOTO_ID},
     56                 null, null, null);
     57         try {
     58             if (cursor.moveToNext()) {
     59                 name = cursor.getString(0);
     60                 phoneNumber = cursor.getString(1);
     61                 phoneType = ContactsContract.CommonDataKinds.Phone.getTypeLabel(
     62                         context.getResources(),
     63                         cursor.getInt(2),
     64                         cursor.getString(3)).toString();
     65                 Long photoId = cursor.getLong(4);
     66                 if (photoId != null && photoId > 0) {
     67                     Uri photoUri = ContentUris.withAppendedId(ContactsContract.Data.CONTENT_URI,
     68                             photoId);
     69                     Cursor cursor2 = context.getContentResolver().query(
     70                             photoUri,
     71                             new String[]{ContactsContract.Contacts.Photo.PHOTO},
     72                             null, null, null);
     73                     try {
     74                         if (cursor2.moveToNext()) {
     75                             byte[] data = cursor2.getBlob(0);
     76                             if (data != null) {
     77                                 photo = BitmapFactory.decodeStream(new ByteArrayInputStream(data));
     78                             }
     79                         }
     80                     } finally {
     81                         if (cursor2 != null) {
     82                             cursor2.close();
     83                         }
     84                     }
     85                 }
     86             }
     87         } finally {
     88             if (cursor != null) {
     89                 cursor.close();
     90             }
     91         }
     92         return new Contact(contactLookupUri, phoneUri, name, phoneNumber, phoneType, photo);
     93     }
     94 
     95     /** Returns whether the phone uri is not null and corresponds to an existing phone number. */
     96     public static boolean isValidEmergencyContact(Context context, Uri phoneUri) {
     97         return phoneUri != null && phoneExists(context, phoneUri);
     98     }
     99 
    100     private static boolean phoneExists(Context context, Uri phoneUri) {
    101         Cursor cursor = null;
    102         try {
    103             cursor = context.getContentResolver().query(phoneUri, null, null, null, null);
    104             if (cursor != null && cursor.moveToFirst()) {
    105                 MetricsLogger.action(context, MetricsEvent.ACTION_PHONE_EXISTS, 1);
    106                 return true;
    107             }
    108         } catch (SecurityException e) {
    109             Log.w(TAG, "Unable to read contact information", e);
    110             MetricsLogger.action(context, MetricsEvent.ACTION_PHONE_EXISTS, 2);
    111             return false;
    112         } finally {
    113             if (cursor != null) {
    114                 cursor.close();
    115             }
    116         }
    117         MetricsLogger.action(context, MetricsEvent.ACTION_PHONE_EXISTS, 0);
    118         return false;
    119     }
    120 
    121     /** Wrapper for a contact with a phone number. */
    122     public static class Contact {
    123         /** The lookup uri is necessary to display the contact. */
    124         private final Uri mContactLookupUri;
    125         /**
    126          * The contact uri is associated to a particular phone number and can be used to reload that
    127          * number and keep the number displayed in the preferences fresh.
    128          */
    129         private final Uri mPhoneUri;
    130         /** The display name of the contact. */
    131         private final String mName;
    132         /** The emergency contact's phone number selected by the user. */
    133         private final String mPhoneNumber;
    134         /** The emergency contact's phone number type (mobile, work, home, etc). */
    135         private final String mPhoneType;
    136         /** The contact's photo. */
    137         private final Bitmap mPhoto;
    138 
    139         /** Constructs a new contact. */
    140         public Contact(Uri contactLookupUri,
    141                        Uri phoneUri,
    142                        String name,
    143                        String phoneNumber,
    144                        String phoneType,
    145                        Bitmap photo) {
    146             mContactLookupUri = contactLookupUri;
    147             mPhoneUri = phoneUri;
    148             mName = name;
    149             mPhoneNumber = phoneNumber;
    150             mPhoneType = phoneType;
    151             mPhoto = photo;
    152         }
    153 
    154         /** Returns the contact's CONTENT_LOOKUP_URI. Use this to display the contact. */
    155         public Uri getContactLookupUri() {
    156             return mContactLookupUri;
    157         }
    158 
    159         /**
    160          * The phone uri as defined in ContactsContract.CommonDataKinds.Phone.CONTENT_URI. Use
    161          * this to reload the contact. This links to a particular phone number of the emergency
    162          * contact.
    163          */
    164         public Uri getPhoneUri() {
    165             return mPhoneUri;
    166         }
    167 
    168         /** Returns the display name of the contact. */
    169         public String getName() {
    170             return mName;
    171         }
    172 
    173         /** Returns the phone number selected by the user. */
    174         public String getPhoneNumber() {
    175             return mPhoneNumber;
    176         }
    177 
    178         /** Returns the phone type (e.g. mobile, work, home, etc.) . */
    179         public String getPhoneType() {
    180             return mPhoneType;
    181         }
    182 
    183         /** Returns the photo assigned to this contact. */
    184         public Bitmap getPhoto() {
    185             return mPhoto;
    186         }
    187     }
    188 }
    189