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

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

Snap for 8069058 from 3cf16624 to tm-d1-release

Change-Id: I4829a14b0b18ae5f7d6bdd11520ca9e45d984bce
parents 4f30d72c 3cf16624
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -261,6 +261,17 @@
            android:launchMode="singleTop"
            android:theme="@style/ContactsPreferencesTheme"/>

        <activity
            android:name=".preference.SetDefaultAccountActivity"
            android:exported="true"
            android:theme="@style/BackgroundOnlyTheme"
            android:excludeFromRecents="true">
            <intent-filter>
                <action android:name="android.provider.action.SET_DEFAULT_ACCOUNT"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

        <activity
            android:name=".activities.LicenseActivity"
            android:exported="true"
+1 −1
Original line number Diff line number Diff line
@@ -26,7 +26,7 @@
        android:title="@string/settings_accounts">
    </Preference>

    <com.android.contacts.preference.DefaultAccountPreference
    <Preference
        android:icon="@null"
        android:key="defaultAccount"
        android:title="@string/default_editor_account"
+67 −9
Original line number Diff line number Diff line
@@ -16,20 +16,29 @@

package com.android.contacts.preference;

import static android.Manifest.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS;

import android.accounts.Account;
import android.annotation.SuppressLint;
import android.app.backup.BackupManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Handler;
import android.os.Looper;
import android.os.StrictMode;
import android.preference.PreferenceManager;
import android.provider.ContactsContract;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.text.TextUtils;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting;
import androidx.core.os.BuildCompat;

