Handle forwarded intents from a managed user in AccountSyncSettings

Bug: 15466880
Change-Id: I4041b69f237033dbe5b78c8eb52f5e6ebb6ff7f7
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 26750e7..2887b1a 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -20,6 +20,7 @@
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.Fragment;
+import android.app.IActivityManager;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -40,6 +41,8 @@
 import android.net.Uri;
 import android.os.BatteryManager;
 import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.preference.Preference;
@@ -52,6 +55,7 @@
 import android.provider.ContactsContract.RawContacts;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
+import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ListView;
@@ -63,13 +67,12 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.InetAddress;
-import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 
 public final class Utils {
-
+    private static final String TAG = "Settings";
     /**
      * Set the preference's title to the matching activity's label.
      */
@@ -608,4 +611,29 @@
         UserInfo currentUser = userManager.getUserInfo(userManager.getUserHandle());
         return currentUser.isManagedProfile();
     }
+
+    /**
+     * Returns the {@link UserHandle} of the profile that a settings screen should refer to.
+     *
+     * <p> This takes into account the id of the user that triggered the settings screen.
+     */
+   public static UserHandle getProfileToDisplay(IActivityManager am, IBinder activityToken,
+           Bundle arguments) {
+       int currentUser = UserHandle.getCallingUserId();
+       // Check to see if it was called from a different user
+       try {
+           int launchedFromUser = UserHandle.getUserId(am.getLaunchedFromUid(activityToken));
+           if (launchedFromUser != currentUser) {
+               // This is a forwarded intent
+               return new UserHandle(launchedFromUser);
+           }
+       } catch (RemoteException e) {
+           // Should not happen
+           Log.v(TAG, "Could not get launching user.");
+       }
+       // TODO: Check fragment arguments. See: http://b/15466880
+
+       // Default to current profile
+       return new UserHandle(currentUser);
+   }
 }
diff --git a/src/com/android/settings/accounts/AccountPreferenceBase.java b/src/com/android/settings/accounts/AccountPreferenceBase.java
index c25831d..6125adc 100644
--- a/src/com/android/settings/accounts/AccountPreferenceBase.java
+++ b/src/com/android/settings/accounts/AccountPreferenceBase.java
@@ -20,6 +20,7 @@
 
 import android.accounts.AuthenticatorDescription;
 import android.app.Activity;
+import android.app.ActivityManagerNative;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.SyncAdapterType;
@@ -38,6 +39,7 @@
 import android.view.ContextThemeWrapper;
 
 import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.Utils;
 
 import java.util.ArrayList;
 import java.util.Date;
