Home | History | Annotate | Download | only in content
      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 
     17 package android.content;
     18 
     19 import android.content.pm.RegisteredServicesCache;
     20 import android.content.pm.XmlSerializerAndParser;
     21 import android.content.res.Resources;
     22 import android.content.res.TypedArray;
     23 import android.text.TextUtils;
     24 import android.util.ArrayMap;
     25 import android.util.AttributeSet;
     26 import android.util.SparseArray;
     27 
     28 import com.android.internal.annotations.GuardedBy;
     29 
     30 import org.xmlpull.v1.XmlPullParser;
     31 import org.xmlpull.v1.XmlSerializer;
     32 import org.xmlpull.v1.XmlPullParserException;
     33 
     34 import java.io.IOException;
     35 import java.util.ArrayList;
     36 import java.util.Collection;
     37 
     38 /**
     39  * A cache of services that export the {@link android.content.ISyncAdapter} interface.
     40  * @hide
     41  */
     42 public class SyncAdaptersCache extends RegisteredServicesCache<SyncAdapterType> {
     43     private static final String TAG = "Account";
     44 
     45     private static final String SERVICE_INTERFACE = "android.content.SyncAdapter";
     46     private static final String SERVICE_META_DATA = "android.content.SyncAdapter";
     47     private static final String ATTRIBUTES_NAME = "sync-adapter";
     48     private static final MySerializer sSerializer = new MySerializer();
     49 
     50     @GuardedBy("mServicesLock")
     51     private SparseArray<ArrayMap<String,String[]>> mAuthorityToSyncAdapters
     52             = new SparseArray<>();
     53 
     54     public SyncAdaptersCache(Context context) {
     55         super(context, SERVICE_INTERFACE, SERVICE_META_DATA, ATTRIBUTES_NAME, sSerializer);
     56     }
     57 
     58     public SyncAdapterType parseServiceAttributes(Resources res,
     59             String packageName, AttributeSet attrs) {
     60         TypedArray sa = res.obtainAttributes(attrs,
     61                 com.android.internal.R.styleable.SyncAdapter);
     62         try {
     63             final String authority =
     64                     sa.getString(com.android.internal.R.styleable.SyncAdapter_contentAuthority);
     65             final String accountType =
     66                     sa.getString(com.android.internal.R.styleable.SyncAdapter_accountType);
     67             if (TextUtils.isEmpty(authority) || TextUtils.isEmpty(accountType)) {
     68                 return null;
     69             }
     70             final boolean userVisible =
     71                     sa.getBoolean(com.android.internal.R.styleable.SyncAdapter_userVisible, true);
     72             final boolean supportsUploading =
     73                     sa.getBoolean(com.android.internal.R.styleable.SyncAdapter_supportsUploading,
     74                             true);
     75             final boolean isAlwaysSyncable =
     76                     sa.getBoolean(com.android.internal.R.styleable.SyncAdapter_isAlwaysSyncable,
     77                             false);
     78             final boolean allowParallelSyncs =
     79                     sa.getBoolean(com.android.internal.R.styleable.SyncAdapter_allowParallelSyncs,
     80                             false);
     81             final String settingsActivity =
     82                     sa.getString(com.android.internal.R.styleable
     83                             .SyncAdapter_settingsActivity);
     84             return new SyncAdapterType(authority, accountType, userVisible, supportsUploading,
     85                     isAlwaysSyncable, allowParallelSyncs, settingsActivity, packageName);
     86         } finally {
     87             sa.recycle();
     88         }
     89     }
     90 
     91     @Override
     92     protected void onServicesChangedLocked(int userId) {
     93         synchronized (mServicesLock) {
     94             ArrayMap<String,String[]> adapterMap = mAuthorityToSyncAdapters.get(userId);
     95             if (adapterMap != null) {
     96                 adapterMap.clear();
     97             }
     98         }
     99 
    100         super.onServicesChangedLocked(userId);
    101     }
    102 
    103     public String[] getSyncAdapterPackagesForAuthority(String authority, int userId) {
    104         synchronized (mServicesLock) {
    105             ArrayMap<String,String[]> adapterMap = mAuthorityToSyncAdapters.get(userId);
    106             if (adapterMap == null) {
    107                 adapterMap = new ArrayMap<>();
    108                 mAuthorityToSyncAdapters.put(userId, adapterMap);
    109             }
    110             // If the mapping exists, return it
    111             if (adapterMap.containsKey(authority)) {
    112                 return adapterMap.get(authority);
    113             }
    114             // Create the mapping and cache it
    115             String[] syncAdapterPackages;
    116             final Collection<RegisteredServicesCache.ServiceInfo<SyncAdapterType>> serviceInfos;
    117             serviceInfos = getAllServices(userId);
    118             ArrayList<String> packages = new ArrayList<>();
    119             for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> serviceInfo : serviceInfos) {
    120                 if (authority.equals(serviceInfo.type.authority)
    121                         && serviceInfo.componentName != null) {
    122                     packages.add(serviceInfo.componentName.getPackageName());
    123                 }
    124             }
    125             syncAdapterPackages = new String[packages.size()];
    126             packages.toArray(syncAdapterPackages);
    127             adapterMap.put(authority, syncAdapterPackages);
    128 
    129             return syncAdapterPackages;
    130         }
    131     }
    132 
    133     @Override
    134     protected void onUserRemoved(int userId) {
    135         synchronized (mServicesLock) {
    136             mAuthorityToSyncAdapters.remove(userId);
    137         }
    138 
    139         super.onUserRemoved(userId);
    140     }
    141 
    142     static class MySerializer implements XmlSerializerAndParser<SyncAdapterType> {
    143         public void writeAsXml(SyncAdapterType item, XmlSerializer out) throws IOException {
    144             out.attribute(null, "authority", item.authority);
    145             out.attribute(null, "accountType", item.accountType);
    146         }
    147 
    148         public SyncAdapterType createFromXml(XmlPullParser parser)
    149                 throws IOException, XmlPullParserException {
    150             final String authority = parser.getAttributeValue(null, "authority");
    151             final String accountType = parser.getAttributeValue(null, "accountType");
    152             return SyncAdapterType.newKey(authority, accountType);
    153         }
    154     }
    155 }
    156