import com.android.contacts.R;
import com.android.contacts.model.account.AccountWithDataSet;
@@ -209,23 +218,45 @@ public class ContactsPreferences implements OnSharedPreferenceChangeListener {
        return mIsDefaultAccountUserChangeable;
    }

    @SuppressLint("NewApi")
    public AccountWithDataSet getDefaultAccount() {
        if (!isDefaultAccountUserChangeable()) {
            return mDefaultAccount;
        }
        if (mDefaultAccount == null) {
            final String accountString = mPreferences
                    .getString(mDefaultAccountKey, null);
            if (!TextUtils.isEmpty(accountString)) {
                mDefaultAccount = AccountWithDataSet.unstringify(accountString);
            Account cp2DefaultAccount = null;
            if (BuildCompat.isAtLeastT()) {
                cp2DefaultAccount = getDefaultAccountFromCp2();
            }

            mDefaultAccount = cp2DefaultAccount == null
                    ? AccountWithDataSet.getNullAccount()
                    : new AccountWithDataSet(cp2DefaultAccount.name, cp2DefaultAccount.type, null);
        }
        return mDefaultAccount;
    }

    @RequiresApi(33)
    private Account getDefaultAccountFromCp2() {
        StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
        StrictMode.setThreadPolicy(
                new StrictMode.ThreadPolicy.Builder(oldPolicy)
                .permitDiskReads()
                .build());
        try {
            return ContactsContract.Settings.getDefaultAccount(
                    mContext.getContentResolver());
        } finally {
            StrictMode.setThreadPolicy(oldPolicy);
        }
    }

    public void clearDefaultAccount() {
        if (mContext.checkSelfPermission(SET_DEFAULT_ACCOUNT_FOR_CONTACTS)
                == PackageManager.PERMISSION_GRANTED) {
            mDefaultAccount = null;
        mPreferences.edit().remove(mDefaultAccountKey).commit();
            setDefaultAccountToCp2(null);
        }
    }

    public void setDefaultAccount(@NonNull AccountWithDataSet accountWithDataSet) {
@@ -233,12 +264,30 @@ public class ContactsPreferences implements OnSharedPreferenceChangeListener {
            throw new IllegalArgumentException(
                    "argument should not be null");
        }
        if (mContext.checkSelfPermission(SET_DEFAULT_ACCOUNT_FOR_CONTACTS)
                == PackageManager.PERMISSION_GRANTED) {
            mDefaultAccount = accountWithDataSet;
        mPreferences.edit().putString(mDefaultAccountKey, accountWithDataSet.stringify()).commit();
            setDefaultAccountToCp2(accountWithDataSet);
        }
    }

    private void setDefaultAccountToCp2(AccountWithDataSet accountWithDataSet) {
        StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
        StrictMode.setThreadPolicy(
                new StrictMode.ThreadPolicy.Builder(oldPolicy)
                        .permitDiskWrites()
                        .permitDiskReads()
                        .build());
        try {
            ContactsContract.Settings.setDefaultAccount(mContext.getContentResolver(),
                    accountWithDataSet == null ? null : accountWithDataSet.getAccountOrNull());
        } finally {
            StrictMode.setThreadPolicy(oldPolicy);
        }
    }

    public boolean isDefaultAccountSet() {
        return mDefaultAccount != null || mPreferences.contains(mDefaultAccountKey);
        return mDefaultAccount != null;
    }

    /**
@@ -391,6 +440,15 @@ public class ContactsPreferences implements OnSharedPreferenceChangeListener {
                setDefaultAccount(accountWithDataSet);
            }
        }

        if (mPreferences.contains(mDefaultAccountKey) && getDefaultAccount() == null) {
            String defaultAccount = mPreferences.getString(mDefaultAccountKey, null);
            if (!TextUtils.isEmpty(defaultAccount)) {
                final AccountWithDataSet accountWithDataSet = AccountWithDataSet.unstringify(
                        defaultAccount);
                setDefaultAccount(accountWithDataSet);
            }
        }
    }

}
+0 −112
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 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.contacts.preference;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.View;

import com.android.contacts.model.account.AccountInfo;
import com.android.contacts.model.account.AccountWithDataSet;
import com.android.contacts.util.AccountsListAdapter;

import java.util.List;

public class DefaultAccountPreference extends DialogPreference {
    private ContactsPreferences mPreferences;
    private AccountsListAdapter mListAdapter;
    private List<AccountInfo> mAccounts;
    private int mChosenIndex = -1;

    public DefaultAccountPreference(Context context) {
        super(context);
        prepare();
    }

    public DefaultAccountPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        prepare();
    }

    public void setAccounts(List<AccountInfo> accounts) {
        mAccounts = accounts;
        if (mListAdapter != null) {
            mListAdapter.setAccounts(accounts, null);
            notifyChanged();
        }
    }

    @Override
    protected View onCreateDialogView() {
        prepare();
        return super.onCreateDialogView();
    }

    private void prepare() {
        mPreferences = new ContactsPreferences(getContext());
        mListAdapter = new AccountsListAdapter(getContext());
        if (mAccounts != null) {
            mListAdapter.setAccounts(mAccounts, null);
        }
    }

    @Override
    protected boolean shouldPersist() {
        return false;   // This preference takes care of its own storage
    }

    @Override
    public CharSequence getSummary() {
        final AccountWithDataSet defaultAccount = mPreferences.getDefaultAccount();
        if (defaultAccount == null || mAccounts == null ||
                !AccountInfo.contains(mAccounts, defaultAccount)) {
            return null;
        } else {
            return AccountInfo.getAccount(mAccounts, defaultAccount).getNameLabel();
        }
    }

    @Override
    protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
        super.onPrepareDialogBuilder(builder);
        // UX recommendation is not to show buttons on such lists.
        builder.setNegativeButton(null, null);
        builder.setPositiveButton(null, null);
        builder.setAdapter(mListAdapter, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                mChosenIndex = which;
            }
        });
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        final AccountWithDataSet currentDefault = mPreferences.getDefaultAccount();

        if (mChosenIndex != -1) {
            final AccountWithDataSet chosenAccount = mListAdapter.getItem(mChosenIndex);
            if (!chosenAccount.equals(currentDefault)) {
                mPreferences.setDefaultAccount(chosenAccount);
                notifyChanged();
            }
        } // else the user dismissed this dialog so leave the preference unchanged.
    }
}
+61 −3
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.contacts.preference;

import android.accounts.Account;
import android.app.Activity;
import android.app.LoaderManager;
import android.content.BroadcastReceiver;
@@ -25,17 +26,21 @@ import android.content.CursorLoader;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.Loader;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.database.Cursor;
import android.icu.text.MessageFormat;
import android.net.Uri;
import android.os.Bundle;
import android.os.StrictMode;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.provider.BlockedNumberContract;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.DisplayNameSources;
import android.provider.ContactsContract.Profile;
import android.provider.ContactsContract.Settings;
import com.google.android.material.snackbar.Snackbar;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import android.telecom.TelecomManager;
@@ -59,11 +64,13 @@ import com.android.contacts.list.ContactListFilterController;
import com.android.contacts.logging.ScreenEvent.ScreenType;
import com.android.contacts.model.AccountTypeManager;
import com.android.contacts.model.account.AccountInfo;
import com.android.contacts.model.account.AccountWithDataSet;
import com.android.contacts.model.account.AccountsLoader;
import com.android.contacts.util.AccountFilterUtil;
import com.android.contacts.util.ImplicitIntentsUtil;
import com.android.contactsbind.HelpUtils;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
@@ -76,6 +83,7 @@ public class DisplayOptionsPreferenceFragment extends PreferenceFragment
        implements Preference.OnPreferenceClickListener, AccountsLoader.AccountsListener {

    private static final int REQUEST_CODE_CUSTOM_CONTACTS_FILTER = 0;
    private static final int REQUEST_CODE_SET_DEFAULT_ACCOUNT_CP2 = 1;

    private static final String ARG_CONTACTS_AVAILABLE = "are_contacts_available";
    private static final String ARG_NEW_LOCAL_PROFILE = "new_local_profile";
@@ -147,6 +155,8 @@ public class DisplayOptionsPreferenceFragment extends PreferenceFragment
    private ViewGroup mRootView;
    private SaveServiceResultListener mSaveServiceListener;

    private List<AccountInfo> accounts = Collections.emptyList();

    private final LoaderManager.LoaderCallbacks<Cursor> mProfileLoaderListener =
            new LoaderManager.LoaderCallbacks<Cursor>() {

@@ -249,6 +259,12 @@ public class DisplayOptionsPreferenceFragment extends PreferenceFragment
            customFilterPreference.setOnPreferenceClickListener(this);
            setCustomContactsFilterSummary();
        }

        final Preference defaultAccountPreference = findPreference(KEY_DEFAULT_ACCOUNT);
        if (defaultAccountPreference != null) {
            defaultAccountPreference.setOnPreferenceClickListener(this);
            defaultAccountPreference.setSummary(getDefaultAccountSummary());
        }
    }

    @Override
@@ -314,9 +330,10 @@ public class DisplayOptionsPreferenceFragment extends PreferenceFragment
    @Override
    public void onAccountsLoaded(List<AccountInfo> accounts) {
        // Hide accounts preferences if no writable accounts exist
        final DefaultAccountPreference preference =
                (DefaultAccountPreference) findPreference(KEY_DEFAULT_ACCOUNT);
        preference.setAccounts(accounts);
        this.accounts = accounts;
        final Preference defaultAccountPreference =
                findPreference(KEY_DEFAULT_ACCOUNT);
        defaultAccountPreference.setSummary(getDefaultAccountSummary());
    }

    @Override
@@ -384,6 +401,13 @@ public class DisplayOptionsPreferenceFragment extends PreferenceFragment
                    ContactListFilterController.getInstance(getContext()).getFilter();
            AccountFilterUtil.startAccountFilterActivityForResult(
                    this, REQUEST_CODE_CUSTOM_CONTACTS_FILTER, filter);
        } else if (KEY_DEFAULT_ACCOUNT.equals(prefKey)) {
            String packageName = getSetDefaultAccountActivityPackage();
            Intent intent = new Intent(Settings.ACTION_SET_DEFAULT_ACCOUNT);
            if (packageName != null) {
                intent.setPackage(packageName);
                startActivityForResult(intent, REQUEST_CODE_SET_DEFAULT_ACCOUNT_CP2);
            }
        }
        return false;
    }
@@ -395,6 +419,12 @@ public class DisplayOptionsPreferenceFragment extends PreferenceFragment
            AccountFilterUtil.handleAccountFilterResult(
                    ContactListFilterController.getInstance(getContext()), resultCode, data);
            setCustomContactsFilterSummary();
        } else if (requestCode == REQUEST_CODE_SET_DEFAULT_ACCOUNT_CP2
                && resultCode == Activity.RESULT_OK) {
            final Preference defaultAccountPreference = findPreference(KEY_DEFAULT_ACCOUNT);
            if (defaultAccountPreference != null) {
                defaultAccountPreference.setSummary(getDefaultAccountSummary());
            }
        } else {
            super.onActivityResult(requestCode, resultCode, data);
        }
@@ -418,6 +448,34 @@ public class DisplayOptionsPreferenceFragment extends PreferenceFragment
        }
    }

    private CharSequence getDefaultAccountSummary() {
        ContactsPreferences preferences = new ContactsPreferences(getContext());
        AccountWithDataSet defaultAccountWithDataSet = preferences.getDefaultAccount();
        AccountInfo defaultAccountInfo = AccountInfo.getAccount(
                accounts, defaultAccountWithDataSet);
        if (defaultAccountInfo != null) {
            return defaultAccountInfo.getNameLabel();
        } else {
            return null;
        }
    }

    private String getSetDefaultAccountActivityPackage() {
        // Only preloaded Contacts App has the permission to call setDefaultAccount.
        Intent intent = new Intent(Settings.ACTION_SET_DEFAULT_ACCOUNT);
        PackageManager packageManager = getContext().getPackageManager();
        List<ResolveInfo> resolveInfos = packageManager.queryIntentActivities(intent, 0);
        for (ResolveInfo resolveInfo : resolveInfos) {
            String packageName = resolveInfo.activityInfo.packageName;
            if (packageManager.checkPermission(
                    android.Manifest.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS, packageName)
                    == PackageManager.PERMISSION_GRANTED) {
                return packageName;
            }
        }
        return null;
    }

    private class SaveServiceResultListener extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
Loading