Merge "[DO NOT MERGE] Use tokens instead of account access trackers" into nyc-mr1-dev

This commit is contained in:
TreeHugger Robot
2016-09-27 20:45:46 +00:00
committed by Android (Google) Code Review
6 changed files with 58 additions and 86 deletions

View File

@@ -63,7 +63,6 @@ LOCAL_SRC_FILES += \
core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl \ core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl \
core/java/android/accounts/IAccountManager.aidl \ core/java/android/accounts/IAccountManager.aidl \
core/java/android/accounts/IAccountManagerResponse.aidl \ core/java/android/accounts/IAccountManagerResponse.aidl \
core/java/android/accounts/IAccountAccessTracker.aidl \
core/java/android/accounts/IAccountAuthenticator.aidl \ core/java/android/accounts/IAccountAuthenticator.aidl \
core/java/android/accounts/IAccountAuthenticatorResponse.aidl \ core/java/android/accounts/IAccountAuthenticatorResponse.aidl \
core/java/android/app/IActivityContainer.aidl \ core/java/android/app/IActivityContainer.aidl \

View File

@@ -18,9 +18,11 @@ package android.accounts;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.content.Context;
import android.os.Parcelable; import android.os.Parcelable;
import android.os.Parcel; import android.os.Parcel;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ServiceManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.ArraySet; import android.util.ArraySet;
import android.util.Log; import android.util.Log;
@@ -41,7 +43,7 @@ public class Account implements Parcelable {
public final String name; public final String name;
public final String type; public final String type;
private final @Nullable IAccountAccessTracker mAccessTracker; private final @Nullable String accessId;
public boolean equals(Object o) { public boolean equals(Object o) {
if (o == this) return true; if (o == this) return true;
@@ -64,14 +66,14 @@ public class Account implements Parcelable {
/** /**
* @hide * @hide
*/ */
public Account(@NonNull Account other, @Nullable IAccountAccessTracker accessTracker) { public Account(@NonNull Account other, @NonNull String accessId) {
this(other.name, other.type, accessTracker); this(other.name, other.type, accessId);
} }
/** /**
* @hide * @hide
*/ */
public Account(String name, String type, IAccountAccessTracker accessTracker) { public Account(String name, String type, String accessId) {
if (TextUtils.isEmpty(name)) { if (TextUtils.isEmpty(name)) {
throw new IllegalArgumentException("the name must not be empty: " + name); throw new IllegalArgumentException("the name must not be empty: " + name);
} }
@@ -80,18 +82,20 @@ public class Account implements Parcelable {
} }
this.name = name; this.name = name;
this.type = type; this.type = type;
this.mAccessTracker = accessTracker; this.accessId = accessId;
} }
public Account(Parcel in) { public Account(Parcel in) {
this.name = in.readString(); this.name = in.readString();
this.type = in.readString(); this.type = in.readString();
this.mAccessTracker = IAccountAccessTracker.Stub.asInterface(in.readStrongBinder()); this.accessId = in.readString();
if (mAccessTracker != null) { if (accessId != null) {
synchronized (sAccessedAccounts) { synchronized (sAccessedAccounts) {
if (sAccessedAccounts.add(this)) { if (sAccessedAccounts.add(this)) {
try { try {
mAccessTracker.onAccountAccessed(); IAccountManager accountManager = IAccountManager.Stub.asInterface(
ServiceManager.getService(Context.ACCOUNT_SERVICE));
accountManager.onAccountAccessed(accessId);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(TAG, "Error noting account access", e); Log.e(TAG, "Error noting account access", e);
} }
@@ -101,8 +105,8 @@ public class Account implements Parcelable {
} }
/** @hide */ /** @hide */
public IAccountAccessTracker getAccessTracker() { public String getAccessId() {
return mAccessTracker; return accessId;
} }
public int describeContents() { public int describeContents() {
@@ -112,7 +116,7 @@ public class Account implements Parcelable {
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name); dest.writeString(name);
dest.writeString(type); dest.writeString(type);
dest.writeStrongInterface(mAccessTracker); dest.writeString(accessId);
} }
public static final Creator<Account> CREATOR = new Creator<Account>() { public static final Creator<Account> CREATOR = new Creator<Account>() {

View File

@@ -179,12 +179,12 @@ public class AccountManager {
public static final String KEY_ACCOUNT_TYPE = "accountType"; public static final String KEY_ACCOUNT_TYPE = "accountType";
/** /**
* Bundle key used for the {@link IAccountAccessTracker} account access tracker * Bundle key used for the account access id used for noting the
* used for noting the account was accessed when unmarshalled from a parcel. * account was accessed when unmarshalled from a parcel.
* *
* @hide * @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 * Bundle key used for the auth token value in results
@@ -821,9 +821,8 @@ public class AccountManager {
public Account bundleToResult(Bundle bundle) throws AuthenticatorException { public Account bundleToResult(Bundle bundle) throws AuthenticatorException {
String name = bundle.getString(KEY_ACCOUNT_NAME); String name = bundle.getString(KEY_ACCOUNT_NAME);
String type = bundle.getString(KEY_ACCOUNT_TYPE); String type = bundle.getString(KEY_ACCOUNT_TYPE);
IAccountAccessTracker tracker = IAccountAccessTracker.Stub.asInterface( String accessId = bundle.getString(KEY_ACCOUNT_ACCESS_ID);
bundle.getBinder(KEY_ACCOUNT_ACCESS_TRACKER)); return new Account(name, type, accessId);
return new Account(name, type, tracker);
} }
}.start(); }.start();
} }
@@ -2279,7 +2278,7 @@ public class AccountManager {
result.putString(KEY_ACCOUNT_NAME, null); result.putString(KEY_ACCOUNT_NAME, null);
result.putString(KEY_ACCOUNT_TYPE, null); result.putString(KEY_ACCOUNT_TYPE, null);
result.putString(KEY_AUTHTOKEN, null); result.putString(KEY_AUTHTOKEN, null);
result.putBinder(KEY_ACCOUNT_ACCESS_TRACKER, null); result.putBinder(KEY_ACCOUNT_ACCESS_ID, null);
try { try {
mResponse.onResult(result); mResponse.onResult(result);
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -2306,9 +2305,7 @@ public class AccountManager {
Account account = new Account( Account account = new Account(
value.getString(KEY_ACCOUNT_NAME), value.getString(KEY_ACCOUNT_NAME),
value.getString(KEY_ACCOUNT_TYPE), value.getString(KEY_ACCOUNT_TYPE),
IAccountAccessTracker.Stub.asInterface( value.getString(KEY_ACCOUNT_ACCESS_ID));
value.getBinder(
KEY_ACCOUNT_ACCESS_TRACKER)));
mFuture = getAuthToken(account, mAuthTokenType, mFuture = getAuthToken(account, mAuthTokenType,
mLoginOptions, mActivity, mMyCallback, mLoginOptions, mActivity, mMyCallback,
mHandler); mHandler);
@@ -2358,9 +2355,8 @@ public class AccountManager {
setException(new AuthenticatorException("account not in result")); setException(new AuthenticatorException("account not in result"));
return; return;
} }
final IAccountAccessTracker tracker = IAccountAccessTracker.Stub.asInterface( final String accessId = result.getString(KEY_ACCOUNT_ACCESS_ID);
result.getBinder(KEY_ACCOUNT_ACCESS_TRACKER)); final Account account = new Account(accountName, accountType, accessId);
final Account account = new Account(accountName, accountType, tracker);
mNumAccounts = 1; mNumAccounts = 1;
getAuthToken(account, mAuthTokenType, null /* options */, mActivity, getAuthToken(account, mAuthTokenType, null /* options */, mActivity,
mMyCallback, mHandler); mMyCallback, mHandler);

View File

@@ -1,26 +0,0 @@
/*
* 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();
}

View File

@@ -110,4 +110,6 @@ interface IAccountManager {
/* Crate an intent to request account access for package and a given user id */ /* Crate an intent to request account access for package and a given user id */
IntentSender createRequestAccountAccessIntentSenderAsUser(in Account account, IntentSender createRequestAccountAccessIntentSenderAsUser(in Account account,
String packageName, in UserHandle userHandle); String packageName, in UserHandle userHandle);
void onAccountAccessed(String token);
} }

View File

@@ -26,7 +26,6 @@ import android.accounts.AccountManagerInternal;
import android.accounts.AuthenticatorDescription; import android.accounts.AuthenticatorDescription;
import android.accounts.CantAddAccountActivity; import android.accounts.CantAddAccountActivity;
import android.accounts.GrantCredentialsPermissionActivity; import android.accounts.GrantCredentialsPermissionActivity;
import android.accounts.IAccountAccessTracker;
import android.accounts.IAccountAuthenticator; import android.accounts.IAccountAuthenticator;
import android.accounts.IAccountAuthenticatorResponse; import android.accounts.IAccountAuthenticatorResponse;
import android.accounts.IAccountManager; import android.accounts.IAccountManager;
@@ -89,7 +88,6 @@ import android.os.UserManager;
import android.os.storage.StorageManager; import android.os.storage.StorageManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.util.PackageUtils;
import android.util.Pair; import android.util.Pair;
import android.util.Slog; import android.util.Slog;
import android.util.SparseArray; import android.util.SparseArray;
@@ -128,6 +126,8 @@ import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@@ -692,7 +692,7 @@ public class AccountManagerService
final Account[] accountsForType = new Account[accountNames.size()]; final Account[] accountsForType = new Account[accountNames.size()];
for (int i = 0; i < accountsForType.length; i++) { for (int i = 0; i < accountsForType.length; i++) {
accountsForType[i] = new Account(accountNames.get(i), accountType, accountsForType[i] = new Account(accountNames.get(i), accountType,
new AccountAccessTracker()); UUID.randomUUID().toString());
} }
accounts.accountCache.put(accountType, accountsForType); accounts.accountCache.put(accountType, accountsForType);
} }
@@ -1502,8 +1502,8 @@ public class AccountManagerService
Bundle result = new Bundle(); Bundle result = new Bundle();
result.putString(AccountManager.KEY_ACCOUNT_NAME, resultingAccount.name); result.putString(AccountManager.KEY_ACCOUNT_NAME, resultingAccount.name);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, resultingAccount.type); result.putString(AccountManager.KEY_ACCOUNT_TYPE, resultingAccount.type);
result.putBinder(AccountManager.KEY_ACCOUNT_ACCESS_TRACKER, result.putString(AccountManager.KEY_ACCOUNT_ACCESS_ID,
resultingAccount.getAccessTracker().asBinder()); resultingAccount.getAccessId());
try { try {
response.onResult(result); response.onResult(result);
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -4079,6 +4079,30 @@ public class AccountManagerService
} }
} }
@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 private abstract class Session extends IAccountAuthenticatorResponse.Stub
implements IBinder.DeathRecipient, ServiceConnection { implements IBinder.DeathRecipient, ServiceConnection {
IAccountManagerResponse mResponse; IAccountManagerResponse mResponse;
@@ -5714,9 +5738,9 @@ public class AccountManagerService
if (accountsForType != null) { if (accountsForType != null) {
System.arraycopy(accountsForType, 0, newAccountsForType, 0, oldLength); System.arraycopy(accountsForType, 0, newAccountsForType, 0, oldLength);
} }
IAccountAccessTracker accessTracker = account.getAccessTracker() != null String token = account.getAccessId() != null ? account.getAccessId()
? account.getAccessTracker() : new AccountAccessTracker(); : UUID.randomUUID().toString();
newAccountsForType[oldLength] = new Account(account, accessTracker); newAccountsForType[oldLength] = new Account(account, token);
accounts.accountCache.put(account.type, newAccountsForType); accounts.accountCache.put(account.type, newAccountsForType);
return newAccountsForType[oldLength]; return newAccountsForType[oldLength];
} }
@@ -5961,33 +5985,6 @@ public class AccountManagerService
} }
} }
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 class AccountManagerInternalImpl extends AccountManagerInternal {
private final Object mLock = new Object(); private final Object mLock = new Object();