mirror of https://github.com/YTVanced/VancedMicroG
GCM: Add support for message acking, deliver to all receivers of package when working permissionless
This commit is contained in:
parent
74c0e28e27
commit
60cc63ed60
|
@ -30,6 +30,7 @@ public final class GcmConstants {
|
||||||
public static final String ACTION_INSTANCE_ID = "com.google.android.gms.iid.InstanceID";
|
public static final String ACTION_INSTANCE_ID = "com.google.android.gms.iid.InstanceID";
|
||||||
|
|
||||||
public static final String EXTRA_APP = "app";
|
public static final String EXTRA_APP = "app";
|
||||||
|
public static final String EXTRA_APP_OVERRIDE = "org.microg.gms.gcm.APP_OVERRIDE";
|
||||||
public static final String EXTRA_APP_ID = "appid";
|
public static final String EXTRA_APP_ID = "appid";
|
||||||
public static final String EXTRA_APP_VERSION_CODE = "app_ver";
|
public static final String EXTRA_APP_VERSION_CODE = "app_ver";
|
||||||
public static final String EXTRA_APP_VERSION_NAME = "app_ver_name";
|
public static final String EXTRA_APP_VERSION_NAME = "app_ver_name";
|
||||||
|
|
|
@ -36,10 +36,12 @@ public final class McsConstants {
|
||||||
public static final int MSG_TEARDOWN = 30;
|
public static final int MSG_TEARDOWN = 30;
|
||||||
public static final int MSG_CONNECT = 40;
|
public static final int MSG_CONNECT = 40;
|
||||||
public static final int MSG_HEARTBEAT = 41;
|
public static final int MSG_HEARTBEAT = 41;
|
||||||
|
public static final int MSG_ACK = 42;
|
||||||
|
|
||||||
public static String ACTION_CONNECT = "org.microg.gms.gcm.mcs.CONNECT";
|
public static String ACTION_CONNECT = "org.microg.gms.gcm.mcs.CONNECT";
|
||||||
public static String ACTION_RECONNECT = "org.microg.gms.gcm.mcs.RECONNECT";
|
public static String ACTION_RECONNECT = "org.microg.gms.gcm.mcs.RECONNECT";
|
||||||
public static String ACTION_HEARTBEAT = "org.microg.gms.gcm.mcs.HEARTBEAT";
|
public static String ACTION_HEARTBEAT = "org.microg.gms.gcm.mcs.HEARTBEAT";
|
||||||
public static String ACTION_SEND = "org.microg.gms.gcm.mcs.SEND";
|
public static String ACTION_SEND = "org.microg.gms.gcm.mcs.SEND";
|
||||||
|
public static String ACTION_ACK = "org.microg.gms.gcm.mcs.ACK";
|
||||||
public static String EXTRA_REASON = "org.microg.gms.gcm.mcs.REASON";
|
public static String EXTRA_REASON = "org.microg.gms.gcm.mcs.REASON";
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.PermissionInfo;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
@ -51,8 +52,10 @@ import org.microg.gms.common.PackageUtils;
|
||||||
import org.microg.gms.gcm.mcs.AppData;
|
import org.microg.gms.gcm.mcs.AppData;
|
||||||
import org.microg.gms.gcm.mcs.Close;
|
import org.microg.gms.gcm.mcs.Close;
|
||||||
import org.microg.gms.gcm.mcs.DataMessageStanza;
|
import org.microg.gms.gcm.mcs.DataMessageStanza;
|
||||||
|
import org.microg.gms.gcm.mcs.Extension;
|
||||||
import org.microg.gms.gcm.mcs.HeartbeatAck;
|
import org.microg.gms.gcm.mcs.HeartbeatAck;
|
||||||
import org.microg.gms.gcm.mcs.HeartbeatPing;
|
import org.microg.gms.gcm.mcs.HeartbeatPing;
|
||||||
|
import org.microg.gms.gcm.mcs.IqStanza;
|
||||||
import org.microg.gms.gcm.mcs.LoginRequest;
|
import org.microg.gms.gcm.mcs.LoginRequest;
|
||||||
import org.microg.gms.gcm.mcs.LoginResponse;
|
import org.microg.gms.gcm.mcs.LoginResponse;
|
||||||
import org.microg.gms.gcm.mcs.Setting;
|
import org.microg.gms.gcm.mcs.Setting;
|
||||||
|
@ -64,6 +67,7 @@ import java.net.Socket;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
|
|
||||||
|
@ -74,6 +78,7 @@ import static android.os.Build.VERSION.SDK_INT;
|
||||||
import static org.microg.gms.common.ForegroundServiceContext.EXTRA_FOREGROUND;
|
import static org.microg.gms.common.ForegroundServiceContext.EXTRA_FOREGROUND;
|
||||||
import static org.microg.gms.gcm.GcmConstants.ACTION_C2DM_RECEIVE;
|
import static org.microg.gms.gcm.GcmConstants.ACTION_C2DM_RECEIVE;
|
||||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_APP;
|
import static org.microg.gms.gcm.GcmConstants.EXTRA_APP;
|
||||||
|
import static org.microg.gms.gcm.GcmConstants.EXTRA_APP_OVERRIDE;
|
||||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_COLLAPSE_KEY;
|
import static org.microg.gms.gcm.GcmConstants.EXTRA_COLLAPSE_KEY;
|
||||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_FROM;
|
import static org.microg.gms.gcm.GcmConstants.EXTRA_FROM;
|
||||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_MESSAGE_ID;
|
import static org.microg.gms.gcm.GcmConstants.EXTRA_MESSAGE_ID;
|
||||||
|
@ -82,6 +87,7 @@ import static org.microg.gms.gcm.GcmConstants.EXTRA_REGISTRATION_ID;
|
||||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_SEND_FROM;
|
import static org.microg.gms.gcm.GcmConstants.EXTRA_SEND_FROM;
|
||||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_SEND_TO;
|
import static org.microg.gms.gcm.GcmConstants.EXTRA_SEND_TO;
|
||||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_TTL;
|
import static org.microg.gms.gcm.GcmConstants.EXTRA_TTL;
|
||||||
|
import static org.microg.gms.gcm.McsConstants.ACTION_ACK;
|
||||||
import static org.microg.gms.gcm.McsConstants.ACTION_CONNECT;
|
import static org.microg.gms.gcm.McsConstants.ACTION_CONNECT;
|
||||||
import static org.microg.gms.gcm.McsConstants.ACTION_HEARTBEAT;
|
import static org.microg.gms.gcm.McsConstants.ACTION_HEARTBEAT;
|
||||||
import static org.microg.gms.gcm.McsConstants.ACTION_RECONNECT;
|
import static org.microg.gms.gcm.McsConstants.ACTION_RECONNECT;
|
||||||
|
@ -91,8 +97,10 @@ import static org.microg.gms.gcm.McsConstants.MCS_CLOSE_TAG;
|
||||||
import static org.microg.gms.gcm.McsConstants.MCS_DATA_MESSAGE_STANZA_TAG;
|
import static org.microg.gms.gcm.McsConstants.MCS_DATA_MESSAGE_STANZA_TAG;
|
||||||
import static org.microg.gms.gcm.McsConstants.MCS_HEARTBEAT_ACK_TAG;
|
import static org.microg.gms.gcm.McsConstants.MCS_HEARTBEAT_ACK_TAG;
|
||||||
import static org.microg.gms.gcm.McsConstants.MCS_HEARTBEAT_PING_TAG;
|
import static org.microg.gms.gcm.McsConstants.MCS_HEARTBEAT_PING_TAG;
|
||||||
|
import static org.microg.gms.gcm.McsConstants.MCS_IQ_STANZA_TAG;
|
||||||
import static org.microg.gms.gcm.McsConstants.MCS_LOGIN_REQUEST_TAG;
|
import static org.microg.gms.gcm.McsConstants.MCS_LOGIN_REQUEST_TAG;
|
||||||
import static org.microg.gms.gcm.McsConstants.MCS_LOGIN_RESPONSE_TAG;
|
import static org.microg.gms.gcm.McsConstants.MCS_LOGIN_RESPONSE_TAG;
|
||||||
|
import static org.microg.gms.gcm.McsConstants.MSG_ACK;
|
||||||
import static org.microg.gms.gcm.McsConstants.MSG_CONNECT;
|
import static org.microg.gms.gcm.McsConstants.MSG_CONNECT;
|
||||||
import static org.microg.gms.gcm.McsConstants.MSG_HEARTBEAT;
|
import static org.microg.gms.gcm.McsConstants.MSG_HEARTBEAT;
|
||||||
import static org.microg.gms.gcm.McsConstants.MSG_INPUT;
|
import static org.microg.gms.gcm.McsConstants.MSG_INPUT;
|
||||||
|
@ -119,6 +127,7 @@ public class McsService extends Service implements Handler.Callback {
|
||||||
private static long lastIncomingNetworkRealtime = 0;
|
private static long lastIncomingNetworkRealtime = 0;
|
||||||
private static long startTimestamp = 0;
|
private static long startTimestamp = 0;
|
||||||
public static String activeNetworkPref = null;
|
public static String activeNetworkPref = null;
|
||||||
|
private AtomicInteger nextMessageId = new AtomicInteger(0x1000000);
|
||||||
|
|
||||||
private static Socket sslSocket;
|
private static Socket sslSocket;
|
||||||
private static McsInputStream inputStream;
|
private static McsInputStream inputStream;
|
||||||
|
@ -307,6 +316,8 @@ public class McsService extends Service implements Handler.Callback {
|
||||||
rootHandler.sendMessage(rootHandler.obtainMessage(MSG_HEARTBEAT, reason));
|
rootHandler.sendMessage(rootHandler.obtainMessage(MSG_HEARTBEAT, reason));
|
||||||
} else if (ACTION_SEND.equals(intent.getAction())) {
|
} else if (ACTION_SEND.equals(intent.getAction())) {
|
||||||
handleSendMessage(intent);
|
handleSendMessage(intent);
|
||||||
|
} else if (ACTION_ACK.equals(intent.getAction())) {
|
||||||
|
rootHandler.sendMessage(rootHandler.obtainMessage(MSG_ACK, reason));
|
||||||
}
|
}
|
||||||
WakefulBroadcastReceiver.completeWakefulIntent(intent);
|
WakefulBroadcastReceiver.completeWakefulIntent(intent);
|
||||||
} else if (connectIntent == null) {
|
} else if (connectIntent == null) {
|
||||||
|
@ -347,12 +358,20 @@ public class McsService extends Service implements Handler.Callback {
|
||||||
Log.w(TAG, "Failed to send message, missing package name");
|
Log.w(TAG, "Failed to send message, missing package name");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (packageName.equals(getPackageName()) && intent.hasExtra(EXTRA_APP_OVERRIDE)) {
|
||||||
|
packageName = intent.getStringExtra(EXTRA_APP_OVERRIDE);
|
||||||
|
intent.removeExtra(EXTRA_APP_OVERRIDE);
|
||||||
|
}
|
||||||
intent.removeExtra(EXTRA_APP);
|
intent.removeExtra(EXTRA_APP);
|
||||||
|
|
||||||
int ttl;
|
int ttl;
|
||||||
try {
|
try {
|
||||||
ttl = Integer.parseInt(intent.getStringExtra(EXTRA_TTL));
|
if (intent.hasExtra(EXTRA_TTL)) {
|
||||||
if (ttl < 0 || ttl > maxTtl) {
|
ttl = Integer.parseInt(intent.getStringExtra(EXTRA_TTL));
|
||||||
|
if (ttl < 0 || ttl > maxTtl) {
|
||||||
|
ttl = maxTtl;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
ttl = maxTtl;
|
ttl = maxTtl;
|
||||||
}
|
}
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
|
@ -403,7 +422,8 @@ public class McsService extends Service implements Handler.Callback {
|
||||||
try {
|
try {
|
||||||
DataMessageStanza msg = new DataMessageStanza.Builder()
|
DataMessageStanza msg = new DataMessageStanza.Builder()
|
||||||
.sent(System.currentTimeMillis() / 1000L)
|
.sent(System.currentTimeMillis() / 1000L)
|
||||||
.id(messageId)
|
.id(Integer.toHexString(nextMessageId.incrementAndGet()))
|
||||||
|
.persistent_id(messageId)
|
||||||
.token(collapseKey)
|
.token(collapseKey)
|
||||||
.from(from)
|
.from(from)
|
||||||
.reg_id(registrationId)
|
.reg_id(registrationId)
|
||||||
|
@ -513,9 +533,11 @@ public class McsService extends Service implements Handler.Callback {
|
||||||
|
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
intent.setAction(ACTION_C2DM_RECEIVE);
|
intent.setAction(ACTION_C2DM_RECEIVE);
|
||||||
intent.setPackage(packageName);
|
|
||||||
intent.putExtra(EXTRA_FROM, msg.from);
|
intent.putExtra(EXTRA_FROM, msg.from);
|
||||||
intent.putExtra(EXTRA_MESSAGE_ID, msg.id);
|
intent.putExtra(EXTRA_MESSAGE_ID, msg.id);
|
||||||
|
if (msg.persistent_id != null) {
|
||||||
|
intent.putExtra(EXTRA_MESSAGE_ID, msg.persistent_id);
|
||||||
|
}
|
||||||
if (app.wakeForDelivery) {
|
if (app.wakeForDelivery) {
|
||||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||||
} else {
|
} else {
|
||||||
|
@ -526,41 +548,52 @@ public class McsService extends Service implements Handler.Callback {
|
||||||
intent.putExtra(appData.key, appData.value);
|
intent.putExtra(appData.key, appData.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
String receiverPermission;
|
String receiverPermission = null;
|
||||||
try {
|
try {
|
||||||
String name = packageName + ".permission.C2D_MESSAGE";
|
String name = packageName + ".permission.C2D_MESSAGE";
|
||||||
getPackageManager().getPermissionInfo(name, 0);
|
PermissionInfo info = getPackageManager().getPermissionInfo(name, 0);
|
||||||
receiverPermission = name;
|
if (info.packageName.equals(packageName)) {
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
receiverPermission = name;
|
||||||
receiverPermission = null;
|
}
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
// Keep null, no valid permission found
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ResolveInfo> infos = getPackageManager().queryBroadcastReceivers(intent, PackageManager.GET_RESOLVED_FILTER);
|
if (receiverPermission == null) {
|
||||||
if (infos == null || infos.isEmpty()) {
|
// Without receiver permission, we only restrict by package name
|
||||||
logd("No target for message, wut?");
|
logd("Deliver message to all receivers in package " + packageName);
|
||||||
|
intent.setPackage(packageName);
|
||||||
|
sendOrderedBroadcast(intent, null);
|
||||||
} else {
|
} else {
|
||||||
for (ResolveInfo resolveInfo : infos) {
|
List<ResolveInfo> infos = getPackageManager().queryBroadcastReceivers(intent, PackageManager.GET_RESOLVED_FILTER);
|
||||||
logd("Target: " + resolveInfo);
|
if (infos == null || infos.isEmpty()) {
|
||||||
Intent targetIntent = new Intent(intent);
|
logd("No target for message, wut?");
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && app.wakeForDelivery) {
|
} else {
|
||||||
try {
|
for (ResolveInfo resolveInfo : infos) {
|
||||||
if (getUserIdMethod != null && addPowerSaveTempWhitelistAppMethod != null && deviceIdleController != null) {
|
Intent targetIntent = new Intent(intent);
|
||||||
int userId = (int) getUserIdMethod.invoke(null, getPackageManager().getApplicationInfo(packageName, 0).uid);
|
targetIntent.setComponent(new ComponentName(resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name));
|
||||||
logd("Adding app " + packageName + " for userId " + userId + " to the temp whitelist");
|
if (resolveInfo.activityInfo.packageName.equals(packageName)) {
|
||||||
addPowerSaveTempWhitelistAppMethod.invoke(deviceIdleController, packageName, 10000, userId, "GCM Push");
|
// Wake up the package itself
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && app.wakeForDelivery) {
|
||||||
|
try {
|
||||||
|
if (getUserIdMethod != null && addPowerSaveTempWhitelistAppMethod != null && deviceIdleController != null) {
|
||||||
|
int userId = (int) getUserIdMethod.invoke(null, getPackageManager().getApplicationInfo(packageName, 0).uid);
|
||||||
|
logd("Adding app " + packageName + " for userId " + userId + " to the temp whitelist");
|
||||||
|
addPowerSaveTempWhitelistAppMethod.invoke(deviceIdleController, packageName, 10000, userId, "GCM Push");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.w(TAG, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
// We don't need receiver permission for our own package
|
||||||
Log.w(TAG, e);
|
logd("Deliver message to own receiver " + resolveInfo);
|
||||||
|
sendOrderedBroadcast(targetIntent, null);
|
||||||
|
} else if (resolveInfo.filter.hasCategory(packageName)) {
|
||||||
|
// Permission required
|
||||||
|
logd("Deliver message to third-party receiver (with permission check)" + resolveInfo);
|
||||||
|
sendOrderedBroadcast(targetIntent, receiverPermission);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
targetIntent.setComponent(new ComponentName(resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name));
|
|
||||||
if (resolveInfo.activityInfo.packageName.equals(packageName)) {
|
|
||||||
sendOrderedBroadcast(targetIntent, null);
|
|
||||||
} else if (receiverPermission != null) {
|
|
||||||
sendOrderedBroadcast(targetIntent, receiverPermission);
|
|
||||||
} else {
|
|
||||||
Log.w(TAG, resolveInfo.activityInfo.packageName + "/" + resolveInfo.activityInfo.name + " matches for C2D message to " + packageName + " but corresponding permission was not declared");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -569,6 +602,7 @@ public class McsService extends Service implements Handler.Callback {
|
||||||
for (AppData appData : msg.app_data) {
|
for (AppData appData : msg.app_data) {
|
||||||
if (IDLE_NOTIFICATION.equals(appData.key)) {
|
if (IDLE_NOTIFICATION.equals(appData.key)) {
|
||||||
DataMessageStanza.Builder msgResponse = new DataMessageStanza.Builder()
|
DataMessageStanza.Builder msgResponse = new DataMessageStanza.Builder()
|
||||||
|
.id(Integer.toHexString(nextMessageId.incrementAndGet()))
|
||||||
.from(FROM_FIELD)
|
.from(FROM_FIELD)
|
||||||
.sent(System.currentTimeMillis() / 1000)
|
.sent(System.currentTimeMillis() / 1000)
|
||||||
.ttl(0)
|
.ttl(0)
|
||||||
|
@ -633,6 +667,22 @@ public class McsService extends Service implements Handler.Callback {
|
||||||
scheduleReconnect(this);
|
scheduleReconnect(this);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
case MSG_ACK:
|
||||||
|
logd("Ack initiated, reason: " + msg.obj);
|
||||||
|
if (isConnected()) {
|
||||||
|
IqStanza.Builder iq = new IqStanza.Builder()
|
||||||
|
.type(IqStanza.IqType.SET)
|
||||||
|
.id("")
|
||||||
|
.extension(new Extension.Builder().id(13).data(ByteString.EMPTY).build()) // StreamAck
|
||||||
|
.status(0L);
|
||||||
|
if (inputStream.newStreamIdAvailable()) {
|
||||||
|
iq.last_stream_id_received(inputStream.getStreamId());
|
||||||
|
}
|
||||||
|
send(MCS_IQ_STANZA_TAG, iq.build());
|
||||||
|
} else {
|
||||||
|
logd("Ignoring ack, not connected!");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
case MSG_OUTPUT_READY:
|
case MSG_OUTPUT_READY:
|
||||||
logd("Sending login request...");
|
logd("Sending login request...");
|
||||||
send(MCS_LOGIN_REQUEST_TAG, buildLoginRequest());
|
send(MCS_LOGIN_REQUEST_TAG, buildLoginRequest());
|
||||||
|
|
|
@ -28,13 +28,17 @@ import android.os.RemoteException;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.microg.gms.checkin.LastCheckinInfo;
|
import org.microg.gms.checkin.LastCheckinInfo;
|
||||||
|
import org.microg.gms.common.ForegroundServiceContext;
|
||||||
import org.microg.gms.common.PackageUtils;
|
import org.microg.gms.common.PackageUtils;
|
||||||
import org.microg.gms.common.Utils;
|
import org.microg.gms.common.Utils;
|
||||||
|
|
||||||
import static org.microg.gms.gcm.GcmConstants.ACTION_C2DM_REGISTRATION;
|
import static org.microg.gms.gcm.GcmConstants.ACTION_C2DM_REGISTRATION;
|
||||||
import static org.microg.gms.gcm.GcmConstants.ERROR_SERVICE_NOT_AVAILABLE;
|
import static org.microg.gms.gcm.GcmConstants.ERROR_SERVICE_NOT_AVAILABLE;
|
||||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_APP;
|
import static org.microg.gms.gcm.GcmConstants.EXTRA_APP;
|
||||||
|
import static org.microg.gms.gcm.GcmConstants.EXTRA_APP_OVERRIDE;
|
||||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_ERROR;
|
import static org.microg.gms.gcm.GcmConstants.EXTRA_ERROR;
|
||||||
|
import static org.microg.gms.gcm.McsConstants.ACTION_ACK;
|
||||||
|
import static org.microg.gms.gcm.McsConstants.ACTION_SEND;
|
||||||
|
|
||||||
class PushRegisterHandler extends Handler {
|
class PushRegisterHandler extends Handler {
|
||||||
private static final String TAG = "GmsGcmRegisterHdl";
|
private static final String TAG = "GmsGcmRegisterHdl";
|
||||||
|
@ -54,40 +58,54 @@ class PushRegisterHandler extends Handler {
|
||||||
return super.sendMessageAtTime(msg, uptimeMillis);
|
return super.sendMessageAtTime(msg, uptimeMillis);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendReply(int what, int id, Messenger replyTo, Bundle data) {
|
private void sendReplyViaMessage(int what, int id, Messenger replyTo, Bundle messageData) {
|
||||||
if (what == 0) {
|
Message response = Message.obtain();
|
||||||
Intent outIntent = new Intent(ACTION_C2DM_REGISTRATION);
|
response.what = what;
|
||||||
outIntent.putExtras(data);
|
response.arg1 = id;
|
||||||
Message message = Message.obtain();
|
response.setData(messageData);
|
||||||
message.obj = outIntent;
|
try {
|
||||||
try {
|
replyTo.send(response);
|
||||||
replyTo.send(message);
|
} catch (RemoteException e) {
|
||||||
} catch (RemoteException e) {
|
Log.w(TAG, e);
|
||||||
Log.w(TAG, e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Bundle messageData = new Bundle();
|
|
||||||
messageData.putBundle("data", data);
|
|
||||||
Message response = Message.obtain();
|
|
||||||
response.what = what;
|
|
||||||
response.arg1 = id;
|
|
||||||
response.setData(messageData);
|
|
||||||
try {
|
|
||||||
replyTo.send(response);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
Log.w(TAG, e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void replyError(int what, int id, Messenger replyTo, String errorMessage) {
|
private void sendReplyViaIntent(Intent outIntent, Messenger replyTo) {
|
||||||
|
Message message = Message.obtain();
|
||||||
|
message.obj = outIntent;
|
||||||
|
try {
|
||||||
|
replyTo.send(message);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.w(TAG, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendReply(int what, int id, Messenger replyTo, Bundle data, boolean oneWay) {
|
||||||
|
if (what == 0) {
|
||||||
|
Intent outIntent = new Intent(ACTION_C2DM_REGISTRATION);
|
||||||
|
outIntent.putExtras(data);
|
||||||
|
sendReplyViaIntent(outIntent, replyTo);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Bundle messageData = new Bundle();
|
||||||
|
messageData.putBundle("data", data);
|
||||||
|
sendReplyViaMessage(what, id, replyTo, messageData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void replyError(int what, int id, Messenger replyTo, String errorMessage, boolean oneWay) {
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putString(EXTRA_ERROR, errorMessage);
|
bundle.putString(EXTRA_ERROR, errorMessage);
|
||||||
sendReply(what, id, replyTo, bundle);
|
sendReply(what, id, replyTo, bundle, oneWay);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void replyNotAvailable(int what, int id, Messenger replyTo) {
|
private void replyNotAvailable(int what, int id, Messenger replyTo) {
|
||||||
replyError(what, id, replyTo, ERROR_SERVICE_NOT_AVAILABLE);
|
replyError(what, id, replyTo, ERROR_SERVICE_NOT_AVAILABLE, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PendingIntent getSelfAuthIntent() {
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.setPackage("com.google.example.invalidpackage");
|
||||||
|
return PendingIntent.getBroadcast(context, 0, intent, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -119,15 +137,9 @@ class PushRegisterHandler extends Handler {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Bundle data = msg.getData();
|
Bundle data = msg.getData();
|
||||||
if (data.getBoolean("oneWay", false)) {
|
|
||||||
Log.w(TAG, "oneWay requested");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String packageName = data.getString("pkg");
|
String packageName = data.getString("pkg");
|
||||||
Bundle subdata = data.getBundle("data");
|
Bundle subdata = data.getBundle("data");
|
||||||
String sender = subdata.getString("sender");
|
|
||||||
boolean delete = subdata.get("delete") != null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PackageUtils.checkPackageUid(context, packageName, callingUid);
|
PackageUtils.checkPackageUid(context, packageName, callingUid);
|
||||||
|
@ -136,16 +148,46 @@ class PushRegisterHandler extends Handler {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: We should checkin and/or ask for permission here.
|
Log.d(TAG, "handleMessage: package=" + packageName + " what=" + what + " id=" + id);
|
||||||
|
|
||||||
PushRegisterManager.completeRegisterRequest(context, database,
|
boolean oneWay = data.getBoolean("oneWay", false);
|
||||||
new RegisterRequest()
|
|
||||||
.build(Utils.getBuild(context))
|
switch (what) {
|
||||||
.sender(sender)
|
case 0:
|
||||||
.checkin(LastCheckinInfo.read(context))
|
case 1:
|
||||||
.app(packageName)
|
// TODO: We should checkin and/or ask for permission here.
|
||||||
.delete(delete)
|
String sender = subdata.getString("sender");
|
||||||
.extraParams(subdata),
|
boolean delete = subdata.get("delete") != null;
|
||||||
bundle -> sendReply(what, id, replyTo, bundle));
|
|
||||||
|
PushRegisterManager.completeRegisterRequest(context, database,
|
||||||
|
new RegisterRequest()
|
||||||
|
.build(Utils.getBuild(context))
|
||||||
|
.sender(sender)
|
||||||
|
.checkin(LastCheckinInfo.read(context))
|
||||||
|
.app(packageName)
|
||||||
|
.delete(delete)
|
||||||
|
.extraParams(subdata),
|
||||||
|
bundle -> sendReply(what, id, replyTo, bundle, oneWay));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
String messageId = subdata.getString("google.message_id");
|
||||||
|
Log.d(TAG, "Ack " + messageId + " for " + packageName);
|
||||||
|
Intent i = new Intent(context, McsService.class);
|
||||||
|
i.setAction(ACTION_ACK);
|
||||||
|
i.putExtra(EXTRA_APP, getSelfAuthIntent());
|
||||||
|
new ForegroundServiceContext(context).startService(i);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putBoolean("unsupported", true);
|
||||||
|
sendReplyViaMessage(what, id, replyTo, bundle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oneWay) {
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putBoolean("ack", true);
|
||||||
|
sendReplyViaMessage(what, id, replyTo, bundle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue