summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
authorAmith Yamasani <yamasani@google.com>2012-12-14 12:09:36 -0800
committerAmith Yamasani <yamasani@google.com>2013-03-06 09:49:44 -0800
commit67df64b3a48a8157d08a98fa90135d0ac0ee621c (patch)
treed390d5c537c976a14688e24c1f9a8a213840ff29 /core/java
parent0ffc81c1ada65b4ef4febaacf044e9fa62309b87 (diff)
downloadframeworks_base-67df64b3a48a8157d08a98fa90135d0ac0ee621c.zip
frameworks_base-67df64b3a48a8157d08a98fa90135d0ac0ee621c.tar.gz
frameworks_base-67df64b3a48a8157d08a98fa90135d0ac0ee621c.tar.bz2
Shared accounts and sharing of apps
API and preliminary implementation for sharing primary user accounts with a secondary user. AbstractAccountAuthenticator has new methods to retrieve and apply a bundle of credentials to clone an account from the primary to a restricted secondary user. The AccountManagerService initiates the account clone when it starts up the user and detects that the user has a shared account registered that hasn't been converted to a real account. AccountManager also has new hidden APIs to add/remove/get shared accounts. There might be further improvements to this API to make shared accounts hidden/visible to select apps. AccountManagerService has a new table to store the shared account information. Added ability in PackageManager to install and uninstall packages for a secondary user. This is required when the primary user selects a few apps to share with a restricted user. Remove shared accounts from secondary users when primary user removes the account. Change-Id: I9378ed0d8c1cc66baf150a4bec0ede56f6f8b06b
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/accounts/AbstractAccountAuthenticator.java82
-rw-r--r--core/java/android/accounts/AccountManager.java51
-rw-r--r--core/java/android/accounts/IAccountAuthenticator.aidl13
-rw-r--r--core/java/android/accounts/IAccountManager.aidl5
-rw-r--r--core/java/android/app/ApplicationPackageManager.java5
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl12
-rw-r--r--core/java/android/content/pm/UserInfo.java4
7 files changed, 165 insertions, 7 deletions
diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java
index e9535ab..fa46689 100644
--- a/core/java/android/accounts/AbstractAccountAuthenticator.java
+++ b/core/java/android/accounts/AbstractAccountAuthenticator.java
@@ -275,6 +275,38 @@ public abstract class AbstractAccountAuthenticator {
handleException(response, "getAccountRemovalAllowed", account.toString(), e);
}
}
+
+ public void getAccountCredentialsForCloning(IAccountAuthenticatorResponse response,
+ Account account) throws RemoteException {
+ checkBinderPermission();
+ try {
+ final Bundle result =
+ AbstractAccountAuthenticator.this.getAccountCredentialsForCloning(
+ new AccountAuthenticatorResponse(response), account);
+ if (result != null) {
+ response.onResult(result);
+ }
+ } catch (Exception e) {
+ handleException(response, "getAccountCredentialsForCloning", account.toString(), e);
+ }
+ }
+
+ public void addAccountFromCredentials(IAccountAuthenticatorResponse response,
+ Account account,
+ Bundle accountCredentials) throws RemoteException {
+ checkBinderPermission();
+ try {
+ final Bundle result =
+ AbstractAccountAuthenticator.this.addAccountFromCredentials(
+ new AccountAuthenticatorResponse(response), account,
+ accountCredentials);
+ if (result != null) {
+ response.onResult(result);
+ }
+ } catch (Exception e) {
+ handleException(response, "addAccountFromCredentials", account.toString(), e);
+ }
+ }
}
private void handleException(IAccountAuthenticatorResponse response, String method,
@@ -471,4 +503,54 @@ public abstract class AbstractAccountAuthenticator {
result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
return result;
}
+
+ /**
+ * @hide
+ * Returns a Bundle that contains whatever is required to clone the account on a different
+ * user. The Bundle is passed to the authenticator instance in the target user via
+ * {@link #addAccountFromCredentials(AccountAuthenticatorResponse, Account, Bundle)}.
+ * The default implementation returns null, indicating that cloning is not supported.
+ * @param response to send the result back to the AccountManager, will never be null
+ * @param account the account to clone, will never be null
+ * @return a Bundle result or null if the result is to be returned via the response.
+ * @throws NetworkErrorException
+ * @see {@link #addAccountFromCredentials(AccountAuthenticatorResponse, Account, Bundle)}
+ */
+ public Bundle getAccountCredentialsForCloning(final AccountAuthenticatorResponse response,
+ final Account account) throws NetworkErrorException {
+ new Thread(new Runnable() {
+ public void run() {
+ Bundle result = new Bundle();
+ result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false);
+ response.onResult(result);
+ }
+ }).start();
+ return null;
+ }
+
+ /**
+ * @hide
+ * Creates an account based on credentials provided by the authenticator instance of another
+ * user on the device, who has chosen to share the account with this user.
+ * @param response to send the result back to the AccountManager, will never be null
+ * @param account the account to clone, will never be null
+ * @param accountCredentials the Bundle containing the required credentials to create the
+ * account. Contents of the Bundle are only meaningful to the authenticator. This Bundle is
+ * provided by {@link #getAccountCredentialsForCloning(AccountAuthenticatorResponse, Account)}.
+ * @return a Bundle result or null if the result is to be returned via the response.
+ * @throws NetworkErrorException
+ * @see {@link #getAccountCredentialsForCloning(AccountAuthenticatorResponse, Account)}
+ */
+ public Bundle addAccountFromCredentials(final AccountAuthenticatorResponse response,
+ Account account,
+ Bundle accountCredentials) throws NetworkErrorException {
+ new Thread(new Runnable() {
+ public void run() {
+ Bundle result = new Bundle();
+ result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false);
+ response.onResult(result);
+ }
+ }).start();
+ return null;
+ }
}
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 6d9bb1d..6aac723 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -1123,6 +1123,57 @@ public class AccountManager {
}
/**
+ * Adds a shared account from the primary user to a secondary user. Adding the shared account
+ * doesn't take effect immediately. When the target user starts up, any pending shared accounts
+ * are attempted to be copied to the target user from the primary via calls to the
+ * authenticator.
+ * @param account the account to share
+ * @param user the target user
+ * @return
+ * @hide
+ */
+ public boolean addSharedAccount(final Account account, UserHandle user) {
+ try {
+ boolean val = mService.addSharedAccountAsUser(account, user.getIdentifier());
+ return val;
+ } catch (RemoteException re) {
+ // won't ever happen
+ throw new RuntimeException(re);
+ }
+ }
+
+ /**
+ * @hide
+ * Removes the shared account.
+ * @param account the account to remove
+ * @param user the user to remove the account from
+ * @return
+ */
+ public boolean removeSharedAccount(final Account account, UserHandle user) {
+ try {
+ boolean val = mService.removeSharedAccountAsUser(account, user.getIdentifier());
+ return val;
+ } catch (RemoteException re) {
+ // won't ever happen
+ throw new RuntimeException(re);
+ }
+ }
+
+ /**
+ * @hide
+ * @param user
+ * @return
+ */
+ public Account[] getSharedAccounts(UserHandle user) {
+ try {
+ return mService.getSharedAccountsAsUser(user.getIdentifier());
+ } catch (RemoteException re) {
+ // won't ever happen
+ throw new RuntimeException(re);
+ }
+ }
+
+ /**
* Confirms that the user knows the password for an account to make extra
* sure they are the owner of the account. The user-entered password can
* be supplied directly, otherwise the authenticator for this account type
diff --git a/core/java/android/accounts/IAccountAuthenticator.aidl b/core/java/android/accounts/IAccountAuthenticator.aidl
index 8860710..58612da 100644
--- a/core/java/android/accounts/IAccountAuthenticator.aidl
+++ b/core/java/android/accounts/IAccountAuthenticator.aidl
@@ -70,4 +70,17 @@ oneway interface IAccountAuthenticator {
* Gets whether or not the account is allowed to be removed.
*/
void getAccountRemovalAllowed(in IAccountAuthenticatorResponse response, in Account account);
+
+ /**
+ * Returns a Bundle containing the required credentials to copy the account across users.
+ */
+ void getAccountCredentialsForCloning(in IAccountAuthenticatorResponse response,
+ in Account account);
+
+ /**
+ * Uses the Bundle containing credentials from another instance of the authenticator to create
+ * a copy of the account on this user.
+ */
+ void addAccountFromCredentials(in IAccountAuthenticatorResponse response, in Account account,
+ in Bundle accountCredentials);
}
diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl
index dbb4924..47b257d 100644
--- a/core/java/android/accounts/IAccountManager.aidl
+++ b/core/java/android/accounts/IAccountManager.aidl
@@ -58,4 +58,9 @@ interface IAccountManager {
in Bundle options, boolean expectActivityLaunch, int userId);
void getAuthTokenLabel(in IAccountManagerResponse response, String accountType,
String authTokenType);
+
+ /* Shared accounts */
+ boolean addSharedAccountAsUser(in Account account, int userId);
+ Account[] getSharedAccountsAsUser(int userId);
+ boolean removeSharedAccountAsUser(in Account account, int userId);
}
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index f09c2fe..6d55dd5 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -50,6 +50,7 @@ import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Process;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.Log;
import android.view.Display;
@@ -1064,7 +1065,7 @@ final class ApplicationPackageManager extends PackageManager {
public int installExistingPackage(String packageName)
throws NameNotFoundException {
try {
- int res = mPM.installExistingPackage(packageName);
+ int res = mPM.installExistingPackageAsUser(packageName, UserHandle.myUserId());
if (res == INSTALL_FAILED_INVALID_URI) {
throw new NameNotFoundException("Package " + packageName + " doesn't exist");
}
@@ -1126,7 +1127,7 @@ final class ApplicationPackageManager extends PackageManager {
@Override
public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
try {
- mPM.deletePackage(packageName, observer, flags);
+ mPM.deletePackageAsUser(packageName, observer, UserHandle.myUserId(), flags);
} catch (RemoteException e) {
// Should never happen!
}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index a368451..a32a201 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -194,20 +194,22 @@ interface IPackageManager {
void setInstallerPackageName(in String targetPackage, in String installerPackageName);
/**
- * Delete a package.
+ * Delete a package for a specific user.
*
* @param packageName The fully qualified name of the package to delete.
* @param observer a callback to use to notify when the package deletion in finished.
+ * @param userId the id of the user for whom to delete the package
* @param flags - possible values: {@link #DONT_DELETE_DATA}
*/
- void deletePackage(in String packageName, IPackageDeleteObserver observer, int flags);
+ void deletePackageAsUser(in String packageName, IPackageDeleteObserver observer,
+ int userId, int flags);
String getInstallerPackageName(in String packageName);
void addPackageToPreferred(String packageName);
-
+
void removePackageFromPreferred(String packageName);
-
+
List<PackageInfo> getPreferredPackages(int flags);
void resetPreferredActivities(int userId);
@@ -381,7 +383,7 @@ interface IPackageManager {
in VerificationParams verificationParams,
in ContainerEncryptionParams encryptionParams);
- int installExistingPackage(String packageName);
+ int installExistingPackageAsUser(String packageName, int userId);
void verifyPendingInstall(int id, int verificationCode);
void extendVerificationTimeout(int id, int verificationCodeAtTimeout, long millisecondsToDelay);
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 593f826..4c87830 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -97,6 +97,10 @@ public class UserInfo implements Parcelable {
return (flags & FLAG_GUEST) == FLAG_GUEST;
}
+ public boolean isRestricted() {
+ return (flags & FLAG_RESTRICTED) == FLAG_RESTRICTED;
+ }
+
public UserInfo() {
}