diff --git a/src/org/microg/gms/gservices/DatabaseHelper.java b/src/org/microg/gms/gservices/DatabaseHelper.java index 5ed712a1..a3857484 100644 --- a/src/org/microg/gms/gservices/DatabaseHelper.java +++ b/src/org/microg/gms/gservices/DatabaseHelper.java @@ -22,6 +22,9 @@ import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; +import java.util.HashMap; +import java.util.Map; + public class DatabaseHelper extends SQLiteOpenHelper { private static final int DB_VERSION = 3; private static final int DB_VERSION_OLD = 1; @@ -70,6 +73,29 @@ public class DatabaseHelper extends SQLiteOpenHelper { return result; } + public Map search(String search) { + Map map = new HashMap<>(); + Cursor cursor = getReadableDatabase().query("overrides", new String[]{"name", "value"}, + "name LIKE ?", new String[]{search}, null, null, null, null); + if (cursor != null) { + while (cursor.moveToNext()) { + map.put(cursor.getString(0), cursor.getString(1)); + } + cursor.close(); + } + cursor = getReadableDatabase().query("main", new String[]{"name", "value"}, + "name LIKE ?", new String[]{search}, null, null, null, null); + if (cursor != null) { + if (cursor.moveToNext()) { + if (!map.containsKey(cursor.getString(0))) + map.put(cursor.getString(0), cursor.getString(1)); + } + cursor.close(); + } + return map; + + } + public void put(String table, ContentValues values) { getWritableDatabase().insertWithOnConflict(table, null, values, SQLiteDatabase.CONFLICT_REPLACE); } diff --git a/src/org/microg/gms/gservices/GServices.java b/src/org/microg/gms/gservices/GServices.java new file mode 100644 index 00000000..0d8a2989 --- /dev/null +++ b/src/org/microg/gms/gservices/GServices.java @@ -0,0 +1,34 @@ +/* + * Copyright 2013-2015 µg Project Team + * + * 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 org.microg.gms.gservices; + +import android.content.ContentResolver; +import android.content.ContentValues; +import android.net.Uri; + +public class GServices { + public static final Uri CONTENT_URI = Uri.parse("content://com.google.android.gsf.gservices"); + public static final Uri MAIN_URI = Uri.parse("content://com.google.android.gsf.gservices/main"); + public static final Uri OVERRIDE_URI = Uri.parse("content://com.google.android.gsf.gservices/override"); + + public static void setString(ContentResolver resolver, String key, String value) { + ContentValues values = new ContentValues(); + values.put("name", key); + values.put("value", value); + resolver.update(MAIN_URI, values, null, null); + } +} diff --git a/src/org/microg/gms/gservices/GServicesProvider.java b/src/org/microg/gms/gservices/GServicesProvider.java index 48ac3dbe..e0f12270 100644 --- a/src/org/microg/gms/gservices/GServicesProvider.java +++ b/src/org/microg/gms/gservices/GServicesProvider.java @@ -25,7 +25,10 @@ import android.os.Build; import android.util.Log; import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; import java.util.Map; +import java.util.Set; /** * Originally found in Google Services Framework (com.google.android.gsf), this provides a generic @@ -35,13 +38,16 @@ import java.util.Map; * if certain "experiments" are enabled on the device. */ public class GServicesProvider extends ContentProvider { - public static final Uri MAIN_URI = Uri.parse("content://com.google.android.gsf.gservices/main"); - public static final Uri OVERRIDE_URI = Uri.parse("content://com.google.android.gsf.gservices/override"); + public static final Uri CONTENT_URI = Uri.parse("content://com.google.android.gsf.gservices/"); + public static final Uri MAIN_URI = Uri.withAppendedPath(CONTENT_URI, "main"); + public static final Uri OVERRIDE_URI = Uri.withAppendedPath(CONTENT_URI, "override"); + public static final Uri PREFIX_URI = Uri.withAppendedPath(CONTENT_URI, "prefix"); private static final String TAG = "GmsServicesProvider"; private DatabaseHelper databaseHelper; private Map cache = new HashMap<>(); + private Set cachedPrefixes = new HashSet<>(); @Override public boolean onCreate() { @@ -60,17 +66,34 @@ public class GServicesProvider extends ContentProvider { @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { MatrixCursor cursor = new MatrixCursor(new String[]{"name", "value"}); - for (String name : selectionArgs) { - String value; - if (cache.containsKey(name)) { - value = cache.get(name); - } else { - value = databaseHelper.get(name); - cache.put(name, value); + if (PREFIX_URI.equals(uri)) { + for (String prefix : selectionArgs) { + if (!cachedPrefixes.contains(prefix)) { + cache.putAll(databaseHelper.search(prefix + "%")); + cachedPrefixes.add(prefix); + } + + for (String name : cache.keySet()) { + if (name.startsWith(prefix)) { + String value = cache.get(name); + Log.d(TAG, "query caller=" + getCallingPackageName() + " name=" + name + " value=" + value); + cursor.addRow(new String[]{name, value}); + } + } } - Log.d(TAG, "query caller=" + getCallingPackageName() + " name=" + name + " value=" + value); - if (value != null) { - cursor.addRow(new String[]{name, value}); + } else { + for (String name : selectionArgs) { + String value; + if (cache.containsKey(name)) { + value = cache.get(name); + } else { + value = databaseHelper.get(name); + cache.put(name, value); + } + Log.d(TAG, "query caller=" + getCallingPackageName() + " name=" + name + " value=" + value); + if (value != null) { + cursor.addRow(new String[]{name, value}); + } } } return cursor; @@ -100,7 +123,10 @@ public class GServicesProvider extends ContentProvider { } else if (uri.equals(OVERRIDE_URI)) { databaseHelper.put("override", values); } - cache.remove(values.getAsString("name")); + String name = values.getAsString("name"); + cache.remove(name); + Iterator iterator = cachedPrefixes.iterator(); + while (iterator.hasNext()) if (name.startsWith(iterator.next())) iterator.remove(); return 1; } }