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

Commit e17434d5 authored by Tingting's avatar Tingting
Browse files

Use CP2 for default account setting in AOSP.

1) read the setting from CP2.
2) add an activity to handle the intent to set the setting
when it's the preloaded contacts app.

Test: manual tests.
Bug: 213629089
Change-Id: Ib8338e9a3c4531eb642d1ee6c6a3cea2546a2dc7
parent 656639e7
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