Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 420eb901 authored by Xiao-Long Chen's avatar Xiao-Long Chen Committed by Michael Bestas
Browse files

Re-add dialer lookup.

BUGBASH-612: do not send phone numbers to non-ssl sites for reverse/forward/people lookups

Change-Id: I677460ad5767b8698ee24d6d43ff159aee55387a
parent 3c1a49e7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -122,6 +122,7 @@ LOCAL_STATIC_JAVA_LIBRARIES := \
	legacy-test \
	libphonenumber \
	volley \
	org.lineageos.platform.internal

LOCAL_STATIC_ANDROID_LIBRARIES := \
	android-support-core-ui \
+6 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import com.android.dialer.blocking.FilteredNumberCompat;
import com.android.dialer.common.LogUtil;
import com.android.dialer.compat.telephony.TelephonyManagerCompat;
import com.android.dialer.configprovider.ConfigProviderBindings;
import com.android.dialer.lookup.LookupSettingsFragment;
import com.android.dialer.proguard.UsedByReflection;
import com.android.dialer.util.PermissionsUtil;
import com.android.dialer.voicemail.settings.VoicemailSettingsFragment;
@@ -113,6 +114,11 @@ public class DialerSettingsActivity extends AppCompatPreferenceActivity {
    quickResponseSettingsHeader.intent = quickResponseSettingsIntent;
    target.add(quickResponseSettingsHeader);

    final Header lookupSettingsHeader = new Header();
    lookupSettingsHeader.titleRes = R.string.lookup_settings_label;
    lookupSettingsHeader.fragment = LookupSettingsFragment.class.getName();
    target.add(lookupSettingsHeader);

    TelephonyManager telephonyManager =
        (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

+63 −1
Original line number Diff line number Diff line
@@ -16,15 +16,34 @@

package com.android.dialer.binary.aosp;

import android.content.Context;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.android.contacts.common.extensions.PhoneDirectoryExtender;
import com.android.contacts.common.extensions.PhoneDirectoryExtenderFactory;
import com.android.contacts.common.list.DirectoryPartition;
import com.android.dialer.binary.common.DialerApplication;
import com.android.dialer.inject.ContextModule;
import com.android.dialer.lookup.LookupCacheService;
import com.android.dialer.lookup.LookupProvider;
import com.android.dialer.lookup.ReverseLookupService;
import com.android.dialer.phonenumbercache.CachedNumberLookupService;
import com.android.dialer.phonenumbercache.PhoneNumberCacheBindings;
import com.android.dialer.phonenumbercache.PhoneNumberCacheBindingsFactory;
import com.android.incallui.bindings.InCallUiBindings;
import com.android.incallui.bindings.InCallUiBindingsFactory;
import com.android.incallui.bindings.InCallUiBindingsStub;
import com.android.incallui.bindings.PhoneNumberService;

import java.util.List;

/**
 * The application class for the AOSP Dialer. This is a version of the Dialer app that has no
 * dependency on Google Play Services.
 */
public class AospDialerApplication extends DialerApplication {
public class AospDialerApplication extends DialerApplication implements
    PhoneNumberCacheBindingsFactory, PhoneDirectoryExtenderFactory, InCallUiBindingsFactory {

  /** Returns a new instance of the root component for the AOSP Dialer. */
  @Override
@@ -32,4 +51,47 @@ public class AospDialerApplication extends DialerApplication {
  protected Object buildRootComponent() {
    return DaggerAospDialerRootComponent.builder().contextModule(new ContextModule(this)).build();
  }

  @Override
  public PhoneDirectoryExtender newPhoneDirectoryExtender() {
    return new PhoneDirectoryExtender() {
      @Override
      public List<DirectoryPartition> getExtendedDirectories(Context context) {
        return LookupProvider.getExtendedDirectories(context);
      }

      @Override
      public boolean isEnabled(Context context) {
        return false;
      }

      @Override
      @Nullable
      public Uri getContentUri() {
        return null;
      }
    };
  }

  @Override
  public InCallUiBindings newInCallUiBindings() {
    return new InCallUiBindingsStub() {
      @Override
      @Nullable
      public PhoneNumberService newPhoneNumberService(Context context) {
        return new ReverseLookupService(context);
      }
    };
  }

  @Override
  public PhoneNumberCacheBindings newPhoneNumberCacheBindings() {
    return new PhoneNumberCacheBindings() {
      @Override
      @Nullable
      public CachedNumberLookupService getCachedNumberLookupService() {
        return new LookupCacheService();
      }
    };
  }
}
+31 −0
Original line number Diff line number Diff line
<!--
  ~ Copyright (C) 2017 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
  -->

<manifest
  xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.android.dialer.lookup">

  <uses-sdk android:minSdkVersion="23"/>
  <uses-permission android:name="lineageos.permission.WRITE_SETTINGS"/>

  <application>
    <provider android:name="com.android.dialer.lookup.LookupProvider"
      android:authorities="com.android.dialer.lookup"
      android:exported="false"
      android:multiprocess="false" />

  </application>
</manifest>
+524 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 Xiao-Long Chen <chillermillerlong@hotmail.com>
 *
 * 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 android.content.ContentResolver;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.ContactsContract.CommonDataKinds.Website;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Directory;
import android.provider.ContactsContract.DisplayNameSources;
import android.text.TextUtils;
import android.util.Log;

import com.android.contacts.common.util.Constants;
import com.android.dialer.phonenumbercache.ContactInfo;
import com.android.dialer.R;

import java.sql.Struct;
import java.util.ArrayList;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.w3c.dom.Text;

public class ContactBuilder {
    private static final String TAG =
            ContactBuilder.class.getSimpleName();

    private static final boolean DEBUG = false;

    /** Used to choose the proper directory ID */
    public static final int FORWARD_LOOKUP = 0;
    public static final int PEOPLE_LOOKUP = 1;
    public static final int REVERSE_LOOKUP = 2;

    /** Default photo for businesses if no other image is found */
    public static final String PHOTO_URI_BUSINESS =
            new Uri.Builder()
            .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
            .authority("com.android.dialer")
            .appendPath(String.valueOf(
                    R.drawable.ic_places_picture_180_holo_light))
            .build()
            .toString();

    private ArrayList<Address> mAddresses = new ArrayList<Address>();
    private ArrayList<PhoneNumber> mPhoneNumbers
            = new ArrayList<PhoneNumber>();
    private ArrayList<WebsiteUrl> mWebsites
            = new ArrayList<WebsiteUrl>();

    private int mDirectoryType;
    private long mDirectoryId = DirectoryId.DEFAULT;

    private Name mName;

    private String mNormalizedNumber;
    private String mFormattedNumber;
    private int mDisplayNameSource = DisplayNameSources.ORGANIZATION;
    private Uri mPhotoUri;

    private boolean mIsBusiness;

    public ContactBuilder(int directoryType, String normalizedNumber,
            String formattedNumber) {
        mDirectoryType = directoryType;
        mNormalizedNumber = normalizedNumber;
        mFormattedNumber = formattedNumber;
    }

    public ContactBuilder(Uri encodedContactUri) throws JSONException {
        String jsonData = encodedContactUri.getEncodedFragment();
        String directoryId =
                encodedContactUri.getQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY);
        if (!TextUtils.isEmpty(directoryId)) {
            try {
                mDirectoryId = Long.parseLong(directoryId);
            } catch (NumberFormatException e) {
                Log.e(TAG, "Error parsing directory id of uri " + encodedContactUri, e);
            }
        }
        try {
            // name
            JSONObject json = new JSONObject(jsonData);
            JSONObject contact = json.optJSONObject(Contacts.CONTENT_ITEM_TYPE);
            JSONObject nameObj = contact.optJSONObject(StructuredName.CONTENT_ITEM_TYPE);
            mName = new Name(nameObj);

            if (contact != null) {
                // numbers
                if (contact.has(Phone.CONTENT_ITEM_TYPE)) {
                    String phoneData = contact.getString(Phone.CONTENT_ITEM_TYPE);
                    Object phoneObject = new JSONTokener(phoneData).nextValue();
                    JSONArray phoneNumbers;
                    if (phoneObject instanceof JSONObject) {
                        phoneNumbers = new JSONArray();
                        phoneNumbers.put(phoneObject);
                    } else {
                        phoneNumbers = contact.getJSONArray(Phone.CONTENT_ITEM_TYPE);
                    }
                    for (int i = 0; i < phoneNumbers.length(); ++i) {
                        JSONObject phoneObj = phoneNumbers.getJSONObject(i);
                        mPhoneNumbers.add(new PhoneNumber(phoneObj));
                    }
                }

                // address
                if (contact.has(StructuredPostal.CONTENT_ITEM_TYPE)) {
                    JSONArray addresses = contact.getJSONArray(StructuredPostal.CONTENT_ITEM_TYPE);
                    for (int i = 0; i < addresses.length(); ++i) {
                        JSONObject addrObj = addresses.getJSONObject(i);
                        mAddresses.add(new Address(addrObj));
                    }
                }

                // websites
                if (contact.has(Website.CONTENT_ITEM_TYPE)) {
                    JSONArray websites = contact.getJSONArray(Website.CONTENT_ITEM_TYPE);
                    for (int i = 0; i < websites.length(); ++i) {
                        JSONObject websiteObj = websites.getJSONObject(i);
                        final WebsiteUrl websiteUrl = new WebsiteUrl(websiteObj);
                        if (!TextUtils.isEmpty(websiteUrl.url)) {
                            mWebsites.add(new WebsiteUrl(websiteObj));
                        }
                    }
                }
            }

        }
        catch(JSONException e) {
            Log.e(TAG, "Error parsing encoded fragment of uri " + encodedContactUri, e);
            throw e;
        }
    }

    public void addAddress(Address address) {
        if (DEBUG) Log.d(TAG, "Adding address");
        if (address != null) {
            mAddresses.add(address);
        }
    }

    public Address[] getAddresses() {
        return mAddresses.toArray(new Address[mAddresses.size()]);
    }

    public void addPhoneNumber(PhoneNumber phoneNumber) {
        if (DEBUG) Log.d(TAG, "Adding phone number");
        if (phoneNumber != null) {
            mPhoneNumbers.add(phoneNumber);
        }
    }

    public PhoneNumber[] getPhoneNumbers() {
        return mPhoneNumbers.toArray(
                new PhoneNumber[mPhoneNumbers.size()]);
    }

    public void addWebsite(WebsiteUrl website) {
        if (DEBUG) Log.d(TAG, "Adding website");
        if (website != null) {
            mWebsites.add(website);
        }
    }

    public WebsiteUrl[] getWebsites() {
        return mWebsites.toArray(new WebsiteUrl[mWebsites.size()]);
    }

    public void setName(Name name) {
        if (DEBUG) Log.d(TAG, "Setting name");
        if (name != null) {
            mName = name;
        }
    }

    public Name getName() {
        return mName;
    }

    public void setPhotoUri(String photoUri) {
        if (photoUri != null) {
            setPhotoUri(Uri.parse(photoUri));
        }
    }

    public void setPhotoUri(Uri photoUri) {
        if (DEBUG) Log.d(TAG, "Setting photo URI");
        mPhotoUri = photoUri;
    }

    public Uri getPhotoUri() {
        return mPhotoUri;
    }

    public long getDirectoryId() {
        return mDirectoryId;
    }

    public void setIsBusiness(boolean isBusiness) {
        if (DEBUG) Log.d(TAG, "Setting isBusiness to " + isBusiness);
        mIsBusiness = isBusiness;
    }

    public boolean isBusiness() {
        return mIsBusiness;
    }

    public ContactInfo build() {
        if (mName == null) {
            throw new IllegalStateException("Name has not been set");
        }

        if (mDirectoryType != FORWARD_LOOKUP
                && mDirectoryType != PEOPLE_LOOKUP
                && mDirectoryType != REVERSE_LOOKUP) {
            throw new IllegalStateException("Invalid directory type");
        }

        // Use the incoming call's phone number if no other phone number
        // is specified. The reverse lookup source could present the phone
        // number differently (eg. without the area code).
        if (mPhoneNumbers.size() == 0) {
            PhoneNumber pn = new PhoneNumber();
            // Use the formatted number where possible
            pn.number = mFormattedNumber != null
                    ? mFormattedNumber : mNormalizedNumber;
            pn.type = Phone.TYPE_MAIN;
            addPhoneNumber(pn);
        }

        try {
            JSONObject contact = new JSONObject();

            // Insert the name
            contact.put(StructuredName.CONTENT_ITEM_TYPE,
                    mName.getJsonObject());

            // Insert phone numbers
            JSONArray phoneNumbers = new JSONArray();
            for (int i = 0; i < mPhoneNumbers.size(); i++) {
                phoneNumbers.put(mPhoneNumbers.get(i).getJsonObject());
            }
            contact.put(Phone.CONTENT_ITEM_TYPE, phoneNumbers);

            // Insert addresses if there are any
            if (mAddresses.size() > 0) {
                JSONArray addresses = new JSONArray();
                for (int i = 0; i < mAddresses.size(); i++) {
                    addresses.put(mAddresses.get(i).getJsonObject());
                }
                contact.put(StructuredPostal.CONTENT_ITEM_TYPE, addresses);
            }

            // Insert websites if there are any
            if (mWebsites.size() > 0) {
                JSONArray websites = new JSONArray();
                for (int i = 0; i < mWebsites.size(); i++) {
                    websites.put(mWebsites.get(i).getJsonObject());
                }
                contact.put(Website.CONTENT_ITEM_TYPE, websites);
            }

            ContactInfo info = new ContactInfo();
            info.name = mName.displayName;
            info.normalizedNumber = mNormalizedNumber;
            info.number = mPhoneNumbers.get(0).number;
            info.type = mPhoneNumbers.get(0).type;
            info.label = mPhoneNumbers.get(0).label;
            info.photoUri = mPhotoUri != null ? mPhotoUri : null;

            String json = new JSONObject()
                    .put(Contacts.DISPLAY_NAME, mName.displayName)
                    .put(Contacts.DISPLAY_NAME_SOURCE, mDisplayNameSource)
                    .put(Directory.EXPORT_SUPPORT,
                            Directory.EXPORT_SUPPORT_ANY_ACCOUNT)
                    .put(Contacts.CONTENT_ITEM_TYPE, contact)
                    .toString();

            if (json != null) {
                long directoryId = -1;
                switch (mDirectoryType) {
                    case FORWARD_LOOKUP:
                        directoryId = DirectoryId.NEARBY;
                        break;
                    case PEOPLE_LOOKUP:
                        directoryId = DirectoryId.PEOPLE;
                        break;
                    case REVERSE_LOOKUP:
                        // use null directory to be backwards compatible with old code
                        directoryId = DirectoryId.NULL;
                        break;
                }

                info.lookupUri = Contacts.CONTENT_LOOKUP_URI
                        .buildUpon()
                        .appendPath(Constants.LOOKUP_URI_ENCODED)
                        .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
                                String.valueOf(directoryId))
                        .encodedFragment(json)
                        .build();
            }

            return info;
        } catch (JSONException e) {
            Log.e(TAG, "Failed to build contact", e);
            return null;
        }
    }

    // android.provider.ContactsContract.CommonDataKinds.StructuredPostal
    public static class Address {
        public String formattedAddress;
        public int type;
        public String label;
        public String street;
        public String poBox;
        public String neighborhood;
        public String city;
        public String region;
        public String postCode;
        public String country;

        public static Address createFormattedHome(String address) {
            Address a = new Address();
            a.formattedAddress = address;
            a.type = StructuredPostal.TYPE_HOME;
            return a;
        }

        public JSONObject getJsonObject() throws JSONException {
            JSONObject json = new JSONObject();
            json.putOpt(StructuredPostal.FORMATTED_ADDRESS,
                    formattedAddress);
            json.put(StructuredPostal.TYPE, type);
            json.putOpt(StructuredPostal.LABEL, label);
            json.putOpt(StructuredPostal.STREET, street);
            json.putOpt(StructuredPostal.POBOX, poBox);
            json.putOpt(StructuredPostal.NEIGHBORHOOD, neighborhood);
            json.putOpt(StructuredPostal.CITY, city);
            json.putOpt(StructuredPostal.REGION, region);
            json.putOpt(StructuredPostal.POSTCODE, postCode);
            json.putOpt(StructuredPostal.COUNTRY, country);
            return json;
        }

        public Address() {}

        public Address(JSONObject json) throws JSONException {
            if (json.has(StructuredPostal.FORMATTED_ADDRESS)) {
                formattedAddress = json.getString(StructuredPostal.FORMATTED_ADDRESS);
            }
        }

        public String toString() {
            return "formattedAddress: " + formattedAddress + "; " +
                    "type: " + type + "; " +
                    "label: " + label + "; " +
                    "street: " + street + "; " +
                    "poBox: " + poBox + "; " +
                    "neighborhood: " + neighborhood + "; " +
                    "city: " + city + "; " +
                    "region: " + region + "; " +
                    "postCode: " + postCode + "; " +
                    "country: " + country;
        }
    }

    // android.provider.ContactsContract.CommonDataKinds.StructuredName
    public static class Name {
        public String displayName;
        public String givenName;
        public String familyName;
        public String prefix;
        public String middleName;
        public String suffix;
        public String phoneticGivenName;
        public String phoneticMiddleName;
        public String phoneticFamilyName;

        public static Name createDisplayName(String displayName) {
            Name name = new Name();
            name.displayName = displayName;
            return name;
        }

        public JSONObject getJsonObject() throws JSONException {
            JSONObject json = new JSONObject();
            json.putOpt(StructuredName.DISPLAY_NAME, displayName);
            json.putOpt(StructuredName.GIVEN_NAME, givenName);
            json.putOpt(StructuredName.FAMILY_NAME, familyName);
            json.putOpt(StructuredName.PREFIX, prefix);
            json.putOpt(StructuredName.MIDDLE_NAME, middleName);
            json.putOpt(StructuredName.SUFFIX, suffix);
            json.putOpt(StructuredName.PHONETIC_GIVEN_NAME,
                    phoneticGivenName);
            json.putOpt(StructuredName.PHONETIC_MIDDLE_NAME,
                    phoneticMiddleName);
            json.putOpt(StructuredName.PHONETIC_FAMILY_NAME,
                    phoneticFamilyName);
            return json;
        }

        public Name(JSONObject json) throws JSONException {
            if (json != null) {
                displayName = json.optString(StructuredName.DISPLAY_NAME, null);
            }
        }

        public Name() {}

        public String toString() {
            return "displayName: " + displayName + "; " +
                    "givenName: " + givenName + "; " +
                    "familyName: " + familyName + "; " +
                    "prefix: " + prefix + "; " +
                    "middleName: " + middleName + "; " +
                    "suffix: " + suffix + "; " +
                    "phoneticGivenName: " + phoneticGivenName + "; " +
                    "phoneticMiddleName: " + phoneticMiddleName + "; " +
                    "phoneticFamilyName: " + phoneticFamilyName;
        }
    }

    // android.provider.ContactsContract.CommonDataKinds.Phone
    public static class PhoneNumber {
        public String number;
        public int type;
        public String label;

        public static PhoneNumber createMainNumber(String number) {
            PhoneNumber n = new PhoneNumber();
            n.number = number;
            n.type = Phone.TYPE_MAIN;
            return n;
        }

        public JSONObject getJsonObject() throws JSONException {
            JSONObject json = new JSONObject();
            json.put(Phone.NUMBER, number);
            json.put(Phone.TYPE, type);
            json.putOpt(Phone.LABEL, label);
            return json;
        }

        public PhoneNumber(JSONObject json) throws JSONException {
            number = json.getString(Phone.NUMBER);
            type = json.getInt(Phone.TYPE);
            if (json.has(Phone.LABEL)) {
                label = json.getString(Phone.LABEL);
            }
        }

        public PhoneNumber() {}

        public String toString() {
            return "number: " + number + "; " +
                    "type: " + type + "; " +
                    "label: " + label;
        }
    }

    // android.provider.ContactsContract.CommonDataKinds.Website
    public static class WebsiteUrl {
        public String url;
        public int type;
        public String label;

        public static WebsiteUrl createProfile(String url) {
            WebsiteUrl u = new WebsiteUrl();
            u.url = url;
            u.type = Website.TYPE_PROFILE;
            return u;
        }

        public JSONObject getJsonObject() throws JSONException {
            JSONObject json = new JSONObject();
            json.put(Website.URL, url);
            json.put(Website.TYPE, type);
            json.putOpt(Website.LABEL, label);
            return json;
        }

        public WebsiteUrl() {}

        public WebsiteUrl(JSONObject json) throws JSONException {
            if (json.has(Website.URL)) {
                url = json.getString(Website.URL);
            }
            if (json.has(Website.TYPE)) {
                type = json.getInt(Website.TYPE);
            }
            if (json.has(Website.LABEL)) {
                label = json.getString(Website.LABEL);
            }
        }

        public String toString() {
            return "url: " + url + "; " +
                    "type: " + type + "; " +
                    "label: " + label;
        }
    }
}
Loading