blob: 6704b75dff7f306634d0e8a2c515a7cc6bb6c1d5 [file] [log] [blame]
Fred Quintana718d8a22009-04-29 17:53:20 -07001/*
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
17package android.content;
18
Fred Quintana718d8a22009-04-29 17:53:20 -070019import android.content.pm.RegisteredServicesCache;
Fred Quintana5ebbb4a2009-11-09 15:42:20 -080020import android.content.pm.XmlSerializerAndParser;
Dianne Hackborn20cb56e2010-03-04 00:58:29 -080021import android.content.res.Resources;
Fred Quintana718d8a22009-04-29 17:53:20 -070022import android.content.res.TypedArray;
Amith Yamasani37a40c22015-06-17 13:25:42 -070023import android.util.ArrayMap;
Fred Quintana718d8a22009-04-29 17:53:20 -070024import android.util.AttributeSet;
Amith Yamasani37a40c22015-06-17 13:25:42 -070025import android.util.SparseArray;
26
27import com.android.internal.annotations.GuardedBy;
28
Fred Quintana5ebbb4a2009-11-09 15:42:20 -080029import org.xmlpull.v1.XmlPullParser;
30import org.xmlpull.v1.XmlSerializer;
31import org.xmlpull.v1.XmlPullParserException;
32
33import java.io.IOException;
Amith Yamasani37a40c22015-06-17 13:25:42 -070034import java.util.ArrayList;
35import java.util.Collection;
Fred Quintana718d8a22009-04-29 17:53:20 -070036
37/**
38 * A cache of services that export the {@link android.content.ISyncAdapter} interface.
39 * @hide
40 */
Jeff Sharkey7a96c392012-11-15 14:01:46 -080041public class SyncAdaptersCache extends RegisteredServicesCache<SyncAdapterType> {
Fred Quintana718d8a22009-04-29 17:53:20 -070042 private static final String TAG = "Account";
43
44 private static final String SERVICE_INTERFACE = "android.content.SyncAdapter";
45 private static final String SERVICE_META_DATA = "android.content.SyncAdapter";
46 private static final String ATTRIBUTES_NAME = "sync-adapter";
Fred Quintana5ebbb4a2009-11-09 15:42:20 -080047 private static final MySerializer sSerializer = new MySerializer();
Fred Quintana718d8a22009-04-29 17:53:20 -070048
Amith Yamasani37a40c22015-06-17 13:25:42 -070049 @GuardedBy("mServicesLock")
50 private SparseArray<ArrayMap<String,String[]>> mAuthorityToSyncAdapters
51 = new SparseArray<>();
52
Jeff Sharkey7a96c392012-11-15 14:01:46 -080053 public SyncAdaptersCache(Context context) {
Fred Quintana5ebbb4a2009-11-09 15:42:20 -080054 super(context, SERVICE_INTERFACE, SERVICE_META_DATA, ATTRIBUTES_NAME, sSerializer);
Fred Quintana718d8a22009-04-29 17:53:20 -070055 }
56
Dianne Hackborn20cb56e2010-03-04 00:58:29 -080057 public SyncAdapterType parseServiceAttributes(Resources res,
58 String packageName, AttributeSet attrs) {
59 TypedArray sa = res.obtainAttributes(attrs,
Fred Quintana718d8a22009-04-29 17:53:20 -070060 com.android.internal.R.styleable.SyncAdapter);
61 try {
62 final String authority =
63 sa.getString(com.android.internal.R.styleable.SyncAdapter_contentAuthority);
64 final String accountType =
65 sa.getString(com.android.internal.R.styleable.SyncAdapter_accountType);
66 if (authority == null || accountType == null) {
67 return null;
68 }
Fred Quintana4a6679b2009-08-17 13:05:39 -070069 final boolean userVisible =
70 sa.getBoolean(com.android.internal.R.styleable.SyncAdapter_userVisible, true);
Fred Quintanae0616ff2009-08-19 13:13:18 -070071 final boolean supportsUploading =
72 sa.getBoolean(com.android.internal.R.styleable.SyncAdapter_supportsUploading,
73 true);
Fred Quintana0c4d04a2010-11-03 17:02:55 -070074 final boolean isAlwaysSyncable =
75 sa.getBoolean(com.android.internal.R.styleable.SyncAdapter_isAlwaysSyncable,
76 false);
77 final boolean allowParallelSyncs =
78 sa.getBoolean(com.android.internal.R.styleable.SyncAdapter_allowParallelSyncs,
79 false);
Fred Quintanae6d60ec2011-08-24 11:29:00 -070080 final String settingsActivity =
81 sa.getString(com.android.internal.R.styleable
82 .SyncAdapter_settingsActivity);
Fred Quintana0c4d04a2010-11-03 17:02:55 -070083 return new SyncAdapterType(authority, accountType, userVisible, supportsUploading,
Fred Quintanae6d60ec2011-08-24 11:29:00 -070084 isAlwaysSyncable, allowParallelSyncs, settingsActivity);
Fred Quintana718d8a22009-04-29 17:53:20 -070085 } finally {
86 sa.recycle();
87 }
88 }
Fred Quintana5ebbb4a2009-11-09 15:42:20 -080089
Amith Yamasani37a40c22015-06-17 13:25:42 -070090 @Override
91 protected void onServicesChangedLocked(int userId) {
92 synchronized (mServicesLock) {
93 ArrayMap<String,String[]> adapterMap = mAuthorityToSyncAdapters.get(userId);
94 if (adapterMap != null) {
95 adapterMap.clear();
96 }
97 }
98
99 super.onServicesChangedLocked(userId);
100 }
101
102 public String[] getSyncAdapterPackagesForAuthority(String authority, int userId) {
103 synchronized (mServicesLock) {
104 ArrayMap<String,String[]> adapterMap = mAuthorityToSyncAdapters.get(userId);
105 if (adapterMap == null) {
106 adapterMap = new ArrayMap<>();
107 mAuthorityToSyncAdapters.put(userId, adapterMap);
108 }
109 // If the mapping exists, return it
110 if (adapterMap.containsKey(authority)) {
111 return adapterMap.get(authority);
112 }
113 // Create the mapping and cache it
114 String[] syncAdapterPackages;
115 final Collection<RegisteredServicesCache.ServiceInfo<SyncAdapterType>> serviceInfos;
116 serviceInfos = getAllServices(userId);
117 ArrayList<String> packages = new ArrayList<>();
118 for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> serviceInfo : serviceInfos) {
119 if (authority.equals(serviceInfo.type.authority)
120 && serviceInfo.componentName != null) {
121 packages.add(serviceInfo.componentName.getPackageName());
122 }
123 }
124 syncAdapterPackages = new String[packages.size()];
125 packages.toArray(syncAdapterPackages);
126 adapterMap.put(authority, syncAdapterPackages);
127
128 return syncAdapterPackages;
129 }
130 }
131
132 @Override
133 protected void onUserRemoved(int userId) {
134 synchronized (mServicesLock) {
135 mAuthorityToSyncAdapters.remove(userId);
136 }
137
138 super.onUserRemoved(userId);
139 }
140
Fred Quintana5ebbb4a2009-11-09 15:42:20 -0800141 static class MySerializer implements XmlSerializerAndParser<SyncAdapterType> {
142 public void writeAsXml(SyncAdapterType item, XmlSerializer out) throws IOException {
143 out.attribute(null, "authority", item.authority);
144 out.attribute(null, "accountType", item.accountType);
145 }
Fred Quintana0c4d04a2010-11-03 17:02:55 -0700146
Fred Quintana5ebbb4a2009-11-09 15:42:20 -0800147 public SyncAdapterType createFromXml(XmlPullParser parser)
148 throws IOException, XmlPullParserException {
149 final String authority = parser.getAttributeValue(null, "authority");
150 final String accountType = parser.getAttributeValue(null, "accountType");
151 return SyncAdapterType.newKey(authority, accountType);
152 }
153 }
Fred Quintana0c4d04a2010-11-03 17:02:55 -0700154}