update new sdk
This commit is contained in:
parent
f33907443a
commit
744c72c133
1643 changed files with 83006 additions and 28021 deletions
213
android/packages/providers/DownloadProvider/src/com/android/providers/downloads/DownloadProvider.java
Normal file → Executable file
213
android/packages/providers/DownloadProvider/src/com/android/providers/downloads/DownloadProvider.java
Normal file → Executable file
|
@ -20,7 +20,9 @@ import static android.provider.BaseColumns._ID;
|
|||
import static android.provider.Downloads.Impl.COLUMN_DESTINATION;
|
||||
import static android.provider.Downloads.Impl.COLUMN_MEDIA_SCANNED;
|
||||
import static android.provider.Downloads.Impl.COLUMN_MIME_TYPE;
|
||||
import static android.provider.Downloads.Impl.COLUMN_OTHER_UID;
|
||||
import static android.provider.Downloads.Impl.DESTINATION_NON_DOWNLOADMANAGER_DOWNLOAD;
|
||||
import static android.provider.Downloads.Impl.PERMISSION_ACCESS_ALL;
|
||||
import static android.provider.Downloads.Impl._DATA;
|
||||
|
||||
import android.app.AppOpsManager;
|
||||
|
@ -99,17 +101,14 @@ public final class DownloadProvider extends ContentProvider {
|
|||
private static final int MY_DOWNLOADS = 1;
|
||||
/** URI matcher constant for the URI of an individual download belonging to the calling UID */
|
||||
private static final int MY_DOWNLOADS_ID = 2;
|
||||
/** URI matcher constant for the URI of all downloads in the system */
|
||||
private static final int ALL_DOWNLOADS = 3;
|
||||
/** URI matcher constant for the URI of an individual download */
|
||||
private static final int ALL_DOWNLOADS_ID = 4;
|
||||
/** URI matcher constant for the URI of a download's request headers */
|
||||
private static final int REQUEST_HEADERS_URI = 5;
|
||||
/** URI matcher constant for the public URI returned by
|
||||
* {@link DownloadManager#getUriForDownloadedFile(long)} if the given downloaded file
|
||||
* is publicly accessible.
|
||||
*/
|
||||
private static final int PUBLIC_DOWNLOAD_ID = 6;
|
||||
private static final int MY_DOWNLOADS_ID_HEADERS = 3;
|
||||
/** URI matcher constant for the URI of all downloads in the system */
|
||||
private static final int ALL_DOWNLOADS = 4;
|
||||
/** URI matcher constant for the URI of an individual download */
|
||||
private static final int ALL_DOWNLOADS_ID = 5;
|
||||
/** URI matcher constant for the URI of a download's request headers */
|
||||
private static final int ALL_DOWNLOADS_ID_HEADERS = 6;
|
||||
static {
|
||||
sURIMatcher.addURI("downloads", "my_downloads", MY_DOWNLOADS);
|
||||
sURIMatcher.addURI("downloads", "my_downloads/#", MY_DOWNLOADS_ID);
|
||||
|
@ -117,19 +116,16 @@ public final class DownloadProvider extends ContentProvider {
|
|||
sURIMatcher.addURI("downloads", "all_downloads/#", ALL_DOWNLOADS_ID);
|
||||
sURIMatcher.addURI("downloads",
|
||||
"my_downloads/#/" + Downloads.Impl.RequestHeaders.URI_SEGMENT,
|
||||
REQUEST_HEADERS_URI);
|
||||
MY_DOWNLOADS_ID_HEADERS);
|
||||
sURIMatcher.addURI("downloads",
|
||||
"all_downloads/#/" + Downloads.Impl.RequestHeaders.URI_SEGMENT,
|
||||
REQUEST_HEADERS_URI);
|
||||
ALL_DOWNLOADS_ID_HEADERS);
|
||||
// temporary, for backwards compatibility
|
||||
sURIMatcher.addURI("downloads", "download", MY_DOWNLOADS);
|
||||
sURIMatcher.addURI("downloads", "download/#", MY_DOWNLOADS_ID);
|
||||
sURIMatcher.addURI("downloads",
|
||||
"download/#/" + Downloads.Impl.RequestHeaders.URI_SEGMENT,
|
||||
REQUEST_HEADERS_URI);
|
||||
sURIMatcher.addURI("downloads",
|
||||
Downloads.Impl.PUBLICLY_ACCESSIBLE_DOWNLOADS_URI_SEGMENT + "/#",
|
||||
PUBLIC_DOWNLOAD_ID);
|
||||
MY_DOWNLOADS_ID_HEADERS);
|
||||
}
|
||||
|
||||
/** Different base URIs that could be used to access an individual download */
|
||||
|
@ -191,43 +187,6 @@ public final class DownloadProvider extends ContentProvider {
|
|||
private int mSystemUid = -1;
|
||||
private int mDefContainerUid = -1;
|
||||
|
||||
/**
|
||||
* This class encapsulates a SQL where clause and its parameters. It makes it possible for
|
||||
* shared methods (like {@link DownloadProvider#getWhereClause(Uri, String, String[], int)})
|
||||
* to return both pieces of information, and provides some utility logic to ease piece-by-piece
|
||||
* construction of selections.
|
||||
*/
|
||||
private static class SqlSelection {
|
||||
public StringBuilder mWhereClause = new StringBuilder();
|
||||
public List<String> mParameters = new ArrayList<String>();
|
||||
|
||||
public <T> void appendClause(String newClause, final T... parameters) {
|
||||
if (newClause == null || newClause.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (mWhereClause.length() != 0) {
|
||||
mWhereClause.append(" AND ");
|
||||
}
|
||||
mWhereClause.append("(");
|
||||
mWhereClause.append(newClause);
|
||||
mWhereClause.append(")");
|
||||
if (parameters != null) {
|
||||
for (Object parameter : parameters) {
|
||||
mParameters.add(parameter.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getSelection() {
|
||||
return mWhereClause.toString();
|
||||
}
|
||||
|
||||
public String[] getParameters() {
|
||||
String[] array = new String[mParameters.size()];
|
||||
return mParameters.toArray(array);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and updated database on demand when opening it.
|
||||
* Helper class to create database the first time the provider is
|
||||
|
@ -526,8 +485,7 @@ public final class DownloadProvider extends ContentProvider {
|
|||
return DOWNLOAD_LIST_TYPE;
|
||||
}
|
||||
case MY_DOWNLOADS_ID:
|
||||
case ALL_DOWNLOADS_ID:
|
||||
case PUBLIC_DOWNLOAD_ID: {
|
||||
case ALL_DOWNLOADS_ID: {
|
||||
// return the mimetype of this id from the database
|
||||
final String id = getDownloadIdFromUri(uri);
|
||||
final SQLiteDatabase db = mOpenHelper.getReadableDatabase();
|
||||
|
@ -942,15 +900,23 @@ public final class DownloadProvider extends ContentProvider {
|
|||
throw new IllegalArgumentException("Unknown URI: " + uri);
|
||||
}
|
||||
|
||||
if (match == REQUEST_HEADERS_URI) {
|
||||
if (match == MY_DOWNLOADS_ID_HEADERS || match == ALL_DOWNLOADS_ID_HEADERS) {
|
||||
if (projection != null || selection != null || sort != null) {
|
||||
throw new UnsupportedOperationException("Request header queries do not support "
|
||||
+ "projections, selections or sorting");
|
||||
}
|
||||
return queryRequestHeaders(db, uri);
|
||||
}
|
||||
|
||||
SqlSelection fullSelection = getWhereClause(uri, selection, selectionArgs, match);
|
||||
// Headers are only available to callers with full access.
|
||||
getContext().enforceCallingOrSelfPermission(
|
||||
Downloads.Impl.PERMISSION_ACCESS_ALL, Constants.TAG);
|
||||
|
||||
final SQLiteQueryBuilder qb = getQueryBuilder(uri, match);
|
||||
projection = new String[] {
|
||||
Downloads.Impl.RequestHeaders.COLUMN_HEADER,
|
||||
Downloads.Impl.RequestHeaders.COLUMN_VALUE
|
||||
};
|
||||
return qb.query(db, projection, null, null, null, null, null);
|
||||
}
|
||||
|
||||
if (shouldRestrictVisibility()) {
|
||||
if (projection == null) {
|
||||
|
@ -978,11 +944,8 @@ public final class DownloadProvider extends ContentProvider {
|
|||
logVerboseQueryInfo(projection, selection, selectionArgs, sort, db);
|
||||
}
|
||||
|
||||
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
|
||||
builder.setTables(DB_TABLE);
|
||||
builder.setStrict(true);
|
||||
Cursor ret = builder.query(db, projection, fullSelection.getSelection(),
|
||||
fullSelection.getParameters(), null, null, sort);
|
||||
final SQLiteQueryBuilder qb = getQueryBuilder(uri, match);
|
||||
final Cursor ret = qb.query(db, projection, selection, selectionArgs, null, null, sort);
|
||||
|
||||
if (ret != null) {
|
||||
ret.setNotificationUri(getContext().getContentResolver(), uri);
|
||||
|
@ -1067,35 +1030,6 @@ public final class DownloadProvider extends ContentProvider {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a query for the custom request headers registered for a download.
|
||||
*/
|
||||
private Cursor queryRequestHeaders(SQLiteDatabase db, Uri uri) {
|
||||
String where = Downloads.Impl.RequestHeaders.COLUMN_DOWNLOAD_ID + "="
|
||||
+ getDownloadIdFromUri(uri);
|
||||
String[] projection = new String[] {Downloads.Impl.RequestHeaders.COLUMN_HEADER,
|
||||
Downloads.Impl.RequestHeaders.COLUMN_VALUE};
|
||||
return db.query(Downloads.Impl.RequestHeaders.HEADERS_DB_TABLE, projection, where,
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete request headers for downloads matching the given query.
|
||||
*/
|
||||
private void deleteRequestHeaders(SQLiteDatabase db, String where, String[] whereArgs) {
|
||||
String[] projection = new String[] {Downloads.Impl._ID};
|
||||
Cursor cursor = db.query(DB_TABLE, projection, where, whereArgs, null, null, null, null);
|
||||
try {
|
||||
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
|
||||
long id = cursor.getLong(0);
|
||||
String idWhere = Downloads.Impl.RequestHeaders.COLUMN_DOWNLOAD_ID + "=" + id;
|
||||
db.delete(Downloads.Impl.RequestHeaders.HEADERS_DB_TABLE, idWhere, null);
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if we should restrict the columns readable by this caller
|
||||
*/
|
||||
|
@ -1178,13 +1112,12 @@ public final class DownloadProvider extends ContentProvider {
|
|||
break;
|
||||
}
|
||||
|
||||
final SqlSelection selection = getWhereClause(uri, where, whereArgs, match);
|
||||
count = db.update(DB_TABLE, filteredValues, selection.getSelection(),
|
||||
selection.getParameters());
|
||||
final SQLiteQueryBuilder qb = getQueryBuilder(uri, match);
|
||||
count = qb.update(db, filteredValues, where, whereArgs);
|
||||
if (updateSchedule || isCompleting) {
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try (Cursor cursor = db.query(DB_TABLE, null, selection.getSelection(),
|
||||
selection.getParameters(), null, null, null)) {
|
||||
try (Cursor cursor = qb.query(db, null, where, whereArgs,
|
||||
null, null, null)) {
|
||||
final DownloadInfo.Reader reader = new DownloadInfo.Reader(resolver,
|
||||
cursor);
|
||||
final DownloadInfo info = new DownloadInfo(context);
|
||||
|
@ -1230,22 +1163,64 @@ public final class DownloadProvider extends ContentProvider {
|
|||
}
|
||||
}
|
||||
|
||||
private SqlSelection getWhereClause(final Uri uri, final String where, final String[] whereArgs,
|
||||
int uriMatch) {
|
||||
SqlSelection selection = new SqlSelection();
|
||||
selection.appendClause(where, whereArgs);
|
||||
if (uriMatch == MY_DOWNLOADS_ID || uriMatch == ALL_DOWNLOADS_ID ||
|
||||
uriMatch == PUBLIC_DOWNLOAD_ID) {
|
||||
selection.appendClause(Downloads.Impl._ID + " = ?", getDownloadIdFromUri(uri));
|
||||
/**
|
||||
* Create a query builder that filters access to the underlying database
|
||||
* based on both the requested {@link Uri} and permissions of the caller.
|
||||
*/
|
||||
private SQLiteQueryBuilder getQueryBuilder(final Uri uri, int match) {
|
||||
final String table;
|
||||
final StringBuilder where = new StringBuilder();
|
||||
switch (match) {
|
||||
// The "my_downloads" view normally limits the caller to operating
|
||||
// on downloads that they either directly own, or have been given
|
||||
// indirect ownership of via OTHER_UID.
|
||||
case MY_DOWNLOADS_ID:
|
||||
appendWhereExpression(where, _ID + "=" + getDownloadIdFromUri(uri));
|
||||
// fall-through
|
||||
case MY_DOWNLOADS:
|
||||
table = DB_TABLE;
|
||||
if (getContext().checkCallingOrSelfPermission(
|
||||
PERMISSION_ACCESS_ALL) != PackageManager.PERMISSION_GRANTED) {
|
||||
appendWhereExpression(where, Constants.UID + "=" + Binder.getCallingUid()
|
||||
+ " OR " + COLUMN_OTHER_UID + "=" + Binder.getCallingUid());
|
||||
}
|
||||
break;
|
||||
|
||||
// The "all_downloads" view is already limited via <path-permission>
|
||||
// to only callers holding the ACCESS_ALL_DOWNLOADS permission, but
|
||||
// access may also be delegated via Uri permission grants.
|
||||
case ALL_DOWNLOADS_ID:
|
||||
appendWhereExpression(where, _ID + "=" + getDownloadIdFromUri(uri));
|
||||
// fall-through
|
||||
case ALL_DOWNLOADS:
|
||||
table = DB_TABLE;
|
||||
break;
|
||||
|
||||
// Headers are limited to callers holding the ACCESS_ALL_DOWNLOADS
|
||||
// permission, since they're only needed for executing downloads.
|
||||
case MY_DOWNLOADS_ID_HEADERS:
|
||||
case ALL_DOWNLOADS_ID_HEADERS:
|
||||
table = Downloads.Impl.RequestHeaders.HEADERS_DB_TABLE;
|
||||
appendWhereExpression(where, Downloads.Impl.RequestHeaders.COLUMN_DOWNLOAD_ID + "="
|
||||
+ getDownloadIdFromUri(uri));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown URI: " + uri);
|
||||
}
|
||||
if ((uriMatch == MY_DOWNLOADS || uriMatch == MY_DOWNLOADS_ID)
|
||||
&& getContext().checkCallingOrSelfPermission(Downloads.Impl.PERMISSION_ACCESS_ALL)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
selection.appendClause(
|
||||
Constants.UID + "= ? OR " + Downloads.Impl.COLUMN_OTHER_UID + "= ?",
|
||||
Binder.getCallingUid(), Binder.getCallingUid());
|
||||
|
||||
final SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
|
||||
qb.setStrict(true);
|
||||
qb.setTables(table);
|
||||
qb.appendWhere(where);
|
||||
return qb;
|
||||
}
|
||||
|
||||
private static void appendWhereExpression(StringBuilder sb, String expression) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(" AND ");
|
||||
}
|
||||
return selection;
|
||||
sb.append('(').append(expression).append(')');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1269,11 +1244,8 @@ public final class DownloadProvider extends ContentProvider {
|
|||
case MY_DOWNLOADS_ID:
|
||||
case ALL_DOWNLOADS:
|
||||
case ALL_DOWNLOADS_ID:
|
||||
final SqlSelection selection = getWhereClause(uri, where, whereArgs, match);
|
||||
deleteRequestHeaders(db, selection.getSelection(), selection.getParameters());
|
||||
|
||||
try (Cursor cursor = db.query(DB_TABLE, null, selection.getSelection(),
|
||||
selection.getParameters(), null, null, null)) {
|
||||
final SQLiteQueryBuilder qb = getQueryBuilder(uri, match);
|
||||
try (Cursor cursor = qb.query(db, null, where, whereArgs, null, null, null)) {
|
||||
final DownloadInfo.Reader reader = new DownloadInfo.Reader(resolver, cursor);
|
||||
final DownloadInfo info = new DownloadInfo(context);
|
||||
while (cursor.moveToNext()) {
|
||||
|
@ -1315,10 +1287,15 @@ public final class DownloadProvider extends ContentProvider {
|
|||
if (!Downloads.Impl.isStatusCompleted(info.mStatus)) {
|
||||
info.sendIntentIfRequested();
|
||||
}
|
||||
|
||||
// Delete any headers for this download
|
||||
db.delete(Downloads.Impl.RequestHeaders.HEADERS_DB_TABLE,
|
||||
Downloads.Impl.RequestHeaders.COLUMN_DOWNLOAD_ID + "=?",
|
||||
new String[] { Long.toString(info.mId) });
|
||||
}
|
||||
}
|
||||
|
||||
count = db.delete(DB_TABLE, selection.getSelection(), selection.getParameters());
|
||||
count = qb.delete(db, where, whereArgs);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
2
android/packages/providers/DownloadProvider/src/com/android/providers/downloads/DownloadThread.java
Normal file → Executable file
2
android/packages/providers/DownloadProvider/src/com/android/providers/downloads/DownloadThread.java
Normal file → Executable file
|
@ -725,7 +725,7 @@ public class DownloadThread extends Thread {
|
|||
if (info.isRoaming() && !mInfo.isRoamingAllowed()) {
|
||||
throw new StopRequestException(STATUS_WAITING_FOR_NETWORK, "Network is roaming");
|
||||
}
|
||||
if (mSystemFacade.isNetworkMetered(mNetwork)
|
||||
if (mSystemFacade.isActiveNetworkMeteredForUid(mInfo.mUid)
|
||||
&& !mInfo.isMeteredAllowed(mInfoDelta.mTotalBytes)) {
|
||||
throw new StopRequestException(STATUS_WAITING_FOR_NETWORK, "Network is metered");
|
||||
}
|
||||
|
|
6
android/packages/providers/DownloadProvider/src/com/android/providers/downloads/RealSystemFacade.java
Normal file → Executable file
6
android/packages/providers/DownloadProvider/src/com/android/providers/downloads/RealSystemFacade.java
Normal file → Executable file
|
@ -67,6 +67,12 @@ class RealSystemFacade implements SystemFacade {
|
|||
.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActiveNetworkMeteredForUid(int uid) {
|
||||
return mContext.getSystemService(ConnectivityManager.class)
|
||||
.isActiveNetworkMeteredForUid(uid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMaxBytesOverMobile() {
|
||||
final Long value = DownloadManager.getMaxBytesOverMobile(mContext);
|
||||
|
|
2
android/packages/providers/DownloadProvider/src/com/android/providers/downloads/SystemFacade.java
Normal file → Executable file
2
android/packages/providers/DownloadProvider/src/com/android/providers/downloads/SystemFacade.java
Normal file → Executable file
|
@ -38,6 +38,8 @@ interface SystemFacade {
|
|||
|
||||
public boolean isNetworkMetered(Network network);
|
||||
|
||||
public boolean isActiveNetworkMeteredForUid(int uid);
|
||||
|
||||
/**
|
||||
* @return maximum size, in bytes, of downloads that may go over a mobile connection; or null if
|
||||
* there's no limit
|
||||
|
|
5
android/packages/providers/DownloadProvider/tests/src/com/android/providers/downloads/FakeSystemFacade.java
Normal file → Executable file
5
android/packages/providers/DownloadProvider/tests/src/com/android/providers/downloads/FakeSystemFacade.java
Normal file → Executable file
|
@ -101,6 +101,11 @@ public class FakeSystemFacade implements SystemFacade {
|
|||
return mIsMetered;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActiveNetworkMeteredForUid(int uid) {
|
||||
return mIsMetered;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMaxBytesOverMobile() {
|
||||
return mMaxBytesOverMobile;
|
||||
|
|
30
android/packages/providers/UserDictionaryProvider/src/com/android/providers/userdictionary/UserDictionaryProvider.java
Normal file → Executable file
30
android/packages/providers/UserDictionaryProvider/src/com/android/providers/userdictionary/UserDictionaryProvider.java
Normal file → Executable file
|
@ -152,6 +152,11 @@ public class UserDictionaryProvider extends ContentProvider {
|
|||
@Override
|
||||
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
|
||||
String sortOrder) {
|
||||
// Only the enabled IMEs and spell checkers can access this provider.
|
||||
if (!canCallerAccessUserDictionary()) {
|
||||
return getEmptyCursorOrThrow(projection);
|
||||
}
|
||||
|
||||
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
|
||||
|
||||
switch (sUriMatcher.match(uri)) {
|
||||
|
@ -170,11 +175,6 @@ public class UserDictionaryProvider extends ContentProvider {
|
|||
throw new IllegalArgumentException("Unknown URI " + uri);
|
||||
}
|
||||
|
||||
// Only the enabled IMEs and spell checkers can access this provider.
|
||||
if (!canCallerAccessUserDictionary()) {
|
||||
return getEmptyCursorOrThrow(projection);
|
||||
}
|
||||
|
||||
// If no sort order is specified use the default
|
||||
String orderBy;
|
||||
if (TextUtils.isEmpty(sortOrder)) {
|
||||
|
@ -257,6 +257,11 @@ public class UserDictionaryProvider extends ContentProvider {
|
|||
|
||||
@Override
|
||||
public int delete(Uri uri, String where, String[] whereArgs) {
|
||||
// Only the enabled IMEs and spell checkers can access this provider.
|
||||
if (!canCallerAccessUserDictionary()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
|
||||
int count;
|
||||
switch (sUriMatcher.match(uri)) {
|
||||
|
@ -274,11 +279,6 @@ public class UserDictionaryProvider extends ContentProvider {
|
|||
throw new IllegalArgumentException("Unknown URI " + uri);
|
||||
}
|
||||
|
||||
// Only the enabled IMEs and spell checkers can access this provider.
|
||||
if (!canCallerAccessUserDictionary()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
getContext().getContentResolver().notifyChange(uri, null);
|
||||
mBackupManager.dataChanged();
|
||||
return count;
|
||||
|
@ -286,6 +286,11 @@ public class UserDictionaryProvider extends ContentProvider {
|
|||
|
||||
@Override
|
||||
public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
|
||||
// Only the enabled IMEs and spell checkers can access this provider.
|
||||
if (!canCallerAccessUserDictionary()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
|
||||
int count;
|
||||
switch (sUriMatcher.match(uri)) {
|
||||
|
@ -303,11 +308,6 @@ public class UserDictionaryProvider extends ContentProvider {
|
|||
throw new IllegalArgumentException("Unknown URI " + uri);
|
||||
}
|
||||
|
||||
// Only the enabled IMEs and spell checkers can access this provider.
|
||||
if (!canCallerAccessUserDictionary()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
getContext().getContentResolver().notifyChange(uri, null);
|
||||
mBackupManager.dataChanged();
|
||||
return count;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue