Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cd9d38b7 authored by Marvin W.'s avatar Marvin W. 🐿️
Browse files

Add some wearable APIs and various fixes

parent 3511c413
Loading
Loading
Loading
Loading
Compare 2c847ce6 to f77b09dc
Original line number Diff line number Diff line
Subproject commit 2c847ce6e8ac1604356dc45fd672cfdd6ad4d73b
Subproject commit f77b09dc0c3c750f7c99d901b6e5ced5f17d9465
+1 −1
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ import java.io.File;

public class PeopleServiceImpl extends IPeopleService.Stub {
    private static final String TAG = "GmsPeopleSvcImpl";
    private Context context;
    private final Context context;

    public PeopleServiceImpl(Context context) {
        this.context = context;
+105 −0
Original line number Diff line number Diff line
/*
 * 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.wearable;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import com.google.android.gms.wearable.ConnectionConfiguration;

import java.util.ArrayList;
import java.util.List;

public class ConfigurationDatabaseHelper extends SQLiteOpenHelper {

    public static final String NULL_STRING = "NULL_STRING";

    public ConfigurationDatabaseHelper(Context context) {
        super(context, "connectionconfig.db", null, 2);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE connectionConfigurations (_id INTEGER PRIMARY KEY AUTOINCREMENT,androidId TEXT,name TEXT NOT NULL,pairedBtAddress TEXT NOT NULL,connectionType INTEGER NOT NULL,role INTEGER NOT NULL,connectionEnabled INTEGER NOT NULL,nodeId TEXT, UNIQUE(name) ON CONFLICT REPLACE);");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    private static ConnectionConfiguration configFromCursor(final Cursor cursor) {
        String name = cursor.getString(cursor.getColumnIndex("name"));
        String pairedBtAddress = cursor.getString(cursor.getColumnIndex("pairedBtAddress"));
        int connectionType = cursor.getInt(cursor.getColumnIndex("connectionType"));
        int role = cursor.getInt(cursor.getColumnIndex("role"));
        int enabled = cursor.getInt(cursor.getColumnIndex("connectionEnabled"));
        String nodeId = cursor.getString(cursor.getColumnIndex("nodeId"));
        if (NULL_STRING.equals(name)) name = null;
        if (NULL_STRING.equals(pairedBtAddress)) pairedBtAddress = null;
        return new ConnectionConfiguration(name, pairedBtAddress, connectionType, role, enabled > 0, nodeId);
    }

    public ConnectionConfiguration getConfiguration(String name) {
        Cursor cursor = getReadableDatabase().query("connectionConfigurations", null, "name=?", new String[]{name}, null, null, null);
        ConnectionConfiguration config = null;
        if (cursor != null) {
            if (cursor.moveToNext())
                config = configFromCursor(cursor);
            cursor.close();
        }
        return config;
    }

    public void putConfiguration(ConnectionConfiguration config) {
        ContentValues contentValues = new ContentValues();
        if (config.name != null) {
            contentValues.put("name", config.name);
        } else if (config.role == 2) {
            contentValues.put("name", "server");
        } else {
            contentValues.put("name", "NULL_STRING");
        }
        if (config.address != null) {
            contentValues.put("pairedBtAddress", config.address);
        } else {
            contentValues.put("pairedBtAddress", "NULL_STRING");
        }
        contentValues.put("connectionType", config.type);
        contentValues.put("role", config.role);
        contentValues.put("connectionEnabled", true);
        contentValues.put("nodeId", config.nodeId);
        getWritableDatabase().insert("connectionConfigurations", null, contentValues);
    }

    public ConnectionConfiguration[] getAllConfigurations() {
        Cursor cursor = getReadableDatabase().query("connectionConfigurations", null, null, null, null, null, null);
        if (cursor != null) {
            List<ConnectionConfiguration> configurations = new ArrayList<ConnectionConfiguration>();
            while (cursor.moveToNext()) {
                configurations.add(configFromCursor(cursor));
            }
            cursor.close();
            return configurations.toArray(new ConnectionConfiguration[configurations.size()]);
        } else {
            return null;
        }
    }
}
+107 −0
Original line number Diff line number Diff line
/*
 * 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.wearable;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;

import com.google.android.gms.wearable.Asset;

import java.util.Map;

public class NodeDatabaseHelper extends SQLiteOpenHelper {
    private static final String DB_NAME = "node.db";
    private static final int VERSION = 7;

    public NodeDatabaseHelper(Context context) {
        super(context, DB_NAME, null, VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE appkeys(_id INTEGER PRIMARY KEY AUTOINCREMENT,packageName TEXT NOT NULL,signatureDigest TEXT NOT NULL);");
        db.execSQL("CREATE TABLE dataitems(_id INTEGER PRIMARY KEY AUTOINCREMENT, appkeys_id INTEGER NOT NULL REFERENCES appkeys(_id), host TEXT NOT NULL, path TEXT NOT NULL, seqId INTEGER NOT NULL, deleted INTEGER NOT NULL, sourceNode TEXT NOT NULL, data BLOB, timestampMs INTEGER NOT NULL, assetsPresent INTEGER NOT NULL);");
        db.execSQL("CREATE TABLE assets(digest TEXT PRIMARY KEY, dataPresent INTEGER NOT NULL DEFAULT 0, timestampMs INTEGER NOT NULL);");
        db.execSQL("CREATE TABLE assetrefs(assetname TEXT NOT NULL, dataitems_id INTEGER NOT NULL REFERENCES dataitems(_id), assets_digest TEXT NOT NULL REFERENCES assets(digest));");
        db.execSQL("CREATE TABLE assetsacls(appkeys_id INTEGER NOT NULL REFERENCES appkeys(_id), assets_digest TEXT NOT NULL);");
        db.execSQL("CREATE VIEW appKeyDataItems AS SELECT appkeys._id AS appkeys_id, appkeys.packageName AS packageName, appkeys.signatureDigest AS signatureDigest, dataitems._id AS dataitems_id, dataitems.host AS host, dataitems.path AS path, dataitems.seqId AS seqId, dataitems.deleted AS deleted, dataitems.sourceNode AS sourceNode, dataitems.data AS data, dataitems.timestampMs AS timestampMs, dataitems.assetsPresent AS assetsPresent FROM appkeys, dataitems WHERE appkeys._id=dataitems.appkeys_id");
        db.execSQL("CREATE VIEW appKeyAcls AS SELECT appkeys._id AS appkeys_id, appkeys.packageName AS packageName, appkeys.signatureDigest AS signatureDigest, assetsacls.assets_digest AS assets_digest FROM appkeys, assetsacls WHERE _id=appkeys_id");
        db.execSQL("CREATE VIEW dataItemsAndAssets AS SELECT appKeyDataItems.packageName AS packageName, appKeyDataItems.signatureDigest AS signatureDigest, appKeyDataItems.dataitems_id AS dataitems_id, appKeyDataItems.host AS host, appKeyDataItems.path AS path, appKeyDataItems.seqId AS seqId, appKeyDataItems.deleted AS deleted, appKeyDataItems.sourceNode AS sourceNode, appKeyDataItems.data AS data, appKeyDataItems.timestampMs AS timestampMs, appKeyDataItems.assetsPresent AS assetsPresent, assetrefs.assetname AS assetname, assetrefs.assets_digest AS assets_digest FROM appKeyDataItems LEFT OUTER JOIN assetrefs ON appKeyDataItems.dataitems_id=assetrefs.dataitems_id");
        db.execSQL("CREATE VIEW assetsReadyStatus AS SELECT  dataitems_id AS dataitems_id,  COUNT(*) = SUM(dataPresent) AS nowReady,  assetsPresent AS markedReady FROM assetrefs, dataitems LEFT OUTER JOIN assets ON  assetrefs.assets_digest = assets.digest WHERE assetrefs.dataitems_id=dataitems._id GROUP BY dataitems_id;");
        db.execSQL("CREATE UNIQUE INDEX appkeys_NAME_AND_SIG ON appkeys(packageName,signatureDigest);");
        db.execSQL("CREATE UNIQUE INDEX assetrefs_ASSET_REFS ON assetrefs(assets_digest,dataitems_id,assetname);");
        db.execSQL("CREATE UNIQUE INDEX assets_DIGEST ON assets(digest);");
        db.execSQL("CREATE UNIQUE INDEX assetsacls_APPKEY_AND_DIGEST ON assetsacls(appkeys_id,assets_digest);");
        db.execSQL("CREATE UNIQUE INDEX dataitems_APPKEY_HOST_AND_PATH ON dataitems(appkeys_id,host,path);");
    }

    public Cursor getDataItemsForDataHolder(String packageName, String signatureDigest) {
        return getDataItemsForDataHolderByHostAndPath(packageName, signatureDigest, null, null);
    }

    public Cursor getDataItemsForDataHolderByHostAndPath(String packageName, String signatureDigest, String host, String path) {
        String[] params;
        String selection;
        if (path == null) {
            params = new String[]{packageName, signatureDigest};
            selection = "packageName =? AND signatureDigest =?";
        } else if (host == null) {
            params = new String[]{packageName, signatureDigest, path};
            selection = "packageName =? AND signatureDigest =? AND path =?";
        } else {
            params = new String[]{packageName, signatureDigest, host, path};
            selection = "packageName =? AND signatureDigest =? AND host =? AND path =?";
        }
        selection += " AND deleted=0 AND assetsPresent !=0";
        return getReadableDatabase().rawQuery("SELECT host AS host,path AS path,data AS data,\'\' AS tags,assetname AS asset_key,assets_digest AS asset_id FROM dataItemsAndAssets WHERE " + selection, params);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    private synchronized long getAppKey(String packageName, String signatureDigest) {
        Cursor cursor = getReadableDatabase().rawQuery("SELECT _id FROM appkeys WHERE packageName=? AND signatureDigest=?", new String[]{packageName, signatureDigest});
        if (cursor != null) {
            if (cursor.moveToNext()) {
                return cursor.getLong(0);
            }
            cursor.close();
        }
        ContentValues appKey = new ContentValues();
        appKey.put("packageName", packageName);
        appKey.put("signatureDigest", signatureDigest);
        return getWritableDatabase().insert("appkeys", null, appKey);
    }

    public void putDataItem(String packageName, String signatureDigest, String host, String path, ContentValues data) {
        ContentValues item = new ContentValues(data);
        item.put("appkeys_id", getAppKey(packageName, signatureDigest));
        item.put("host", host);
        item.put("path", path);
        getWritableDatabase().insertWithOnConflict("dataitems", "host", item, SQLiteDatabase.CONFLICT_REPLACE);
    }

    public void deleteDataItem(String packageName, String signatureDigest, String host, String path) {
        getWritableDatabase().delete("dataitems", "packageName=? AND signatureDigest=? AND host=? AND path=?", new String[]{packageName, signatureDigest, host, packageName});
    }
}
+27 −9
Original line number Diff line number Diff line
@@ -16,17 +16,35 @@

package org.microg.gms.wearable;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.os.Binder;
import android.os.RemoteException;

public class WearableService extends Service {
    private static final String TAG = "GmsWearSvc";
import com.google.android.gms.common.internal.GetServiceRequest;
import com.google.android.gms.common.internal.IGmsCallbacks;

import org.microg.gms.BaseService;
import org.microg.gms.common.PackageUtils;
import org.microg.gms.common.Services;

public class WearableService extends BaseService {

    private ConfigurationDatabaseHelper configurationDatabaseHelper;
    private NodeDatabaseHelper nodeDatabaseHelper;

    public WearableService() {
        super("GmsWearSvc", Services.WEARABLE.SERVICE_ID);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        configurationDatabaseHelper = new ConfigurationDatabaseHelper(this);
        nodeDatabaseHelper = new NodeDatabaseHelper(this);
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind: " + intent);
        return null;
    public void handleServiceRequest(IGmsCallbacks callback, GetServiceRequest request) throws RemoteException {
        PackageUtils.checkPackageUid(this, request.packageName, Binder.getCallingUid());
        callback.onPostInitComplete(0, new WearableServiceImpl(this, nodeDatabaseHelper, configurationDatabaseHelper, request.packageName), null);
    }
}
Loading