@@ -47,23 +49,28 @@
         implements AuthenticatorHelper.OnAccountsUpdateListener {
 
     protected static final String TAG = "AccountSettings";
+
     public static final String AUTHORITIES_FILTER_KEY = "authorities";
     public static final String ACCOUNT_TYPES_FILTER_KEY = "account_types";
+
     private final Handler mHandler = new Handler();
+
     private UserManager mUm;
     private Object mStatusChangeListenerHandle;
     private HashMap<String, ArrayList<String>> mAccountTypeToAuthorities = null;
     protected AuthenticatorHelper mAuthenticatorHelper;
+    protected UserHandle mUserHandle;
+
     private java.text.DateFormat mDateFormat;
     private java.text.DateFormat mTimeFormat;
 
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-        // TODO: This needs to handle different users, get the user id from the intent
         mUm = (UserManager) getSystemService(Context.USER_SERVICE);
-        mAuthenticatorHelper = new AuthenticatorHelper(
-                getActivity(), UserHandle.getCallingUserHandle(), mUm, this);
+        mUserHandle = Utils.getProfileToDisplay(ActivityManagerNative.getDefault(),
+                getActivity().getActivityToken(), icicle);
+        mAuthenticatorHelper = new AuthenticatorHelper(getActivity(), mUserHandle, mUm, this);
     }
 
     /**
diff --git a/src/com/android/settings/accounts/AccountSyncSettings.java b/src/com/android/settings/accounts/AccountSyncSettings.java
index e33e37a..a9e43c7 100644
--- a/src/com/android/settings/accounts/AccountSyncSettings.java
+++ b/src/com/android/settings/accounts/AccountSyncSettings.java
@@ -181,9 +181,9 @@
         Bundle arguments = getArguments();
         if (arguments == null) {
             Log.e(TAG, "No arguments provided when starting intent. ACCOUNT_KEY needed.");
+            finish();
             return;
         }
-
         mAccount = (Account) arguments.getParcelable(ACCOUNT_KEY);
         if (mAccount != null) {
             if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "Got account: " + mAccount);
@@ -211,7 +211,8 @@
         SyncStateCheckBoxPreference item =
                 new SyncStateCheckBoxPreference(getActivity(), account, authority);
         item.setPersistent(false);
-        final ProviderInfo providerInfo = getPackageManager().resolveContentProvider(authority, 0);
+        final ProviderInfo providerInfo = getPackageManager().resolveContentProviderAsUser(
+                authority, 0, mUserHandle.getIdentifier());
         if (providerInfo == null) {
             return;
         }
@@ -235,7 +236,6 @@
         MenuItem syncCancel = menu.add(0, MENU_SYNC_CANCEL_ID, 0,
                 getString(R.string.sync_menu_sync_cancel))
                 .setIcon(com.android.internal.R.drawable.ic_menu_close_clear_cancel);
-
         final UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
         if (!um.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
             MenuItem removeAccount = menu.add(0, MENU_REMOVE_ACCOUNT_ID, 0,
@@ -255,7 +255,9 @@
     @Override
     public void onPrepareOptionsMenu(Menu menu) {
         super.onPrepareOptionsMenu(menu);
-        boolean syncActive = ContentResolver.getCurrentSync() != null;
+        // Note that this also counts accounts that are not currently displayed
+        boolean syncActive = ContentResolver.getCurrentSyncsAsUser(
+                mUserHandle.getIdentifier()).isEmpty();
         menu.findItem(MENU_SYNC_NOW_ID).setVisible(!syncActive);
         menu.findItem(MENU_SYNC_CANCEL_ID).setVisible(syncActive);
     }
@@ -344,9 +346,10 @@
         if (flag) {
             Bundle extras = new Bundle();
             extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
-            ContentResolver.requestSync(account, authority, extras);
+            ContentResolver.requestSyncAsUser(account, authority, mUserHandle.getIdentifier(),
+                    extras);
         } else {
-            ContentResolver.cancelSync(account, authority);
+            ContentResolver.cancelSyncAsUser(account, authority, mUserHandle.getIdentifier());
         }
     }
 
@@ -368,7 +371,8 @@
     private void setFeedsState() {
         // iterate over all the preferences, setting the state properly for each
         Date date = new Date();
-        List<SyncInfo> currentSyncs = ContentResolver.getCurrentSyncs();
+        final int userId = mUserHandle.getIdentifier();
+        List<SyncInfo> currentSyncs = ContentResolver.getCurrentSyncsAsUser(userId);
         boolean syncIsFailing = false;
 
         // Refresh the sync status checkboxes - some syncs may have become active.
@@ -384,8 +388,9 @@
             String authority = syncPref.getAuthority();
             Account account = syncPref.getAccount();
 
-            SyncStatusInfo status = ContentResolver.getSyncStatus(account, authority);
-            boolean syncEnabled = ContentResolver.getSyncAutomatically(account, authority);
+            SyncStatusInfo status = ContentResolver.getSyncStatusAsUser(account, authority, userId);
+            boolean syncEnabled = ContentResolver.getSyncAutomaticallyAsUser(account, authority,
+                    userId);
             boolean authorityIsPending = status == null ? false : status.pending;
             boolean initialSync = status == null ? false : status.initialize;
 
@@ -415,7 +420,7 @@
             } else {
                 syncPref.setSummary("");
             }
-            int syncState = ContentResolver.getIsSyncable(account, authority);
+            int syncState = ContentResolver.getIsSyncableAsUser(account, authority, userId);
 
             syncPref.setActive(activelySyncing && (syncState >= 0) &&
                     !initialSync);
@@ -425,7 +430,8 @@
             syncPref.setFailed(lastSyncFailed);
             ConnectivityManager connManager =
                 (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
-            final boolean masterSyncAutomatically = ContentResolver.getMasterSyncAutomatically();
+            final boolean masterSyncAutomatically =
+                    ContentResolver.getMasterSyncAutomaticallyAsUser(userId);
             final boolean backgroundDataEnabled = connManager.getBackgroundDataSetting();
             final boolean oneTimeSyncMode = !masterSyncAutomatically || !backgroundDataEnabled;
             syncPref.setOneTimeSyncMode(oneTimeSyncMode);
@@ -438,7 +444,8 @@
     @Override
     public void onAccountsUpdate(final UserHandle userHandle) {
         super.onAccountsUpdate(userHandle);
-        mAccounts = AccountManager.get(getActivity()).getAccounts();
+        mAccounts = AccountManager.get(getActivity()).getAccountsAsUser(
+                mUserHandle.getIdentifier());
         updateAccountCheckboxes(mAccounts);
         onSyncStateUpdated();
     }
@@ -446,7 +453,8 @@
     private void updateAccountCheckboxes(Account[] accounts) {
         mInvisibleAdapters.clear();
 
-        SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypes();
+       SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypesAsUser(
+                mUserHandle.getIdentifier());
         HashMap<String, ArrayList<String>> accountTypeToAuthorities =
             Maps.newHashMap();
         for (int i = 0, n = syncAdapters.length; i < n; i++) {
@@ -484,7 +492,8 @@
                 for (int j = 0, m = authorities.size(); j < m; j++) {
                     final String authority = authorities.get(j);
                     // We could check services here....
-                    int syncState = ContentResolver.getIsSyncable(account, authority);
+                    int syncState = ContentResolver.getIsSyncableAsUser(account, authority,
+                            mUserHandle.getIdentifier());
                     if (Log.isLoggable(TAG, Log.VERBOSE)) {
                         Log.d(TAG, "  found authority " + authority + " " + syncState);
                     }