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.provider;
18 
19 import android.net.Uri;
20 import android.content.ContentProviderClient;
21 import android.content.ContentValues;
22 import android.content.ContentProviderOperation;
23 import android.content.ContentUris;
24 import android.accounts.Account;
25 import android.database.Cursor;
26 import android.os.RemoteException;
27 import android.util.Pair;
28 
29 /**
30  * The ContentProvider contract for associating data with ana data array account.
31  * This may be used by providers that want to store this data in a standard way.
32  */
33 public class SyncStateContract {
34     public interface Columns extends BaseColumns {
35         /**
36          * A reference to the name of the account to which this data belongs
37          * <P>Type: STRING</P>
38          */
39         public static final String ACCOUNT_NAME = "account_name";
40 
41         /**
42          * A reference to the type of the account to which this data belongs
43          * <P>Type: STRING</P>
44          */
45         public static final String ACCOUNT_TYPE = "account_type";
46 
47         /**
48          * The sync data associated with this account.
49          * <P>Type: NONE</P>
50          */
51         public static final String DATA = "data";
52     }
53 
54     public static class Constants implements Columns {
55         public static final String CONTENT_DIRECTORY = "syncstate";
56     }
57 
58     public static final class Helpers {
59         private static final String[] DATA_PROJECTION = new String[]{Columns.DATA, Columns._ID};
60         private static final String SELECT_BY_ACCOUNT =
61                 Columns.ACCOUNT_NAME + "=? AND " + Columns.ACCOUNT_TYPE + "=?";
62 
63         /**
64          * Get the sync state that is associated with the account or null.
65          * @param provider the {@link ContentProviderClient} that is to be used to communicate
66          * with the {@link android.content.ContentProvider} that contains the sync state.
67          * @param uri the uri of the sync state
68          * @param account the {@link Account} whose sync state should be returned
69          * @return the sync state or null if there is no sync state associated with the account
70          * @throws RemoteException if there is a failure communicating with the remote
71          * {@link android.content.ContentProvider}
72          */
get(ContentProviderClient provider, Uri uri, Account account)73         public static byte[] get(ContentProviderClient provider, Uri uri,
74                 Account account) throws RemoteException {
75             Cursor c = provider.query(uri, DATA_PROJECTION, SELECT_BY_ACCOUNT,
76                     new String[]{account.name, account.type}, null);
77 
78             // Unable to query the provider
79             if (c == null) {
80                 throw new RemoteException();
81             }
82 
83             try {
84                 if (c.moveToNext()) {
85                     return c.getBlob(c.getColumnIndexOrThrow(Columns.DATA));
86                 }
87             } finally {
88                 c.close();
89             }
90             return null;
91         }
92 
93         /**
94          * Assigns the data array as the sync state for the given account.
95          * @param provider the {@link ContentProviderClient} that is to be used to communicate
96          * with the {@link android.content.ContentProvider} that contains the sync state.
97          * @param uri the uri of the sync state
98          * @param account the {@link Account} whose sync state should be set
99          * @param data the byte[] that contains the sync state
100          * @throws RemoteException if there is a failure communicating with the remote
101          * {@link android.content.ContentProvider}
102          */
set(ContentProviderClient provider, Uri uri, Account account, byte[] data)103         public static void set(ContentProviderClient provider, Uri uri,
104                 Account account, byte[] data) throws RemoteException {
105             ContentValues values = new ContentValues();
106             values.put(Columns.DATA, data);
107             values.put(Columns.ACCOUNT_NAME, account.name);
108             values.put(Columns.ACCOUNT_TYPE, account.type);
109             provider.insert(uri, values);
110         }
111 
insert(ContentProviderClient provider, Uri uri, Account account, byte[] data)112         public static Uri insert(ContentProviderClient provider, Uri uri,
113                 Account account, byte[] data) throws RemoteException {
114             ContentValues values = new ContentValues();
115             values.put(Columns.DATA, data);
116             values.put(Columns.ACCOUNT_NAME, account.name);
117             values.put(Columns.ACCOUNT_TYPE, account.type);
118             return provider.insert(uri, values);
119         }
120 
update(ContentProviderClient provider, Uri uri, byte[] data)121         public static void update(ContentProviderClient provider, Uri uri, byte[] data)
122                 throws RemoteException {
123             ContentValues values = new ContentValues();
124             values.put(Columns.DATA, data);
125             provider.update(uri, values, null, null);
126         }
127 
getWithUri(ContentProviderClient provider, Uri uri, Account account)128         public static Pair<Uri, byte[]> getWithUri(ContentProviderClient provider, Uri uri,
129                 Account account) throws RemoteException {
130             Cursor c = provider.query(uri, DATA_PROJECTION, SELECT_BY_ACCOUNT,
131                     new String[]{account.name, account.type}, null);
132 
133             if (c == null) {
134                 throw new RemoteException();
135             }
136 
137             try {
138                 if (c.moveToNext()) {
139                     long rowId = c.getLong(1);
140                     byte[] blob = c.getBlob(c.getColumnIndexOrThrow(Columns.DATA));
141                     return Pair.create(ContentUris.withAppendedId(uri, rowId), blob);
142                 }
143             } finally {
144                 c.close();
145             }
146             return null;
147         }
148 
149         /**
150          * Creates and returns a ContentProviderOperation that assigns the data array as the
151          * sync state for the given account.
152          * @param uri the uri of the sync state
153          * @param account the {@link Account} whose sync state should be set
154          * @param data the byte[] that contains the sync state
155          * @return the new ContentProviderOperation that assigns the data array as the
156          * account's sync state
157          */
newSetOperation(Uri uri, Account account, byte[] data)158         public static ContentProviderOperation newSetOperation(Uri uri,
159                 Account account, byte[] data) {
160             ContentValues values = new ContentValues();
161             values.put(Columns.DATA, data);
162             return ContentProviderOperation
163                     .newInsert(uri)
164                     .withValue(Columns.ACCOUNT_NAME, account.name)
165                     .withValue(Columns.ACCOUNT_TYPE, account.type)
166                     .withValues(values)
167                     .build();
168         }
169 
170         /**
171          * Creates and returns a ContentProviderOperation that assigns the data array as the
172          * sync state for the given account.
173          * @param uri the uri of the specific sync state to set
174          * @param data the byte[] that contains the sync state
175          * @return the new ContentProviderOperation that assigns the data array as the
176          * account's sync state
177          */
newUpdateOperation(Uri uri, byte[] data)178         public static ContentProviderOperation newUpdateOperation(Uri uri, byte[] data) {
179             ContentValues values = new ContentValues();
180             values.put(Columns.DATA, data);
181             return ContentProviderOperation
182                     .newUpdate(uri)
183                     .withValues(values)
184                     .build();
185         }
186     }
187 }
188