diff --git a/extern/GmsApi b/extern/GmsApi
index cf2927f2..417ec258 160000
--- a/extern/GmsApi
+++ b/extern/GmsApi
@@ -1 +1 @@
-Subproject commit cf2927f275c53099781dbf965acb7c7f8ed36e97
+Subproject commit 417ec2585f085c5a599e45aa9ee3b3df6239c628
diff --git a/extern/Wearable b/extern/Wearable
index 796c8b6b..853f0382 160000
--- a/extern/Wearable
+++ b/extern/Wearable
@@ -1 +1 @@
-Subproject commit 796c8b6b87d564e3bc2e5000c6d4ed348c606083
+Subproject commit 853f0382b960fcfcad8d7d3655d7963a58095069
diff --git a/play-services-core/src/main/AndroidManifest.xml b/play-services-core/src/main/AndroidManifest.xml
index 1d967e60..87a1909a 100644
--- a/play-services-core/src/main/AndroidManifest.xml
+++ b/play-services-core/src/main/AndroidManifest.xml
@@ -129,6 +129,14 @@
+
+
+
+
+
+
getAssets() {
return Collections.unmodifiableMap(new HashMap(assets));
}
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("DataItemInternal{");
+ sb.append("uri=").append(uri);
+ sb.append('}');
+ return sb.toString();
+ }
}
diff --git a/play-services-core/src/main/java/org/microg/gms/wearable/DataItemRecord.java b/play-services-core/src/main/java/org/microg/gms/wearable/DataItemRecord.java
index 9c8d85ce..af1b9294 100644
--- a/play-services-core/src/main/java/org/microg/gms/wearable/DataItemRecord.java
+++ b/play-services-core/src/main/java/org/microg/gms/wearable/DataItemRecord.java
@@ -19,6 +19,7 @@ package org.microg.gms.wearable;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
+import android.util.Log;
import com.google.android.gms.common.data.DataHolder;
import com.google.android.gms.wearable.Asset;
diff --git a/play-services-core/src/main/java/org/microg/gms/wearable/MessageHandler.java b/play-services-core/src/main/java/org/microg/gms/wearable/MessageHandler.java
index 7da789ff..d2d0212e 100644
--- a/play-services-core/src/main/java/org/microg/gms/wearable/MessageHandler.java
+++ b/play-services-core/src/main/java/org/microg/gms/wearable/MessageHandler.java
@@ -44,7 +44,7 @@ import java.util.Arrays;
public class MessageHandler extends ServerMessageListener {
private static final String TAG = "GmsWearMsgHandler";
private final WearableImpl wearable;
- private final String thisNodeId;
+ private final String oldConfigNodeId;
private String peerNodeId;
public MessageHandler(WearableImpl wearable, ConnectionConfiguration config) {
@@ -54,28 +54,28 @@ public class MessageHandler extends ServerMessageListener {
private MessageHandler(WearableImpl wearable, ConnectionConfiguration config, String name, String networkId, long androidId) {
super(new Connect.Builder()
.name(name)
- .id(config.nodeId)
+ .id(wearable.getLocalNodeId())
.networkId(networkId)
.peerAndroidId(androidId)
.unknown4(3)
.peerVersion(1)
.build());
this.wearable = wearable;
- this.thisNodeId = config.nodeId;
+ this.oldConfigNodeId = config.nodeId;
}
@Override
public void onConnect(Connect connect) {
super.onConnect(connect);
peerNodeId = connect.id;
- wearable.onConnectReceived(getConnection(), thisNodeId, connect);
+ wearable.onConnectReceived(getConnection(), oldConfigNodeId, connect);
try {
getConnection().writeMessage(new RootMessage.Builder().syncStart(new SyncStart.Builder()
.receivedSeqId(-1L)
.version(2)
.syncTable(Arrays.asList(
new SyncTableEntry.Builder().key("cloud").value(1L).build(),
- new SyncTableEntry.Builder().key(thisNodeId).value(wearable.getCurrentSeqId(thisNodeId)).build(), // TODO
+ new SyncTableEntry.Builder().key(wearable.getLocalNodeId()).value(wearable.getCurrentSeqId(wearable.getLocalNodeId())).build(), // TODO
new SyncTableEntry.Builder().key(peerNodeId).value(wearable.getCurrentSeqId(peerNodeId)).build() // TODO
)).build()).build());
} catch (IOException e) {
@@ -85,7 +85,10 @@ public class MessageHandler extends ServerMessageListener {
@Override
public void onDisconnected() {
- wearable.onDisconnectReceived(getConnection(), thisNodeId, getRemoteConnect());
+ Connect connect = getRemoteConnect();
+ if (connect == null)
+ connect = new Connect.Builder().id(oldConfigNodeId).name("Wear device").build();
+ wearable.onDisconnectReceived(getConnection(), connect);
super.onDisconnected();
}
@@ -120,13 +123,13 @@ public class MessageHandler extends ServerMessageListener {
boolean hasLocalNode = false;
if (syncStart.syncTable != null) {
for (SyncTableEntry entry : syncStart.syncTable) {
- wearable.syncToPeer(getConnection(), entry.key, entry.value);
+ wearable.syncToPeer(peerNodeId, entry.key, entry.value);
if (wearable.getLocalNodeId().equals(entry.key)) hasLocalNode = true;
}
} else {
Log.d(TAG, "No sync table given.");
}
- if (!hasLocalNode) wearable.syncToPeer(getConnection(), wearable.getLocalNodeId(), 0);
+ if (!hasLocalNode) wearable.syncToPeer(peerNodeId, wearable.getLocalNodeId(), 0);
}
@Override
@@ -138,7 +141,7 @@ public class MessageHandler extends ServerMessageListener {
@Override
public void onRpcRequest(Request rpcRequest) {
Log.d(TAG, "onRpcRequest: " + rpcRequest);
- if (TextUtils.isEmpty(rpcRequest.targetNodeId) || rpcRequest.targetNodeId.equals(thisNodeId)) {
+ if (TextUtils.isEmpty(rpcRequest.targetNodeId) || rpcRequest.targetNodeId.equals(wearable.getLocalNodeId())) {
MessageEventParcelable messageEvent = new MessageEventParcelable();
messageEvent.data = rpcRequest.rawData != null ? rpcRequest.rawData.toByteArray() : null;
messageEvent.path = rpcRequest.path;
diff --git a/play-services-core/src/main/java/org/microg/gms/wearable/NodeDatabaseHelper.java b/play-services-core/src/main/java/org/microg/gms/wearable/NodeDatabaseHelper.java
index 9ea6f3e9..dfef5bfc 100644
--- a/play-services-core/src/main/java/org/microg/gms/wearable/NodeDatabaseHelper.java
+++ b/play-services-core/src/main/java/org/microg/gms/wearable/NodeDatabaseHelper.java
@@ -22,6 +22,7 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.text.TextUtils;
+import android.util.Log;
import com.google.android.gms.wearable.Asset;
@@ -73,18 +74,25 @@ public class NodeDatabaseHelper extends SQLiteOpenHelper {
String selection;
if (path == null) {
params = new String[]{packageName, signatureDigest};
- selection = "packageName =? AND signatureDigest =?";
+ selection = "packageName = ? AND signatureDigest = ?";
} else if (host == null) {
+ if (path.endsWith("/")) path = path + "%";
params = new String[]{packageName, signatureDigest, path};
- selection = "packageName =? AND signatureDigest =? AND path =?";
+ selection = "packageName = ? AND signatureDigest = ? AND path LIKE ?";
} else {
+ if (path.endsWith("/")) path = path + "%";
params = new String[]{packageName, signatureDigest, host, path};
- selection = "packageName =? AND signatureDigest =? AND host =? AND path =?";
+ selection = "packageName = ? AND signatureDigest = ? AND host = ? AND path LIKE ?";
}
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);
}
+ public synchronized Cursor getDataItemsByHostAndPath(String packageName, String signatureDigest, String host, String path) {
+ Log.d(TAG, "getDataItemsByHostAndPath: " + packageName + ", " + signatureDigest + ", " + host + ", " + path);
+ return getDataItemsByHostAndPath(getReadableDatabase(), packageName, signatureDigest, host, path);
+ }
+
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion != VERSION) {
@@ -240,7 +248,7 @@ public class NodeDatabaseHelper extends SQLiteOpenHelper {
return res;
}
- public void putAsset(Asset asset, boolean dataPresent) {
+ public synchronized void putAsset(Asset asset, boolean dataPresent) {
ContentValues cv = new ContentValues();
cv.put("digest", asset.getDigest());
cv.put("dataPresent", dataPresent ? 1 : 0);
@@ -248,11 +256,39 @@ public class NodeDatabaseHelper extends SQLiteOpenHelper {
getWritableDatabase().insertWithOnConflict("assets", null, cv, SQLiteDatabase.CONFLICT_REPLACE);
}
- public void allowAssetAccess(String digest, String packageName, String signatureDigest) {
+ public synchronized void allowAssetAccess(String digest, String packageName, String signatureDigest) {
SQLiteDatabase db = getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put("assets_digest", digest);
cv.put("appkeys_id", getAppKey(db, packageName, signatureDigest));
- db.insert("assetsacls", null, cv);
+ db.insertWithOnConflict("assetsacls", null, cv, SQLiteDatabase.CONFLICT_REPLACE);
+ }
+
+ public Cursor listMissingAssets() {
+ return getReadableDatabase().query("dataItemsAndAssets", GDIBHAP_FIELDS, "assetsPresent = 0 AND assets_digest NOT NULL", null, null, null, "packageName, signatureDigest, host, path");
+ }
+
+ public boolean hasAsset(Asset asset) {
+ Cursor cursor = getReadableDatabase().query("assets", new String[]{"dataPresent"}, "digest=?", new String[]{asset.getDigest()}, null, null, null);
+ if (cursor == null) return false;
+ try {
+ return (cursor.moveToNext() && cursor.getInt(0) == 1);
+ } finally {
+ cursor.close();
+ }
+ }
+
+ public synchronized void markAssetAsPresent(String digest) {
+ ContentValues cv = new ContentValues();
+ cv.put("dataPresent", 1);
+ SQLiteDatabase db = getWritableDatabase();
+ db.update("assets", cv, "digest=?", new String[]{digest});
+ Cursor status = db.query("assetsReadyStatus", null, "nowReady != markedReady", null, null, null, null);
+ while (status.moveToNext()) {
+ cv = new ContentValues();
+ cv.put("assetsPresent", status.getInt(status.getColumnIndex("nowReady")));
+ db.update("dataitems", cv, "_id=?", new String[]{Integer.toString(status.getInt(status.getColumnIndex("dataitems_id")))});
+ }
+ status.close();
}
}
diff --git a/play-services-core/src/main/java/org/microg/gms/wearable/RpcHelper.java b/play-services-core/src/main/java/org/microg/gms/wearable/RpcHelper.java
new file mode 100644
index 00000000..b3746029
--- /dev/null
+++ b/play-services-core/src/main/java/org/microg/gms/wearable/RpcHelper.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2013-2016 microG 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.Context;
+import android.content.SharedPreferences;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class RpcHelper {
+ private final Map rpcStateMap = new HashMap();
+ private final SharedPreferences preferences;
+ private final Context context;
+
+ public RpcHelper(Context context) {
+ this.context = context;
+ this.preferences = context.getSharedPreferences("wearable.rpc_service.settings", 0);
+ }
+
+ private String getRpcConnectionId(String packageName, String targetNodeId, String path) {
+ String mode = "lo";
+ if (packageName.equals("com.google.android.wearable.app") && path.startsWith("/s3"))
+ mode = "hi";
+ return targetNodeId + ":" + mode;
+ }
+
+ public RpcHelper.RpcConnectionState useConnectionState(String packageName, String targetNodeId, String path) {
+ String rpcConnectionId = getRpcConnectionId(packageName, targetNodeId, path);
+ synchronized (rpcStateMap) {
+ if (!rpcStateMap.containsKey(rpcConnectionId)) {
+ int g = preferences.getInt(rpcConnectionId, 1)+1;
+ preferences.edit().putInt(rpcConnectionId, g).apply();
+ rpcStateMap.put(rpcConnectionId, new RpcConnectionState(g));
+ }
+ RpcHelper.RpcConnectionState res = rpcStateMap.get(rpcConnectionId);
+ res.lastRequestId++;
+ return res.freeze();
+ }
+ }
+
+ public static class RpcConnectionState {
+ public int generation;
+ public int lastRequestId;
+
+ public RpcConnectionState(int generation) {
+ this.generation = generation;
+ }
+
+ public RpcConnectionState freeze() {
+ RpcConnectionState res = new RpcConnectionState(generation);
+ res.lastRequestId = lastRequestId;
+ return res;
+ }
+ }
+}
diff --git a/play-services-core/src/main/java/org/microg/gms/wearable/WearableImpl.java b/play-services-core/src/main/java/org/microg/gms/wearable/WearableImpl.java
index 249da20d..d50539f5 100644
--- a/play-services-core/src/main/java/org/microg/gms/wearable/WearableImpl.java
+++ b/play-services-core/src/main/java/org/microg/gms/wearable/WearableImpl.java
@@ -44,7 +44,9 @@ import org.microg.wearable.proto.AckAsset;
import org.microg.wearable.proto.AppKey;
import org.microg.wearable.proto.AppKeys;
import org.microg.wearable.proto.Connect;
+import org.microg.wearable.proto.FetchAsset;
import org.microg.wearable.proto.FilePiece;
+import org.microg.wearable.proto.Request;
import org.microg.wearable.proto.RootMessage;
import org.microg.wearable.proto.SetAsset;
@@ -76,7 +78,8 @@ public class WearableImpl {
private final ConfigurationDatabaseHelper configDatabase;
private final Map> listeners = new HashMap>();
private final Set connectedNodes = new HashSet();
- private final Set activeConnections = new HashSet();
+ private final Map activeConnections = new HashMap();
+ private RpcHelper rpcHelper;
private SocketConnectionThread sct;
private ConnectionConfiguration[] configurations;
private boolean configurationsUpdated = false;
@@ -87,6 +90,7 @@ public class WearableImpl {
this.nodeDatabase = nodeDatabase;
this.configDatabase = configDatabase;
this.clockworkNodePreferences = new ClockworkNodePreferences(context);
+ this.rpcHelper = new RpcHelper(context);
}
public String getLocalNodeId() {
@@ -108,6 +112,13 @@ public class WearableImpl {
public DataItemRecord putDataItem(DataItemRecord record) {
nodeDatabase.putRecord(record);
+ if (!record.assetsAreReady) {
+ for (Asset asset : record.dataItem.getAssets().values()) {
+ if (!nodeDatabase.hasAsset(asset)) {
+ Log.d(TAG, "Asset is missing: " + asset);
+ }
+ }
+ }
try {
getListener(record.packageName, "com.google.android.gms.wearable.DATA_CHANGED", record.dataItem.uri)
.onDataChanged(record.toEventDataHolder());
@@ -151,7 +162,7 @@ public class WearableImpl {
return null;
}
- private File createAssetFile(String digest) {
+ public File createAssetFile(String digest) {
File dir = new File(new File(context.getFilesDir(), "assets"), digest.substring(digest.length() - 2));
dir.mkdirs();
return new File(dir, digest + ".asset");
@@ -183,6 +194,7 @@ public class WearableImpl {
if (newConfiguration.name.equals(configuration.name)) {
newConfiguration.connected = configuration.connected;
newConfiguration.peerNodeId = configuration.peerNodeId;
+ newConfiguration.nodeId = configuration.nodeId;
break;
}
}
@@ -211,52 +223,50 @@ public class WearableImpl {
return context;
}
- public void syncToPeer(WearableConnection connection, String nodeId, long seqId) {
- Log.d(TAG, "-- Start syncing over " + connection + ", nodeId " + nodeId + " starting with seqId " + seqId);
+ public void syncToPeer(String peerNodeId, String nodeId, long seqId) {
+ Log.d(TAG, "-- Start syncing over to " + peerNodeId + ", nodeId " + nodeId + " starting with seqId " + seqId);
Cursor cursor = nodeDatabase.getModifiedDataItems(nodeId, seqId, true);
if (cursor != null) {
while (cursor.moveToNext()) {
- if (!syncRecordToPeer(connection, DataItemRecord.fromCursor(cursor))) break;
+ if (!syncRecordToPeer(peerNodeId, DataItemRecord.fromCursor(cursor))) break;
}
cursor.close();
}
- Log.d(TAG, "-- Done syncing over " + connection + ", nodeId " + nodeId + " starting with seqId " + seqId);
+ Log.d(TAG, "-- Done syncing over to " + peerNodeId + ", nodeId " + nodeId + " starting with seqId " + seqId);
}
private void syncRecordToAll(DataItemRecord record) {
Log.d(TAG, "Syncing record " + record + " over " + activeConnections.size() + " connections.");
- for (WearableConnection connection : new ArrayList(activeConnections)) {
- if (!syncRecordToPeer(connection, record)) {
- Log.d(TAG, "Removing connection as it seems not usable: " + connection);
- activeConnections.remove(connection);
- }
+ for (String nodeId : new ArrayList(activeConnections.keySet())) {
+ syncRecordToPeer(nodeId, record);
}
}
- private boolean syncRecordToPeer(WearableConnection connection, DataItemRecord record) {
+ private boolean syncRecordToPeer(String nodeId, DataItemRecord record) {
for (Asset asset : record.dataItem.getAssets().values()) {
- syncAssetToPeer(connection, record, asset);
+ syncAssetToPeer(nodeId, record, asset);
}
- Log.d(TAG, "Sync over " + connection + ": " + record);
+ Log.d(TAG, "Sync over to " + nodeId + ": " + record);
try {
- connection.writeMessage(new RootMessage.Builder().setDataItem(record.toSetDataItem()).build());
+ activeConnections.get(nodeId).writeMessage(new RootMessage.Builder().setDataItem(record.toSetDataItem()).build());
} catch (IOException e) {
+ closeConnection(nodeId);
Log.w(TAG, e);
return false;
}
return true;
}
- private void syncAssetToPeer(WearableConnection connection, DataItemRecord record, Asset asset) {
+ private void syncAssetToPeer(String nodeId, DataItemRecord record, Asset asset) {
try {
- Log.d(TAG, "Sync over " + connection + ": " + asset);
+ Log.d(TAG, "Sync over to " + nodeId + ": " + asset);
RootMessage announceMessage = new RootMessage.Builder().setAsset(new SetAsset.Builder()
.digest(asset.getDigest())
.appkeys(new AppKeys(Collections.singletonList(new AppKey(record.packageName, record.signatureDigest))))
.build()).hasAsset(true).build();
- connection.writeMessage(announceMessage);
+ activeConnections.get(nodeId).writeMessage(announceMessage);
File assetFile = createAssetFile(asset.getDigest());
String fileName = calculateDigest(announceMessage.toByteArray());
FileInputStream fis = new FileInputStream(assetFile);
@@ -265,15 +275,16 @@ public class WearableImpl {
int c = 0;
while ((c = fis.read(arr)) > 0) {
if (lastPiece != null) {
- Log.d(TAG, "Sync over " + connection + ": Asset piece for fileName " + fileName + ": " + lastPiece);
- connection.writeMessage(new RootMessage.Builder().filePiece(new FilePiece(fileName, false, lastPiece, null)).build());
+ Log.d(TAG, "Sync over to " + nodeId + ": Asset piece for fileName " + fileName + ": " + lastPiece);
+ activeConnections.get(nodeId).writeMessage(new RootMessage.Builder().filePiece(new FilePiece(fileName, false, lastPiece, null)).build());
}
lastPiece = ByteString.of(arr, 0, c);
}
- Log.d(TAG, "Sync over " + connection + ": Last asset piece for fileName " + fileName + ": " + lastPiece);
- connection.writeMessage(new RootMessage.Builder().filePiece(new FilePiece(fileName, true, lastPiece, asset.getDigest())).build());
+ Log.d(TAG, "Sync over to " + nodeId + ": Last asset piece for fileName " + fileName + ": " + lastPiece);
+ activeConnections.get(nodeId).writeMessage(new RootMessage.Builder().filePiece(new FilePiece(fileName, true, lastPiece, asset.getDigest())).build());
} catch (IOException e) {
Log.w(TAG, e);
+ closeConnection(nodeId);
}
}
@@ -303,7 +314,7 @@ public class WearableImpl {
String digest = calculateDigest(Utils.readStreamToEnd(new FileInputStream(file)));
if (digest.equals(finalPieceDigest)) {
if (file.renameTo(createAssetFile(digest))) {
- // TODO: Mark as stored in db
+ nodeDatabase.markAssetAsPresent(digest);
connection.writeMessage(new RootMessage.Builder().ackAsset(new AckAsset(digest)).build());
} else {
Log.w(TAG, "Could not rename to target file name. delete=" + file.delete());
@@ -320,23 +331,47 @@ public class WearableImpl {
public void onConnectReceived(WearableConnection connection, String nodeId, Connect connect) {
for (ConnectionConfiguration config : getConfigurations()) {
if (config.nodeId.equals(nodeId)) {
+ if (config.nodeId != nodeId) {
+ config.nodeId = connect.id;
+ configDatabase.putConfiguration(config, nodeId);
+ }
config.peerNodeId = connect.id;
config.connected = true;
}
}
- Log.d(TAG, "Adding connection to list of open connections: " + connection);
- activeConnections.add(connection);
+ Log.d(TAG, "Adding connection to list of open connections: " + connection + " with connect " + connect);
+ activeConnections.put(connect.id, connection);
onPeerConnected(new NodeParcelable(connect.id, connect.name));
+ // Fetch missing assets
+ Cursor cursor = nodeDatabase.listMissingAssets();
+ if (cursor != null) {
+ while (cursor.moveToNext()) {
+ try {
+ Log.d(TAG, "Fetch for " + cursor.getString(12));
+ connection.writeMessage(new RootMessage.Builder()
+ .fetchAsset(new FetchAsset.Builder()
+ .assetName(cursor.getString(12))
+ .packageName(cursor.getString(1))
+ .signatureDigest(cursor.getString(2))
+ .permission(false)
+ .build()).build());
+ } catch (IOException e) {
+ Log.w(TAG, e);
+ closeConnection(connect.id);
+ }
+ }
+ cursor.close();
+ }
}
- public void onDisconnectReceived(WearableConnection connection, String nodeId, Connect connect) {
+ public void onDisconnectReceived(WearableConnection connection, Connect connect) {
for (ConnectionConfiguration config : getConfigurations()) {
- if (config.nodeId.equals(nodeId)) {
+ if (config.nodeId.equals(connect.id)) {
config.connected = false;
}
}
Log.d(TAG, "Removing connection from list of open connections: " + connection);
- activeConnections.remove(connection);
+ activeConnections.remove(connect.id);
onPeerDisconnected(new NodeParcelable(connect.id, connect.name));
}
@@ -421,7 +456,7 @@ public class WearableImpl {
}
dataHolderItems.moveToFirst();
dataHolderItems.moveToPrevious();
- return DataHolder.fromCursor(dataHolderItems, 0, null);
+ return new DataHolder(dataHolderItems, 0, null);
}
public DataHolder getDataItemForRecordAsHolder(DataItemRecord record) {
@@ -431,7 +466,7 @@ public class WearableImpl {
}
dataHolderItems.moveToFirst();
dataHolderItems.moveToPrevious();
- return DataHolder.fromCursor(dataHolderItems, 0, null);
+ return new DataHolder(dataHolderItems, 0, null);
}
public synchronized void addListener(String packageName, IWearableListener listener) {
@@ -451,6 +486,7 @@ public class WearableImpl {
configDatabase.setEnabledState(name, true);
configurationsUpdated = true;
if (name.equals("server") && sct == null) {
+ Log.d(TAG, "Starting server on :" + WEAR_TCP_PORT);
(sct = SocketConnectionThread.serverListen(WEAR_TCP_PORT, new MessageHandler(this, configDatabase.getConfiguration(name)))).start();
}
}
@@ -497,7 +533,7 @@ public class WearableImpl {
}
public DataItemRecord getDataItemByUri(Uri uri, String packageName) {
- Cursor cursor = nodeDatabase.getDataItemsForDataHolderByHostAndPath(packageName, PackageUtils.firstSignatureDigest(context, packageName), uri.getHost(), uri.getPath());
+ Cursor cursor = nodeDatabase.getDataItemsByHostAndPath(packageName, PackageUtils.firstSignatureDigest(context, packageName), uri.getHost(), uri.getPath());
DataItemRecord record = null;
if (cursor != null) {
if (cursor.moveToNext()) {
@@ -505,6 +541,7 @@ public class WearableImpl {
}
cursor.close();
}
+ Log.d(TAG, "getDataItem: " + record);
return record;
}
@@ -522,7 +559,49 @@ public class WearableImpl {
}
}
- public void sendMessage(String targetNodeId, String path, byte[] data) {
- Log.d(TAG, "sendMessage not yet implemented!");
+ private void closeConnection(String nodeId) {
+ WearableConnection connection = activeConnections.get(nodeId);
+ try {
+ connection.close();
+ } catch (IOException e1) {
+ Log.w(TAG, e1);
+ }
+ if (connection == sct.getWearableConnection()) {
+ sct.close();
+ sct = null;
+ }
+ activeConnections.remove(nodeId);
+ for (ConnectionConfiguration config : getConfigurations()) {
+ if (config.nodeId.equals(nodeId) || config.peerNodeId.equals(nodeId)) {
+ config.connected = false;
+ }
+ }
+ onPeerDisconnected(new NodeParcelable(nodeId, "Wear device"));
+ Log.d(TAG, "Closed connection to " + nodeId + " on error");
+ }
+
+ public int sendMessage(String packageName, String targetNodeId, String path, byte[] data) {
+ if (activeConnections.containsKey(targetNodeId)) {
+ WearableConnection connection = activeConnections.get(targetNodeId);
+ RpcHelper.RpcConnectionState state = rpcHelper.useConnectionState(packageName, targetNodeId, path);
+ try {
+ connection.writeMessage(new RootMessage.Builder().rpcRequest(new Request.Builder()
+ .targetNodeId(targetNodeId)
+ .path(path)
+ .rawData(ByteString.of(data))
+ .packageName(packageName)
+ .signatureDigest(PackageUtils.firstSignatureDigest(context, packageName))
+ .sourceNodeId(getLocalNodeId())
+ .generation(state.generation)
+ .requestId(state.lastRequestId)
+ .build()).build());
+ } catch (IOException e) {
+ Log.w(TAG, "Error while writing, closing link", e);
+ closeConnection(targetNodeId);
+ return -1;
+ }
+ return (state.generation + 527) * 31 + state.lastRequestId;
+ }
+ return -1;
}
}
diff --git a/play-services-core/src/main/java/org/microg/gms/wearable/WearableLocationListener.java b/play-services-core/src/main/java/org/microg/gms/wearable/WearableLocationListener.java
new file mode 100644
index 00000000..6510b3b9
--- /dev/null
+++ b/play-services-core/src/main/java/org/microg/gms/wearable/WearableLocationListener.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2013-2016 microG 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.Context;
+import android.content.pm.PackageManager;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.google.android.gms.common.data.DataHolder;
+import com.google.android.gms.location.LocationRequest;
+import com.google.android.gms.location.internal.ClientIdentity;
+import com.google.android.gms.location.internal.LocationRequestInternal;
+import com.google.android.gms.wearable.internal.AmsEntityUpdateParcelable;
+import com.google.android.gms.wearable.internal.AncsNotificationParcelable;
+import com.google.android.gms.wearable.internal.CapabilityInfoParcelable;
+import com.google.android.gms.wearable.internal.ChannelEventParcelable;
+import com.google.android.gms.wearable.internal.IWearableListener;
+import com.google.android.gms.wearable.internal.MessageEventParcelable;
+import com.google.android.gms.wearable.internal.NodeParcelable;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+public class WearableLocationListener extends IWearableListener.Stub {
+ public static final String LOCATION_REQUESTS = "com/google/android/location/fused/wearable/LOCATION_REQUESTS";
+ public static final String CAPABILITY_QUERY = "com/google/android/location/fused/wearable/CAPABILITY_QUERY";
+
+ private static final String TAG = "GmsWearLocListener";
+
+ private WearableLocationService locationService;
+
+ public WearableLocationListener(WearableLocationService locationService) {
+ this.locationService = locationService;
+ }
+
+ @Override
+ public void onDataChanged(DataHolder data) throws RemoteException {
+ }
+
+ @Override
+ public void onMessageReceived(MessageEventParcelable messageEvent) throws RemoteException {
+ if (messageEvent.getPath().equals(LOCATION_REQUESTS)) {
+ //DataMap dataMap = DataMap.fromByteArray(messageEvent.getData());
+ //locationService.onLocationRequests(messageEvent.getSourceNodeId(), parseLocationRequestList(dataMap, locationService), dataMap.getBoolean("TRIGGER_UPDATE", false));
+ } else if (messageEvent.getPath().equals(CAPABILITY_QUERY)) {
+ locationService.onCapabilityQuery(messageEvent.getSourceNodeId());
+ }
+ }
+
+ @Override
+ public void onPeerConnected(NodeParcelable node) throws RemoteException {
+ }
+
+ @Override
+ public void onPeerDisconnected(NodeParcelable node) throws RemoteException {
+ locationService.onLocationRequests(node.getId(), Collections.emptyList(), false);
+ }
+
+ @Override
+ public void onConnectedNodes(List nodes) throws RemoteException {
+ }
+
+ @Override
+ public void onNotificationReceived(AncsNotificationParcelable notification) throws RemoteException {
+ }
+
+ @Override
+ public void onChannelEvent(ChannelEventParcelable channelEvent) throws RemoteException {
+ }
+
+ @Override
+ public void onConnectedCapabilityChanged(CapabilityInfoParcelable capabilityInfo) throws RemoteException {
+ }
+
+ @Override
+ public void onEntityUpdate(AmsEntityUpdateParcelable update) throws RemoteException {
+ }
+
+ /*public static Collection parseLocationRequestList(DataMap dataMap, Context context) {
+ if (!dataMap.containsKey("REQUEST_LIST")) {
+ Log.w(TAG, "malformed DataMap: missing key REQUEST_LIST");
+ return Collections.emptyList();
+ }
+ List requestMapList = dataMap.getDataMapArrayList("REQUEST_LIST");
+ List locationRequests = new ArrayList();
+ for (DataMap map : requestMapList) {
+ locationRequests.add(parseLocationRequest(map, context));
+ }
+ return locationRequests;
+ }
+
+ private static LocationRequestInternal parseLocationRequest(DataMap dataMap, Context context) {
+ LocationRequestInternal request = new LocationRequestInternal();
+ request.triggerUpdate = true;
+ request.request = new LocationRequest();
+ request.clients = Collections.emptyList();
+
+ if (dataMap.containsKey("PRIORITY"))
+ request.request.setPriority(dataMap.getInt("PRIORITY", 0));
+ if (dataMap.containsKey("INTERVAL_MS"))
+ request.request.setInterval(dataMap.getLong("INTERVAL_MS", 0));
+ if (dataMap.containsKey("FASTEST_INTERVAL_MS"))
+ request.request.setFastestInterval(dataMap.getLong("FASTEST_INTERVAL_MS", 0));
+ //if (dataMap.containsKey("MAX_WAIT_TIME_MS"))
+ if (dataMap.containsKey("SMALLEST_DISPLACEMENT_METERS"))
+ request.request.setSmallestDisplacement(dataMap.getFloat("SMALLEST_DISPLACEMENT_METERS", 0));
+ if (dataMap.containsKey("NUM_UPDATES"))
+ request.request.setNumUpdates(dataMap.getInt("NUM_UPDATES", 0));
+ if (dataMap.containsKey("EXPIRATION_DURATION_MS"))
+ request.request.setExpirationDuration(dataMap.getLong("EXPIRATION_DURATION_MS", 0));
+ if (dataMap.containsKey("TAG"))
+ request.tag = dataMap.getString("TAG");
+ if (dataMap.containsKey("CLIENTS_PACKAGE_ARRAY")) {
+ String[] packages = dataMap.getStringArray("CLIENTS_PACKAGE_ARRAY");
+ if (packages != null) {
+ request.clients = new ArrayList();
+ for (String packageName : packages) {
+ request.clients.add(generateClientIdentity(packageName, context));
+ }
+ }
+ }
+
+ return request;
+ }
+
+ private static ClientIdentity generateClientIdentity(String packageName, Context context) {
+ return null;
+ try {
+ return new ClientIdentity(context.getPackageManager().getApplicationInfo(packageName, 0).uid, packageName);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "Unknown client identity: " + packageName, e);
+ return new ClientIdentity(context.getApplicationInfo().uid, context.getPackageName());
+ }
+ }*/
+}
diff --git a/play-services-core/src/main/java/org/microg/gms/wearable/WearableLocationService.java b/play-services-core/src/main/java/org/microg/gms/wearable/WearableLocationService.java
new file mode 100644
index 00000000..0b194425
--- /dev/null
+++ b/play-services-core/src/main/java/org/microg/gms/wearable/WearableLocationService.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2013-2016 microG 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.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.support.annotation.Nullable;
+
+import com.google.android.gms.location.internal.LocationRequestInternal;
+
+import java.util.Collection;
+
+public class WearableLocationService extends Service {
+ // TODO: Implement and use WearableListenerService
+ private static final String TAG = "GmsWearLocSvc";
+
+ private WearableLocationListener listener;
+
+ @Override
+ public void onCreate() {
+ listener = new WearableLocationListener(this);
+ }
+
+ @Nullable
+ @Override
+ public IBinder onBind(Intent intent) {
+ if (intent.getAction().equals("com.google.android.gms.wearable.BIND_LISTENER")) {
+ return listener.asBinder();
+ }
+ return null;
+ }
+
+ public void onLocationRequests(String nodeId, Collection requests, boolean triggerUpdate) {
+
+ }
+
+ public void onCapabilityQuery(String nodeId) {
+
+ }
+}
diff --git a/play-services-core/src/main/java/org/microg/gms/wearable/WearableServiceImpl.java b/play-services-core/src/main/java/org/microg/gms/wearable/WearableServiceImpl.java
index 2bd3a501..14df7e53 100644
--- a/play-services-core/src/main/java/org/microg/gms/wearable/WearableServiceImpl.java
+++ b/play-services-core/src/main/java/org/microg/gms/wearable/WearableServiceImpl.java
@@ -19,24 +19,33 @@ package org.microg.gms.wearable;
import android.content.Context;
import android.net.Uri;
import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.Log;
import com.google.android.gms.common.api.Status;
+import com.google.android.gms.wearable.Asset;
import com.google.android.gms.wearable.ConnectionConfiguration;
import com.google.android.gms.wearable.internal.AddListenerRequest;
+import com.google.android.gms.wearable.internal.AncsNotificationParcelable;
import com.google.android.gms.wearable.internal.DeleteDataItemsResponse;
+import com.google.android.gms.wearable.internal.GetCloudSyncSettingResponse;
import com.google.android.gms.wearable.internal.GetConfigResponse;
import com.google.android.gms.wearable.internal.GetConfigsResponse;
import com.google.android.gms.wearable.internal.GetConnectedNodesResponse;
import com.google.android.gms.wearable.internal.GetDataItemResponse;
+import com.google.android.gms.wearable.internal.GetFdForAssetResponse;
import com.google.android.gms.wearable.internal.GetLocalNodeResponse;
+import com.google.android.gms.wearable.internal.IChannelStreamCallbacks;
import com.google.android.gms.wearable.internal.IWearableCallbacks;
import com.google.android.gms.wearable.internal.IWearableService;
import com.google.android.gms.wearable.internal.NodeParcelable;
import com.google.android.gms.wearable.internal.PutDataRequest;
import com.google.android.gms.wearable.internal.PutDataResponse;
import com.google.android.gms.wearable.internal.RemoveListenerRequest;
+import com.google.android.gms.wearable.internal.SendMessageResponse;
+
+import java.io.FileNotFoundException;
public class WearableServiceImpl extends IWearableService.Stub {
private static final String TAG = "GmsWearSvcImpl";
@@ -51,6 +60,50 @@ public class WearableServiceImpl extends IWearableService.Stub {
this.packageName = packageName;
}
+ /*
+ * Config
+ */
+
+ @Override
+ public void putConfig(IWearableCallbacks callbacks, ConnectionConfiguration config) throws RemoteException {
+ wearable.createConnection(config);
+ callbacks.onStatus(Status.SUCCESS);
+ }
+
+ @Override
+ public void deleteConfig(IWearableCallbacks callbacks, String name) throws RemoteException {
+ wearable.deleteConnection(name);
+ callbacks.onStatus(Status.SUCCESS);
+ }
+
+ @Override
+ public void getConfigs(IWearableCallbacks callbacks) throws RemoteException {
+ Log.d(TAG, "getConfigs");
+ try {
+ callbacks.onGetConfigsResponse(new GetConfigsResponse(0, wearable.getConfigurations()));
+ } catch (Exception e) {
+ callbacks.onGetConfigsResponse(new GetConfigsResponse(8, new ConnectionConfiguration[0]));
+ }
+ }
+
+
+ @Override
+ public void enableConfig(IWearableCallbacks callbacks, String name) throws RemoteException {
+ Log.d(TAG, "enableConfig: " + name);
+ wearable.enableConnection(name);
+ callbacks.onStatus(Status.SUCCESS);
+ }
+
+ @Override
+ public void disableConfig(IWearableCallbacks callbacks, String name) throws RemoteException {
+ Log.d(TAG, "disableConfig: " + name);
+ wearable.disableConnection(name);
+ callbacks.onStatus(Status.SUCCESS);
+ }
+
+ /*
+ * DataItems
+ */
@Override
public void putData(IWearableCallbacks callbacks, PutDataRequest request) throws RemoteException {
@@ -74,32 +127,88 @@ public class WearableServiceImpl extends IWearableService.Stub {
@Override
public void getDataItems(IWearableCallbacks callbacks) throws RemoteException {
Log.d(TAG, "getDataItems: " + callbacks);
- callbacks.onDataHolder(wearable.getDataItemsAsHolder(packageName));
+ callbacks.onDataItemChanged(wearable.getDataItemsAsHolder(packageName));
}
@Override
- public void sendMessage(IWearableCallbacks callbacks, String targetNodeId, String path, byte[] data) throws RemoteException {
- Log.d(TAG, "sendMessage: " + targetNodeId + " / " + path);
- wearable.sendMessage(targetNodeId, path, data);
+ public void getDataItemsByUri(IWearableCallbacks callbacks, Uri uri) throws RemoteException {
+ getDataItemsByUriWithFilter(callbacks, uri, 0);
}
@Override
- public void getDataItemsByUri(IWearableCallbacks callbacks, Uri uri, int i) throws RemoteException {
+ public void getDataItemsByUriWithFilter(IWearableCallbacks callbacks, Uri uri, int typeFilter) throws RemoteException {
Log.d(TAG, "getDataItemsByUri: " + uri);
- callbacks.onDataHolder(wearable.getDataItemsByUriAsHolder(uri, packageName));
+ callbacks.onDataItemChanged(wearable.getDataItemsByUriAsHolder(uri, packageName));
}
@Override
public void deleteDataItems(IWearableCallbacks callbacks, Uri uri) throws RemoteException {
+ deleteDataItemsWithFilter(callbacks, uri, 0);
+ }
+
+ @Override
+ public void deleteDataItemsWithFilter(IWearableCallbacks callbacks, Uri uri, int typeFilter) throws RemoteException {
Log.d(TAG, "deleteDataItems: " + uri);
callbacks.onDeleteDataItemsResponse(new DeleteDataItemsResponse(0, wearable.deleteDataItems(uri, packageName)));
}
+ @Override
+ public void sendMessage(IWearableCallbacks callbacks, String targetNodeId, String path, byte[] data) throws RemoteException {
+ Log.d(TAG, "sendMessage: " + targetNodeId + " / " + path);
+ SendMessageResponse sendMessageResponse = new SendMessageResponse();
+ try {
+ sendMessageResponse.resultId = wearable.sendMessage(packageName, targetNodeId, path, data);
+ if (sendMessageResponse.resultId == -1) {
+ sendMessageResponse.statusCode = 4000;
+ }
+ } catch (Exception e) {
+ sendMessageResponse.statusCode = 8;
+ }
+ callbacks.onSendMessageResponse(sendMessageResponse);
+ }
+
+ @Override
+ public void getFdForAsset(IWearableCallbacks callbacks, Asset asset) throws RemoteException {
+ Log.d(TAG, "getFdForAsset " + asset);
+ // TODO: Access control
+ try {
+ callbacks.onGetFdForAssetResponse(new GetFdForAssetResponse(0, ParcelFileDescriptor.open(wearable.createAssetFile(asset.getDigest()), ParcelFileDescriptor.MODE_READ_ONLY)));
+ } catch (FileNotFoundException e) {
+ callbacks.onGetFdForAssetResponse(new GetFdForAssetResponse(8, null));
+ }
+ }
+
@Override
public void optInCloudSync(IWearableCallbacks callbacks, boolean enable) throws RemoteException {
callbacks.onStatus(Status.SUCCESS);
}
+ @Override
+ @Deprecated
+ public void getCloudSyncOptInDone(IWearableCallbacks callbacks) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: getCloudSyncOptInDone");
+ }
+
+ @Override
+ public void setCloudSyncSetting(IWearableCallbacks callbacks, boolean enable) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: setCloudSyncSetting");
+ }
+
+ @Override
+ public void getCloudSyncSetting(IWearableCallbacks callbacks) throws RemoteException {
+ callbacks.onGetCloudSyncSettingResponse(new GetCloudSyncSettingResponse(0, false));
+ }
+
+ @Override
+ public void getCloudSyncOptInStatus(IWearableCallbacks callbacks) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: getCloudSyncOptInStatus");
+ }
+
+ @Override
+ public void sendRemoteCommand(IWearableCallbacks callbacks, byte b) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: sendRemoteCommand: " + b);
+ }
+
@Override
public void getLocalNode(IWearableCallbacks callbacks) throws RemoteException {
try {
@@ -111,13 +220,35 @@ public class WearableServiceImpl extends IWearableService.Stub {
@Override
public void getConnectedNodes(IWearableCallbacks callbacks) throws RemoteException {
- Log.d(TAG, "getConnectedNodes");
callbacks.onGetConnectedNodesResponse(new GetConnectedNodesResponse(0, wearable.getConnectedNodesParcelableList()));
}
+ /*
+ * Capability
+ */
+
+ @Override
+ public void getConnectedCapability(IWearableCallbacks callbacks, String s1, int i) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: getConnectedCapability " + s1 + ", " + i);
+ }
+
+ @Override
+ public void getConnectedCapaibilties(IWearableCallbacks callbacks, int i) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: getConnectedCapaibilties: " + i);
+ }
+
+ @Override
+ public void addLocalCapability(IWearableCallbacks callbacks, String cap) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: addLocalCapability: " + cap);
+ }
+
+ @Override
+ public void removeLocalCapability(IWearableCallbacks callbacks, String cap) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: removeLocalCapability: " + cap);
+ }
+
@Override
public void addListener(IWearableCallbacks callbacks, AddListenerRequest request) throws RemoteException {
- Log.d(TAG, "addListener[nyp]: " + request);
if (request.listener != null) {
wearable.addListener(packageName, request.listener);
}
@@ -126,25 +257,112 @@ public class WearableServiceImpl extends IWearableService.Stub {
@Override
public void removeListener(IWearableCallbacks callbacks, RemoveListenerRequest request) throws RemoteException {
- Log.d(TAG, "removeListener[nyp]: " + request);
wearable.removeListener(request.listener);
callbacks.onStatus(Status.SUCCESS);
}
@Override
- public void putConfig(IWearableCallbacks callbacks, ConnectionConfiguration config) throws RemoteException {
- wearable.createConnection(config);
- callbacks.onStatus(Status.SUCCESS);
+ public void getStrorageInformation(IWearableCallbacks callbacks) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: getStrorageInformation");
}
@Override
- public void deleteConfig(IWearableCallbacks callbacks, String name) throws RemoteException {
- wearable.deleteConnection(name);
- callbacks.onStatus(Status.SUCCESS);
+ public void clearStorage(IWearableCallbacks callbacks) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: clearStorage");
}
@Override
- public void getConfig(IWearableCallbacks callbacks) throws RemoteException {
+ public void endCall(IWearableCallbacks callbacks) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: endCall");
+ }
+
+ @Override
+ public void acceptRingingCall(IWearableCallbacks callbacks) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: acceptRingingCall");
+ }
+
+ @Override
+ public void silenceRinger(IWearableCallbacks callbacks) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: silenceRinger");
+ }
+
+ /*
+ * Apple Notification Center Service
+ */
+
+ @Override
+ public void injectAncsNotificationForTesting(IWearableCallbacks callbacks, AncsNotificationParcelable notification) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: injectAncsNotificationForTesting: " + notification);
+ }
+
+ @Override
+ public void doAncsPositiveAction(IWearableCallbacks callbacks, int i) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: doAncsPositiveAction: " + i);
+ }
+
+ @Override
+ public void doAncsNegativeAction(IWearableCallbacks callbacks, int i) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: doAncsNegativeAction: " + i);
+ }
+
+ @Override
+ public void openChannel(IWearableCallbacks callbacks, String s1, String s2) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: openChannel; " + s1 + ", " + s2);
+ }
+
+ /*
+ * Channels
+ */
+
+ @Override
+ public void closeChannel(IWearableCallbacks callbacks, String s) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: closeChannel: " + s);
+ }
+
+ @Override
+ public void closeChannelWithError(IWearableCallbacks callbacks, String s, int errorCode) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: closeChannelWithError:" + s + ", " + errorCode);
+
+ }
+
+ @Override
+ public void getChannelInputStream(IWearableCallbacks callbacks, IChannelStreamCallbacks channelCallbacks, String s) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: getChannelInputStream: " + s);
+ }
+
+ @Override
+ public void getChannelOutputStream(IWearableCallbacks callbacks, IChannelStreamCallbacks channelCallbacks, String s) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: getChannelOutputStream: " + s);
+ }
+
+ @Override
+ public void writeChannelInputToFd(IWearableCallbacks callbacks, String s, ParcelFileDescriptor fd) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: writeChannelInputToFd: " + s);
+ }
+
+ @Override
+ public void readChannelOutputFromFd(IWearableCallbacks callbacks, String s, ParcelFileDescriptor fd, long l1, long l2) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: readChannelOutputFromFd: " + s + ", " + l1 + ", " + l2);
+ }
+
+ @Override
+ public void syncWifiCredentials(IWearableCallbacks callbacks) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: syncWifiCredentials");
+ }
+
+ /*
+ * Connection deprecated
+ */
+
+ @Override
+ @Deprecated
+ public void putConnection(IWearableCallbacks callbacks, ConnectionConfiguration config) throws RemoteException {
+ Log.d(TAG, "unimplemented Method: putConnection");
+ }
+
+ @Override
+ @Deprecated
+ public void getConnection(IWearableCallbacks callbacks) throws RemoteException {
Log.d(TAG, "getConfig");
ConnectionConfiguration[] configurations = wearable.getConfigurations();
if (configurations == null || configurations.length == 0) {
@@ -155,28 +373,21 @@ public class WearableServiceImpl extends IWearableService.Stub {
}
@Override
- public void getConfigs(IWearableCallbacks callbacks) throws RemoteException {
- Log.d(TAG, "getConfigs");
- try {
- callbacks.onGetConfigsResponse(new GetConfigsResponse(0, wearable.getConfigurations()));
- } catch (Exception e) {
- callbacks.onGetConfigsResponse(new GetConfigsResponse(8, new ConnectionConfiguration[0]));
+ @Deprecated
+ public void enableConnection(IWearableCallbacks callbacks) throws RemoteException {
+ ConnectionConfiguration[] configurations = wearable.getConfigurations();
+ if (configurations.length > 0) {
+ enableConfig(callbacks, configurations[0].name);
}
}
-
@Override
- public void enableConnection(IWearableCallbacks callbacks, String name) throws RemoteException {
- Log.d(TAG, "enableConnection: " + name);
- wearable.enableConnection(name);
- callbacks.onStatus(Status.SUCCESS);
- }
-
- @Override
- public void disableConnection(IWearableCallbacks callbacks, String name) throws RemoteException {
- Log.d(TAG, "disableConnection: " + name);
- wearable.disableConnection(name);
- callbacks.onStatus(Status.SUCCESS);
+ @Deprecated
+ public void disableConnection(IWearableCallbacks callbacks) throws RemoteException {
+ ConnectionConfiguration[] configurations = wearable.getConfigurations();
+ if (configurations.length > 0) {
+ disableConfig(callbacks, configurations[0].name);
+ }
}
@Override