From c9ec565b4559d71c97649afd94a77258c2494a1f Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Fri, 20 Feb 2015 00:39:04 +0100 Subject: [PATCH] Add basic functionality to GServicesProvider (permission check missing!) --- .../microg/gms/gservices/DatabaseHelper.java | 76 +++++++++++++++++++ .../gms/gservices/GServicesProvider.java | 61 +++++++++++++-- 2 files changed, 131 insertions(+), 6 deletions(-) create mode 100644 src/org/microg/gms/gservices/DatabaseHelper.java diff --git a/src/org/microg/gms/gservices/DatabaseHelper.java b/src/org/microg/gms/gservices/DatabaseHelper.java new file mode 100644 index 00000000..5ed712a1 --- /dev/null +++ b/src/org/microg/gms/gservices/DatabaseHelper.java @@ -0,0 +1,76 @@ +/* + * 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.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; + +public class DatabaseHelper extends SQLiteOpenHelper { + private static final int DB_VERSION = 3; + private static final int DB_VERSION_OLD = 1; + + public DatabaseHelper(Context context) { + super(context, "gservices.db", null, DB_VERSION); + } + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL("CREATE TABLE main (name TEXT PRIMARY KEY, value TEXT)"); + db.execSQL("CREATE TABLE overrides (name TEXT PRIMARY KEY, value TEXT)"); + db.execSQL("CREATE TABLE saved_system (name TEXT PRIMARY KEY, value TEXT)"); + db.execSQL("CREATE TABLE saved_secure (name TEXT PRIMARY KEY, value TEXT)"); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + if (oldVersion == DB_VERSION_OLD) { + db.execSQL("DROP TABLE IF EXISTS main"); + db.execSQL("DROP TABLE IF EXISTS overrides"); + onCreate(db); + } + db.setVersion(newVersion); + } + + public String get(String name) { + String result = null; + Cursor cursor = getReadableDatabase().query("overrides", new String[]{"value"}, "name=?", + new String[]{name}, null, null, null, null); + if (cursor != null) { + if (cursor.moveToNext()) { + result = cursor.getString(0); + } + cursor.close(); + } + if (result != null) return result; + cursor = getReadableDatabase().query("main", new String[]{"value"}, "name=?", + new String[]{name}, null, null, null, null); + if (cursor != null) { + if (cursor.moveToNext()) { + result = cursor.getString(0); + } + cursor.close(); + } + return result; + } + + public void put(String table, ContentValues values) { + getWritableDatabase().insertWithOnConflict(table, null, values, SQLiteDatabase.CONFLICT_REPLACE); + } +} diff --git a/src/org/microg/gms/gservices/GServicesProvider.java b/src/org/microg/gms/gservices/GServicesProvider.java index ad4d0410..48ac3dbe 100644 --- a/src/org/microg/gms/gservices/GServicesProvider.java +++ b/src/org/microg/gms/gservices/GServicesProvider.java @@ -21,17 +21,58 @@ import android.content.ContentValues; import android.database.Cursor; import android.database.MatrixCursor; import android.net.Uri; +import android.os.Build; +import android.util.Log; + +import java.util.HashMap; +import java.util.Map; + +/** + * Originally found in Google Services Framework (com.google.android.gsf), this provides a generic + * key-value store, that is written by the checkin service and read from various Google Apps. + *

+ * Google uses the checkin process to store various device or country specific settings and + * 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"); + + private static final String TAG = "GmsServicesProvider"; + + private DatabaseHelper databaseHelper; + private Map cache = new HashMap<>(); -public class GServicesProvider extends ContentProvider{ @Override public boolean onCreate() { - return false; + databaseHelper = new DatabaseHelper(getContext()); + return true; + } + + private String getCallingPackageName() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + return getCallingPackage(); + } else { + return "unknown"; + } } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { MatrixCursor cursor = new MatrixCursor(new String[]{"name", "value"}); - cursor.addRow(new Object[]{"", null}); + 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; } @@ -42,16 +83,24 @@ public class GServicesProvider extends ContentProvider{ @Override public Uri insert(Uri uri, ContentValues values) { - return null; + throw new UnsupportedOperationException(); } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { - return 0; + throw new UnsupportedOperationException(); } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - return 0; + Log.d(TAG, "update caller=" + getCallingPackageName() + " table=" + uri.getLastPathSegment() + + " name=" + values.getAsString("name") + " value=" + values.getAsString("value")); + if (uri.equals(MAIN_URI)) { + databaseHelper.put("main", values); + } else if (uri.equals(OVERRIDE_URI)) { + databaseHelper.put("override", values); + } + cache.remove(values.getAsString("name")); + return 1; } }