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

Commit bcf4a216 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 13444741 from 2aae8e5b to 25Q4-release

Change-Id: Id0620c7796f3fef59445e1bd82d91bae1e4fc885
parents 0c69765a 2aae8e5b
Loading
Loading
Loading
Loading
+2 −9
Original line number Diff line number Diff line
@@ -20,8 +20,8 @@
          android:versionName="1.7.34">

    <uses-sdk
        android:minSdkVersion="34"
        android:targetSdkVersion="34"/>
        android:minSdkVersion="36"
        android:targetSdkVersion="36"/>

    <original-package android:name="com.android.contacts"/>

@@ -392,13 +392,6 @@

        </activity-alias>

        <!-- Accounts changed prompt that can appear when creating a new contact. -->
        <activity
            android:name=".activities.ContactEditorAccountsChangedActivity"
            android:exported="false"
            android:theme="@style/ContactEditorAccountsChangedActivityTheme"
            android:windowSoftInputMode="adjustResize"/>

        <!-- Edit or create a contact with only the most important fields displayed initially. -->
        <activity
            android:name=".activities.ContactEditorActivity"
+0 −8
Original line number Diff line number Diff line
@@ -289,14 +289,6 @@
        <item name="android:windowCloseOnTouchOutside">true</item>
    </style>

    <style name="ContactEditorAccountsChangedActivityTheme" parent="@android:style/Theme.Material.Light.Dialog.NoActionBar.MinWidth">
        <item name="android:windowCloseOnTouchOutside">true</item>
        <item name="android:textColorPrimary">@color/primary_text_color</item>
        <item name="android:textColorSecondary">@color/secondary_text_color</item>
        <item name="android:listViewStyle">@style/ListViewStyle</item>
        <item name="android:colorAccent">@color/primary_color</item>
    </style>

    <style name="SelectableItem" parent="@android:style/Theme.Material.Light">
        <item name="android:background">?android:attr/selectableItemBackground</item>
    </style>
+2 −3
Original line number Diff line number Diff line
@@ -26,11 +26,10 @@
        android:title="@string/settings_accounts">
    </Preference>

    <com.android.contacts.preference.DefaultAccountPreference
    <Preference
        android:icon="@null"
        android:key="defaultAccount"
        android:title="@string/default_editor_account"
        android:dialogTitle="@string/default_editor_account" />
        android:title="@string/default_editor_account" />

    <Preference
        android:icon="@null"
+109 −32
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.contacts;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
@@ -24,28 +25,34 @@ import android.provider.ContactsContract;
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

import com.android.contacts.model.account.AccountType;

import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberUtil;

/**
 * Shared static contact utility methods.
 */
/** Shared static contact utility methods. */
public class MoreContactUtils {

    private static final String WAIT_SYMBOL_AS_STRING = String.valueOf(PhoneNumberUtils.WAIT);

