Home | History | Annotate | Download | only in accounts
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package android.accounts;
     17 
     18 import android.app.Activity;
     19 import android.app.ActivityManager;
     20 import android.app.ActivityTaskManager;
     21 import android.content.Context;
     22 import android.content.pm.PackageManager;
     23 import android.content.res.Resources;
     24 import android.graphics.drawable.Drawable;
     25 import android.os.Bundle;
     26 import android.os.IBinder;
     27 import android.os.Parcelable;
     28 import android.os.RemoteException;
     29 import android.os.Process;
     30 import android.os.UserHandle;
     31 import android.util.Log;
     32 import android.view.LayoutInflater;
     33 import android.view.View;
     34 import android.view.ViewGroup;
     35 import android.widget.AdapterView;
     36 import android.widget.ArrayAdapter;
     37 import android.widget.ImageView;
     38 import android.widget.ListView;
     39 import android.widget.TextView;
     40 import com.android.internal.R;
     41 
     42 import java.util.HashMap;
     43 
     44 /**
     45  * @hide
     46  */
     47 public class ChooseAccountActivity extends Activity {
     48 
     49     private static final String TAG = "AccountManager";
     50 
     51     private Parcelable[] mAccounts = null;
     52     private AccountManagerResponse mAccountManagerResponse = null;
     53     private Bundle mResult;
     54     private int mCallingUid;
     55     private String mCallingPackage;
     56 
     57     private HashMap<String, AuthenticatorDescription> mTypeToAuthDescription
     58             = new HashMap<String, AuthenticatorDescription>();
     59 
     60     @Override
     61     public void onCreate(Bundle savedInstanceState) {
     62         super.onCreate(savedInstanceState);
     63         mAccounts = getIntent().getParcelableArrayExtra(AccountManager.KEY_ACCOUNTS);
     64         mAccountManagerResponse =
     65                 getIntent().getParcelableExtra(AccountManager.KEY_ACCOUNT_MANAGER_RESPONSE);
     66 
     67         // KEY_ACCOUNTS is a required parameter
     68         if (mAccounts == null) {
     69             setResult(RESULT_CANCELED);
     70             finish();
     71             return;
     72         }
     73 
     74         try {
     75             IBinder activityToken = getActivityToken();
     76             mCallingUid = ActivityTaskManager.getService().getLaunchedFromUid(activityToken);
     77             mCallingPackage = ActivityTaskManager.getService().getLaunchedFromPackage(
     78                     activityToken);
     79         } catch (RemoteException re) {
     80             // Couldn't figure out caller details
     81             Log.w(getClass().getSimpleName(), "Unable to get caller identity \n" + re);
     82         }
     83 
     84         if (UserHandle.isSameApp(mCallingUid, Process.SYSTEM_UID) &&
     85             getIntent().getStringExtra(AccountManager.KEY_ANDROID_PACKAGE_NAME) != null) {
     86             mCallingPackage = getIntent().getStringExtra(
     87                 AccountManager.KEY_ANDROID_PACKAGE_NAME);
     88         }
     89 
     90         if (!UserHandle.isSameApp(mCallingUid, Process.SYSTEM_UID) &&
     91                 getIntent().getStringExtra(AccountManager.KEY_ANDROID_PACKAGE_NAME) != null) {
     92             Log.w(getClass().getSimpleName(),
     93                 "Non-system Uid: " + mCallingUid + " tried to override packageName \n");
     94         }
     95 
     96         getAuthDescriptions();
     97 
     98         AccountInfo[] mAccountInfos = new AccountInfo[mAccounts.length];
     99         for (int i = 0; i < mAccounts.length; i++) {
    100             mAccountInfos[i] = new AccountInfo(((Account) mAccounts[i]).name,
    101                     getDrawableForType(((Account) mAccounts[i]).type));
    102         }
    103 
    104         setContentView(R.layout.choose_account);
    105 
    106         // Setup the list
    107         ListView list = findViewById(android.R.id.list);
    108         // Use an existing ListAdapter that will map an array of strings to TextViews
    109         list.setAdapter(new AccountArrayAdapter(this,
    110                 android.R.layout.simple_list_item_1, mAccountInfos));
    111         list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
    112         list.setTextFilterEnabled(true);
    113         list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    114             public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
    115                 onListItemClick((ListView)parent, v, position, id);
    116             }
    117         });
    118     }
    119 
    120     private void getAuthDescriptions() {
    121         for(AuthenticatorDescription desc : AccountManager.get(this).getAuthenticatorTypes()) {
    122             mTypeToAuthDescription.put(desc.type, desc);
    123         }
    124     }
    125 
    126     private Drawable getDrawableForType(String accountType) {
    127         Drawable icon = null;
    128         if(mTypeToAuthDescription.containsKey(accountType)) {
    129             try {
    130                 AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
    131                 Context authContext = createPackageContext(desc.packageName, 0);
    132                 icon = authContext.getDrawable(desc.iconId);
    133             } catch (PackageManager.NameNotFoundException e) {
    134                 // Nothing we can do much here, just log
    135                 if (Log.isLoggable(TAG, Log.WARN)) {
    136                     Log.w(TAG, "No icon name for account type " + accountType);
    137                 }
    138             } catch (Resources.NotFoundException e) {
    139                 // Nothing we can do much here, just log
    140                 if (Log.isLoggable(TAG, Log.WARN)) {
    141                     Log.w(TAG, "No icon resource for account type " + accountType);
    142                 }
    143             }
    144         }
    145         return icon;
    146     }
    147 
    148     protected void onListItemClick(ListView l, View v, int position, long id) {
    149         Account account = (Account) mAccounts[position];
    150         // Mark account as visible since user chose it.
    151         AccountManager am = AccountManager.get(this);
    152         Integer oldVisibility = am.getAccountVisibility(account, mCallingPackage);
    153         if (oldVisibility != null
    154                 && oldVisibility == AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE) {
    155             am.setAccountVisibility(account, mCallingPackage,
    156                 AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);
    157         }
    158         Log.d(TAG, "selected account " + account);
    159         Bundle bundle = new Bundle();
    160         bundle.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
    161         bundle.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
    162         mResult = bundle;
    163         finish();
    164     }
    165 
    166     public void finish() {
    167         if (mAccountManagerResponse != null) {
    168             if (mResult != null) {
    169                 mAccountManagerResponse.onResult(mResult);
    170             } else {
    171                 mAccountManagerResponse.onError(AccountManager.ERROR_CODE_CANCELED, "canceled");
    172             }
    173         }
    174         super.finish();
    175     }
    176 
    177     private static class AccountInfo {
    178         final String name;
    179         final Drawable drawable;
    180 
    181         AccountInfo(String name, Drawable drawable) {
    182             this.name = name;
    183             this.drawable = drawable;
    184         }
    185     }
    186 
    187     private static class ViewHolder {
    188         ImageView icon;
    189         TextView text;
    190     }
    191 
    192     private static class AccountArrayAdapter extends ArrayAdapter<AccountInfo> {
    193         private LayoutInflater mLayoutInflater;
    194         private AccountInfo[] mInfos;
    195 
    196         public AccountArrayAdapter(Context context, int textViewResourceId, AccountInfo[] infos) {
    197             super(context, textViewResourceId, infos);
    198             mInfos = infos;
    199             mLayoutInflater = (LayoutInflater) context.getSystemService(
    200                     Context.LAYOUT_INFLATER_SERVICE);
    201         }
    202 
    203         @Override
    204         public View getView(int position, View convertView, ViewGroup parent) {
    205             ViewHolder holder;
    206 
    207             if (convertView == null) {
    208                 convertView = mLayoutInflater.inflate(R.layout.choose_account_row, null);
    209                 holder = new ViewHolder();
    210                 holder.text = (TextView) convertView.findViewById(R.id.account_row_text);
    211                 holder.icon = (ImageView) convertView.findViewById(R.id.account_row_icon);
    212                 convertView.setTag(holder);
    213             } else {
    214                 holder = (ViewHolder) convertView.getTag();
    215             }
    216 
    217             holder.text.setText(mInfos[position].name);
    218             holder.icon.setImageDrawable(mInfos[position].drawable);
    219 
    220             return convertView;
    221         }
    222     }
    223 }
    224