core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl \
core/java/android/accounts/IAccountManager.aidl \
core/java/android/accounts/IAccountManagerResponse.aidl \
- core/java/android/accounts/IAccountAccessTracker.aidl \
core/java/android/accounts/IAccountAuthenticator.aidl \
core/java/android/accounts/IAccountAuthenticatorResponse.aidl \
core/java/android/app/IActivityContainer.aidl \
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.Context;
import android.os.Parcelable;
import android.os.Parcel;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
public final String name;
public final String type;
- private final @Nullable IAccountAccessTracker mAccessTracker;
+ private final @Nullable String accessId;
public boolean equals(Object o) {
if (o == this) return true;
/**
* @hide
*/
- public Account(@NonNull Account other, @Nullable IAccountAccessTracker accessTracker) {
- this(other.name, other.type, accessTracker);
+ public Account(@NonNull Account other, @NonNull String accessId) {
+ this(other.name, other.type, accessId);
}
/**
* @hide
*/
- public Account(String name, String type, IAccountAccessTracker accessTracker) {
+ public Account(String name, String type, String accessId) {
if (TextUtils.isEmpty(name)) {
throw new IllegalArgumentException("the name must not be empty: " + name);
}
}
this.name = name;
this.type = type;
- this.mAccessTracker = accessTracker;
+ this.accessId = accessId;
}
public Account(Parcel in) {
this.name = in.readString();
this.type = in.readString();
- this.mAccessTracker = IAccountAccessTracker.Stub.asInterface(in.readStrongBinder());
- if (mAccessTracker != null) {
+ this.accessId = in.readString();
+ if (accessId != null) {
synchronized (sAccessedAccounts) {
if (sAccessedAccounts.add(this)) {
try {
- mAccessTracker.onAccountAccessed();
+ IAccountManager accountManager = IAccountManager.Stub.asInterface(
+ ServiceManager.getService(Context.ACCOUNT_SERVICE));
+ accountManager.onAccountAccessed(accessId);
} catch (RemoteException e) {
Log.e(TAG, "Error noting account access", e);
}
}
/** @hide */
- public IAccountAccessTracker getAccessTracker() {
- return mAccessTracker;
+ public String getAccessId() {
+ return accessId;
}
public int describeContents() {
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(type);
- dest.writeStrongInterface(mAccessTracker);
+ dest.writeString(accessId);
}
public static final Creator<Account> CREATOR = new Creator<Account>() {
public static final String KEY_ACCOUNT_TYPE = "accountType";
/**
- * Bundle key used for the {@link IAccountAccessTracker} account access tracker
- * used for noting the account was accessed when unmarshalled from a parcel.
+ * Bundle key used for the account access id used for noting the
+ * account was accessed when unmarshalled from a parcel.
*
* @hide
*/
- public static final String KEY_ACCOUNT_ACCESS_TRACKER = "accountAccessTracker";
+ public static final String KEY_ACCOUNT_ACCESS_ID = "accountAccessId";
/**
* Bundle key used for the auth token value in results
public Account bundleToResult(Bundle bundle) throws AuthenticatorException {
String name = bundle.getString(KEY_ACCOUNT_NAME);
String type = bundle.getString(KEY_ACCOUNT_TYPE);
- IAccountAccessTracker tracker = IAccountAccessTracker.Stub.asInterface(
- bundle.getBinder(KEY_ACCOUNT_ACCESS_TRACKER));
- return new Account(name, type, tracker);
+ String accessId = bundle.getString(KEY_ACCOUNT_ACCESS_ID);
+ return new Account(name, type, accessId);
}
}.start();
}
result.putString(KEY_ACCOUNT_NAME, null);
result.putString(KEY_ACCOUNT_TYPE, null);
result.putString(KEY_AUTHTOKEN, null);
- result.putBinder(KEY_ACCOUNT_ACCESS_TRACKER, null);
+ result.putBinder(KEY_ACCOUNT_ACCESS_ID, null);
try {
mResponse.onResult(result);
} catch (RemoteException e) {
Account account = new Account(
value.getString(KEY_ACCOUNT_NAME),
value.getString(KEY_ACCOUNT_TYPE),
- IAccountAccessTracker.Stub.asInterface(
- value.getBinder(
- KEY_ACCOUNT_ACCESS_TRACKER)));
+ value.getString(KEY_ACCOUNT_ACCESS_ID));
mFuture = getAuthToken(account, mAuthTokenType,
mLoginOptions, mActivity, mMyCallback,
mHandler);
setException(new AuthenticatorException("account not in result"));
return;
}
- final IAccountAccessTracker tracker = IAccountAccessTracker.Stub.asInterface(
- result.getBinder(KEY_ACCOUNT_ACCESS_TRACKER));
- final Account account = new Account(accountName, accountType, tracker);
+ final String accessId = result.getString(KEY_ACCOUNT_ACCESS_ID);
+ final Account account = new Account(accountName, accountType, accessId);
mNumAccounts = 1;
getAuthToken(account, mAuthTokenType, null /* options */, mActivity,
mMyCallback, mHandler);
+++ /dev/null
-/*
- * Copyright (C) 2016 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 android.accounts;
-
-/**
- * Interface to track which apps accessed an account
- *
- * @hide
- */
-oneway interface IAccountAccessTracker {
- void onAccountAccessed();
-}
/* Crate an intent to request account access for package and a given user id */
IntentSender createRequestAccountAccessIntentSenderAsUser(in Account account,
String packageName, in UserHandle userHandle);
+
+ void onAccountAccessed(String token);
}
import android.accounts.AuthenticatorDescription;
import android.accounts.CantAddAccountActivity;
import android.accounts.GrantCredentialsPermissionActivity;
-import android.accounts.IAccountAccessTracker;
import android.accounts.IAccountAuthenticator;
import android.accounts.IAccountAuthenticatorResponse;
import android.accounts.IAccountManager;
import android.os.storage.StorageManager;
import android.text.TextUtils;
import android.util.Log;
-import android.util.PackageUtils;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
final Account[] accountsForType = new Account[accountNames.size()];
for (int i = 0; i < accountsForType.length; i++) {
accountsForType[i] = new Account(accountNames.get(i), accountType,
- new AccountAccessTracker());
+ UUID.randomUUID().toString());
}
accounts.accountCache.put(accountType, accountsForType);
}
Bundle result = new Bundle();
result.putString(AccountManager.KEY_ACCOUNT_NAME, resultingAccount.name);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, resultingAccount.type);
- result.putBinder(AccountManager.KEY_ACCOUNT_ACCESS_TRACKER,
- resultingAccount.getAccessTracker().asBinder());
+ result.putString(AccountManager.KEY_ACCOUNT_ACCESS_ID,
+ resultingAccount.getAccessId());
try {
response.onResult(result);
} catch (RemoteException e) {
}
}
+ @Override
+ public void onAccountAccessed(String token) throws RemoteException {
+ final int uid = Binder.getCallingUid();
+ if (UserHandle.getAppId(uid) == Process.SYSTEM_UID) {
+ return;
+ }
+ final int userId = UserHandle.getCallingUserId();
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ for (Account account : getAccounts(userId, mContext.getOpPackageName())) {
+ if (Objects.equals(account.getAccessId(), token)) {
+ // An app just accessed the account. At this point it knows about
+ // it and there is not need to hide this account from the app.
+ if (!hasAccountAccess(account, null, uid)) {
+ updateAppPermission(account, AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE,
+ uid, true);
+ }
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
private abstract class Session extends IAccountAuthenticatorResponse.Stub
implements IBinder.DeathRecipient, ServiceConnection {
IAccountManagerResponse mResponse;
if (accountsForType != null) {
System.arraycopy(accountsForType, 0, newAccountsForType, 0, oldLength);
}
- IAccountAccessTracker accessTracker = account.getAccessTracker() != null
- ? account.getAccessTracker() : new AccountAccessTracker();
- newAccountsForType[oldLength] = new Account(account, accessTracker);
+ String token = account.getAccessId() != null ? account.getAccessId()
+ : UUID.randomUUID().toString();
+ newAccountsForType[oldLength] = new Account(account, token);
accounts.accountCache.put(account.type, newAccountsForType);
return newAccountsForType[oldLength];
}
}
}
- private final class AccountAccessTracker extends IAccountAccessTracker.Stub {
- @Override
- public void onAccountAccessed() throws RemoteException {
- final int uid = Binder.getCallingUid();
- if (UserHandle.getAppId(uid) == Process.SYSTEM_UID) {
- return;
- }
- final int userId = UserHandle.getCallingUserId();
- final long identity = Binder.clearCallingIdentity();
- try {
- for (Account account : getAccounts(userId, mContext.getOpPackageName())) {
- IAccountAccessTracker accountTracker = account.getAccessTracker();
- if (accountTracker != null && asBinder() == accountTracker.asBinder()) {
- // An app just accessed the account. At this point it knows about
- // it and there is not need to hide this account from the app.
- if (!hasAccountAccess(account, null, uid)) {
- updateAppPermission(account, AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE,
- uid, true);
- }
- }
- }
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
- }
-
private final class AccountManagerInternalImpl extends AccountManagerInternal {
private final Object mLock = new Object();