use of android.database.MatrixCursor in project XPrivacy by M66B.
the class XContentResolver method handleUriAfter.
@SuppressLint("DefaultLocale")
private void handleUriAfter(XParam param) throws Throwable {
// Check URI
if (param.args.length > 1 && param.args[0] instanceof Uri && param.getResult() != null) {
String uri = ((Uri) param.args[0]).toString().toLowerCase();
String[] projection = (param.args[1] instanceof String[] ? (String[]) param.args[1] : null);
String selection = (param.args[2] instanceof String ? (String) param.args[2] : null);
Cursor cursor = (Cursor) param.getResult();
if (uri.startsWith("content://applications")) {
// Applications provider: allow selected applications
if (isRestrictedExtra(param, PrivacyManager.cSystem, "ApplicationsProvider", uri)) {
MatrixCursor result = new MatrixCursor(cursor.getColumnNames());
while (cursor.moveToNext()) {
int colPackage = cursor.getColumnIndex("package");
String packageName = (colPackage < 0 ? null : cursor.getString(colPackage));
if (packageName != null && XPackageManager.isPackageAllowed(0, packageName))
copyColumns(cursor, result);
}
result.respond(cursor.getExtras());
param.setResult(result);
cursor.close();
}
} else if (uri.startsWith("content://com.google.android.gsf.gservices")) {
// Google services provider: block only android_id
if (param.args.length > 3 && param.args[3] != null) {
List<String> listSelection = Arrays.asList((String[]) param.args[3]);
if (listSelection.contains("android_id"))
if (isRestrictedExtra(param, PrivacyManager.cIdentification, "GservicesProvider", uri)) {
int ikey = cursor.getColumnIndex("key");
int ivalue = cursor.getColumnIndex("value");
if (ikey == 0 && ivalue == 1 && cursor.getColumnCount() == 2) {
MatrixCursor result = new MatrixCursor(cursor.getColumnNames());
while (cursor.moveToNext()) {
if ("android_id".equals(cursor.getString(ikey)) && cursor.getString(ivalue) != null)
result.addRow(new Object[] { "android_id", PrivacyManager.getDefacedProp(Binder.getCallingUid(), "GSF_ID") });
else
copyColumns(cursor, result);
}
result.respond(cursor.getExtras());
param.setResult(result);
cursor.close();
} else
Util.log(this, Log.ERROR, "Unexpected result uri=" + uri + " columns=" + cursor.getColumnNames());
}
}
} else if (uri.startsWith("content://com.android.contacts/contacts/name_phone_or_email")) {
// Do nothing
} else if (uri.startsWith("content://com.android.contacts/") && !uri.equals("content://com.android.contacts/")) {
// Contacts provider: allow selected contacts
String[] components = uri.replace("content://com.android.", "").split("/");
String methodName = components[0] + "/" + components[1].split("\\?")[0];
if (methodName.equals("contacts/contacts") || methodName.equals("contacts/data") || methodName.equals("contacts/phone_lookup") || methodName.equals("contacts/raw_contacts")) {
if (isRestrictedExtra(param, PrivacyManager.cContacts, methodName, uri)) {
// Get ID from URL if any
int urlid = -1;
if ((methodName.equals("contacts/contacts") || methodName.equals("contacts/phone_lookup")) && components.length > 2 && TextUtils.isDigitsOnly(components[2]))
urlid = Integer.parseInt(components[2]);
// Modify column names back
Object column_added = param.getObjectExtra("column_added");
boolean added = (column_added == null ? false : (Boolean) param.getObjectExtra("column_added"));
List<String> listColumn = new ArrayList<String>();
listColumn.addAll(Arrays.asList(cursor.getColumnNames()));
if (added)
listColumn.remove(listColumn.size() - 1);
// Get blacklist setting
int uid = Binder.getCallingUid();
boolean blacklist = PrivacyManager.getSettingBool(-uid, PrivacyManager.cSettingBlacklist, false);
MatrixCursor result = new MatrixCursor(listColumn.toArray(new String[0]));
// Filter rows
String cid = getIdForUri(uri);
int iid = (cid == null ? -1 : cursor.getColumnIndex(cid));
if (iid >= 0 || urlid >= 0)
while (cursor.moveToNext()) {
// Check if allowed
long id = (urlid >= 0 ? urlid : cursor.getLong(iid));
boolean allowed = PrivacyManager.getSettingBool(-uid, Meta.cTypeContact, Long.toString(id), false);
if (blacklist)
allowed = !allowed;
if (allowed)
copyColumns(cursor, result, listColumn.size());
}
else
Util.log(this, Log.WARN, "ID missing URI=" + uri + " added=" + added + "/" + cid + " columns=" + TextUtils.join(",", cursor.getColumnNames()) + " projection=" + (projection == null ? "null" : TextUtils.join(",", projection)) + " selection=" + selection);
result.respond(cursor.getExtras());
param.setResult(result);
cursor.close();
}
} else {
methodName = null;
if (uri.startsWith("content://com.android.contacts/profile"))
methodName = "contacts/profile";
else
// fall-back
methodName = "ContactsProvider2";
if (methodName != null)
if (isRestrictedExtra(param, PrivacyManager.cContacts, methodName, uri)) {
// Return empty cursor
MatrixCursor result = new MatrixCursor(cursor.getColumnNames());
result.respond(cursor.getExtras());
param.setResult(result);
cursor.close();
}
}
} else {
// Other uri restrictions
String restrictionName = null;
String methodName = null;
if (uri.startsWith("content://browser")) {
restrictionName = PrivacyManager.cBrowser;
methodName = "BrowserProvider2";
} else if (uri.startsWith("content://com.android.calendar")) {
restrictionName = PrivacyManager.cCalendar;
methodName = "CalendarProvider2";
} else if (uri.startsWith("content://call_log")) {
restrictionName = PrivacyManager.cCalling;
methodName = "CallLogProvider";
} else if (uri.startsWith("content://contacts/people")) {
restrictionName = PrivacyManager.cContacts;
methodName = "contacts/people";
} else if (uri.startsWith("content://downloads")) {
restrictionName = PrivacyManager.cBrowser;
methodName = "Downloads";
} else if (uri.startsWith("content://com.android.email.provider")) {
restrictionName = PrivacyManager.cEMail;
methodName = "EMailProvider";
} else if (uri.startsWith("content://com.google.android.gm")) {
restrictionName = PrivacyManager.cEMail;
methodName = "GMailProvider";
} else if (uri.startsWith("content://icc")) {
restrictionName = PrivacyManager.cContacts;
methodName = "IccProvider";
} else if (uri.startsWith("content://mms")) {
restrictionName = PrivacyManager.cMessages;
methodName = "MmsProvider";
} else if (uri.startsWith("content://mms-sms")) {
restrictionName = PrivacyManager.cMessages;
methodName = "MmsSmsProvider";
} else if (uri.startsWith("content://sms")) {
restrictionName = PrivacyManager.cMessages;
methodName = "SmsProvider";
} else if (uri.startsWith("content://telephony")) {
restrictionName = PrivacyManager.cPhone;
methodName = "TelephonyProvider";
} else if (uri.startsWith("content://user_dictionary")) {
restrictionName = PrivacyManager.cDictionary;
methodName = "UserDictionary";
} else if (uri.startsWith("content://com.android.voicemail")) {
restrictionName = PrivacyManager.cMessages;
methodName = "VoicemailContentProvider";
}
// Check if know / restricted
if (restrictionName != null && methodName != null) {
if (isRestrictedExtra(param, restrictionName, methodName, uri)) {
// Return empty cursor
MatrixCursor result = new MatrixCursor(cursor.getColumnNames());
result.respond(cursor.getExtras());
param.setResult(result);
cursor.close();
}
}
}
}
}
use of android.database.MatrixCursor in project Android-Developers-Samples by johnjohndoe.
the class MyCloudProvider method querySearchDocuments.
// END_INCLUDE(query_recent_documents)
// BEGIN_INCLUDE(query_search_documents)
@Override
public Cursor querySearchDocuments(String rootId, String query, String[] projection) throws FileNotFoundException {
Log.v(TAG, "querySearchDocuments");
// Create a cursor with the requested projection, or the default projection.
final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
final File parent = getFileForDocId(rootId);
// This example implementation searches file names for the query and doesn't rank search
// results, so we can stop as soon as we find a sufficient number of matches. Other
// implementations might use other data about files, rather than the file name, to
// produce a match; it might also require a network call to query a remote server.
// Iterate through all files in the file structure under the root until we reach the
// desired number of matches.
final LinkedList<File> pending = new LinkedList<File>();
// Start by adding the parent to the list of files to be processed
pending.add(parent);
// Do while we still have unexamined files, and fewer than the max search results
while (!pending.isEmpty() && result.getCount() < MAX_SEARCH_RESULTS) {
// Take a file from the list of unprocessed files
final File file = pending.removeFirst();
if (file.isDirectory()) {
// If it's a directory, add all its children to the unprocessed list
Collections.addAll(pending, file.listFiles());
} else {
// If it's a file and it matches, add it to the result cursor.
if (file.getName().toLowerCase().contains(query)) {
includeFile(result, null, file);
}
}
}
return result;
}
use of android.database.MatrixCursor in project Android-Developers-Samples by johnjohndoe.
the class MyCloudProvider method queryChildDocuments.
// END_INCLUDE(query_document)
// BEGIN_INCLUDE(query_child_documents)
@Override
public Cursor queryChildDocuments(String parentDocumentId, String[] projection, String sortOrder) throws FileNotFoundException {
Log.v(TAG, "queryChildDocuments, parentDocumentId: " + parentDocumentId + " sortOrder: " + sortOrder);
final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
final File parent = getFileForDocId(parentDocumentId);
for (File file : parent.listFiles()) {
includeFile(result, null, file);
}
return result;
}
use of android.database.MatrixCursor in project Android-Developers-Samples by johnjohndoe.
the class MyCloudProvider method includeFile.
/**
* Add a representation of a file to a cursor.
*
* @param result the cursor to modify
* @param docId the document ID representing the desired file (may be null if given file)
* @param file the File object representing the desired file (may be null if given docID)
* @throws java.io.FileNotFoundException
*/
private void includeFile(MatrixCursor result, String docId, File file) throws FileNotFoundException {
if (docId == null) {
docId = getDocIdForFile(file);
} else {
file = getFileForDocId(docId);
}
int flags = 0;
if (file.isDirectory()) {
// Add FLAG_DIR_SUPPORTS_CREATE if the file is a writable directory.
if (file.isDirectory() && file.canWrite()) {
flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
}
} else if (file.canWrite()) {
// If the file is writable set FLAG_SUPPORTS_WRITE and
// FLAG_SUPPORTS_DELETE
flags |= Document.FLAG_SUPPORTS_WRITE;
flags |= Document.FLAG_SUPPORTS_DELETE;
}
final String displayName = file.getName();
final String mimeType = getTypeForFile(file);
if (mimeType.startsWith("image/")) {
// Allow the image to be represented by a thumbnail rather than an icon
flags |= Document.FLAG_SUPPORTS_THUMBNAIL;
}
final MatrixCursor.RowBuilder row = result.newRow();
row.add(Document.COLUMN_DOCUMENT_ID, docId);
row.add(Document.COLUMN_DISPLAY_NAME, displayName);
row.add(Document.COLUMN_SIZE, file.length());
row.add(Document.COLUMN_MIME_TYPE, mimeType);
row.add(Document.COLUMN_LAST_MODIFIED, file.lastModified());
row.add(Document.COLUMN_FLAGS, flags);
// Add a custom icon
row.add(Document.COLUMN_ICON, R.drawable.ic_launcher);
}
use of android.database.MatrixCursor in project Android-Developers-Samples by johnjohndoe.
the class MyCloudProvider method queryRecentDocuments.
// END_INCLUDE(query_roots)
// BEGIN_INCLUDE(query_recent_documents)
@Override
public Cursor queryRecentDocuments(String rootId, String[] projection) throws FileNotFoundException {
Log.v(TAG, "queryRecentDocuments");
// This example implementation walks a local file structure to find the most recently
// modified files. Other implementations might include making a network call to query a
// server.
// Create a cursor with the requested projection, or the default projection.
final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
final File parent = getFileForDocId(rootId);
// Create a queue to store the most recent documents, which orders by last modified.
PriorityQueue<File> lastModifiedFiles = new PriorityQueue<File>(5, new Comparator<File>() {
public int compare(File i, File j) {
return Long.compare(i.lastModified(), j.lastModified());
}
});
// Iterate through all files and directories in the file structure under the root. If
// the file is more recent than the least recently modified, add it to the queue,
// limiting the number of results.
final LinkedList<File> pending = new LinkedList<File>();
// Start by adding the parent to the list of files to be processed
pending.add(parent);
// Do while we still have unexamined files
while (!pending.isEmpty()) {
// Take a file from the list of unprocessed files
final File file = pending.removeFirst();
if (file.isDirectory()) {
// If it's a directory, add all its children to the unprocessed list
Collections.addAll(pending, file.listFiles());
} else {
// If it's a file, add it to the ordered queue.
lastModifiedFiles.add(file);
}
}
// Add the most recent files to the cursor, not exceeding the max number of results.
for (int i = 0; i < Math.min(MAX_LAST_MODIFIED + 1, lastModifiedFiles.size()); i++) {
final File file = lastModifiedFiles.remove();
includeFile(result, null, file);
}
return result;
}
Aggregations