blob: f7f67eb9a015af8481234e7b11a26d9c18725944 [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.contacts.callblocking;
import android.content.AsyncQueryHandler;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabaseCorruptException;
import android.net.Uri;
import android.provider.BlockedNumberContract.BlockedNumbers;
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
public class FilteredNumberAsyncQueryHandler extends AsyncQueryHandler {
private static final int NO_TOKEN = 0;
public FilteredNumberAsyncQueryHandler(ContentResolver cr) {
super(cr);
}
/**
* Methods for FilteredNumberAsyncQueryHandler result returns.
*/
private static abstract class Listener {
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
}
protected void onInsertComplete(int token, Object cookie, Uri uri) {
}
protected void onUpdateComplete(int token, Object cookie, int result) {
}
protected void onDeleteComplete(int token, Object cookie, int result) {
}
}
public interface OnCheckBlockedListener {
/**
* Invoked after querying if a number is blocked.
* @param id The ID of the row if blocked, null otherwise.
*/
void onCheckComplete(Long id);
}
public interface OnBlockNumberListener {
/**
* Invoked after inserting a blocked number.
* @param uri The uri of the newly created row.
*/
void onBlockComplete(Uri uri);
}
public interface OnUnblockNumberListener {
/**
* Invoked after removing a blocked number
* @param rows The number of rows affected (expected value 1).
* @param values The deleted data (used for restoration).
*/
void onUnblockComplete(int rows, ContentValues values);
}
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
if (cookie != null) {
((Listener) cookie).onQueryComplete(token, cookie, cursor);
}
}
@Override
protected void onInsertComplete(int token, Object cookie, Uri uri) {
if (cookie != null) {
((Listener) cookie).onInsertComplete(token, cookie, uri);
}
}
@Override
protected void onUpdateComplete(int token, Object cookie, int result) {
if (cookie != null) {
((Listener) cookie).onUpdateComplete(token, cookie, result);
}
}
@Override
protected void onDeleteComplete(int token, Object cookie, int result) {
if (cookie != null) {
((Listener) cookie).onDeleteComplete(token, cookie, result);
}
}
/**
* Check if this number has been blocked.
*
* @return {@code false} if the number was invalid and couldn't be checked,
* {@code true} otherwise,
*/
public final boolean isBlockedNumber(
final OnCheckBlockedListener listener, String number, String countryIso) {
final String normalizedNumber = PhoneNumberUtils.formatNumberToE164(number, countryIso);
if (TextUtils.isEmpty(normalizedNumber)) {
return false;
}
startQuery(NO_TOKEN,
new Listener() {
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
if (cursor == null || cursor.getCount() != 1) {
listener.onCheckComplete(null);
return;
}
cursor.moveToFirst();
listener.onCheckComplete(cursor.getLong(
cursor.getColumnIndex(BlockedNumbers.COLUMN_ID)));
}
},
BlockedNumbers.CONTENT_URI,
new String[]{ BlockedNumbers.COLUMN_ID},
BlockedNumbers.COLUMN_E164_NUMBER + " = ?",
new String[]{ normalizedNumber },
null);
return true;
}
public final void blockNumber(
final OnBlockNumberListener listener, String number, String countryIso) {
blockNumber(listener, null, number, countryIso);
}
/**
* Add a number manually blocked by the user.
*/
public final void blockNumber(
final OnBlockNumberListener listener,
String normalizedNumber,
String number,
String countryIso) {
if (normalizedNumber == null) {
normalizedNumber = PhoneNumberUtils.formatNumberToE164(number, countryIso);
}
ContentValues v = new ContentValues();
v.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, number);
v.put(BlockedNumbers.COLUMN_E164_NUMBER, normalizedNumber);
blockNumber(listener, v);
}
/**
* Block a number with specified ContentValues. Can be manually added or a restored row
* from performing the 'undo' action after unblocking.
*/
public final void blockNumber(final OnBlockNumberListener listener, ContentValues values) {
startInsert(NO_TOKEN,
new Listener() {
@Override
public void onInsertComplete(int token, Object cookie, Uri uri) {
if (listener != null ) {
listener.onBlockComplete(uri);
}
}
}, BlockedNumbers.CONTENT_URI, values);
}
/**
* Removes row from database.
* Caller should call {@link FilteredNumberAsyncQueryHandler#startBlockedQuery} first.
* @param id The ID of row to remove, from {@link FilteredNumberAsyncQueryHandler#startBlockedQuery}.
*/
public final void unblock(final OnUnblockNumberListener listener, Integer id) {
if (id == null) {
throw new IllegalArgumentException("Null id passed into unblock");
}
unblock(listener, ContentUris.withAppendedId(BlockedNumbers.CONTENT_URI, id));
}
/**
* Removes row from database.
* @param uri The uri of row to remove, from
* {@link FilteredNumberAsyncQueryHandler#blockNumber}.
*/
public final void unblock(final OnUnblockNumberListener listener, final Uri uri) {
startQuery(NO_TOKEN, new Listener() {
@Override
public void onQueryComplete(int token, Object cookie, Cursor cursor) {
int rowsReturned = cursor == null ? 0 : cursor.getCount();
if (rowsReturned != 1) {
throw new SQLiteDatabaseCorruptException
("Returned " + rowsReturned + " rows for uri "
+ uri + "where 1 expected.");
}
cursor.moveToFirst();
final ContentValues values = new ContentValues();
DatabaseUtils.cursorRowToContentValues(cursor, values);
values.remove(BlockedNumbers.COLUMN_ID);
startDelete(NO_TOKEN, new Listener() {
@Override
public void onDeleteComplete(int token, Object cookie, int result) {
if (listener != null) {
listener.onUnblockComplete(result, values);
}
}
}, uri, null, null);
}
}, uri, null, null, null, null);
}
}