/* * Copyright (C) 2018 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.car.settings.accounts; import android.accounts.Account; import android.accounts.AccountManager; import android.app.Activity; import android.car.drivingstate.CarUxRestrictions; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentSender; import android.content.SyncAdapterType; import android.content.SyncInfo; import android.content.SyncStatusInfo; import android.content.SyncStatusObserver; import android.content.pm.PackageManager; import android.os.UserHandle; import android.text.format.DateFormat; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.collection.ArrayMap; import androidx.preference.Preference; import androidx.preference.PreferenceGroup; import com.android.car.settings.R; import com.android.car.settings.common.FragmentController; import com.android.car.settings.common.Logger; import com.android.car.settings.common.PreferenceController; import com.android.settingslib.accounts.AuthenticatorHelper; import com.android.settingslib.utils.ThreadUtils; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * Controller that presents all visible sync adapters for an account. * *
Largely derived from {@link com.android.settings.accounts.AccountSyncSettings}.
*/
public class AccountSyncDetailsPreferenceController extends
PreferenceController Largely derived from
* {@link com.android.settings.accounts.AccountSyncSettings#onPreferenceTreeClick}.
*/
private boolean onSyncPreferenceClicked(SyncPreference preference) {
String authority = preference.getKey();
String packageName = preference.getPackageName();
int uid = preference.getUid();
if (preference.isOneTimeSyncMode()) {
// If the sync adapter doesn't have access to the account we either
// request access by starting an activity if possible or kick off the
// sync which will end up posting an access request notification.
if (requestAccountAccessIfNeeded(packageName, uid)) {
return true;
}
requestSync(authority);
} else {
boolean syncOn = preference.isChecked();
int userId = mUserHandle.getIdentifier();
boolean oldSyncState = ContentResolver.getSyncAutomaticallyAsUser(mAccount,
authority, userId);
if (syncOn != oldSyncState) {
// Toggling this switch triggers sync but we may need a user approval. If the
// sync adapter doesn't have access to the account we either request access by
// starting an activity if possible or kick off the sync which will end up
// posting an access request notification.
if (syncOn && requestAccountAccessIfNeeded(packageName, uid)) {
return true;
}
// If we're enabling sync, this will request a sync as well.
ContentResolver.setSyncAutomaticallyAsUser(mAccount, authority, syncOn, userId);
if (syncOn) {
requestSync(authority);
} else {
cancelSync(authority);
}
}
}
return true;
}
private void requestSync(String authority) {
AccountSyncHelper.requestSyncIfAllowed(mAccount, authority, mUserHandle.getIdentifier());
}
private void cancelSync(String authority) {
ContentResolver.cancelSyncAsUser(mAccount, authority, mUserHandle.getIdentifier());
}
/**
* Requests account access if needed.
*
* Copied from
* {@link com.android.settings.accounts.AccountSyncSettings#requestAccountAccessIfNeeded}.
*/
private boolean requestAccountAccessIfNeeded(String packageName, int uid) {
if (packageName == null) {
return false;
}
AccountManager accountManager = getContext().getSystemService(AccountManager.class);
if (!accountManager.hasAccountAccess(mAccount, packageName, mUserHandle)) {
IntentSender intent = accountManager.createRequestAccountAccessIntentSenderAsUser(
mAccount, packageName, mUserHandle);
if (intent != null) {
try {
getFragmentController().startIntentSenderForResult(intent,
uid, /* fillInIntent= */ null, /* flagsMask= */ 0,
/* flagsValues= */ 0, /* options= */ null,
this::onAccountRequestApproved);
return true;
} catch (IntentSender.SendIntentException e) {
LOG.e("Error requesting account access", e);
}
}
}
return false;
}
/** Handles a sync adapter refresh when an account request was approved. */
public void onAccountRequestApproved(int uid, int resultCode, @Nullable Intent data) {
if (resultCode == Activity.RESULT_OK) {
for (SyncPreference pref : mSyncPreferences.values()) {
if (pref.getUid() == uid) {
onSyncPreferenceClicked(pref);
return;
}
}
}
}
/** Forces a refresh of the sync adapter preferences. */
private void forceUpdateSyncCategory() {
Set Derived from {@link com.android.settings.accounts.AccountSyncSettings#setFeedsState}
* and {@link com.android.settings.accounts.AccountSyncSettings#updateAccountSwitches}.
*
* @param preferencesToRemove the keys for the preferences currently being shown; only the keys
* for preferences to be removed will remain after method execution
*/
private List