diff --git a/extern/Wearable b/extern/Wearable index 5c24adaa..666ef2a8 160000 --- a/extern/Wearable +++ b/extern/Wearable @@ -1 +1 @@ -Subproject commit 5c24adaa3928de68167ce31c0fa5b9b1a3256677 +Subproject commit 666ef2a8628b1c76701a2d5f138d4fd90751b5e9 diff --git a/play-services-core/src/main/java/org/microg/gms/common/MultiListenerProxy.java b/play-services-core/src/main/java/org/microg/gms/common/MultiListenerProxy.java index 26d24b61..0e0baa04 100644 --- a/play-services-core/src/main/java/org/microg/gms/common/MultiListenerProxy.java +++ b/play-services-core/src/main/java/org/microg/gms/common/MultiListenerProxy.java @@ -17,6 +17,7 @@ package org.microg.gms.common; import android.os.IInterface; +import android.support.annotation.NonNull; import android.util.Log; import java.lang.reflect.InvocationHandler; @@ -25,17 +26,22 @@ import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Collection; import java.util.HashSet; +import java.util.Iterator; public class MultiListenerProxy implements InvocationHandler { private static final String TAG = "GmsMultiListener"; public static T get(Class tClass, final Collection listeners) { - return (T) Proxy.newProxyInstance(tClass.getClassLoader(), new Class[]{tClass}, new MultiListenerProxy(listeners)); + return get(tClass, new CollectionListenerPool(listeners)); } - private final Collection listeners; + public static T get(Class tClass, final ListenerPool listenerPool) { + return (T) Proxy.newProxyInstance(tClass.getClassLoader(), new Class[]{tClass}, new MultiListenerProxy(listenerPool)); + } - private MultiListenerProxy(Collection listeners) { + private final ListenerPool listeners; + + private MultiListenerProxy(ListenerPool listeners) { this.listeners = listeners; } @@ -44,14 +50,175 @@ public class MultiListenerProxy implements InvocationHandl for (T listener : new HashSet(listeners)) { try { method.invoke(listener, args); - } catch (IllegalAccessException e) { + } catch (Exception e) { Log.w(TAG, e); listeners.remove(listener); - } catch (InvocationTargetException e) { - Log.w(TAG, e.getTargetException()); - listeners.remove(listener); } } return null; } + + public static abstract class ListenerPool implements Collection { + @Override + public boolean addAll(Collection collection) { + return false; + } + + @Override + public boolean add(T object) { + return false; + } + + @Override + public boolean containsAll(Collection collection) { + for (Object o : collection) { + if (!contains(o)) return false; + } + return true; + } + + @Override + public boolean removeAll(Collection collection) { + boolean x = true; + for (Object o : collection) { + if (!remove(o)) x = false; + } + return x; + } + + @Override + public boolean retainAll(Collection collection) { + return false; + } + + @NonNull + @Override + public Object[] toArray() { + throw new IllegalArgumentException(); + } + + @NonNull + @Override + public T1[] toArray(T1[] array) { + throw new IllegalArgumentException(); + } + } + + private static class CollectionListenerPool extends ListenerPool { + + private Collection listeners; + + public CollectionListenerPool(Collection listeners) { + this.listeners = listeners; + } + + @Override + public void clear() { + listeners.clear(); + } + + @Override + public boolean contains(Object object) { + return listeners.contains(object); + } + + @Override + public boolean isEmpty() { + return listeners.isEmpty(); + } + + @NonNull + @Override + public Iterator iterator() { + return listeners.iterator(); + } + + @Override + public boolean remove(Object object) { + return listeners.remove(object); + } + + @Override + public int size() { + return listeners.size(); + } + } + + public static class MultiCollectionListenerPool extends ListenerPool { + private Collection> multiCol; + + public MultiCollectionListenerPool(Collection> multiCol) { + this.multiCol = multiCol; + } + + @Override + public void clear() { + for (Collection ts : multiCol) { + ts.clear(); + } + } + + @Override + public boolean contains(Object object) { + for (Collection ts : multiCol) { + if (ts.contains(object)) return true; + } + return false; + } + + @Override + public boolean isEmpty() { + for (Collection ts : multiCol) { + if (!ts.isEmpty()) return false; + } + return true; + } + + @NonNull + @Override + public Iterator iterator() { + final Iterator> interMed = multiCol.iterator(); + return new Iterator() { + private Iterator med; + + @Override + public boolean hasNext() { + while ((med == null || !med.hasNext()) && interMed.hasNext()) { + med = interMed.next().iterator(); + } + return med != null && med.hasNext(); + } + + @Override + public T next() { + while (med == null || !med.hasNext()) { + med = interMed.next().iterator(); + } + return med.next(); + } + + @Override + public void remove() { + med.remove(); + } + }; + } + + @Override + public boolean remove(Object object) { + for (Collection ts : multiCol) { + if (ts.remove(object)) return true; + } + return false; + } + + @Override + public int size() { + int sum = 0; + for (Collection ts : multiCol) { + sum += ts.size(); + } + return sum; + } + } } diff --git a/play-services-core/src/main/java/org/microg/gms/wearable/ClockworkNodePreferences.java b/play-services-core/src/main/java/org/microg/gms/wearable/ClockworkNodePreferences.java new file mode 100644 index 00000000..db439819 --- /dev/null +++ b/play-services-core/src/main/java/org/microg/gms/wearable/ClockworkNodePreferences.java @@ -0,0 +1,62 @@ +/* + * 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.UUID; + +public class ClockworkNodePreferences { + + private static final String CLOCKWORK_NODE_PREFERENCES = "cw_node"; + private static final String CLOCKWORK_NODE_PREFERENCE_NODE_ID = "node_id"; + private static final String CLOCKWORK_NODE_PREFERENCE_NEXT_SEQ_ID_BLOCK = "nextSeqIdBlock"; + + private static final Object lock = new Object(); + private static long seqIdBlock; + private static long seqIdInBlock = -1; + + private Context context; + + public ClockworkNodePreferences(Context context) { + this.context = context; + } + + public String getLocalNodeId() { + SharedPreferences preferences = context.getSharedPreferences(CLOCKWORK_NODE_PREFERENCES, Context.MODE_PRIVATE); + String nodeId = preferences.getString(CLOCKWORK_NODE_PREFERENCE_NODE_ID, null); + if (nodeId == null) { + nodeId = UUID.randomUUID().toString(); + preferences.edit().putString(CLOCKWORK_NODE_PREFERENCE_NODE_ID, nodeId).apply(); + } + return nodeId; + } + + public long getNextSeqId() { + synchronized (lock) { + SharedPreferences preferences = context.getSharedPreferences(CLOCKWORK_NODE_PREFERENCES, Context.MODE_PRIVATE); + if (seqIdInBlock < 0) seqIdInBlock = 1000; + if (seqIdInBlock >= 1000) { + seqIdBlock = preferences.getLong(CLOCKWORK_NODE_PREFERENCE_NEXT_SEQ_ID_BLOCK, 100); + preferences.edit().putLong(CLOCKWORK_NODE_PREFERENCE_NEXT_SEQ_ID_BLOCK, seqIdBlock + seqIdInBlock).apply(); + seqIdInBlock = 0; + } + return seqIdBlock + seqIdInBlock++; + } + } +} 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 59a7b275..07f66889 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 @@ -58,7 +58,7 @@ public class MessageHandler extends ServerMessageListener { .networkId(networkId) .peerAndroidId(androidId) .unknown4(3) - .unknown5(1) + .peerVersion(1) .build()); this.wearable = wearable; this.thisNodeId = config.nodeId; @@ -83,6 +83,12 @@ public class MessageHandler extends ServerMessageListener { } } + @Override + public void onDisconnected() { + wearable.onDisconnectReceived(getConnection(), thisNodeId, getRemoteConnect()); + super.onDisconnected(); + } + @Override public void onSetAsset(SetAsset setAsset) { Log.d(TAG, "onSetAsset: " + setAsset); @@ -132,8 +138,7 @@ public class MessageHandler extends ServerMessageListener { @Override public void onRpcRequest(Request rpcRequest) { Log.d(TAG, "onRpcRequest: " + rpcRequest); - if (TextUtils.isEmpty(rpcRequest.targetNodeId)) { - // TODO: That's probably not how it should go! + if (TextUtils.isEmpty(rpcRequest.targetNodeId) || rpcRequest.targetNodeId.equals(thisNodeId)) { 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/NetworkConnectionThread.java b/play-services-core/src/main/java/org/microg/gms/wearable/NetworkConnectionThread.java deleted file mode 100644 index 0e00e4e6..00000000 --- a/play-services-core/src/main/java/org/microg/gms/wearable/NetworkConnectionThread.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2013-2015 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.util.Log; - -import com.google.android.gms.wearable.ConnectionConfiguration; - -import org.microg.wearable.SocketWearableConnection; -import org.microg.wearable.WearableConnection; - -import java.io.IOException; -import java.net.ServerSocket; -import java.net.Socket; - -class NetworkConnectionThread extends Thread { - private static final String TAG = "GmsWearNetConnThr"; - private static final int WEAR_TCP_PORT = 5601; - - private ConnectionConfiguration config; - private ServerSocket socket; - private MessageHandler handler; - private WearableConnection wearableConnection; - - public NetworkConnectionThread(WearableImpl wearable, ConnectionConfiguration config) { - this.config = config; - this.handler = new MessageHandler(wearable, config); - } - - public void close() { - try { - socket.close(); - } catch (IOException e) { - Log.w(TAG, e); - } - } - - public WearableConnection getWearableConnection() { - return wearableConnection; - } - - @Override - public void run() { - try { - socket = new ServerSocket(WEAR_TCP_PORT); - Log.d(TAG, "Listening for connections on TCP :" + WEAR_TCP_PORT); - Socket accepted = socket.accept(); - (wearableConnection = new SocketWearableConnection(accepted, handler)).run(); - Log.d(TAG, "Connection terminated, me too"); - } catch (IOException e) { - Log.w(TAG, e); - } - } -} 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 d59f5d98..a40233d6 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 @@ -25,6 +25,8 @@ import android.text.TextUtils; import com.google.android.gms.wearable.Asset; +import java.util.ArrayList; +import java.util.List; import java.util.Map; public class NodeDatabaseHelper extends SQLiteOpenHelper { @@ -34,8 +36,11 @@ public class NodeDatabaseHelper extends SQLiteOpenHelper { private static final String[] GDIBHAP_FIELDS = new String[]{"dataitems_id", "packageName", "signatureDigest", "host", "path", "seqId", "deleted", "sourceNode", "data", "timestampMs", "assetsPresent", "assetname", "assets_digest", "v1SourceNode", "v1SeqId"}; private static final int VERSION = 9; + private ClockworkNodePreferences clockworkNodePreferences; + public NodeDatabaseHelper(Context context) { super(context, DB_NAME, null, VERSION); + clockworkNodePreferences = new ClockworkNodePreferences(context); } @Override @@ -198,27 +203,32 @@ public class NodeDatabaseHelper extends SQLiteOpenHelper { return getReadableDatabase().query("dataItemsAndAssets", GDIBHAP_FIELDS, selection, new String[]{nodeId, Long.toString(seqId)}, null, null, "seqId", null); } - public synchronized int deleteDataItems(String packageName, String signatureDigest, String host, String path) { + public synchronized List deleteDataItems(String packageName, String signatureDigest, String host, String path) { + List updated = new ArrayList(); SQLiteDatabase db = getWritableDatabase(); db.beginTransaction(); Cursor cursor = getDataItemsByHostAndPath(db, packageName, signatureDigest, host, path); - int n = 0; while (cursor.moveToNext()) { DataItemRecord record = DataItemRecord.fromCursor(cursor); record.deleted = true; record.assetsAreReady = true; record.dataItem.data = null; + record.seqId = clockworkNodePreferences.getNextSeqId(); + record.v1SeqId = record.seqId; updateRecord(db, cursor.getString(0), record); - n++; + updated.add(record); } db.setTransactionSuccessful(); db.endTransaction(); - return n; + return updated; } public long getCurrentSeqId(String sourceNode) { if (TextUtils.isEmpty(sourceNode)) return 1; - SQLiteDatabase db = getReadableDatabase(); + return getCurrentSeqId(getReadableDatabase(), sourceNode); + } + + private long getCurrentSeqId(SQLiteDatabase db, String sourceNode) { Cursor cursor = db.query("dataItemsAndAssets", new String[]{"seqId"}, "sourceNode=?", new String[]{sourceNode}, null, null, "seqId DESC", "1"); long res = 1; if (cursor != null) { 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 498540da..4255e8e7 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 @@ -17,10 +17,10 @@ package org.microg.gms.wearable; import android.content.Context; -import android.content.SharedPreferences; import android.database.Cursor; import android.net.Uri; import android.os.RemoteException; +import android.support.annotation.NonNull; import android.text.TextUtils; import android.util.Base64; import android.util.Log; @@ -37,6 +37,7 @@ import com.google.android.gms.wearable.internal.PutDataRequest; import org.microg.gms.common.MultiListenerProxy; import org.microg.gms.common.PackageUtils; import org.microg.gms.common.Utils; +import org.microg.wearable.SocketConnectionThread; import org.microg.wearable.WearableConnection; import org.microg.wearable.proto.AckAsset; import org.microg.wearable.proto.AppKey; @@ -54,12 +55,14 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.UUID; import okio.ByteString; @@ -67,48 +70,28 @@ public class WearableImpl { private static final String TAG = "GmsWear"; - private static final String CLOCKWORK_NODE_PREFERENCES = "cw_node"; - private static final String CLOCKWORK_NODE_PREFERENCE_NODE_ID = "node_id"; - private static final String CLOCKWORK_NODE_PREFERENCE_NEXT_SEQ_ID_BLOCK = "nextSeqIdBlock"; + private static final int WEAR_TCP_PORT = 5601; private final Context context; private final NodeDatabaseHelper nodeDatabase; private final ConfigurationDatabaseHelper configDatabase; - private final Set listeners = new HashSet(); + private final Map> listeners = new HashMap>(); private final Set connectedNodes = new HashSet(); private final Set activeConnections = new HashSet(); - private NetworkConnectionThread nct; + private SocketConnectionThread sct; private ConnectionConfiguration[] configurations; private boolean configurationsUpdated = false; - - private long seqIdBlock; - private long seqIdInBlock = -1; + private ClockworkNodePreferences clockworkNodePreferences; public WearableImpl(Context context, NodeDatabaseHelper nodeDatabase, ConfigurationDatabaseHelper configDatabase) { this.context = context; this.nodeDatabase = nodeDatabase; this.configDatabase = configDatabase; + this.clockworkNodePreferences = new ClockworkNodePreferences(context); } public String getLocalNodeId() { - SharedPreferences preferences = context.getSharedPreferences(CLOCKWORK_NODE_PREFERENCES, Context.MODE_PRIVATE); - String nodeId = preferences.getString(CLOCKWORK_NODE_PREFERENCE_NODE_ID, null); - if (nodeId == null) { - nodeId = UUID.randomUUID().toString(); - preferences.edit().putString(CLOCKWORK_NODE_PREFERENCE_NODE_ID, nodeId).apply(); - } - return nodeId; - } - - private synchronized long getNextSeqId() { - SharedPreferences preferences = context.getSharedPreferences(CLOCKWORK_NODE_PREFERENCES, Context.MODE_PRIVATE); - if (seqIdInBlock < 0) seqIdInBlock = 1000; - if (seqIdInBlock >= 1000) { - seqIdBlock = preferences.getLong(CLOCKWORK_NODE_PREFERENCE_NEXT_SEQ_ID_BLOCK, 100); - preferences.edit().putLong(CLOCKWORK_NODE_PREFERENCE_NEXT_SEQ_ID_BLOCK, seqIdBlock + seqIdInBlock).apply(); - seqIdInBlock = 0; - } - return seqIdBlock + seqIdInBlock++; + return clockworkNodePreferences.getLocalNodeId(); } public DataItemRecord putDataItem(String packageName, String signatureDigest, String source, DataItemInternal dataItem) { @@ -118,7 +101,7 @@ public class WearableImpl { record.deleted = false; record.source = source; record.dataItem = dataItem; - record.v1SeqId = getNextSeqId(); + record.v1SeqId = clockworkNodePreferences.getNextSeqId(); if (record.source.equals(getLocalNodeId())) record.seqId = record.v1SeqId; nodeDatabase.putRecord(record); return record; @@ -127,7 +110,11 @@ public class WearableImpl { public DataItemRecord putDataItem(DataItemRecord record) { nodeDatabase.putRecord(record); try { - getAllListeners().onDataChanged(getDataItemsByUri(record.dataItem.uri, record.packageName)); + if (listeners.containsKey(record.packageName)) { + MultiListenerProxy.get(IWearableListener.class, listeners.get(record.packageName)).onDataChanged(getDataItemForRecord(record)); + } else { + + } } catch (RemoteException e) { Log.w(TAG, e); } @@ -272,7 +259,7 @@ public class WearableImpl { RootMessage announceMessage = new RootMessage.Builder().setAsset(new SetAsset.Builder() .digest(asset.getDigest()) .appkeys(new AppKeys(Collections.singletonList(new AppKey(record.packageName, record.signatureDigest)))) - .build()).unknown13(true).build(); + .build()).hasAsset(true).build(); connection.writeMessage(announceMessage); File assetFile = createAssetFile(asset.getDigest()); String fileName = calculateDigest(announceMessage.toByteArray()); @@ -346,6 +333,16 @@ public class WearableImpl { onPeerConnected(new NodeParcelable(connect.id, connect.name)); } + public void onDisconnectReceived(WearableConnection connection, String nodeId, Connect connect) { + for (ConnectionConfiguration config : getConfigurations()) { + if (config.nodeId.equals(nodeId)) { + config.connected = false; + } + } + Log.d(TAG, "Removing connection from list of open connections: " + connection); + activeConnections.remove(connection); + onPeerDisconnected(new NodeParcelable(connect.id, connect.name)); + } public List getConnectedNodesParcelableList() { List nodes = new ArrayList(); @@ -356,7 +353,7 @@ public class WearableImpl { } public IWearableListener getAllListeners() { - return MultiListenerProxy.get(IWearableListener.class, listeners); + return MultiListenerProxy.get(IWearableListener.class, new MultiListenerProxy.MultiCollectionListenerPool(listeners.values())); } public void onPeerConnected(NodeParcelable node) { @@ -369,6 +366,16 @@ public class WearableImpl { addConnectedNode(node); } + public void onPeerDisconnected(NodeParcelable node) { + Log.d(TAG, "onPeerDisconnected: " + node); + try { + getAllListeners().onPeerDisconnected(node); + } catch (RemoteException e) { + Log.w(TAG, e); + } + removeConnectedNode(node.getId()); + } + public void onConnectedNodes(List nodes) { Log.d(TAG, "onConnectedNodes: " + nodes); try { @@ -406,7 +413,13 @@ public class WearableImpl { } public DataHolder getDataItemsByUri(Uri uri, String packageName) { - Cursor dataHolderItems = nodeDatabase.getDataItemsForDataHolderByHostAndPath(packageName, PackageUtils.firstSignatureDigest(context, packageName), uri.getHost(), uri.getPath()); + String firstSignature; + try { + firstSignature = PackageUtils.firstSignatureDigest(context, packageName); + } catch (Exception e) { + return null; + } + Cursor dataHolderItems = nodeDatabase.getDataItemsForDataHolderByHostAndPath(packageName, firstSignature, uri.getHost(), uri.getPath()); while (dataHolderItems.moveToNext()) { Log.d(TAG, "getDataItems[]: path=" + Uri.parse(dataHolderItems.getString(1)).getPath()); } @@ -415,30 +428,45 @@ public class WearableImpl { return DataHolder.fromCursor(dataHolderItems, 0, null); } - public void addListener(IWearableListener listener) { - listeners.add(listener); + public DataHolder getDataItemForRecord(DataItemRecord record) { + Cursor dataHolderItems = nodeDatabase.getDataItemsForDataHolderByHostAndPath(record.packageName, record.signatureDigest, record.dataItem.uri.getHost(), record.dataItem.uri.getPath()); + while (dataHolderItems.moveToNext()) { + Log.d(TAG, "getDataItems[]: path=" + Uri.parse(dataHolderItems.getString(1)).getPath()); + } + dataHolderItems.moveToFirst(); + dataHolderItems.moveToPrevious(); + return DataHolder.fromCursor(dataHolderItems, 0, null); + } + + public synchronized void addListener(String packageName, IWearableListener listener) { + if (!listeners.containsKey(packageName)) { + listeners.put(packageName, new ArrayList()); + } + listeners.get(packageName).add(listener); } public void removeListener(IWearableListener listener) { - listeners.add(listener); + for (List list : listeners.values()) { + list.remove(listener); + } } public void enableConnection(String name) { configDatabase.setEnabledState(name, true); configurationsUpdated = true; - if (name.equals("server") && nct == null) { - (nct = new NetworkConnectionThread(this, configDatabase.getConfiguration(name))).start(); + if (name.equals("server") && sct == null) { + (sct = SocketConnectionThread.serverListen(WEAR_TCP_PORT, new MessageHandler(this, configDatabase.getConfiguration(name)))).start(); } } public void disableConnection(String name) { configDatabase.setEnabledState(name, false); configurationsUpdated = true; - if (name.equals("server") && nct != null) { - activeConnections.remove(nct.getWearableConnection()); - nct.close(); - nct.interrupt(); - nct = null; + if (name.equals("server") && sct != null) { + activeConnections.remove(sct.getWearableConnection()); + sct.close(); + sct.interrupt(); + sct = null; } } @@ -455,7 +483,11 @@ public class WearableImpl { } public int deleteDataItems(Uri uri, String packageName) { - return nodeDatabase.deleteDataItems(packageName, PackageUtils.firstSignatureDigest(context, packageName), uri.getHost(), uri.getPath()); + List records = nodeDatabase.deleteDataItems(packageName, PackageUtils.firstSignatureDigest(context, packageName), uri.getHost(), uri.getPath()); + for (DataItemRecord record : records) { + syncRecordToAll(record); + } + return records.size(); } public void sendMessageReceived(MessageEventParcelable messageEvent) { 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 a92e8d84..9eb02da4 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 @@ -20,6 +20,7 @@ import android.content.Context; import android.net.Uri; import android.os.Parcel; import android.os.RemoteException; +import android.support.v7.app.NotificationCompat; import android.util.Log; import com.google.android.gms.common.api.Status; @@ -113,7 +114,7 @@ public class WearableServiceImpl extends IWearableService.Stub { public void addListener(IWearableCallbacks callbacks, AddListenerRequest request) throws RemoteException { Log.d(TAG, "addListener[nyp]: " + request); if (request.listener != null) { - wearable.addListener(request.listener); + wearable.addListener(packageName, request.listener); } callbacks.onStatus(Status.SUCCESS); }