mirror of
https://github.com/TeamVanced/VancedMicroG
synced 2025-02-02 14:07:32 +01:00
Add heartbeat feature for MCS
This commit is contained in:
parent
f8be4c534c
commit
a1a27167e6
3
.gitignore
vendored
3
.gitignore
vendored
@ -2,6 +2,7 @@
|
|||||||
gen/
|
gen/
|
||||||
bin/
|
bin/
|
||||||
build/
|
build/
|
||||||
|
.gradle/
|
||||||
user.gradle
|
user.gradle
|
||||||
local.properties
|
local.properties
|
||||||
.directory
|
.directory
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2013-2015 µg Project Team
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.microg.gms.gcm;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import org.microg.gms.checkin.LastCheckinInfo;
|
|
||||||
import org.microg.gms.common.PackageUtils;
|
|
||||||
import org.microg.gms.common.Utils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class GcmManager {
|
|
||||||
private static final String TAG = "GmsGcmManager";
|
|
||||||
|
|
||||||
public static String register(Context context, String app, String sender, String info) {
|
|
||||||
try {
|
|
||||||
return new RegisterRequest()
|
|
||||||
.build(Utils.getBuild(context))
|
|
||||||
.sender(sender)
|
|
||||||
.info(info)
|
|
||||||
.checkin(LastCheckinInfo.read(context))
|
|
||||||
.app(app, PackageUtils.firstSignatureDigest(context, app), PackageUtils.versionCode(context, app))
|
|
||||||
.getResponse()
|
|
||||||
.token;
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.w(TAG, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -18,6 +18,7 @@ package org.microg.gms.gcm;
|
|||||||
|
|
||||||
import android.app.IntentService;
|
import android.app.IntentService;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -25,6 +26,12 @@ import android.os.Message;
|
|||||||
import android.os.Messenger;
|
import android.os.Messenger;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.microg.gms.checkin.LastCheckinInfo;
|
||||||
|
import org.microg.gms.common.PackageUtils;
|
||||||
|
import org.microg.gms.common.Utils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public class PushRegisterService extends IntentService {
|
public class PushRegisterService extends IntentService {
|
||||||
private static final String TAG = "GmsGcmRegisterSvc";
|
private static final String TAG = "GmsGcmRegisterSvc";
|
||||||
|
|
||||||
@ -66,7 +73,7 @@ public class PushRegisterService extends IntentService {
|
|||||||
Log.d(TAG, "register[req]: " + extras);
|
Log.d(TAG, "register[req]: " + extras);
|
||||||
Intent outIntent = new Intent("com.google.android.c2dm.intent.REGISTRATION");
|
Intent outIntent = new Intent("com.google.android.c2dm.intent.REGISTRATION");
|
||||||
outIntent.setPackage(app);
|
outIntent.setPackage(app);
|
||||||
String regId = GcmManager.register(this, app, sender, null);
|
String regId = register(this, app, sender, null);
|
||||||
if (regId != null) {
|
if (regId != null) {
|
||||||
outIntent.putExtra("registration_id", regId);
|
outIntent.putExtra("registration_id", regId);
|
||||||
} else {
|
} else {
|
||||||
@ -87,6 +94,23 @@ public class PushRegisterService extends IntentService {
|
|||||||
sendOrderedBroadcast(outIntent, null);
|
sendOrderedBroadcast(outIntent, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String register(Context context, String app, String sender, String info) {
|
||||||
|
try {
|
||||||
|
return new RegisterRequest()
|
||||||
|
.build(Utils.getBuild(context))
|
||||||
|
.sender(sender)
|
||||||
|
.info(info)
|
||||||
|
.checkin(LastCheckinInfo.read(context))
|
||||||
|
.app(app, PackageUtils.firstSignatureDigest(context, app), PackageUtils.versionCode(context, app))
|
||||||
|
.getResponse()
|
||||||
|
.token;
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.w(TAG, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private void unregister(Intent intent) {
|
private void unregister(Intent intent) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package org.microg.gms.gcm.mcs;
|
package org.microg.gms.gcm.mcs;
|
||||||
|
|
||||||
public class Constants {
|
public class Constants {
|
||||||
|
public static final int MCS_HEARTBEAT_PING_TAG = 0;
|
||||||
public static final int MCS_HEARTBEAT_ACK_TAG = 1;
|
public static final int MCS_HEARTBEAT_ACK_TAG = 1;
|
||||||
public static final int MCS_LOGIN_REQUEST_TAG = 2;
|
public static final int MCS_LOGIN_REQUEST_TAG = 2;
|
||||||
public static final int MCS_LOGIN_RESPONSE_TAG = 3;
|
public static final int MCS_LOGIN_RESPONSE_TAG = 3;
|
||||||
|
@ -28,6 +28,7 @@ import java.io.InputStream;
|
|||||||
import static org.microg.gms.gcm.mcs.Constants.MCS_CLOSE_TAG;
|
import static org.microg.gms.gcm.mcs.Constants.MCS_CLOSE_TAG;
|
||||||
import static org.microg.gms.gcm.mcs.Constants.MCS_DATA_MESSAGE_STANZA_TAG;
|
import static org.microg.gms.gcm.mcs.Constants.MCS_DATA_MESSAGE_STANZA_TAG;
|
||||||
import static org.microg.gms.gcm.mcs.Constants.MCS_HEARTBEAT_ACK_TAG;
|
import static org.microg.gms.gcm.mcs.Constants.MCS_HEARTBEAT_ACK_TAG;
|
||||||
|
import static org.microg.gms.gcm.mcs.Constants.MCS_HEARTBEAT_PING_TAG;
|
||||||
import static org.microg.gms.gcm.mcs.Constants.MCS_IQ_STANZA_TAG;
|
import static org.microg.gms.gcm.mcs.Constants.MCS_IQ_STANZA_TAG;
|
||||||
import static org.microg.gms.gcm.mcs.Constants.MCS_LOGIN_REQUEST_TAG;
|
import static org.microg.gms.gcm.mcs.Constants.MCS_LOGIN_REQUEST_TAG;
|
||||||
import static org.microg.gms.gcm.mcs.Constants.MCS_LOGIN_RESPONSE_TAG;
|
import static org.microg.gms.gcm.mcs.Constants.MCS_LOGIN_RESPONSE_TAG;
|
||||||
@ -94,6 +95,8 @@ public class McsInputStream {
|
|||||||
private static Message read(int mcsTag, byte[] bytes, int len) throws IOException {
|
private static Message read(int mcsTag, byte[] bytes, int len) throws IOException {
|
||||||
Wire wire = new Wire();
|
Wire wire = new Wire();
|
||||||
switch (mcsTag) {
|
switch (mcsTag) {
|
||||||
|
case MCS_HEARTBEAT_PING_TAG:
|
||||||
|
return wire.parseFrom(bytes, 0, len, HeartbeatPing.class);
|
||||||
case MCS_HEARTBEAT_ACK_TAG:
|
case MCS_HEARTBEAT_ACK_TAG:
|
||||||
return wire.parseFrom(bytes, 0, len, HeartbeatAck.class);
|
return wire.parseFrom(bytes, 0, len, HeartbeatAck.class);
|
||||||
case MCS_LOGIN_REQUEST_TAG:
|
case MCS_LOGIN_REQUEST_TAG:
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
package org.microg.gms.gcm.mcs;
|
||||||
|
|
||||||
|
public class McsMessage {
|
||||||
|
}
|
@ -58,6 +58,10 @@ public class McsOutputStream {
|
|||||||
write(ack, MCS_HEARTBEAT_ACK_TAG);
|
write(ack, MCS_HEARTBEAT_ACK_TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void write(HeartbeatPing ping) throws IOException{
|
||||||
|
write(ping, MCS_HEARTBEAT_PING_TAG);
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized void write(Message message, int tag) throws IOException {
|
public synchronized void write(Message message, int tag) throws IOException {
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
Log.d(TAG, "Write MCS version code: " + version);
|
Log.d(TAG, "Write MCS version code: " + version);
|
||||||
|
@ -29,6 +29,7 @@ import org.microg.gms.checkin.LastCheckinInfo;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
@ -45,12 +46,16 @@ public class McsService extends IntentService {
|
|||||||
public static final String SELF_CATEGORY = "com.google.android.gsf.gtalkservice";
|
public static final String SELF_CATEGORY = "com.google.android.gsf.gtalkservice";
|
||||||
public static final String IDLE_NOTIFICATION = "IdleNotification";
|
public static final String IDLE_NOTIFICATION = "IdleNotification";
|
||||||
public static final String FROM_FIELD = "gcm@android.com";
|
public static final String FROM_FIELD = "gcm@android.com";
|
||||||
|
public static final int HEARTBEAT_MS = 60000;
|
||||||
private static AtomicBoolean connected = new AtomicBoolean(false);
|
private static AtomicBoolean connected = new AtomicBoolean(false);
|
||||||
|
|
||||||
private Socket socket;
|
private Socket socket;
|
||||||
private Socket sslSocket;
|
private Socket sslSocket;
|
||||||
private McsInputStream inputStream;
|
private McsInputStream inputStream;
|
||||||
private McsOutputStream outputStream;
|
private McsOutputStream outputStream;
|
||||||
|
private Thread connectionThread;
|
||||||
|
private Thread heartbeatThread;
|
||||||
|
private long lastMsgTime;
|
||||||
|
|
||||||
public McsService() {
|
public McsService() {
|
||||||
super(TAG);
|
super(TAG);
|
||||||
@ -59,17 +64,50 @@ public class McsService extends IntentService {
|
|||||||
@Override
|
@Override
|
||||||
protected void onHandleIntent(Intent intent) {
|
protected void onHandleIntent(Intent intent) {
|
||||||
if (connected.compareAndSet(false, true)) {
|
if (connected.compareAndSet(false, true)) {
|
||||||
new Thread(new Runnable() {
|
connectionThread = new Thread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
connect();
|
connect();
|
||||||
}
|
}
|
||||||
}).start();
|
});
|
||||||
|
connectionThread.start();
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, "MCS connection already started");
|
Log.d(TAG, "MCS connection already started");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void heartbeatLoop() {
|
||||||
|
try {
|
||||||
|
while (!Thread.interrupted()) {
|
||||||
|
try {
|
||||||
|
long waitTime;
|
||||||
|
while ((waitTime = lastMsgTime + HEARTBEAT_MS - System.currentTimeMillis()) > 0) {
|
||||||
|
synchronized (heartbeatThread) {
|
||||||
|
Log.d(TAG, "Waiting for " + waitTime + "ms");
|
||||||
|
heartbeatThread.wait(waitTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HeartbeatPing.Builder ping = new HeartbeatPing.Builder();
|
||||||
|
if (inputStream.newStreamIdAvailable()) {
|
||||||
|
ping.last_stream_id_received(inputStream.getStreamId());
|
||||||
|
}
|
||||||
|
outputStream.write(ping.build());
|
||||||
|
lastMsgTime = System.currentTimeMillis();
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
Log.w(TAG, ie);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.w(TAG, e);
|
||||||
|
connectionThread.interrupt();
|
||||||
|
}
|
||||||
|
if (heartbeatThread == Thread.currentThread()) {
|
||||||
|
heartbeatThread = null;
|
||||||
|
}
|
||||||
|
Log.d(TAG, "Heartbeating stopped");
|
||||||
|
}
|
||||||
|
|
||||||
private void connect() {
|
private void connect() {
|
||||||
try {
|
try {
|
||||||
Log.d(TAG, "Starting MCS connection...");
|
Log.d(TAG, "Starting MCS connection...");
|
||||||
@ -86,6 +124,7 @@ public class McsService extends IntentService {
|
|||||||
boolean close = false;
|
boolean close = false;
|
||||||
while (!close) {
|
while (!close) {
|
||||||
Message o = inputStream.read();
|
Message o = inputStream.read();
|
||||||
|
lastMsgTime = System.currentTimeMillis();
|
||||||
if (o instanceof DataMessageStanza) {
|
if (o instanceof DataMessageStanza) {
|
||||||
handleMessage((DataMessageStanza) o);
|
handleMessage((DataMessageStanza) o);
|
||||||
} else if (o instanceof HeartbeatPing) {
|
} else if (o instanceof HeartbeatPing) {
|
||||||
@ -96,7 +135,7 @@ public class McsService extends IntentService {
|
|||||||
handleLoginresponse((LoginResponse) o);
|
handleLoginresponse((LoginResponse) o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
socket.close();
|
sslSocket.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, e);
|
Log.w(TAG, e);
|
||||||
try {
|
try {
|
||||||
@ -104,7 +143,12 @@ public class McsService extends IntentService {
|
|||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (heartbeatThread != null) {
|
||||||
|
heartbeatThread.interrupt();
|
||||||
|
heartbeatThread = null;
|
||||||
|
}
|
||||||
connected.set(false);
|
connected.set(false);
|
||||||
|
Log.d(TAG, "Connection closed");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleClose(Close close) throws IOException {
|
private void handleClose(Close close) throws IOException {
|
||||||
@ -118,6 +162,15 @@ public class McsService extends IntentService {
|
|||||||
} else {
|
} else {
|
||||||
throw new IOException("Could not login: " + loginResponse.error);
|
throw new IOException("Could not login: " + loginResponse.error);
|
||||||
}
|
}
|
||||||
|
if (heartbeatThread == null) {
|
||||||
|
heartbeatThread = new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
heartbeatLoop();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
heartbeatThread.start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleMessage(DataMessageStanza message) throws IOException {
|
private void handleMessage(DataMessageStanza message) throws IOException {
|
||||||
@ -181,7 +234,7 @@ public class McsService extends IntentService {
|
|||||||
.sent(System.currentTimeMillis() / 1000)
|
.sent(System.currentTimeMillis() / 1000)
|
||||||
.ttl(0)
|
.ttl(0)
|
||||||
.category(SELF_CATEGORY)
|
.category(SELF_CATEGORY)
|
||||||
.app_data(Arrays.asList(new AppData(IDLE_NOTIFICATION, "false")));
|
.app_data(Collections.singletonList(new AppData(IDLE_NOTIFICATION, "false")));
|
||||||
if (inputStream.newStreamIdAvailable()) {
|
if (inputStream.newStreamIdAvailable()) {
|
||||||
msgResponse.last_stream_id_received(inputStream.getStreamId());
|
msgResponse.last_stream_id_received(inputStream.getStreamId());
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user