    /**
     * 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
     * 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) {
    public static boolean shouldCollapse(
            CharSequence mimetype1,
            CharSequence data1,
            CharSequence mimetype2,
            CharSequence data2) {
        // different mimetypes? don't collapse
        if (!TextUtils.equals(mimetype1, mimetype2)) return false;

@@ -57,8 +64,8 @@ public class MoreContactUtils {

        // 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)) {
        if (!TextUtils.equals(
                ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE, mimetype1)) {
            return false;
        }

@@ -165,18 +172,18 @@ public class MoreContactUtils {
                case SHORT_NSN_MATCH:
                    return false;
                default:
                    throw new IllegalStateException("Unknown result value from phone number " +
                            "library");
                    throw new IllegalStateException(
                            "Unknown result value from phone number " + "library");
            }
        }
        return true;
    }

    /**
     * Returns the {@link android.graphics.Rect} with left, top, right, and bottom coordinates
     * that are equivalent to the given {@link android.view.View}'s bounds. This is equivalent to
     * how the target {@link android.graphics.Rect} is calculated in
     * {@link android.provider.ContactsContract.QuickContact#showQuickContact}.
     * Returns the {@link android.graphics.Rect} with left, top, right, and bottom coordinates that
     * are equivalent to the given {@link android.view.View}'s bounds. This is equivalent to how the
     * target {@link android.graphics.Rect} is calculated in {@link
     * android.provider.ContactsContract.QuickContact#showQuickContact}.
     */
    public static Rect getTargetRectFromView(View view) {
        final int[] pos = new int[2];
@@ -191,8 +198,8 @@ public class MoreContactUtils {
    }

    /**
     * Returns a header view based on the R.layout.list_separator, where the
     * containing {@link android.widget.TextView} is set using the given textResourceId.
     * Returns a header view based on the R.layout.list_separator, where the containing {@link
     * android.widget.TextView} is set using the given textResourceId.
     */
    public static TextView createHeaderView(Context context, int textResourceId) {
        final TextView textView = (TextView) View.inflate(context, R.layout.list_separator, null);
@@ -201,29 +208,37 @@ public class MoreContactUtils {
    }

    /**
     * Set the top padding on the header view dynamically, based on whether the header is in
     * the first row or not.
     * Set the top padding on the header view dynamically, based on whether the header is in the
     * first row or not.
     */
    public static void setHeaderViewBottomPadding(Context context, TextView textView,
            boolean isFirstRow) {
    public static void setHeaderViewBottomPadding(
            Context context, TextView textView, boolean isFirstRow) {
        final int topPadding;
        if (isFirstRow) {
            topPadding = (int) context.getResources().getDimension(
                    R.dimen.frequently_contacted_title_top_margin_when_first_row);
            topPadding =
                    (int)
                            context.getResources()
                                    .getDimension(
                                            R.dimen
                                                    .frequently_contacted_title_top_margin_when_first_row);
        } else {
            topPadding = (int) context.getResources().getDimension(
                    R.dimen.frequently_contacted_title_top_margin);
            topPadding =
                    (int)
                            context.getResources()
                                    .getDimension(R.dimen.frequently_contacted_title_top_margin);
        }
        textView.setPaddingRelative(textView.getPaddingStart(), topPadding,
                textView.getPaddingEnd(), textView.getPaddingBottom());
        textView.setPaddingRelative(
                textView.getPaddingStart(),
                topPadding,
                textView.getPaddingEnd(),
                textView.getPaddingBottom());
    }


    /**
     * Returns the intent to launch for the given invitable account type and contact lookup URI.
     * This will return null if the account type is not invitable (i.e. there is no
     * {@link AccountType#getInviteContactActivityClassName()} or
     * {@link AccountType#syncAdapterPackageName}).
     * This will return null if the account type is not invitable (i.e. there is no {@link
     * AccountType#getInviteContactActivityClassName()} or {@link
     * AccountType#syncAdapterPackageName}).
     */
    public static Intent getInvitableIntent(AccountType accountType, Uri lookupUri) {
        String syncAdapterPackageName = accountType.syncAdapterPackageName;
@@ -240,4 +255,66 @@ public class MoreContactUtils {
        intent.setData(lookupUri);
        return intent;
    }

    /**
     * Enable new edge to edge feature.
     *
     * @param activity the Activity need to setup the edge to edge feature.
     */
    public static void setupEdgeToEdge(@NonNull Activity activity, EdgeToEdgeInsetHandler handler) {
        ViewCompat.setOnApplyWindowInsetsListener(
                activity.findViewById(android.R.id.content),
                (v, windowInsets) -> {
                    final Insets insets =
                            windowInsets.getInsets(
                                    WindowInsetsCompat.Type.systemBars()
                                            | WindowInsetsCompat.Type.ime()
                                            | WindowInsetsCompat.Type.displayCutout());

                    // Apply the insets paddings to the view.
                    v.setPadding(
                            insets.left,
                            handler == null ? insets.top : v.getPaddingTop(),
                            insets.right,
                            insets.bottom);

                    if (handler != null) {
                        handler.applyTopInset(insets.top);
                    }

                    // Return CONSUMED if you don't want the window insets to keep being
                    // passed down to descendant views.
                    return WindowInsetsCompat.CONSUMED;
                });
    }

    /** Handles setting the insets on a {@link View}. */
    public static class EdgeToEdgeInsetHandler {

        private final View mView;

        private int mOriginalHeight = -1;
        private int mOriginalPaddingTop = -1;

        public EdgeToEdgeInsetHandler(View view) {
            mView = view;
        }

        public void applyTopInset(int top) {
            ViewGroup.LayoutParams layoutParams = mView.getLayoutParams();
            if (mOriginalHeight == -1) {
                mOriginalHeight = layoutParams.height;
            }
            if (mOriginalPaddingTop == -1) {
                mOriginalPaddingTop = mView.getPaddingTop();
            }
            layoutParams.height = mOriginalHeight + top;
            mView.setLayoutParams(layoutParams);
            mView.setPadding(
                    mView.getPaddingLeft(),
                    mOriginalPaddingTop + top,
                    mView.getPaddingRight(),
                    mView.getPaddingBottom());
        }
    }
}
+96 −82
Original line number Diff line number Diff line
@@ -22,14 +22,6 @@ import android.content.Context;
import android.content.IntentFilter;
import android.content.Loader;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.snackbar.Snackbar;

import androidx.collection.ArrayMap;
import androidx.core.view.ViewCompat;
import androidx.core.widget.ContentLoadingProgressBar;
import androidx.appcompat.widget.Toolbar;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.View;
@@ -40,6 +32,15 @@ import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import androidx.collection.ArrayMap;
import androidx.core.view.ViewCompat;
import androidx.core.widget.ContentLoadingProgressBar;

import com.android.contacts.MoreContactUtils;
import com.android.contacts.MoreContactUtils.EdgeToEdgeInsetHandler;
import com.android.contacts.compat.CompatUtils;
import com.android.contacts.database.SimContactDao;
import com.android.contacts.editor.AccountHeaderPresenter;
@@ -51,6 +52,8 @@ import com.android.contacts.model.account.AccountWithDataSet;
import com.android.contacts.preference.ContactsPreferences;
import com.android.contacts.util.concurrent.ContactsExecutors;
import com.android.contacts.util.concurrent.ListenableFutureLoader;

import com.google.android.material.snackbar.Snackbar;
import com.google.common.base.Function;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
@@ -70,7 +73,8 @@ import java.util.concurrent.Callable;
 */
public class SimImportFragment extends Fragment
        implements LoaderManager.LoaderCallbacks<SimImportFragment.LoaderResult>,
        AdapterView.OnItemClickListener, AbsListView.OnScrollListener {
                AdapterView.OnItemClickListener,
                AbsListView.OnScrollListener {

    private static final String KEY_SUFFIX_SELECTED_IDS = "_selectedIds";
    private static final String ARG_SUBSCRIPTION_ID = "subscriptionId";
@@ -102,8 +106,10 @@ public class SimImportFragment extends Fragment
        mAdapter = new SimContactAdapter(getActivity());

        final Bundle args = getArguments();
        mSubscriptionId = args == null ? SimCard.NO_SUBSCRIPTION_ID :
                args.getInt(ARG_SUBSCRIPTION_ID, SimCard.NO_SUBSCRIPTION_ID);
        mSubscriptionId =
                args == null
                        ? SimCard.NO_SUBSCRIPTION_ID
                        : args.getInt(ARG_SUBSCRIPTION_ID, SimCard.NO_SUBSCRIPTION_ID);
    }

    @Override
@@ -114,15 +120,14 @@ public class SimImportFragment extends Fragment

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
    public View onCreateView(
            LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        final View view = inflater.inflate(R.layout.fragment_sim_import, container, false);

        mAccountHeaderContainer = view.findViewById(R.id.account_header_container);
        mAccountScrolledElevationPixels = getResources()
                .getDimension(R.dimen.contact_list_header_elevation);
        mAccountHeaderPresenter = new AccountHeaderPresenter(
                mAccountHeaderContainer);
        mAccountScrolledElevationPixels =
                getResources().getDimension(R.dimen.contact_list_header_elevation);
        mAccountHeaderPresenter = new AccountHeaderPresenter(mAccountHeaderContainer);
        if (savedInstanceState != null) {
            mAccountHeaderPresenter.onRestoreInstanceState(savedInstanceState);
        } else {
@@ -130,7 +135,8 @@ public class SimImportFragment extends Fragment
            // after they are loaded.
            mAccountHeaderPresenter.setCurrentAccount(mPreferences.getDefaultAccount());
        }
        mAccountHeaderPresenter.setObserver(new AccountHeaderPresenter.Observer() {
        mAccountHeaderPresenter.setObserver(
                new AccountHeaderPresenter.Observer() {
                    @Override
                    public void onChange(AccountHeaderPresenter sender) {
                        rememberSelectionsForCurrentAccount();
@@ -147,7 +153,8 @@ public class SimImportFragment extends Fragment
        mListView.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE);
        mListView.setOnItemClickListener(this);
        mImportButton = view.findViewById(R.id.import_button);
        mImportButton.setOnClickListener(new View.OnClickListener() {
        mImportButton.setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        importCurrentSelections();
@@ -158,7 +165,9 @@ public class SimImportFragment extends Fragment
                });

        mToolbar = (Toolbar) view.findViewById(R.id.toolbar);
        mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
        MoreContactUtils.setupEdgeToEdge(getActivity(), new EdgeToEdgeInsetHandler(mToolbar));
        mToolbar.setNavigationOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        getActivity().setResult(Activity.RESULT_CANCELED);
@@ -188,8 +197,8 @@ public class SimImportFragment extends Fragment
            return;
        }
        for (int i = 0, len = mListView.getCount(); i < len; i++) {
            mListView.setItemChecked(i,
                    Arrays.binarySearch(ids, mListView.getItemIdAtPosition(i)) >= 0);
            mListView.setItemChecked(
                    i, Arrays.binarySearch(ids, mListView.getItemIdAtPosition(i)) >= 0);
        }
    }

@@ -243,8 +252,7 @@ public class SimImportFragment extends Fragment
    }

    @Override
    public void onLoadFinished(Loader<LoaderResult> loader,
            LoaderResult data) {
    public void onLoadFinished(Loader<LoaderResult> loader, LoaderResult data) {
        mLoadingIndicator.hide();
        if (data == null) {
            return;
@@ -259,8 +267,7 @@ public class SimImportFragment extends Fragment
    }

    @Override
    public void onLoaderReset(Loader<LoaderResult> loader) {
    }
    public void onLoaderReset(Loader<LoaderResult> loader) {}

    private void restoreAdapterSelectedStates(List<AccountInfo> accounts) {
        if (mSavedInstanceState == null) {
@@ -268,7 +275,8 @@ public class SimImportFragment extends Fragment
        }

        for (AccountInfo account : accounts) {
            final long[] selections = mSavedInstanceState.getLongArray(
            final long[] selections =
                    mSavedInstanceState.getLongArray(
                            account.getAccount().stringify() + KEY_SUFFIX_SELECTED_IDS);
            mPerAccountCheckedIds.put(account.getAccount(), selections);
        }
@@ -282,8 +290,8 @@ public class SimImportFragment extends Fragment

        // Make sure the selections are up-to-date
        for (Map.Entry<AccountWithDataSet, long[]> entry : mPerAccountCheckedIds.entrySet()) {
            outState.putLongArray(entry.getKey().stringify() + KEY_SUFFIX_SELECTED_IDS,
                    entry.getValue());
            outState.putLongArray(
                    entry.getKey().stringify() + KEY_SUFFIX_SELECTED_IDS, entry.getValue());
        }
    }

@@ -297,14 +305,17 @@ public class SimImportFragment extends Fragment
                importableContacts.add(mAdapter.getItem(checked.keyAt(i)));
            }
        }
        SimImportService.startImport(getContext(), mSubscriptionId, importableContacts,
        SimImportService.startImport(
                getContext(),
                mSubscriptionId,
                importableContacts,
                mAccountHeaderPresenter.getCurrentAccount());
    }

    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        if (mAdapter.existsInCurrentAccount(position)) {
            Snackbar.make(getView(), R.string.sim_import_contact_exists_toast,
                    Snackbar.LENGTH_LONG).show();
            Snackbar.make(getView(), R.string.sim_import_contact_exists_toast, Snackbar.LENGTH_LONG)
                    .show();
        } else {
            updateToolbarWithCurrentSelections();
        }
@@ -321,8 +332,8 @@ public class SimImportFragment extends Fragment
    public void onScrollStateChanged(AbsListView view, int scrollState) {}

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
            int totalItemCount) {
    public void onScroll(
            AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        int firstCompletelyVisibleItem = firstVisibleItem;
        if (view != null && view.getChildAt(0) != null && view.getChildAt(0).getTop() < 0) {
            firstCompletelyVisibleItem++;
@@ -335,9 +346,7 @@ public class SimImportFragment extends Fragment
        }
    }

    /**
     * Creates a fragment that will display contacts stored on the default SIM card
     */
    /** Creates a fragment that will display contacts stored on the default SIM card */
    public static SimImportFragment newInstance() {
        return new SimImportFragment();
    }
@@ -394,9 +403,10 @@ public class SimImportFragment extends Fragment
        public View getView(int position, View convertView, ViewGroup parent) {
            TextView text = (TextView) convertView;
            if (text == null) {
                final int layoutRes = existsInCurrentAccount(position) ?
                        R.layout.sim_import_list_item_disabled :
                        R.layout.sim_import_list_item;
                final int layoutRes =
                        existsInCurrentAccount(position)
                                ? R.layout.sim_import_list_item_disabled
                                : R.layout.sim_import_list_item;
                text = (TextView) mInflater.inflate(layoutRes, parent, false);
            }
            text.setText(getItemLabel(getItem(position)));
@@ -444,7 +454,6 @@ public class SimImportFragment extends Fragment
        }
    }


    private static class SimContactLoader extends ListenableFutureLoader<LoaderResult> {
        private SimContactDao mDao;
        private AccountTypeManager mAccountTypeManager;
@@ -459,17 +468,21 @@ public class SimImportFragment extends Fragment

        @Override
        protected ListenableFuture<LoaderResult> loadData() {
            final ListenableFuture<List<Object>> future = Futures.<Object>allAsList(
                    mAccountTypeManager
                            .filterAccountsAsync(AccountTypeManager.writableFilter()),
                    ContactsExecutors.getSimReadExecutor().<Object>submit(
            final ListenableFuture<List<Object>> future =
                    Futures.<Object>allAsList(
                            mAccountTypeManager.filterAccountsAsync(
                                    AccountTypeManager.insertableFilter(getContext())),
                            ContactsExecutors.getSimReadExecutor()
                                    .<Object>submit(
                                            new Callable<Object>() {
                                                @Override
                                                public LoaderResult call() throws Exception {
                                                    return loadFromSim();
                                                }
                                            }));
            return Futures.transform(future, new Function<List<Object>, LoaderResult>() {
            return Futures.transform(
                    future,
                    new Function<List<Object>, LoaderResult>() {
                        @Override
                        public LoaderResult apply(List<Object> input) {
                            final List<AccountInfo> accounts = (List<AccountInfo>) input.get(0);
@@ -477,7 +490,8 @@ public class SimImportFragment extends Fragment
                            simLoadResult.accounts = accounts;
                            return simLoadResult;
                        }
            }, MoreExecutors.directExecutor());
                    },
                    MoreExecutors.directExecutor());
        }

        private LoaderResult loadFromSim() {
Loading