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.annotation.Nullable;
20 import android.compat.annotation.UnsupportedAppUsage;
21 import android.os.Build;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 import android.text.TextUtils;
25 
26 /**
27  * Value type that represents a SyncAdapterType. This object overrides {@link #equals} and
28  * {@link #hashCode}, making it suitable for use as the key of a {@link java.util.Map}
29  */
30 public class SyncAdapterType implements Parcelable {
31     public final String authority;
32     public final String accountType;
33     public final boolean isKey;
34     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
35     private final boolean userVisible;
36     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
37     private final boolean supportsUploading;
38     @UnsupportedAppUsage
39     private final boolean isAlwaysSyncable;
40     @UnsupportedAppUsage
41     private final boolean allowParallelSyncs;
42     @UnsupportedAppUsage
43     private final String settingsActivity;
44     private final String packageName;
45 
SyncAdapterType(String authority, String accountType, boolean userVisible, boolean supportsUploading)46     public SyncAdapterType(String authority, String accountType, boolean userVisible,
47             boolean supportsUploading) {
48         if (TextUtils.isEmpty(authority)) {
49             throw new IllegalArgumentException("the authority must not be empty: " + authority);
50         }
51         if (TextUtils.isEmpty(accountType)) {
52             throw new IllegalArgumentException("the accountType must not be empty: " + accountType);
53         }
54         this.authority = authority;
55         this.accountType = accountType;
56         this.userVisible = userVisible;
57         this.supportsUploading = supportsUploading;
58         this.isAlwaysSyncable = false;
59         this.allowParallelSyncs = false;
60         this.settingsActivity = null;
61         this.isKey = false;
62         this.packageName = null;
63     }
64 
65     /** @hide */
SyncAdapterType(String authority, String accountType, boolean userVisible, boolean supportsUploading, boolean isAlwaysSyncable, boolean allowParallelSyncs, String settingsActivity, String packageName)66     public SyncAdapterType(String authority, String accountType, boolean userVisible,
67             boolean supportsUploading,
68             boolean isAlwaysSyncable,
69             boolean allowParallelSyncs,
70             String settingsActivity,
71             String packageName) {
72         if (TextUtils.isEmpty(authority)) {
73             throw new IllegalArgumentException("the authority must not be empty: " + authority);
74         }
75         if (TextUtils.isEmpty(accountType)) {
76             throw new IllegalArgumentException("the accountType must not be empty: " + accountType);
77         }
78         this.authority = authority;
79         this.accountType = accountType;
80         this.userVisible = userVisible;
81         this.supportsUploading = supportsUploading;
82         this.isAlwaysSyncable = isAlwaysSyncable;
83         this.allowParallelSyncs = allowParallelSyncs;
84         this.settingsActivity = settingsActivity;
85         this.isKey = false;
86         this.packageName = packageName;
87     }
88 
89     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
SyncAdapterType(String authority, String accountType)90     private SyncAdapterType(String authority, String accountType) {
91         if (TextUtils.isEmpty(authority)) {
92             throw new IllegalArgumentException("the authority must not be empty: " + authority);
93         }
94         if (TextUtils.isEmpty(accountType)) {
95             throw new IllegalArgumentException("the accountType must not be empty: " + accountType);
96         }
97         this.authority = authority;
98         this.accountType = accountType;
99         this.userVisible = true;
100         this.supportsUploading = true;
101         this.isAlwaysSyncable = false;
102         this.allowParallelSyncs = false;
103         this.settingsActivity = null;
104         this.isKey = true;
105         this.packageName = null;
106     }
107 
supportsUploading()108     public boolean supportsUploading() {
109         if (isKey) {
110             throw new IllegalStateException(
111                     "this method is not allowed to be called when this is a key");
112         }
113         return supportsUploading;
114     }
115 
isUserVisible()116     public boolean isUserVisible() {
117         if (isKey) {
118             throw new IllegalStateException(
119                     "this method is not allowed to be called when this is a key");
120         }
121         return userVisible;
122     }
123 
124     /**
125      * @return True if this SyncAdapter supports syncing multiple accounts simultaneously.
126      * If false then the SyncManager will take care to only start one sync at a time
127      * using this SyncAdapter.
128      */
allowParallelSyncs()129     public boolean allowParallelSyncs() {
130         if (isKey) {
131             throw new IllegalStateException(
132                     "this method is not allowed to be called when this is a key");
133         }
134         return allowParallelSyncs;
135     }
136 
137     /**
138      * If true then the SyncManager will never issue an initialization sync to the SyncAdapter
139      * and will instead automatically call
140      * {@link ContentResolver#setIsSyncable(android.accounts.Account, String, int)} with a
141      * value of 1 for each account and provider that this sync adapter supports.
142      * @return true if the SyncAdapter does not require initialization and if it is ok for the
143      * SyncAdapter to treat it as syncable automatically.
144      */
isAlwaysSyncable()145     public boolean isAlwaysSyncable() {
146         if (isKey) {
147             throw new IllegalStateException(
148                     "this method is not allowed to be called when this is a key");
149         }
150         return isAlwaysSyncable;
151     }
152 
153     /**
154      * @return The activity to use to invoke this SyncAdapter's settings activity.
155      * May be null.
156      */
getSettingsActivity()157     public String getSettingsActivity() {
158         if (isKey) {
159             throw new IllegalStateException(
160                     "this method is not allowed to be called when this is a key");
161         }
162         return settingsActivity;
163     }
164 
165     /**
166      * The package hosting the sync adapter.
167      * @return The package name.
168      *
169      * @hide
170      */
getPackageName()171     public @Nullable String getPackageName() {
172         return packageName;
173     }
174 
newKey(String authority, String accountType)175     public static SyncAdapterType newKey(String authority, String accountType) {
176         return new SyncAdapterType(authority, accountType);
177     }
178 
equals(Object o)179     public boolean equals(Object o) {
180         if (o == this) return true;
181         if (!(o instanceof SyncAdapterType)) return false;
182         final SyncAdapterType other = (SyncAdapterType)o;
183         // don't include userVisible or supportsUploading in the equality check
184         return authority.equals(other.authority) && accountType.equals(other.accountType);
185     }
186 
hashCode()187     public int hashCode() {
188         int result = 17;
189         result = 31 * result + authority.hashCode();
190         result = 31 * result + accountType.hashCode();
191         // don't include userVisible or supportsUploading  the hash
192         return result;
193     }
194 
toString()195     public String toString() {
196         if (isKey) {
197             return "SyncAdapterType Key {name=" + authority
198                     + ", type=" + accountType
199                     + "}";
200         } else {
201             return "SyncAdapterType {name=" + authority
202                     + ", type=" + accountType
203                     + ", userVisible=" + userVisible
204                     + ", supportsUploading=" + supportsUploading
205                     + ", isAlwaysSyncable=" + isAlwaysSyncable
206                     + ", allowParallelSyncs=" + allowParallelSyncs
207                     + ", settingsActivity=" + settingsActivity
208                     + ", packageName=" + packageName
209                     + "}";
210         }
211     }
212 
describeContents()213     public int describeContents() {
214         return 0;
215     }
216 
writeToParcel(Parcel dest, int flags)217     public void writeToParcel(Parcel dest, int flags) {
218         if (isKey) {
219             throw new IllegalStateException("keys aren't parcelable");
220         }
221 
222         dest.writeString(authority);
223         dest.writeString(accountType);
224         dest.writeInt(userVisible ? 1 : 0);
225         dest.writeInt(supportsUploading ? 1 : 0);
226         dest.writeInt(isAlwaysSyncable ? 1 : 0);
227         dest.writeInt(allowParallelSyncs ? 1 : 0);
228         dest.writeString(settingsActivity);
229         dest.writeString(packageName);
230     }
231 
SyncAdapterType(Parcel source)232     public SyncAdapterType(Parcel source) {
233         this(
234                 source.readString(),
235                 source.readString(),
236                 source.readInt() != 0,
237                 source.readInt() != 0,
238                 source.readInt() != 0,
239                 source.readInt() != 0,
240                 source.readString(),
241                 source.readString());
242     }
243 
244     public static final @android.annotation.NonNull Creator<SyncAdapterType> CREATOR = new Creator<SyncAdapterType>() {
245         public SyncAdapterType createFromParcel(Parcel source) {
246             return new SyncAdapterType(source);
247         }
248 
249         public SyncAdapterType[] newArray(int size) {
250             return new SyncAdapterType[size];
251         }
252     };
253 }
254