Merge change Ib839afc3 into eclair-mr2
* changes: remove the bind helper and bind directly
This commit is contained in:
@ -21,6 +21,8 @@ import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.ComponentName;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.RegisteredServicesCache;
|
||||
import android.content.pm.PackageInfo;
|
||||
@ -90,11 +92,8 @@ public class AccountManagerService
|
||||
|
||||
// Messages that can be sent on mHandler
|
||||
private static final int MESSAGE_TIMED_OUT = 3;
|
||||
private static final int MESSAGE_CONNECTED = 7;
|
||||
private static final int MESSAGE_DISCONNECTED = 8;
|
||||
|
||||
private final AccountAuthenticatorCache mAuthenticatorCache;
|
||||
private final AuthenticatorBindHelper mBindHelper;
|
||||
private final DatabaseHelper mOpenHelper;
|
||||
private final SimWatcher mSimWatcher;
|
||||
|
||||
@ -220,8 +219,6 @@ public class AccountManagerService
|
||||
|
||||
mAuthenticatorCache = new AccountAuthenticatorCache(mContext);
|
||||
mAuthenticatorCache.setListener(this);
|
||||
mBindHelper = new AuthenticatorBindHelper(mContext, mAuthenticatorCache, mMessageHandler,
|
||||
MESSAGE_CONNECTED, MESSAGE_DISCONNECTED);
|
||||
|
||||
if (SystemProperties.getBoolean("ro.config.sim_password_clear", false)) {
|
||||
mSimWatcher = new SimWatcher(mContext);
|
||||
@ -1072,7 +1069,7 @@ public class AccountManagerService
|
||||
}
|
||||
|
||||
private abstract class Session extends IAccountAuthenticatorResponse.Stub
|
||||
implements AuthenticatorBindHelper.Callback, IBinder.DeathRecipient {
|
||||
implements IBinder.DeathRecipient, ServiceConnection {
|
||||
IAccountManagerResponse mResponse;
|
||||
final String mAccountType;
|
||||
final boolean mExpectActivityLaunch;
|
||||
@ -1154,7 +1151,7 @@ public class AccountManagerService
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "initiating bind to authenticator type " + mAccountType);
|
||||
}
|
||||
if (!mBindHelper.bind(mAccountType, this)) {
|
||||
if (!bindToAuthenticator(mAccountType)) {
|
||||
Log.d(TAG, "bind attempt failed for " + toDebugString());
|
||||
onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION, "bind failure");
|
||||
}
|
||||
@ -1163,7 +1160,7 @@ public class AccountManagerService
|
||||
private void unbind() {
|
||||
if (mAuthenticator != null) {
|
||||
mAuthenticator = null;
|
||||
mBindHelper.unbind(this);
|
||||
mContext.unbindService(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1176,7 +1173,7 @@ public class AccountManagerService
|
||||
mMessageHandler.removeMessages(MESSAGE_TIMED_OUT, this);
|
||||
}
|
||||
|
||||
public void onConnected(IBinder service) {
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
mAuthenticator = IAccountAuthenticator.Stub.asInterface(service);
|
||||
try {
|
||||
run();
|
||||
@ -1186,9 +1183,7 @@ public class AccountManagerService
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void run() throws RemoteException;
|
||||
|
||||
public void onDisconnected() {
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
mAuthenticator = null;
|
||||
IAccountManagerResponse response = getResponseAndClose();
|
||||
if (response != null) {
|
||||
@ -1197,6 +1192,8 @@ public class AccountManagerService
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void run() throws RemoteException;
|
||||
|
||||
public void onTimedOut() {
|
||||
IAccountManagerResponse response = getResponseAndClose();
|
||||
if (response != null) {
|
||||
@ -1266,6 +1263,39 @@ public class AccountManagerService
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* find the component name for the authenticator and initiate a bind
|
||||
* if no authenticator or the bind fails then return false, otherwise return true
|
||||
*/
|
||||
private boolean bindToAuthenticator(String authenticatorType) {
|
||||
AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo =
|
||||
mAuthenticatorCache.getServiceInfo(
|
||||
AuthenticatorDescription.newKey(authenticatorType));
|
||||
if (authenticatorInfo == null) {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "there is no authenticator for " + authenticatorType
|
||||
+ ", bailing out");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(AccountManager.ACTION_AUTHENTICATOR_INTENT);
|
||||
intent.setComponent(authenticatorInfo.componentName);
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "performing bindService to " + authenticatorInfo.componentName);
|
||||
}
|
||||
if (!mContext.bindService(intent, this, Context.BIND_AUTO_CREATE)) {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "bindService to " + authenticatorInfo.componentName + " failed");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class MessageHandler extends Handler {
|
||||
@ -1274,9 +1304,6 @@ public class AccountManagerService
|
||||
}
|
||||
|
||||
public void handleMessage(Message msg) {
|
||||
if (mBindHelper.handleMessage(msg)) {
|
||||
return;
|
||||
}
|
||||
switch (msg.what) {
|
||||
case MESSAGE_TIMED_OUT:
|
||||
Session session = (Session)msg.obj;
|
||||
@ -1571,16 +1598,17 @@ public class AccountManagerService
|
||||
private boolean permissionIsGranted(Account account, String authTokenType, int callerUid) {
|
||||
final boolean fromAuthenticator = hasAuthenticatorUid(account.type, callerUid);
|
||||
final boolean hasExplicitGrants = hasExplicitlyGrantedPermission(account, authTokenType);
|
||||
final boolean inSystemImage = inSystemImage(callerUid);
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "checkGrantsOrCallingUidAgainstAuthenticator: caller uid "
|
||||
+ callerUid + ", account " + account
|
||||
+ ": is authenticator? " + fromAuthenticator
|
||||
+ ", has explicit permission? " + hasExplicitGrants);
|
||||
}
|
||||
return fromAuthenticator || hasExplicitGrants || inSystemImage(callerUid);
|
||||
return fromAuthenticator || hasExplicitGrants || inSystemImage;
|
||||
}
|
||||
|
||||
private boolean hasAuthenticatorUid(String accountType, int callingUid) {
|
||||
private boolean hasAuthenticatorcontextUid(String accountType, int callingUid) {
|
||||
for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo :
|
||||
mAuthenticatorCache.getAllServices()) {
|
||||
if (serviceInfo.type.type.equals(accountType)) {
|
||||
|
@ -1,258 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2009 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;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.android.collect.Lists;
|
||||
import com.google.android.collect.Maps;
|
||||
|
||||
/**
|
||||
* A helper object that simplifies binding to Account Authenticators. It uses the
|
||||
* {@link AccountAuthenticatorCache} to find the component name of the authenticators,
|
||||
* allowing the user to bind by account name. It also allows multiple, simultaneous binds
|
||||
* to the same authenticator, with each bind call guaranteed to return either
|
||||
* {@link Callback#onConnected} or {@link Callback#onDisconnected} if the bind() call
|
||||
* itself succeeds, even if the authenticator is already bound internally.
|
||||
* @hide
|
||||
*/
|
||||
public class AuthenticatorBindHelper {
|
||||
private static final String TAG = "Accounts";
|
||||
private final Handler mHandler;
|
||||
private final Context mContext;
|
||||
private final int mMessageWhatConnected;
|
||||
private final int mMessageWhatDisconnected;
|
||||
private final Map<String, MyServiceConnection> mServiceConnections = Maps.newHashMap();
|
||||
private final Map<String, ArrayList<Callback>> mServiceUsers = Maps.newHashMap();
|
||||
private final AccountAuthenticatorCache mAuthenticatorCache;
|
||||
|
||||
public AuthenticatorBindHelper(Context context,
|
||||
AccountAuthenticatorCache authenticatorCache, Handler handler,
|
||||
int messageWhatConnected, int messageWhatDisconnected) {
|
||||
mContext = context;
|
||||
mHandler = handler;
|
||||
mAuthenticatorCache = authenticatorCache;
|
||||
mMessageWhatConnected = messageWhatConnected;
|
||||
mMessageWhatDisconnected = messageWhatDisconnected;
|
||||
}
|
||||
|
||||
public interface Callback {
|
||||
void onConnected(IBinder service);
|
||||
void onDisconnected();
|
||||
}
|
||||
|
||||
public boolean bind(String authenticatorType, Callback callback) {
|
||||
// if the authenticator is connecting or connected then return true
|
||||
synchronized (mServiceConnections) {
|
||||
if (mServiceConnections.containsKey(authenticatorType)) {
|
||||
MyServiceConnection connection = mServiceConnections.get(authenticatorType);
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "service connection already exists for " + authenticatorType);
|
||||
}
|
||||
mServiceUsers.get(authenticatorType).add(callback);
|
||||
if (connection.mService != null) {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "the service is connected, scheduling a connected message for "
|
||||
+ authenticatorType);
|
||||
}
|
||||
connection.scheduleCallbackConnectedMessage(callback);
|
||||
} else {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "the service is *not* connected, waiting for for "
|
||||
+ authenticatorType);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "there is no service connection for " + authenticatorType);
|
||||
}
|
||||
|
||||
// otherwise find the component name for the authenticator and initiate a bind
|
||||
// if no authenticator or the bind fails then return false, otherwise return true
|
||||
AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo =
|
||||
mAuthenticatorCache.getServiceInfo(
|
||||
AuthenticatorDescription.newKey(authenticatorType));
|
||||
if (authenticatorInfo == null) {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "there is no authenticator for " + authenticatorType
|
||||
+ ", bailing out");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
MyServiceConnection connection = new MyServiceConnection(authenticatorType);
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setAction("android.accounts.AccountAuthenticator");
|
||||
intent.setComponent(authenticatorInfo.componentName);
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "performing bindService to " + authenticatorInfo.componentName);
|
||||
}
|
||||
if (!mContext.bindService(intent, connection, Context.BIND_AUTO_CREATE)) {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "bindService to " + authenticatorInfo.componentName + " failed");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
mServiceConnections.put(authenticatorType, connection);
|
||||
mServiceUsers.put(authenticatorType, Lists.newArrayList(callback));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void unbind(Callback callbackToUnbind) {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "unbinding callback " + callbackToUnbind);
|
||||
}
|
||||
synchronized (mServiceConnections) {
|
||||
for (Map.Entry<String, ArrayList<Callback>> entry : mServiceUsers.entrySet()) {
|
||||
final String authenticatorType = entry.getKey();
|
||||
final ArrayList<Callback> serviceUsers = entry.getValue();
|
||||
for (Callback callback : serviceUsers) {
|
||||
if (callback == callbackToUnbind) {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "found callback in service" + authenticatorType);
|
||||
}
|
||||
serviceUsers.remove(callbackToUnbind);
|
||||
if (serviceUsers.isEmpty()) {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "there are no more callbacks for service "
|
||||
+ authenticatorType + ", unbinding service");
|
||||
}
|
||||
unbindFromServiceLocked(authenticatorType);
|
||||
} else {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "leaving service " + authenticatorType
|
||||
+ " around since there are still callbacks using it");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.e(TAG, "did not find callback " + callbackToUnbind + " in any of the services");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* You must synchronized on mServiceConnections before calling this
|
||||
*/
|
||||
private void unbindFromServiceLocked(String authenticatorType) {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "unbindService from " + authenticatorType);
|
||||
}
|
||||
mContext.unbindService(mServiceConnections.get(authenticatorType));
|
||||
mServiceUsers.remove(authenticatorType);
|
||||
mServiceConnections.remove(authenticatorType);
|
||||
}
|
||||
|
||||
private class ConnectedMessagePayload {
|
||||
public final IBinder mService;
|
||||
public final Callback mCallback;
|
||||
public ConnectedMessagePayload(IBinder service, Callback callback) {
|
||||
mService = service;
|
||||
mCallback = callback;
|
||||
}
|
||||
}
|
||||
|
||||
private class MyServiceConnection implements ServiceConnection {
|
||||
private final String mAuthenticatorType;
|
||||
private IBinder mService = null;
|
||||
|
||||
public MyServiceConnection(String authenticatorType) {
|
||||
mAuthenticatorType = authenticatorType;
|
||||
}
|
||||
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "onServiceConnected for account type " + mAuthenticatorType);
|
||||
}
|
||||
// post a message for each service user to tell them that the service is connected
|
||||
synchronized (mServiceConnections) {
|
||||
mService = service;
|
||||
for (Callback callback : mServiceUsers.get(mAuthenticatorType)) {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "the service became connected, scheduling a connected "
|
||||
+ "message for " + mAuthenticatorType);
|
||||
}
|
||||
scheduleCallbackConnectedMessage(callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void scheduleCallbackConnectedMessage(Callback callback) {
|
||||
final ConnectedMessagePayload payload =
|
||||
new ConnectedMessagePayload(mService, callback);
|
||||
mHandler.obtainMessage(mMessageWhatConnected, payload).sendToTarget();
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "onServiceDisconnected for account type " + mAuthenticatorType);
|
||||
}
|
||||
// post a message for each service user to tell them that the service is disconnected,
|
||||
// and unbind from the service.
|
||||
synchronized (mServiceConnections) {
|
||||
final ArrayList<Callback> callbackList = mServiceUsers.get(mAuthenticatorType);
|
||||
if (callbackList != null) {
|
||||
for (Callback callback : callbackList) {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "the service became disconnected, scheduling a "
|
||||
+ "disconnected message for "
|
||||
+ mAuthenticatorType);
|
||||
}
|
||||
mHandler.obtainMessage(mMessageWhatDisconnected, callback).sendToTarget();
|
||||
}
|
||||
unbindFromServiceLocked(mAuthenticatorType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean handleMessage(Message message) {
|
||||
if (message.what == mMessageWhatConnected) {
|
||||
ConnectedMessagePayload payload = (ConnectedMessagePayload)message.obj;
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "notifying callback " + payload.mCallback + " that it is connected");
|
||||
}
|
||||
payload.mCallback.onConnected(payload.mService);
|
||||
return true;
|
||||
} else if (message.what == mMessageWhatDisconnected) {
|
||||
Callback callback = (Callback)message.obj;
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.v(TAG, "notifying callback " + callback + " that it is disconnected");
|
||||
}
|
||||
callback.onDisconnected();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user