• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 com.android.dialer.preferredsim.impl;
18 
19 import android.Manifest.permission;
20 import android.content.ContentProvider;
21 import android.content.ContentValues;
22 import android.content.pm.PackageManager;
23 import android.database.Cursor;
24 import android.net.Uri;
25 import android.support.annotation.NonNull;
26 import android.support.annotation.Nullable;
27 import android.text.TextUtils;
28 import com.android.dialer.preferredsim.PreferredSimFallbackContract;
29 import com.android.dialer.preferredsim.PreferredSimFallbackContract.PreferredSim;
30 
31 /**
32  * Content provider for preferred SIM columns that is only available in ContactsProvider after P.
33  * Only supports {@link PreferredSimFallbackContract#CONTENT_URI} without id. Insert and delete not
34  * supported because there are no current use case.
35  *
36  * @see PreferredSimFallbackContract
37  */
38 public class PreferredSimFallbackProvider extends ContentProvider {
39 
40   private static final String UPDATE_ID_SELECTION = PreferredSim.DATA_ID + " = ?";
41 
42   private PreferredSimDatabaseHelper databaseHelper;
43 
44   @Override
onCreate()45   public boolean onCreate() {
46     databaseHelper = new PreferredSimDatabaseHelper(getContext());
47     return true;
48   }
49 
50   @Nullable
51   @Override
query( @onNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder)52   public Cursor query(
53       @NonNull Uri uri,
54       @Nullable String[] projection,
55       @Nullable String selection,
56       @Nullable String[] selectionArgs,
57       @Nullable String sortOrder) {
58     checkReadContactsPermission();
59     return databaseHelper
60         .getReadableDatabase()
61         .query(
62             PreferredSimDatabaseHelper.TABLE,
63             projection,
64             selection,
65             selectionArgs,
66             null,
67             null,
68             sortOrder);
69   }
70 
71   @Nullable
72   @Override
getType(@onNull Uri uri)73   public String getType(@NonNull Uri uri) {
74     return null;
75   }
76 
77   @Nullable
78   @Override
insert(@onNull Uri uri, @Nullable ContentValues values)79   public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
80     throw new IllegalArgumentException("Unsupported operation");
81   }
82 
83   /**
84    * A row should only be deleted through {@link android.provider.ContactsContract.Data}. Since
85    * {@link android.provider.ContactsContract.Data#_ID} is AUTOINCREMENT and could not be reused,
86    * rows in this database will simply be orphaned and not cleaned up. To unset preference, update
87    * {@link PreferredSim#PREFERRED_PHONE_ACCOUNT_COMPONENT_NAME} and {@link
88    * PreferredSim#PREFERRED_PHONE_ACCOUNT_ID} to {@code null}. Delete is only allowed from dialer so
89    * simulator can wipe all preference.
90    */
91   @Override
delete( @onNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs)92   public int delete(
93       @NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
94     checkWriteContactsPermission();
95 
96     if (PreferredSimFallbackContract.CONTENT_URI.equals(uri)
97         && selection == null
98         && selectionArgs == null) {
99       return databaseHelper
100           .getWritableDatabase()
101           .delete(PreferredSimDatabaseHelper.TABLE, null, null);
102     }
103 
104     if (!TextUtils.equals(getContext().getPackageName(), getCallingPackage())) {
105       throw new IllegalArgumentException("Unsupported operation");
106     }
107 
108     return databaseHelper
109         .getWritableDatabase()
110         .delete(PreferredSimDatabaseHelper.TABLE, selection, selectionArgs);
111   }
112 
113   /**
114    * Data will be inserted if {@link PreferredSim#DATA_ID} does not already exist in the database.
115    * During update the whole row will be replaced.
116    *
117    * @param uri must be {@link PreferredSimFallbackContract#CONTENT_URI}
118    * @param values must contains exactly the keys {@link
119    *     PreferredSim#PREFERRED_PHONE_ACCOUNT_COMPONENT_NAME} {@link
120    *     PreferredSim#PREFERRED_PHONE_ACCOUNT_ID}. The value may be {@code null}
121    * @param selection must equals "data_id = ?"
122    * @param selectionArgs must contains exactly the {@link PreferredSim#DATA_ID}
123    */
124   @Override
update( @onNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs)125   public int update(
126       @NonNull Uri uri,
127       @Nullable ContentValues values,
128       @Nullable String selection,
129       @Nullable String[] selectionArgs) {
130     checkWriteContactsPermission();
131     if (values == null) {
132       return 0;
133     }
134     if (!UPDATE_ID_SELECTION.equals(selection)
135         || selectionArgs == null
136         || selectionArgs.length != 1) {
137       throw new IllegalArgumentException("Unsupported operation");
138     }
139     values.put(PreferredSim.DATA_ID, selectionArgs[0]);
140     if (databaseHelper.getWritableDatabase().replace(PreferredSimDatabaseHelper.TABLE, null, values)
141         == -1) {
142       throw new IllegalStateException("update failed");
143     }
144     getContext().getContentResolver().notifyChange(PreferredSimFallbackContract.CONTENT_URI, null);
145     return 1;
146   }
147 
checkReadContactsPermission()148   private void checkReadContactsPermission() {
149     if (getContext().checkCallingOrSelfPermission(permission.READ_CONTACTS)
150         == PackageManager.PERMISSION_DENIED) {
151       throw new SecurityException("READ_CONTACTS required");
152     }
153   }
154 
checkWriteContactsPermission()155   private void checkWriteContactsPermission() {
156     if (getContext().checkCallingOrSelfPermission(permission.WRITE_CONTACTS)
157         == PackageManager.PERMISSION_DENIED) {
158       throw new SecurityException("WRITE_CONTACTS required");
159     }
160   }
161 }
162