Loading play-services-core/src/main/java/org/microg/gms/common/RemoteListenerProxy.java +10 −5 Original line number Diff line number Diff line /* * Copyright (C) 2013-2017 microG Project Team * Copyright (C) 2013-2019 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. Loading Loading @@ -66,7 +66,6 @@ public class RemoteListenerProxy<T extends IInterface> implements ServiceConnect if (!connecting) Log.d(TAG, "Could not connect to: " + intent); return connecting; } Log.d(TAG, "Unable to resolve: " + searchIntent); return false; } catch (Exception e) { Log.w(TAG, e); Loading @@ -91,11 +90,17 @@ public class RemoteListenerProxy<T extends IInterface> implements ServiceConnect synchronized (this) { remote = service; if (!waiting.isEmpty()) { try { for (Runnable runnable : waiting) { runnable.run(); } } catch (Exception e) { } waiting.clear(); try { context.unbindService(RemoteListenerProxy.this); } catch (Exception e) { } connecting = false; remote = null; } Loading play-services-core/src/main/java/org/microg/gms/wearable/WearableImpl.java +106 −107 Original line number Diff line number Diff line /* * Copyright (C) 2013-2017 microG Project Team * Copyright (C) 2013-2019 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. Loading @@ -16,14 +16,15 @@ package org.microg.gms.wearable; import android.annotation.TargetApi; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.Cursor; import android.net.Uri; import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.Base64; import android.util.Log; Loading @@ -37,7 +38,6 @@ import com.google.android.gms.wearable.internal.MessageEventParcelable; import com.google.android.gms.wearable.internal.NodeParcelable; 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.RemoteListenerProxy; import org.microg.gms.common.Utils; Loading @@ -52,6 +52,7 @@ import org.microg.wearable.proto.FilePiece; import org.microg.wearable.proto.Request; import org.microg.wearable.proto.RootMessage; import org.microg.wearable.proto.SetAsset; import org.microg.wearable.proto.SetDataItem; import java.io.File; import java.io.FileInputStream; Loading @@ -70,8 +71,6 @@ import java.util.Set; import okio.ByteString; import static android.os.Build.VERSION.SDK_INT; public class WearableImpl { private static final String TAG = "GmsWear"; Loading @@ -81,7 +80,7 @@ public class WearableImpl { private final Context context; private final NodeDatabaseHelper nodeDatabase; private final ConfigurationDatabaseHelper configDatabase; private final Map<String, List<IWearableListener>> listeners = new HashMap<String, List<IWearableListener>>(); private final Map<String, List<ListenerInfo>> listeners = new HashMap<String, List<ListenerInfo>>(); private final Set<Node> connectedNodes = new HashSet<Node>(); private final Map<String, WearableConnection> activeConnections = new HashMap<String, WearableConnection>(); private RpcHelper rpcHelper; Loading Loading @@ -130,12 +129,10 @@ public class WearableImpl { } } } try { getListener(record.packageName, "com.google.android.gms.wearable.DATA_CHANGED", record.dataItem.uri) .onDataChanged(record.toEventDataHolder()); } catch (RemoteException e) { Log.w(TAG, e); } Intent intent = new Intent("com.google.android.gms.wearable.DATA_CHANGED"); intent.setPackage(record.packageName); intent.setData(record.dataItem.uri); invokeListeners(intent, listener -> listener.onDataChanged(record.toEventDataHolder())); return record; } Loading Loading @@ -247,8 +244,7 @@ public class WearableImpl { } private void syncRecordToAll(DataItemRecord record) { Log.d(TAG, "Syncing record " + record + " over " + activeConnections.size() + " connections."); void syncRecordToAll(DataItemRecord record) { for (String nodeId : new ArrayList<String>(activeConnections.keySet())) { syncRecordToPeer(nodeId, record); } Loading @@ -256,23 +252,27 @@ public class WearableImpl { private boolean syncRecordToPeer(String nodeId, DataItemRecord record) { for (Asset asset : record.dataItem.getAssets().values()) { try { syncAssetToPeer(nodeId, record, asset); } catch (Exception e) { Log.w(TAG, "Could not sync asset " + asset + " for " + nodeId + " and " + record, e); closeConnection(nodeId); return false; } } Log.d(TAG, "Sync over to " + nodeId + ": " + record); try { activeConnections.get(nodeId).writeMessage(new RootMessage.Builder().setDataItem(record.toSetDataItem()).build()); } catch (IOException e) { closeConnection(nodeId); SetDataItem item = record.toSetDataItem(); activeConnections.get(nodeId).writeMessage(new RootMessage.Builder().setDataItem(item).build()); } catch (Exception e) { Log.w(TAG, e); closeConnection(nodeId); return false; } return true; } private void syncAssetToPeer(String nodeId, DataItemRecord record, Asset asset) { try { Log.d(TAG, "Sync over to " + nodeId + ": " + asset); private void syncAssetToPeer(String nodeId, DataItemRecord record, Asset asset) throws IOException { RootMessage announceMessage = new RootMessage.Builder().setAsset(new SetAsset.Builder() .digest(asset.getDigest()) .appkeys(new AppKeys(Collections.singletonList(new AppKey(record.packageName, record.signatureDigest)))) Loading @@ -286,17 +286,11 @@ public class WearableImpl { int c = 0; while ((c = fis.read(arr)) > 0) { if (lastPiece != null) { 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 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); } } public void addAssetToDatabase(Asset asset, List<AppKey> appKeys) { Loading Loading @@ -394,37 +388,59 @@ public class WearableImpl { return nodes; } public IWearableListener getAllListeners() { return MultiListenerProxy.get(IWearableListener.class, new MultiListenerProxy.MultiCollectionListenerPool<IWearableListener>(listeners.values())); interface ListenerInvoker { void invoke(IWearableListener listener) throws RemoteException; } public void onPeerConnected(NodeParcelable node) { Log.d(TAG, "onPeerConnected: " + node); private void invokeListeners(@Nullable Intent intent, ListenerInvoker invoker) { for (String packageName : new ArrayList<>(listeners.keySet())) { List<ListenerInfo> listeners = this.listeners.get(packageName); if (listeners == null) continue; for (int i = 0; i < listeners.size(); i++) { boolean filterMatched = false; if (intent != null) { for (IntentFilter filter : listeners.get(i).filters) { filterMatched |= filter.match(context.getContentResolver(), intent, false, TAG) > 0; } } if (filterMatched || listeners.get(i).filters.length == 0) { try { getAllListeners().onPeerConnected(node); invoker.invoke(listeners.get(i).listener); } catch (RemoteException e) { Log.w(TAG, e); Log.w(TAG, "Registered listener at package " + packageName + " failed, removing."); listeners.remove(i); i--; } } } if (listeners.isEmpty()) { this.listeners.remove(packageName); } } if (intent != null) { try { invoker.invoke(RemoteListenerProxy.get(context, intent, IWearableListener.class, "com.google.android.gms.wearable.BIND_LISTENER")); } catch (RemoteException e) { Log.w(TAG, "Failed to deliver message received to " + intent, e); } } } public void onPeerConnected(NodeParcelable node) { Log.d(TAG, "onPeerConnected: " + node); invokeListeners(null, listener -> listener.onPeerConnected(node)); addConnectedNode(node); } public void onPeerDisconnected(NodeParcelable node) { Log.d(TAG, "onPeerDisconnected: " + node); try { getAllListeners().onPeerDisconnected(node); } catch (RemoteException e) { Log.w(TAG, e); } invokeListeners(null, listener -> listener.onPeerDisconnected(node)); removeConnectedNode(node.getId()); } public void onConnectedNodes(List<NodeParcelable> nodes) { Log.d(TAG, "onConnectedNodes: " + nodes); try { getAllListeners().onConnectedNodes(nodes); } catch (RemoteException e) { Log.w(TAG, e); } invokeListeners(null, listener -> listener.onConnectedNodes(nodes)); } public DataItemRecord putData(PutDataRequest request, String packageName) { Loading @@ -444,11 +460,6 @@ public class WearableImpl { public DataHolder getDataItemsAsHolder(String packageName) { Cursor dataHolderItems = nodeDatabase.getDataItemsForDataHolder(packageName, PackageUtils.firstSignatureDigest(context, packageName)); while (dataHolderItems.moveToNext()) { Log.d(TAG, "getDataItems[]: path=" + Uri.parse(dataHolderItems.getString(1)).getPath()); } dataHolderItems.moveToFirst(); dataHolderItems.moveToPrevious(); return new DataHolder(dataHolderItems, 0, null); } Loading @@ -467,40 +478,26 @@ public class WearableImpl { return null; } Cursor dataHolderItems = nodeDatabase.getDataItemsForDataHolderByHostAndPath(packageName, firstSignature, fixHost(uri.getHost(), false), uri.getPath()); maybeDebugCursor("getDataItems",dataHolderItems); dataHolderItems.moveToFirst(); dataHolderItems.moveToPrevious(); DataHolder dataHolder = new DataHolder(dataHolderItems, 0, null); Log.d(TAG, "Returning data holder of size " + dataHolder.getCount() + " for query " + uri); return dataHolder; } @TargetApi(11) private void maybeDebugCursor(String what, Cursor cursor) { if (SDK_INT >= 11) { int j = 0; while (cursor.moveToNext()) { for (int i = 0; i < cursor.getColumnCount(); i++) { if (cursor.getType(i) == Cursor.FIELD_TYPE_STRING) { Log.d(TAG, what+"[" + j + "]: " + cursor.getColumnName(i) + "=" + cursor.getString(i)); } if (cursor.getType(i) == Cursor.FIELD_TYPE_INTEGER) Log.d(TAG, what+"[" + j + "]: " + cursor.getColumnName(i) + "=" + cursor.getLong(i)); } } } } public synchronized void addListener(String packageName, IWearableListener listener) { public synchronized void addListener(String packageName, IWearableListener listener, IntentFilter[] filters) { if (!listeners.containsKey(packageName)) { listeners.put(packageName, new ArrayList<IWearableListener>()); listeners.put(packageName, new ArrayList<ListenerInfo>()); } listeners.get(packageName).add(listener); listeners.get(packageName).add(new ListenerInfo(listener, filters)); } public void removeListener(IWearableListener listener) { for (List<IWearableListener> list : listeners.values()) { list.remove(listener); for (List<ListenerInfo> list : listeners.values()) { for (int i = 0; i < list.size(); i++) { if (list.get(i).listener.equals(listener)) { list.remove(i); i--; } } } } Loading Loading @@ -546,12 +543,10 @@ public class WearableImpl { public void sendMessageReceived(String packageName, MessageEventParcelable messageEvent) { Log.d(TAG, "onMessageReceived: " + messageEvent); try { getListener(packageName, "com.google.android.gms.wearable.MESSAGE_RECEIVED", Uri.parse("wear://" + getLocalNodeId() + "/" + messageEvent.getPath())) .onMessageReceived(messageEvent); } catch (RemoteException e) { Log.w(TAG, e); } Intent intent = new Intent("com.google.android.gms.wearable.MESSAGE_RECEIVED"); intent.setPackage(packageName); intent.setData(Uri.parse("wear://" + getLocalNodeId() + "/" + messageEvent.getPath())); invokeListeners(intent, listener -> listener.onMessageReceived(messageEvent)); } public DataItemRecord getDataItemByUri(Uri uri, String packageName) { Loading @@ -568,17 +563,11 @@ public class WearableImpl { } private IWearableListener getListener(String packageName, String action, Uri uri) { synchronized (this) { List<IWearableListener> l = new ArrayList<IWearableListener>(listeners.containsKey(packageName) ? listeners.get(packageName) : Collections.<IWearableListener>emptyList()); Intent intent = new Intent(action); intent.setPackage(packageName); intent.setData(uri); l.add(RemoteListenerProxy.get(context, intent, IWearableListener.class, "com.google.android.gms.wearable.BIND_LISTENER")); return MultiListenerProxy.get(IWearableListener.class, l); } return RemoteListenerProxy.get(context, intent, IWearableListener.class, "com.google.android.gms.wearable.BIND_LISTENER"); } private void closeConnection(String nodeId) { Loading @@ -594,7 +583,7 @@ public class WearableImpl { } activeConnections.remove(nodeId); for (ConnectionConfiguration config : getConfigurations()) { if (config.nodeId.equals(nodeId) || config.peerNodeId.equals(nodeId)) { if (nodeId.equals(config.nodeId) || nodeId.equals(config.peerNodeId)) { config.connected = false; } } Loading Loading @@ -631,4 +620,14 @@ public class WearableImpl { public void stop() { this.networkHandler.getLooper().quit(); } private class ListenerInfo { private IWearableListener listener; private IntentFilter[] filters; private ListenerInfo(IWearableListener listener, IntentFilter[] filters) { this.listener = listener; this.filters = filters; } } } play-services-core/src/main/java/org/microg/gms/wearable/WearableServiceImpl.java +44 −12 Original line number Diff line number Diff line /* * Copyright (C) 2013-2017 microG Project Team * Copyright (C) 2013-2019 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. Loading Loading @@ -29,8 +29,11 @@ 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.AddLocalCapabilityResponse; import com.google.android.gms.wearable.internal.AncsNotificationParcelable; import com.google.android.gms.wearable.internal.CapabilityInfoParcelable; import com.google.android.gms.wearable.internal.DeleteDataItemsResponse; import com.google.android.gms.wearable.internal.GetCapabilityResponse; import com.google.android.gms.wearable.internal.GetCloudSyncSettingResponse; import com.google.android.gms.wearable.internal.GetConfigResponse; import com.google.android.gms.wearable.internal.GetConfigsResponse; Loading @@ -45,9 +48,13 @@ 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.RemoveLocalCapabilityResponse; import com.google.android.gms.wearable.internal.SendMessageResponse; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; import java.util.Set; public class WearableServiceImpl extends IWearableService.Stub { private static final String TAG = "GmsWearSvcImpl"; Loading @@ -56,11 +63,13 @@ public class WearableServiceImpl extends IWearableService.Stub { private final String packageName; private final WearableImpl wearable; private final Handler mainHandler; private final CapabilityManager capabilities; public WearableServiceImpl(Context context, WearableImpl wearable, String packageName) { this.context = context; this.wearable = wearable; this.packageName = packageName; this.capabilities = new CapabilityManager(context, wearable, packageName); this.mainHandler = new Handler(context.getMainLooper()); } Loading Loading @@ -191,8 +200,11 @@ public class WearableServiceImpl extends IWearableService.Stub { @Override public void deleteDataItemsWithFilter(IWearableCallbacks callbacks, final Uri uri, int typeFilter) throws RemoteException { Log.d(TAG, "deleteDataItems: " + uri); postMain(callbacks, () -> { this.wearable.networkHandler.post(new CallbackRunnable(callbacks) { @Override public void run(IWearableCallbacks callbacks) throws RemoteException { callbacks.onDeleteDataItemsResponse(new DeleteDataItemsResponse(0, wearable.deleteDataItems(uri, packageName))); } }); } Loading Loading @@ -289,29 +301,49 @@ public class WearableServiceImpl extends IWearableService.Stub { */ @Override public void getConnectedCapability(IWearableCallbacks callbacks, String s1, int i) throws RemoteException { Log.d(TAG, "unimplemented Method: getConnectedCapability " + s1 + ", " + i); public void getConnectedCapability(IWearableCallbacks callbacks, String capability, int nodeFilter) throws RemoteException { Log.d(TAG, "unimplemented Method: getConnectedCapability " + capability + ", " + nodeFilter); postMain(callbacks, () -> { List<NodeParcelable> nodes = new ArrayList<>(); for (String host : capabilities.getNodesForCapability(capability)) { nodes.add(new NodeParcelable(host, host)); } CapabilityInfoParcelable capabilityInfo = new CapabilityInfoParcelable(capability, nodes); callbacks.onGetCapabilityResponse(new GetCapabilityResponse(0, capabilityInfo)); }); } @Override public void getConnectedCapaibilties(IWearableCallbacks callbacks, int i) throws RemoteException { Log.d(TAG, "unimplemented Method: getConnectedCapaibilties: " + i); public void getConnectedCapaibilties(IWearableCallbacks callbacks, int nodeFilter) throws RemoteException { Log.d(TAG, "unimplemented Method: getConnectedCapaibilties: " + nodeFilter); } @Override public void addLocalCapability(IWearableCallbacks callbacks, String cap) throws RemoteException { Log.d(TAG, "unimplemented Method: addLocalCapability: " + cap); public void addLocalCapability(IWearableCallbacks callbacks, String capability) throws RemoteException { Log.d(TAG, "unimplemented Method: addLocalCapability: " + capability); this.wearable.networkHandler.post(new CallbackRunnable(callbacks) { @Override public void run(IWearableCallbacks callbacks) throws RemoteException { callbacks.onAddLocalCapabilityResponse(new AddLocalCapabilityResponse(capabilities.add(capability))); } }); } @Override public void removeLocalCapability(IWearableCallbacks callbacks, String cap) throws RemoteException { Log.d(TAG, "unimplemented Method: removeLocalCapability: " + cap); public void removeLocalCapability(IWearableCallbacks callbacks, String capability) throws RemoteException { Log.d(TAG, "unimplemented Method: removeLocalCapability: " + capability); this.wearable.networkHandler.post(new CallbackRunnable(callbacks) { @Override public void run(IWearableCallbacks callbacks) throws RemoteException { callbacks.onRemoveLocalCapabilityResponse(new RemoveLocalCapabilityResponse(capabilities.remove(capability))); } }); } @Override public void addListener(IWearableCallbacks callbacks, AddListenerRequest request) throws RemoteException { if (request.listener != null) { wearable.addListener(packageName, request.listener); wearable.addListener(packageName, request.listener, request.intentFilters); } callbacks.onStatus(Status.SUCCESS); } Loading Loading
play-services-core/src/main/java/org/microg/gms/common/RemoteListenerProxy.java +10 −5 Original line number Diff line number Diff line /* * Copyright (C) 2013-2017 microG Project Team * Copyright (C) 2013-2019 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. Loading Loading @@ -66,7 +66,6 @@ public class RemoteListenerProxy<T extends IInterface> implements ServiceConnect if (!connecting) Log.d(TAG, "Could not connect to: " + intent); return connecting; } Log.d(TAG, "Unable to resolve: " + searchIntent); return false; } catch (Exception e) { Log.w(TAG, e); Loading @@ -91,11 +90,17 @@ public class RemoteListenerProxy<T extends IInterface> implements ServiceConnect synchronized (this) { remote = service; if (!waiting.isEmpty()) { try { for (Runnable runnable : waiting) { runnable.run(); } } catch (Exception e) { } waiting.clear(); try { context.unbindService(RemoteListenerProxy.this); } catch (Exception e) { } connecting = false; remote = null; } Loading
play-services-core/src/main/java/org/microg/gms/wearable/WearableImpl.java +106 −107 Original line number Diff line number Diff line /* * Copyright (C) 2013-2017 microG Project Team * Copyright (C) 2013-2019 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. Loading @@ -16,14 +16,15 @@ package org.microg.gms.wearable; import android.annotation.TargetApi; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.Cursor; import android.net.Uri; import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.Base64; import android.util.Log; Loading @@ -37,7 +38,6 @@ import com.google.android.gms.wearable.internal.MessageEventParcelable; import com.google.android.gms.wearable.internal.NodeParcelable; 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.RemoteListenerProxy; import org.microg.gms.common.Utils; Loading @@ -52,6 +52,7 @@ import org.microg.wearable.proto.FilePiece; import org.microg.wearable.proto.Request; import org.microg.wearable.proto.RootMessage; import org.microg.wearable.proto.SetAsset; import org.microg.wearable.proto.SetDataItem; import java.io.File; import java.io.FileInputStream; Loading @@ -70,8 +71,6 @@ import java.util.Set; import okio.ByteString; import static android.os.Build.VERSION.SDK_INT; public class WearableImpl { private static final String TAG = "GmsWear"; Loading @@ -81,7 +80,7 @@ public class WearableImpl { private final Context context; private final NodeDatabaseHelper nodeDatabase; private final ConfigurationDatabaseHelper configDatabase; private final Map<String, List<IWearableListener>> listeners = new HashMap<String, List<IWearableListener>>(); private final Map<String, List<ListenerInfo>> listeners = new HashMap<String, List<ListenerInfo>>(); private final Set<Node> connectedNodes = new HashSet<Node>(); private final Map<String, WearableConnection> activeConnections = new HashMap<String, WearableConnection>(); private RpcHelper rpcHelper; Loading Loading @@ -130,12 +129,10 @@ public class WearableImpl { } } } try { getListener(record.packageName, "com.google.android.gms.wearable.DATA_CHANGED", record.dataItem.uri) .onDataChanged(record.toEventDataHolder()); } catch (RemoteException e) { Log.w(TAG, e); } Intent intent = new Intent("com.google.android.gms.wearable.DATA_CHANGED"); intent.setPackage(record.packageName); intent.setData(record.dataItem.uri); invokeListeners(intent, listener -> listener.onDataChanged(record.toEventDataHolder())); return record; } Loading Loading @@ -247,8 +244,7 @@ public class WearableImpl { } private void syncRecordToAll(DataItemRecord record) { Log.d(TAG, "Syncing record " + record + " over " + activeConnections.size() + " connections."); void syncRecordToAll(DataItemRecord record) { for (String nodeId : new ArrayList<String>(activeConnections.keySet())) { syncRecordToPeer(nodeId, record); } Loading @@ -256,23 +252,27 @@ public class WearableImpl { private boolean syncRecordToPeer(String nodeId, DataItemRecord record) { for (Asset asset : record.dataItem.getAssets().values()) { try { syncAssetToPeer(nodeId, record, asset); } catch (Exception e) { Log.w(TAG, "Could not sync asset " + asset + " for " + nodeId + " and " + record, e); closeConnection(nodeId); return false; } } Log.d(TAG, "Sync over to " + nodeId + ": " + record); try { activeConnections.get(nodeId).writeMessage(new RootMessage.Builder().setDataItem(record.toSetDataItem()).build()); } catch (IOException e) { closeConnection(nodeId); SetDataItem item = record.toSetDataItem(); activeConnections.get(nodeId).writeMessage(new RootMessage.Builder().setDataItem(item).build()); } catch (Exception e) { Log.w(TAG, e); closeConnection(nodeId); return false; } return true; } private void syncAssetToPeer(String nodeId, DataItemRecord record, Asset asset) { try { Log.d(TAG, "Sync over to " + nodeId + ": " + asset); private void syncAssetToPeer(String nodeId, DataItemRecord record, Asset asset) throws IOException { RootMessage announceMessage = new RootMessage.Builder().setAsset(new SetAsset.Builder() .digest(asset.getDigest()) .appkeys(new AppKeys(Collections.singletonList(new AppKey(record.packageName, record.signatureDigest)))) Loading @@ -286,17 +286,11 @@ public class WearableImpl { int c = 0; while ((c = fis.read(arr)) > 0) { if (lastPiece != null) { 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 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); } } public void addAssetToDatabase(Asset asset, List<AppKey> appKeys) { Loading Loading @@ -394,37 +388,59 @@ public class WearableImpl { return nodes; } public IWearableListener getAllListeners() { return MultiListenerProxy.get(IWearableListener.class, new MultiListenerProxy.MultiCollectionListenerPool<IWearableListener>(listeners.values())); interface ListenerInvoker { void invoke(IWearableListener listener) throws RemoteException; } public void onPeerConnected(NodeParcelable node) { Log.d(TAG, "onPeerConnected: " + node); private void invokeListeners(@Nullable Intent intent, ListenerInvoker invoker) { for (String packageName : new ArrayList<>(listeners.keySet())) { List<ListenerInfo> listeners = this.listeners.get(packageName); if (listeners == null) continue; for (int i = 0; i < listeners.size(); i++) { boolean filterMatched = false; if (intent != null) { for (IntentFilter filter : listeners.get(i).filters) { filterMatched |= filter.match(context.getContentResolver(), intent, false, TAG) > 0; } } if (filterMatched || listeners.get(i).filters.length == 0) { try { getAllListeners().onPeerConnected(node); invoker.invoke(listeners.get(i).listener); } catch (RemoteException e) { Log.w(TAG, e); Log.w(TAG, "Registered listener at package " + packageName + " failed, removing."); listeners.remove(i); i--; } } } if (listeners.isEmpty()) { this.listeners.remove(packageName); } } if (intent != null) { try { invoker.invoke(RemoteListenerProxy.get(context, intent, IWearableListener.class, "com.google.android.gms.wearable.BIND_LISTENER")); } catch (RemoteException e) { Log.w(TAG, "Failed to deliver message received to " + intent, e); } } } public void onPeerConnected(NodeParcelable node) { Log.d(TAG, "onPeerConnected: " + node); invokeListeners(null, listener -> listener.onPeerConnected(node)); addConnectedNode(node); } public void onPeerDisconnected(NodeParcelable node) { Log.d(TAG, "onPeerDisconnected: " + node); try { getAllListeners().onPeerDisconnected(node); } catch (RemoteException e) { Log.w(TAG, e); } invokeListeners(null, listener -> listener.onPeerDisconnected(node)); removeConnectedNode(node.getId()); } public void onConnectedNodes(List<NodeParcelable> nodes) { Log.d(TAG, "onConnectedNodes: " + nodes); try { getAllListeners().onConnectedNodes(nodes); } catch (RemoteException e) { Log.w(TAG, e); } invokeListeners(null, listener -> listener.onConnectedNodes(nodes)); } public DataItemRecord putData(PutDataRequest request, String packageName) { Loading @@ -444,11 +460,6 @@ public class WearableImpl { public DataHolder getDataItemsAsHolder(String packageName) { Cursor dataHolderItems = nodeDatabase.getDataItemsForDataHolder(packageName, PackageUtils.firstSignatureDigest(context, packageName)); while (dataHolderItems.moveToNext()) { Log.d(TAG, "getDataItems[]: path=" + Uri.parse(dataHolderItems.getString(1)).getPath()); } dataHolderItems.moveToFirst(); dataHolderItems.moveToPrevious(); return new DataHolder(dataHolderItems, 0, null); } Loading @@ -467,40 +478,26 @@ public class WearableImpl { return null; } Cursor dataHolderItems = nodeDatabase.getDataItemsForDataHolderByHostAndPath(packageName, firstSignature, fixHost(uri.getHost(), false), uri.getPath()); maybeDebugCursor("getDataItems",dataHolderItems); dataHolderItems.moveToFirst(); dataHolderItems.moveToPrevious(); DataHolder dataHolder = new DataHolder(dataHolderItems, 0, null); Log.d(TAG, "Returning data holder of size " + dataHolder.getCount() + " for query " + uri); return dataHolder; } @TargetApi(11) private void maybeDebugCursor(String what, Cursor cursor) { if (SDK_INT >= 11) { int j = 0; while (cursor.moveToNext()) { for (int i = 0; i < cursor.getColumnCount(); i++) { if (cursor.getType(i) == Cursor.FIELD_TYPE_STRING) { Log.d(TAG, what+"[" + j + "]: " + cursor.getColumnName(i) + "=" + cursor.getString(i)); } if (cursor.getType(i) == Cursor.FIELD_TYPE_INTEGER) Log.d(TAG, what+"[" + j + "]: " + cursor.getColumnName(i) + "=" + cursor.getLong(i)); } } } } public synchronized void addListener(String packageName, IWearableListener listener) { public synchronized void addListener(String packageName, IWearableListener listener, IntentFilter[] filters) { if (!listeners.containsKey(packageName)) { listeners.put(packageName, new ArrayList<IWearableListener>()); listeners.put(packageName, new ArrayList<ListenerInfo>()); } listeners.get(packageName).add(listener); listeners.get(packageName).add(new ListenerInfo(listener, filters)); } public void removeListener(IWearableListener listener) { for (List<IWearableListener> list : listeners.values()) { list.remove(listener); for (List<ListenerInfo> list : listeners.values()) { for (int i = 0; i < list.size(); i++) { if (list.get(i).listener.equals(listener)) { list.remove(i); i--; } } } } Loading Loading @@ -546,12 +543,10 @@ public class WearableImpl { public void sendMessageReceived(String packageName, MessageEventParcelable messageEvent) { Log.d(TAG, "onMessageReceived: " + messageEvent); try { getListener(packageName, "com.google.android.gms.wearable.MESSAGE_RECEIVED", Uri.parse("wear://" + getLocalNodeId() + "/" + messageEvent.getPath())) .onMessageReceived(messageEvent); } catch (RemoteException e) { Log.w(TAG, e); } Intent intent = new Intent("com.google.android.gms.wearable.MESSAGE_RECEIVED"); intent.setPackage(packageName); intent.setData(Uri.parse("wear://" + getLocalNodeId() + "/" + messageEvent.getPath())); invokeListeners(intent, listener -> listener.onMessageReceived(messageEvent)); } public DataItemRecord getDataItemByUri(Uri uri, String packageName) { Loading @@ -568,17 +563,11 @@ public class WearableImpl { } private IWearableListener getListener(String packageName, String action, Uri uri) { synchronized (this) { List<IWearableListener> l = new ArrayList<IWearableListener>(listeners.containsKey(packageName) ? listeners.get(packageName) : Collections.<IWearableListener>emptyList()); Intent intent = new Intent(action); intent.setPackage(packageName); intent.setData(uri); l.add(RemoteListenerProxy.get(context, intent, IWearableListener.class, "com.google.android.gms.wearable.BIND_LISTENER")); return MultiListenerProxy.get(IWearableListener.class, l); } return RemoteListenerProxy.get(context, intent, IWearableListener.class, "com.google.android.gms.wearable.BIND_LISTENER"); } private void closeConnection(String nodeId) { Loading @@ -594,7 +583,7 @@ public class WearableImpl { } activeConnections.remove(nodeId); for (ConnectionConfiguration config : getConfigurations()) { if (config.nodeId.equals(nodeId) || config.peerNodeId.equals(nodeId)) { if (nodeId.equals(config.nodeId) || nodeId.equals(config.peerNodeId)) { config.connected = false; } } Loading Loading @@ -631,4 +620,14 @@ public class WearableImpl { public void stop() { this.networkHandler.getLooper().quit(); } private class ListenerInfo { private IWearableListener listener; private IntentFilter[] filters; private ListenerInfo(IWearableListener listener, IntentFilter[] filters) { this.listener = listener; this.filters = filters; } } }
play-services-core/src/main/java/org/microg/gms/wearable/WearableServiceImpl.java +44 −12 Original line number Diff line number Diff line /* * Copyright (C) 2013-2017 microG Project Team * Copyright (C) 2013-2019 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. Loading Loading @@ -29,8 +29,11 @@ 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.AddLocalCapabilityResponse; import com.google.android.gms.wearable.internal.AncsNotificationParcelable; import com.google.android.gms.wearable.internal.CapabilityInfoParcelable; import com.google.android.gms.wearable.internal.DeleteDataItemsResponse; import com.google.android.gms.wearable.internal.GetCapabilityResponse; import com.google.android.gms.wearable.internal.GetCloudSyncSettingResponse; import com.google.android.gms.wearable.internal.GetConfigResponse; import com.google.android.gms.wearable.internal.GetConfigsResponse; Loading @@ -45,9 +48,13 @@ 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.RemoveLocalCapabilityResponse; import com.google.android.gms.wearable.internal.SendMessageResponse; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; import java.util.Set; public class WearableServiceImpl extends IWearableService.Stub { private static final String TAG = "GmsWearSvcImpl"; Loading @@ -56,11 +63,13 @@ public class WearableServiceImpl extends IWearableService.Stub { private final String packageName; private final WearableImpl wearable; private final Handler mainHandler; private final CapabilityManager capabilities; public WearableServiceImpl(Context context, WearableImpl wearable, String packageName) { this.context = context; this.wearable = wearable; this.packageName = packageName; this.capabilities = new CapabilityManager(context, wearable, packageName); this.mainHandler = new Handler(context.getMainLooper()); } Loading Loading @@ -191,8 +200,11 @@ public class WearableServiceImpl extends IWearableService.Stub { @Override public void deleteDataItemsWithFilter(IWearableCallbacks callbacks, final Uri uri, int typeFilter) throws RemoteException { Log.d(TAG, "deleteDataItems: " + uri); postMain(callbacks, () -> { this.wearable.networkHandler.post(new CallbackRunnable(callbacks) { @Override public void run(IWearableCallbacks callbacks) throws RemoteException { callbacks.onDeleteDataItemsResponse(new DeleteDataItemsResponse(0, wearable.deleteDataItems(uri, packageName))); } }); } Loading Loading @@ -289,29 +301,49 @@ public class WearableServiceImpl extends IWearableService.Stub { */ @Override public void getConnectedCapability(IWearableCallbacks callbacks, String s1, int i) throws RemoteException { Log.d(TAG, "unimplemented Method: getConnectedCapability " + s1 + ", " + i); public void getConnectedCapability(IWearableCallbacks callbacks, String capability, int nodeFilter) throws RemoteException { Log.d(TAG, "unimplemented Method: getConnectedCapability " + capability + ", " + nodeFilter); postMain(callbacks, () -> { List<NodeParcelable> nodes = new ArrayList<>(); for (String host : capabilities.getNodesForCapability(capability)) { nodes.add(new NodeParcelable(host, host)); } CapabilityInfoParcelable capabilityInfo = new CapabilityInfoParcelable(capability, nodes); callbacks.onGetCapabilityResponse(new GetCapabilityResponse(0, capabilityInfo)); }); } @Override public void getConnectedCapaibilties(IWearableCallbacks callbacks, int i) throws RemoteException { Log.d(TAG, "unimplemented Method: getConnectedCapaibilties: " + i); public void getConnectedCapaibilties(IWearableCallbacks callbacks, int nodeFilter) throws RemoteException { Log.d(TAG, "unimplemented Method: getConnectedCapaibilties: " + nodeFilter); } @Override public void addLocalCapability(IWearableCallbacks callbacks, String cap) throws RemoteException { Log.d(TAG, "unimplemented Method: addLocalCapability: " + cap); public void addLocalCapability(IWearableCallbacks callbacks, String capability) throws RemoteException { Log.d(TAG, "unimplemented Method: addLocalCapability: " + capability); this.wearable.networkHandler.post(new CallbackRunnable(callbacks) { @Override public void run(IWearableCallbacks callbacks) throws RemoteException { callbacks.onAddLocalCapabilityResponse(new AddLocalCapabilityResponse(capabilities.add(capability))); } }); } @Override public void removeLocalCapability(IWearableCallbacks callbacks, String cap) throws RemoteException { Log.d(TAG, "unimplemented Method: removeLocalCapability: " + cap); public void removeLocalCapability(IWearableCallbacks callbacks, String capability) throws RemoteException { Log.d(TAG, "unimplemented Method: removeLocalCapability: " + capability); this.wearable.networkHandler.post(new CallbackRunnable(callbacks) { @Override public void run(IWearableCallbacks callbacks) throws RemoteException { callbacks.onRemoveLocalCapabilityResponse(new RemoveLocalCapabilityResponse(capabilities.remove(capability))); } }); } @Override public void addListener(IWearableCallbacks callbacks, AddListenerRequest request) throws RemoteException { if (request.listener != null) { wearable.addListener(packageName, request.listener); wearable.addListener(packageName, request.listener, request.intentFilters); } callbacks.onStatus(Status.SUCCESS); } Loading