Clean up PhoneAccountRegistrar.
Cleanup lots of duplicate code and consolidate all phone account
retrievals into a single method: getPhoneAccounts(...).
Consolidate checks for capabilities, package-name, uri, and
isVisibleForUser(...). This will be very helpful when
implementing enable/disable for phone accounts.
Bug: 20303449
Change-Id: I24d63cd313876f5d9390f2eb31c0ce79d7cb0ab2
diff --git a/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java b/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
index 0dec0f4..dd2e5dd 100644
--- a/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
+++ b/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
@@ -742,13 +742,15 @@
PhoneAccount account = null;
if (call != null) {
// First try to get the network name of the foreground call.
- account = mPhoneAccountRegistrar.getPhoneAccount(call.getTargetPhoneAccount());
+ account = mPhoneAccountRegistrar.getPhoneAccountCheckCallingUser(
+ call.getTargetPhoneAccount());
}
if (account == null) {
// Second, Try to get the label for the default Phone Account.
- account = mPhoneAccountRegistrar.getPhoneAccount(
- mPhoneAccountRegistrar.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL));
+ account = mPhoneAccountRegistrar.getPhoneAccountCheckCallingUser(
+ mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(
+ PhoneAccount.SCHEME_TEL));
}
return account;
}
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 182590d..a638a3e 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -547,12 +547,8 @@
if (phoneAccountHandle == null) {
// No preset account, check if default exists that supports the URI scheme for the
// handle.
- PhoneAccountHandle defaultAccountHandle =
- mPhoneAccountRegistrar.getDefaultOutgoingPhoneAccount(
- handle.getScheme());
- if (defaultAccountHandle != null) {
- phoneAccountHandle = defaultAccountHandle;
- }
+ phoneAccountHandle =
+ mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(handle.getScheme());
}
call.setTargetPhoneAccount(phoneAccountHandle);
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index 854a645..82b99cc 100644
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -957,15 +957,11 @@
// Make a list of ConnectionServices that are listed as being associated with SIM accounts
final Set<ConnectionServiceWrapper> simServices = Collections.newSetFromMap(
new ConcurrentHashMap<ConnectionServiceWrapper, Boolean>(8, 0.9f, 1));
- for (PhoneAccountHandle handle : mPhoneAccountRegistrar.getCallCapablePhoneAccounts()) {
- PhoneAccount account = mPhoneAccountRegistrar.getPhoneAccount(handle);
- if ((account.getCapabilities() & PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) != 0) {
- ConnectionServiceWrapper service =
- mConnectionServiceRepository.getService(handle.getComponentName(),
- handle.getUserHandle());
- if (service != null) {
- simServices.add(service);
- }
+ for (PhoneAccountHandle handle : mPhoneAccountRegistrar.getSimPhoneAccounts()) {
+ ConnectionServiceWrapper service = mConnectionServiceRepository.getService(
+ handle.getComponentName(), handle.getUserHandle());
+ if (service != null) {
+ simServices.add(service);
}
}
diff --git a/src/com/android/server/telecom/CreateConnectionProcessor.java b/src/com/android/server/telecom/CreateConnectionProcessor.java
index 13ee4e9..c90f9de 100644
--- a/src/com/android/server/telecom/CreateConnectionProcessor.java
+++ b/src/com/android/server/telecom/CreateConnectionProcessor.java
@@ -168,7 +168,7 @@
if (mAttemptRecordIterator.hasNext()) {
attempt = mAttemptRecordIterator.next();
- if (!mPhoneAccountRegistrar.phoneAccountHasPermission(
+ if (!mPhoneAccountRegistrar.phoneAccountRequiresBindPermission(
attempt.connectionManagerPhoneAccount)) {
Log.w(this,
"Connection mgr does not have BIND_CONNECTION_SERVICE for attempt: %s",
@@ -178,9 +178,10 @@
}
// If the target PhoneAccount differs from the ConnectionManager phone acount, ensure it
- // also has BIND_CONNECTION_SERVICE permission.
+ // also requires the BIND_CONNECTION_SERVICE permission.
if (!attempt.connectionManagerPhoneAccount.equals(attempt.targetPhoneAccount) &&
- !mPhoneAccountRegistrar.phoneAccountHasPermission(attempt.targetPhoneAccount)) {
+ !mPhoneAccountRegistrar.phoneAccountRequiresBindPermission(
+ attempt.targetPhoneAccount)) {
Log.w(this,
"Target PhoneAccount does not have BIND_CONNECTION_SERVICE for attempt: %s",
attempt);
@@ -265,7 +266,8 @@
}
// Connection managers are only allowed to manage SIM subscriptions.
- PhoneAccount targetPhoneAccount = mPhoneAccountRegistrar.getPhoneAccount(
+ // TODO: Should this really be checking the "calling user" test for phone account?
+ PhoneAccount targetPhoneAccount = mPhoneAccountRegistrar.getPhoneAccountCheckCallingUser(
targetPhoneAccountHandle);
if (targetPhoneAccount == null) {
Log.d(this, "shouldSetConnectionManager, phone account not found");
@@ -328,13 +330,14 @@
// Next, add the connection manager account as a backup if it can place emergency calls.
PhoneAccountHandle callManagerHandle = mPhoneAccountRegistrar.getSimCallManager();
if (mShouldUseConnectionManager && callManagerHandle != null) {
+ // TODO: Should this really be checking the "calling user" test for phone account?
PhoneAccount callManager = mPhoneAccountRegistrar
- .getPhoneAccount(callManagerHandle);
+ .getPhoneAccountCheckCallingUser(callManagerHandle);
if (callManager != null && callManager.hasCapabilities(
PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS)) {
CallAttemptRecord callAttemptRecord = new CallAttemptRecord(callManagerHandle,
mPhoneAccountRegistrar.
- getDefaultOutgoingPhoneAccount(mCall.getHandle().getScheme())
+ getOutgoingPhoneAccountForScheme(mCall.getHandle().getScheme())
);
if (!mAttemptRecords.contains(callAttemptRecord)) {
diff --git a/src/com/android/server/telecom/PhoneAccountRegistrar.java b/src/com/android/server/telecom/PhoneAccountRegistrar.java
index 759a31d..dd1fd6e 100644
--- a/src/com/android/server/telecom/PhoneAccountRegistrar.java
+++ b/src/com/android/server/telecom/PhoneAccountRegistrar.java
@@ -74,10 +74,34 @@
/**
* Handles writing and reading PhoneAccountHandle registration entries. This is a simple verbatim
- * delegate for all the account handling methods on {@link android.telecom.TelecomManager} as implemented in
- * {@link TelecomServiceImpl}, with the notable exception that {@link TelecomServiceImpl} is
- * responsible for security checking to make sure that the caller has proper authority over
- * the {@code ComponentName}s they are declaring in their {@code PhoneAccountHandle}s.
+ * delegate for all the account handling methods on {@link android.telecom.TelecomManager} as
+ * implemented in {@link TelecomServiceImpl}, with the notable exception that
+ * {@link TelecomServiceImpl} is responsible for security checking to make sure that the caller has
+ * proper authority over the {@code ComponentName}s they are declaring in their
+ * {@code PhoneAccountHandle}s.
+ *
+ *
+ * -- About Users and Phone Accounts --
+ *
+ * When it comes to PhoneAccounts, we store all phone account in a single place,
+ * which means that there are three users that we deal with:
+ * 1) The Android User that is currently active on the device.
+ * 2) The user which owns/registers the phone account.
+ * 3) The user running the app that is requesting the phone account information.
+ *
+ * For example, I have a device with 2 users, primary (A) and secondary (B), and the secondary user
+ * has a work profile running as another user (B2). Lets say that user B opens the phone settings
+ * (not currently supported, but theoretically speaking), and phone settings queries for a phone
+ * account list. Lets also say that an app running in the work profile has registered a phone account.
+ * This means that:
+ *
+ * Since phone settings always runs as the primary user, We have the following situation:
+ * User A (settings) is requesting a list of phone accounts while the active user is User B, and that
+ * list contains a phone account for profile User B2.
+ *
+ * In practice, (2) is stored with the phone account handle and is part of the handle's ID. (1) is
+ * saved in {@link #mCurrentUserHandle} and (3) we get from Binder.getCallingUser(). We check these
+ * users for visibility before returning any phone accounts.
*/
public final class PhoneAccountRegistrar {
@@ -139,11 +163,9 @@
* @return The value of the subscription id or -1 if it does not exist or is not valid.
*/
public int getSubscriptionIdForPhoneAccount(PhoneAccountHandle accountHandle) {
- PhoneAccount account = getPhoneAccountInternal(accountHandle);
+ PhoneAccount account = getPhoneAccountCheckCallingUser(accountHandle);
- if (account != null
- && account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
- && isVisibleForUser(accountHandle)) {
+ if (account != null && account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
TelephonyManager tm =
(TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
return tm.getSubIdForPhoneAccount(account);
@@ -159,15 +181,14 @@
* @param uriScheme The URI scheme for the outgoing call.
* @return The {@link PhoneAccountHandle} to use.
*/
- public PhoneAccountHandle getDefaultOutgoingPhoneAccount(String uriScheme) {
+ public PhoneAccountHandle getOutgoingPhoneAccountForScheme(String uriScheme) {
final PhoneAccountHandle userSelected = getUserSelectedOutgoingPhoneAccount();
if (userSelected != null) {
// If there is a default PhoneAccount, ensure it supports calls to handles with the
// specified uriScheme.
- final PhoneAccount userSelectedAccount = getPhoneAccountInternal(userSelected);
- if (userSelectedAccount.supportsUriScheme(uriScheme)
- && isVisibleForUser(userSelected)) {
+ final PhoneAccount userSelectedAccount = getPhoneAccountCheckCallingUser(userSelected);
+ if (userSelectedAccount.supportsUriScheme(uriScheme)) {
return userSelected;
}
}
@@ -179,11 +200,7 @@
return null;
case 1:
// There is only one account, which is by definition the default.
- PhoneAccountHandle onlyHandle = outgoing.get(0);
- if (isVisibleForUser(onlyHandle)) {
- return outgoing.get(0);
- }
- return null;
+ return outgoing.get(0);
default:
// There are multiple accounts with no selected default
return null;
@@ -195,49 +212,37 @@
* if it was set by another user).
*/
PhoneAccountHandle getUserSelectedOutgoingPhoneAccount() {
- if (mState.defaultOutgoing != null) {
- // Return the registered outgoing default iff it still exists (we keep a sticky
- // default to survive account deletion and re-addition)
- for (int i = 0; i < mState.accounts.size(); i++) {
- if (mState.accounts.get(i).getAccountHandle().equals(mState.defaultOutgoing)
- && isVisibleForUser(mState.defaultOutgoing)) {
- return mState.defaultOutgoing;
- }
- }
- // At this point, there was a registered default but it has been deleted; proceed
- // as though there were no default
+ PhoneAccount account = getPhoneAccountCheckCallingUser(mState.defaultOutgoing);
+ if (account != null) {
+ return mState.defaultOutgoing;
}
return null;
}
+ /**
+ * Sets the phone account with which to place all calls by default. Set by the user
+ * within phone settings.
+ */
public void setUserSelectedOutgoingPhoneAccount(PhoneAccountHandle accountHandle) {
if (accountHandle == null) {
// Asking to clear the default outgoing is a valid request
mState.defaultOutgoing = null;
} else {
- boolean found = false;
- for (PhoneAccount m : mState.accounts) {
- if (Objects.equals(accountHandle, m.getAccountHandle())) {
- found = true;
- break;
- }
- }
-
- if (!found) {
+ // TODO: Do we really want to return for *any* user?
+ PhoneAccount account = getPhoneAccount(accountHandle);
+ if (account == null) {
Log.w(this, "Trying to set nonexistent default outgoing %s",
accountHandle);
return;
}
- if (!getPhoneAccountInternal(accountHandle).hasCapabilities(
- PhoneAccount.CAPABILITY_CALL_PROVIDER)) {
+ if (!account.hasCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)) {
Log.w(this, "Trying to set non-call-provider default outgoing %s",
accountHandle);
return;
}
- if (getPhoneAccountInternal(accountHandle).hasCapabilities(
- PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
+ if (account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
// If the account selected is a SIM account, propagate down to the subscription
// record.
int subId = getSubscriptionIdForPhoneAccount(accountHandle);
@@ -258,7 +263,8 @@
public void setSimCallManager(PhoneAccountHandle callManager) {
if (callManager != null) {
- PhoneAccount callManagerAccount = getPhoneAccountInternal(callManager);
+ // TODO: Do we really want to return for *any* user?
+ PhoneAccount callManagerAccount = getPhoneAccount(callManager);
if (callManagerAccount == null) {
Log.d(this, "setSimCallManager: Nonexistent call manager: %s", callManager);
return;
@@ -280,22 +286,15 @@
* @return The {@link PhoneAccount}s which are visible to {@link #mCurrentUserHandle}.
*/
public PhoneAccountHandle getSimCallManager() {
- if (mState.simCallManager != null) {
- if (NO_ACCOUNT_SELECTED.equals(mState.simCallManager)) {
- return null;
- }
- // Return the registered sim call manager iff it still exists (we keep a sticky
- // setting to survive account deletion and re-addition)
- for (int i = 0; i < mState.accounts.size(); i++) {
- if (mState.accounts.get(i).getAccountHandle().equals(mState.simCallManager)
- && !resolveComponent(mState.simCallManager).isEmpty()
- && isVisibleForUser(mState.simCallManager)) {
- return mState.simCallManager;
- }
- }
+ PhoneAccount account = getPhoneAccountCheckCallingUser(mState.simCallManager);
+
+ // Return the registered sim call manager iff it still exists (we keep a sticky
+ // setting to survive account deletion and re-addition)
+ if (account != null && !resolveComponent(mState.simCallManager).isEmpty()) {
+ return mState.simCallManager;
}
- // See if the OEM has specified a default one.
+ // We have no set call manager, but check to see if the OEM has specified a default one.
String defaultConnectionMgr =
mContext.getResources().getString(R.string.default_connection_manager_component);
if (!TextUtils.isEmpty(defaultConnectionMgr)) {
@@ -314,8 +313,7 @@
// See if there is registered PhoneAccount by this component.
List<PhoneAccountHandle> handles = getAllPhoneAccountHandles();
for (PhoneAccountHandle handle : handles) {
- if (componentName.equals(handle.getComponentName())
- && isVisibleForUser(handle)) {
+ if (componentName.equals(handle.getComponentName())) {
return handle;
}
}
@@ -331,24 +329,11 @@
}
/**
- * A version of {@link #getPhoneAccount} which does not guard for the current user.
- *
- * @param handle
- * @return
- */
- PhoneAccount getPhoneAccountInternal(PhoneAccountHandle handle) {
- for (PhoneAccount m : mState.accounts) {
- if (Objects.equals(handle, m.getAccountHandle())) {
- return m;
- }
- }
- return null;
- }
-
- /**
* Update the current UserHandle to track when users are switched. This will allow the
* PhoneAccountRegistar to self-filter the PhoneAccounts to make sure we don't leak anything
* across users.
+ * We cannot simply check the calling user because that would always return the primary user for
+ * all invocations originating with the system process.
*
* @param userHandle The {@link UserHandle}, as delivered by
* {@link Intent#ACTION_USER_SWITCHED}.
@@ -362,14 +347,6 @@
mCurrentUserHandle = userHandle;
}
- private boolean isVisibleForUser(PhoneAccountHandle accountHandle) {
- if (accountHandle == null) {
- return false;
- }
-
- return isVisibleForUser(getPhoneAccountInternal(accountHandle));
- }
-
private boolean isVisibleForUser(PhoneAccount account) {
if (account == null) {
return false;
@@ -395,6 +372,7 @@
return true;
}
+ // Special check for work profiles.
// Unlike in TelecomServiceImpl, we only care about *profiles* here. We want to make sure
// that we don't resolve PhoneAccount across *users*, but resolving across *profiles* is
// fine.
@@ -439,32 +417,11 @@
* @return The list of {@link PhoneAccountHandle}s.
*/
public List<PhoneAccountHandle> getAllPhoneAccountHandles() {
- List<PhoneAccountHandle> accountHandles = new ArrayList<>();
- for (PhoneAccount m : mState.accounts) {
- if (isVisibleForUser(m)) {
- accountHandles.add(m.getAccountHandle());
- }
- }
- return accountHandles;
+ return getPhoneAccountHandles(0, null, null);
}
public List<PhoneAccount> getAllPhoneAccounts() {
- List<PhoneAccount> accounts = new ArrayList<>(mState.accounts.size());
- for (PhoneAccount account : mState.accounts) {
- if (isVisibleForUser(account)) {
- accounts.add(account);
- }
- }
- return accounts;
- }
-
- /**
- * Retrieves a list of all call provider phone accounts.
- *
- * @return The phone account handles.
- */
- public List<PhoneAccountHandle> getCallCapablePhoneAccounts() {
- return getPhoneAccountHandles(PhoneAccount.CAPABILITY_CALL_PROVIDER);
+ return getPhoneAccounts(0, null, null);
}
/**
@@ -475,7 +432,16 @@
* @return The phone account handles.
*/
public List<PhoneAccountHandle> getCallCapablePhoneAccounts(String uriScheme) {
- return getPhoneAccountHandles(PhoneAccount.CAPABILITY_CALL_PROVIDER, uriScheme);
+ return getPhoneAccountHandles(PhoneAccount.CAPABILITY_CALL_PROVIDER, uriScheme, null);
+ }
+
+ /**
+ * Retrieves a list of all the SIM-based phone accounts.
+ */
+ public List<PhoneAccountHandle> getSimPhoneAccounts() {
+ return getPhoneAccountHandles(
+ PhoneAccount.CAPABILITY_CALL_PROVIDER | PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION,
+ null, null);
}
/**
@@ -485,16 +451,7 @@
* @return The phone account handles.
*/
public List<PhoneAccountHandle> getPhoneAccountsForPackage(String packageName) {
- List<PhoneAccountHandle> accountHandles = new ArrayList<>();
- for (PhoneAccount m : mState.accounts) {
- if (Objects.equals(
- packageName,
- m.getAccountHandle().getComponentName().getPackageName())
- && isVisibleForUser(m)) {
- accountHandles.add(m.getAccountHandle());
- }
- }
- return accountHandles;
+ return getPhoneAccountHandles(0, null, packageName);
}
/**
@@ -503,18 +460,7 @@
* @return The phone account handles.
*/
public List<PhoneAccountHandle> getConnectionManagerPhoneAccounts() {
- return getPhoneAccountHandles(PhoneAccount.CAPABILITY_CONNECTION_MANAGER,
- null /* supportedUriScheme */);
- }
-
- public PhoneAccount getPhoneAccount(PhoneAccountHandle handle) {
- for (PhoneAccount m : mState.accounts) {
- if (Objects.equals(handle, m.getAccountHandle())
- && isVisibleForUser(m)) {
- return m;
- }
- }
- return null;
+ return getPhoneAccountHandles(PhoneAccount.CAPABILITY_CONNECTION_MANAGER, null, null);
}
// TODO: Should we implement an artificial limit for # of accounts associated with a single
@@ -522,7 +468,7 @@
public void registerPhoneAccount(PhoneAccount account) {
// Enforce the requirement that a connection service for a phone account has the correct
// permission.
- if (!phoneAccountHasPermission(account.getAccountHandle())) {
+ if (!phoneAccountRequiresBindPermission(account.getAccountHandle())) {
Log.w(this, "Phone account %s does not have BIND_CONNECTION_SERVICE permission.",
account.getAccountHandle());
throw new SecurityException(
@@ -541,32 +487,24 @@
Log.d(this, "addOrReplacePhoneAccount(%s -> %s)",
account.getAccountHandle(), account);
- mState.accounts.add(account);
- // Search for duplicates and remove any that are found.
- for (int i = 0; i < mState.accounts.size() - 1; i++) {
- if (Objects.equals(
- account.getAccountHandle(), mState.accounts.get(i).getAccountHandle())) {
- // replace existing entry.
- mState.accounts.remove(i);
- break;
- }
+ PhoneAccount oldAccount = getPhoneAccount(account.getAccountHandle());
+ if (oldAccount != null) {
+ mState.accounts.remove(oldAccount);
}
+ mState.accounts.add(account);
write();
fireAccountsChanged();
}
public void unregisterPhoneAccount(PhoneAccountHandle accountHandle) {
- for (int i = 0; i < mState.accounts.size(); i++) {
- PhoneAccountHandle handle = mState.accounts.get(i).getAccountHandle();
- if (Objects.equals(accountHandle, handle)) {
- mState.accounts.remove(i);
- break;
+ PhoneAccount account = getPhoneAccount(accountHandle);
+ if (account != null) {
+ if (mState.accounts.remove(account)) {
+ write();
+ fireAccountsChanged();
}
}
-
- write();
- fireAccountsChanged();
}
/**
@@ -629,13 +567,13 @@
}
/**
- * Determines if the connection service specified by a {@link PhoneAccountHandle} has the
+ * Determines if the connection service specified by a {@link PhoneAccountHandle} requires the
* {@link Manifest.permission#BIND_CONNECTION_SERVICE} permission.
*
* @param phoneAccountHandle The phone account to check.
* @return {@code True} if the phone account has permission.
*/
- public boolean phoneAccountHasPermission(PhoneAccountHandle phoneAccountHandle) {
+ public boolean phoneAccountRequiresBindPermission(PhoneAccountHandle phoneAccountHandle) {
List<ResolveInfo> resolveInfos = resolveComponent(phoneAccountHandle);
if (resolveInfos.isEmpty()) {
Log.w(this, "phoneAccount %s not found", phoneAccountHandle.getComponentName());
@@ -643,37 +581,73 @@
}
for (ResolveInfo resolveInfo : resolveInfos) {
ServiceInfo serviceInfo = resolveInfo.serviceInfo;
- if (serviceInfo == null || !Objects.equals(serviceInfo.permission,
- Manifest.permission.BIND_CONNECTION_SERVICE)) {
+ if (serviceInfo == null ||
+ !Manifest.permission.BIND_CONNECTION_SERVICE.equals(serviceInfo.permission)) {
return false;
}
}
return true;
}
- ////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Methods for retrieving PhoneAccounts and PhoneAccountHandles
+ //
/**
- * Returns a list of phone account handles with the specified flag.
+ * Returns the PhoneAccount for the specified handle. Does no user checking.
*
- * @param flags Flags which the {@code PhoneAccount} must have.
+ * @param handle
+ * @return The corresponding phone account if one exists.
*/
- private List<PhoneAccountHandle> getPhoneAccountHandles(int flags) {
- return getPhoneAccountHandles(flags, null);
+ PhoneAccount getPhoneAccount(PhoneAccountHandle handle) {
+ for (PhoneAccount m : mState.accounts) {
+ if (Objects.equals(handle, m.getAccountHandle())) {
+ return m;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Like getPhoneAccount, but checks to see if the current user is allowed to see the phone
+ * account before returning it. The current user is the active user on the actual android
+ * device.
+ */
+ public PhoneAccount getPhoneAccountCheckCallingUser(PhoneAccountHandle handle) {
+ PhoneAccount account = getPhoneAccount(handle);
+ if (account != null && isVisibleForUser(account)) {
+ return account;
+ }
+ return null;
+ }
+
+ /**
+ * Returns a list of phone account handles with the specified capabilities, uri scheme,
+ * and package name.
+ */
+ private List<PhoneAccountHandle> getPhoneAccountHandles(
+ int capabilities, String uriScheme, String packageName) {
+ List<PhoneAccountHandle> handles = new ArrayList<>();
+ for (PhoneAccount account : getPhoneAccounts(capabilities, uriScheme, packageName)) {
+ handles.add(account.getAccountHandle());
+ }
+ return handles;
}
/**
* Returns a list of phone account handles with the specified flag, supporting the specified
- * URI scheme.
+ * URI scheme, within the specified package name.
*
- * @param flags Flags which the {@code PhoneAccount} must have.
- * @param uriScheme URI schemes the PhoneAccount must handle. {@code Null} bypasses the
+ * @param capabilities Capabilities which the {@code PhoneAccount} must have. Ignored if 0.
+ * @param uriScheme URI schemes the PhoneAccount must handle. {@code null} bypasses the
* URI scheme check.
+ * @param packageName Package name of the PhoneAccount. {@code null} bypasses packageName check.
*/
- private List<PhoneAccountHandle> getPhoneAccountHandles(int flags, String uriScheme) {
- List<PhoneAccountHandle> accountHandles = new ArrayList<>();
+ private List<PhoneAccount> getPhoneAccounts(
+ int capabilities, String uriScheme, String packageName) {
+ List<PhoneAccount> accounts = new ArrayList<>(mState.accounts.size());
for (PhoneAccount m : mState.accounts) {
- if (!m.hasCapabilities(flags)) {
+ if (capabilities != 0 && !m.hasCapabilities(capabilities)) {
// Account doesn't have the right capabilities; skip this one.
continue;
}
@@ -681,19 +655,30 @@
// Account doesn't support this URI scheme; skip this one.
continue;
}
- if (resolveComponent(m.getAccountHandle()).isEmpty()) {
+ PhoneAccountHandle handle = m.getAccountHandle();
+
+ if (resolveComponent(handle).isEmpty()) {
// This component cannot be resolved anymore; skip this one.
continue;
}
+ if (packageName != null &&
+ !packageName.equals(handle.getComponentName().getPackageName())) {
+ // Not the right package name; skip this one.
+ continue;
+ }
if (!isVisibleForUser(m)) {
// Account is not visible for the current user; skip this one.
continue;
}
- accountHandles.add(m.getAccountHandle());
+ accounts.add(m);
}
- return accountHandles;
+ return accounts;
}
+ //
+ // State Implementation for PhoneAccountRegistrar
+ //
+
/**
* The state of this {@code PhoneAccountRegistrar}.
*/
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index f9ee74c..ac9d4cc 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -68,7 +68,7 @@
long token = Binder.clearCallingIdentity();
try {
PhoneAccountHandle defaultOutgoingPhoneAccount =
- mPhoneAccountRegistrar.getDefaultOutgoingPhoneAccount(uriScheme);
+ mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(uriScheme);
// Make sure that the calling user can see this phone account.
if (defaultOutgoingPhoneAccount != null
&& !isVisibleToCaller(defaultOutgoingPhoneAccount)) {
@@ -127,7 +127,7 @@
long token = Binder.clearCallingIdentity();
try {
return filterForAccountsVisibleToCaller(
- mPhoneAccountRegistrar.getCallCapablePhoneAccounts());
+ mPhoneAccountRegistrar.getCallCapablePhoneAccounts(null));
} catch (Exception e) {
Log.e(this, e, "getCallCapablePhoneAccounts");
throw e;
@@ -179,7 +179,8 @@
Log.w(this, "%s is not visible for the calling user", accountHandle);
return null;
}
- return mPhoneAccountRegistrar.getPhoneAccountInternal(accountHandle);
+ // TODO: Do we really want to return for *any* user?
+ return mPhoneAccountRegistrar.getPhoneAccount(accountHandle);
} catch (Exception e) {
Log.e(this, e, "getPhoneAccount %s", accountHandle);
throw e;
@@ -833,9 +834,7 @@
if (accountHandle == null) {
return false;
}
-
- return isVisibleToCaller(mPhoneAccountRegistrar
- .getPhoneAccountInternal(accountHandle));
+ return isVisibleToCaller(mPhoneAccountRegistrar.getPhoneAccount(accountHandle));
}
private boolean isVisibleToCaller(PhoneAccount account) {
diff --git a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
index a5fc04c..34575a7 100644
--- a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
+++ b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
@@ -130,9 +130,9 @@
.build());
assertEquals(4, mRegistrar.getAllPhoneAccountHandles().size());
- assertEquals(3, mRegistrar.getCallCapablePhoneAccounts().size());
+ assertEquals(3, mRegistrar.getCallCapablePhoneAccounts(null).size());
assertEquals(null, mRegistrar.getSimCallManager());
- assertEquals(null, mRegistrar.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL));
+ assertEquals(null, mRegistrar.getOutgoingPhoneAccountForScheme(PhoneAccount.SCHEME_TEL));
}
public void testSimCallManager() throws Exception {
@@ -180,7 +180,7 @@
Mockito.mock(IConnectionService.class));
// By default, there is no default outgoing account (nothing has been registered)
- assertNull(mRegistrar.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL));
+ assertNull(mRegistrar.getOutgoingPhoneAccountForScheme(PhoneAccount.SCHEME_TEL));
// Register one tel: account
PhoneAccountHandle telAccount = makeQuickAccountHandle("tel_acct");
@@ -189,7 +189,7 @@
.addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
.build());
PhoneAccountHandle defaultAccount =
- mRegistrar.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL);
+ mRegistrar.getOutgoingPhoneAccountForScheme(PhoneAccount.SCHEME_TEL);
assertEquals(telAccount, defaultAccount);
// Add a SIP account, make sure tel: doesn't change
@@ -198,9 +198,9 @@
.setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
.addSupportedUriScheme(PhoneAccount.SCHEME_SIP)
.build());
- defaultAccount = mRegistrar.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_SIP);
+ defaultAccount = mRegistrar.getOutgoingPhoneAccountForScheme(PhoneAccount.SCHEME_SIP);
assertEquals(sipAccount, defaultAccount);
- defaultAccount = mRegistrar.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL);
+ defaultAccount = mRegistrar.getOutgoingPhoneAccountForScheme(PhoneAccount.SCHEME_TEL);
assertEquals(telAccount, defaultAccount);
// Add a connection manager, make sure tel: doesn't change
@@ -209,12 +209,12 @@
.setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)
.addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
.build());
- defaultAccount = mRegistrar.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL);
+ defaultAccount = mRegistrar.getOutgoingPhoneAccountForScheme(PhoneAccount.SCHEME_TEL);
assertEquals(telAccount, defaultAccount);
// Unregister the tel: account, make sure there is no tel: default now.
mRegistrar.unregisterPhoneAccount(telAccount);
- assertNull(mRegistrar.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL));
+ assertNull(mRegistrar.getOutgoingPhoneAccountForScheme(PhoneAccount.SCHEME_TEL));
}
public void testPhoneAccountParceling() throws Exception {