mirror of
https://github.com/TeamVanced/VancedMicroG
synced 2025-02-02 14:07:32 +01:00
Push Messaging: Handle more edge cases, fix some apps not showing up as registered
This commit is contained in:
parent
e47101856d
commit
719cd51d3d
@ -205,16 +205,18 @@
|
||||
android:permission="com.google.android.c2dm.permission.RECEIVE">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.android.c2dm.intent.REGISTER"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.google.android.c2dm.intent.UNREGISTER"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<receiver android:name="org.microg.gms.gcm.PushRegisterReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.iid.TOKEN_REQUEST"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service android:name="org.microg.gms.gcm.McsService"/>
|
||||
|
||||
<receiver
|
||||
|
@ -81,7 +81,13 @@ public class HttpFormClient {
|
||||
os.close();
|
||||
|
||||
if (connection.getResponseCode() != 200) {
|
||||
throw new IOException(connection.getResponseMessage());
|
||||
String error = connection.getResponseMessage();
|
||||
try {
|
||||
error = new String(Utils.readStreamToEnd(connection.getErrorStream()));
|
||||
} catch (IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
throw new IOException(error);
|
||||
}
|
||||
|
||||
String result = new String(Utils.readStreamToEnd(connection.getInputStream()));
|
||||
|
@ -155,4 +155,12 @@ public class PackageUtils {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static String versionName(Context context, String packageName) {
|
||||
try {
|
||||
return context.getPackageManager().getPackageInfo(packageName, 0).versionName;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.gcm;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import org.microg.gms.checkin.LastCheckinInfo;
|
||||
import org.microg.gms.common.PackageUtils;
|
||||
import org.microg.gms.common.Utils;
|
||||
|
||||
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.EXTRA_APP;
|
||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_ERROR;
|
||||
|
||||
class PushRegisterHandler extends Handler {
|
||||
private static final String TAG = "GmsGcmRegisterHdl";
|
||||
|
||||
private Context context;
|
||||
private int callingUid;
|
||||
private GcmDatabase database;
|
||||
|
||||
public PushRegisterHandler(Context context, GcmDatabase database) {
|
||||
this.context = context;
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
|
||||
this.callingUid = Binder.getCallingUid();
|
||||
return super.sendMessageAtTime(msg, uptimeMillis);
|
||||
}
|
||||
|
||||
private void sendReply(int what, int id, Messenger replyTo, Bundle data) {
|
||||
if (what == 0) {
|
||||
Intent outIntent = new Intent(ACTION_C2DM_REGISTRATION);
|
||||
outIntent.putExtras(data);
|
||||
Message message = Message.obtain();
|
||||
message.obj = outIntent;
|
||||
try {
|
||||
replyTo.send(message);
|
||||
} catch (RemoteException 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) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(EXTRA_ERROR, errorMessage);
|
||||
sendReply(what, id, replyTo, bundle);
|
||||
}
|
||||
|
||||
private void replyNotAvailable(int what, int id, Messenger replyTo) {
|
||||
replyError(what, id, replyTo, ERROR_SERVICE_NOT_AVAILABLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
if (msg.what == 0) {
|
||||
if (msg.obj instanceof Intent) {
|
||||
Message nuMsg = Message.obtain();
|
||||
nuMsg.what = msg.what;
|
||||
nuMsg.arg1 = 0;
|
||||
nuMsg.replyTo = null;
|
||||
PendingIntent pendingIntent = ((Intent) msg.obj).getParcelableExtra(EXTRA_APP);
|
||||
String packageName = PackageUtils.packageFromPendingIntent(pendingIntent);
|
||||
Bundle data = new Bundle();
|
||||
data.putBoolean("oneWay", false);
|
||||
data.putString("pkg", packageName);
|
||||
data.putBundle("data", msg.getData());
|
||||
nuMsg.setData(data);
|
||||
msg = nuMsg;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int what = msg.what;
|
||||
int id = msg.arg1;
|
||||
Messenger replyTo = msg.replyTo;
|
||||
if (replyTo == null) {
|
||||
Log.w(TAG, "replyTo is null");
|
||||
return;
|
||||
}
|
||||
Bundle data = msg.getData();
|
||||
if (data.getBoolean("oneWay", false)) {
|
||||
Log.w(TAG, "oneWay requested");
|
||||
return;
|
||||
}
|
||||
|
||||
String packageName = data.getString("pkg");
|
||||
Bundle subdata = data.getBundle("data");
|
||||
String sender = subdata.getString("sender");
|
||||
boolean delete = subdata.get("delete") != null;
|
||||
|
||||
try {
|
||||
PackageUtils.checkPackageUid(context, packageName, callingUid);
|
||||
} catch (SecurityException e) {
|
||||
Log.w(TAG, e);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: We should checkin and/or ask for permission here.
|
||||
|
||||
PushRegisterManager.completeRegisterRequest(context, database,
|
||||
new RegisterRequest()
|
||||
.build(Utils.getBuild(context))
|
||||
.sender(sender)
|
||||
.checkin(LastCheckinInfo.read(context))
|
||||
.app(packageName)
|
||||
.delete(delete)
|
||||
.appid(subdata.getString("appid"), subdata.getString("gmp_app_id")),
|
||||
bundle -> sendReply(what, id, replyTo, bundle));
|
||||
}
|
||||
}
|
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.gcm;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import org.microg.gms.checkin.LastCheckinInfo;
|
||||
import org.microg.gms.common.HttpFormClient;
|
||||
import org.microg.gms.common.PackageUtils;
|
||||
import org.microg.gms.common.Utils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.microg.gms.gcm.GcmConstants.ERROR_SERVICE_NOT_AVAILABLE;
|
||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_ERROR;
|
||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_REGISTRATION_ID;
|
||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_RETRY_AFTER;
|
||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_UNREGISTERED;
|
||||
|
||||
public class PushRegisterManager {
|
||||
private static final String TAG = "GmsGcmRegisterMgr";
|
||||
|
||||
public static RegisterResponse unregister(Context context, String packageName, String pkgSignature, String sender, String info) {
|
||||
GcmDatabase database = new GcmDatabase(context);
|
||||
RegisterResponse response = new RegisterResponse();
|
||||
try {
|
||||
response = new RegisterRequest()
|
||||
.build(Utils.getBuild(context))
|
||||
.sender(sender)
|
||||
.info(info)
|
||||
.checkin(LastCheckinInfo.read(context))
|
||||
.app(packageName, pkgSignature)
|
||||
.delete(true)
|
||||
.getResponse();
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
if (!packageName.equals(response.deleted)) {
|
||||
database.noteAppRegistrationError(packageName, response.responseText);
|
||||
} else {
|
||||
database.noteAppUnregistered(packageName, pkgSignature);
|
||||
}
|
||||
database.close();
|
||||
return response;
|
||||
}
|
||||
|
||||
public interface BundleCallback {
|
||||
void onResult(Bundle bundle);
|
||||
}
|
||||
|
||||
public static void completeRegisterRequest(Context context, GcmDatabase database, RegisterRequest request, BundleCallback callback) {
|
||||
completeRegisterRequest(context, database, null, request, callback);
|
||||
}
|
||||
|
||||
public static void completeRegisterRequest(Context context, GcmDatabase database, String requestId, RegisterRequest request, BundleCallback callback) {
|
||||
if (request.app != null) {
|
||||
if (request.appSignature == null)
|
||||
request.appSignature = PackageUtils.firstSignatureDigest(context, request.app);
|
||||
if (request.appVersion <= 0)
|
||||
request.appVersion = PackageUtils.versionCode(context, request.app);
|
||||
if (request.appVersionName == null)
|
||||
request.appVersionName = PackageUtils.versionName(context, request.app);
|
||||
}
|
||||
|
||||
GcmDatabase.App app = database.getApp(request.app);
|
||||
GcmPrefs prefs = GcmPrefs.get(context);
|
||||
if (!request.delete) {
|
||||
if (!prefs.isEnabled() ||
|
||||
(app != null && !app.allowRegister) ||
|
||||
LastCheckinInfo.read(context).lastCheckin <= 0 ||
|
||||
(app == null && prefs.isConfirmNewApps())) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(EXTRA_ERROR, ERROR_SERVICE_NOT_AVAILABLE);
|
||||
callback.onResult(bundle);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (database.getRegistrationsByApp(request.app).isEmpty()) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(EXTRA_UNREGISTERED, attachRequestId(request.app, requestId));
|
||||
callback.onResult(bundle);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
request.getResponseAsync(new HttpFormClient.Callback<RegisterResponse>() {
|
||||
@Override
|
||||
public void onResponse(RegisterResponse response) {
|
||||
callback.onResult(handleResponse(database, request, response, requestId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(Exception e) {
|
||||
Log.w(TAG, e);
|
||||
callback.onResult(handleResponse(database, request, e, requestId));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static Bundle handleResponse(GcmDatabase database, RegisterRequest request, RegisterResponse response, String requestId) {
|
||||
return handleResponse(database, request, response, null, requestId);
|
||||
}
|
||||
|
||||
private static Bundle handleResponse(GcmDatabase database, RegisterRequest request, Exception e, String requestId) {
|
||||
return handleResponse(database, request, null, e, requestId);
|
||||
}
|
||||
|
||||
private static Bundle handleResponse(GcmDatabase database, RegisterRequest request, RegisterResponse response, Exception e, String requestId) {
|
||||
Bundle resultBundle = new Bundle();
|
||||
if (response == null && e == null) {
|
||||
resultBundle.putString(EXTRA_ERROR, attachRequestId(ERROR_SERVICE_NOT_AVAILABLE, requestId));
|
||||
} else if (e != null) {
|
||||
if (e.getMessage() != null && e.getMessage().startsWith("Error=")) {
|
||||
String errorMessage = e.getMessage().substring(6);
|
||||
database.noteAppRegistrationError(request.app, errorMessage);
|
||||
resultBundle.putString(EXTRA_ERROR, attachRequestId(errorMessage, requestId));
|
||||
} else {
|
||||
resultBundle.putString(EXTRA_ERROR, attachRequestId(ERROR_SERVICE_NOT_AVAILABLE, requestId));
|
||||
}
|
||||
} else {
|
||||
if (!request.delete) {
|
||||
if (response.token == null) {
|
||||
database.noteAppRegistrationError(request.app, response.responseText);
|
||||
resultBundle.putString(EXTRA_ERROR, attachRequestId(ERROR_SERVICE_NOT_AVAILABLE, requestId));
|
||||
} else {
|
||||
database.noteAppRegistered(request.app, request.appSignature, response.token);
|
||||
resultBundle.putString(EXTRA_REGISTRATION_ID, attachRequestId(response.token, requestId));
|
||||
}
|
||||
} else {
|
||||
if (!request.app.equals(response.deleted) && !request.app.equals(response.token)) {
|
||||
database.noteAppRegistrationError(request.app, response.responseText);
|
||||
resultBundle.putString(EXTRA_ERROR, attachRequestId(ERROR_SERVICE_NOT_AVAILABLE, requestId));
|
||||
} else {
|
||||
database.noteAppUnregistered(request.app, request.appSignature);
|
||||
resultBundle.putString(EXTRA_UNREGISTERED, attachRequestId(request.app, requestId));
|
||||
}
|
||||
}
|
||||
|
||||
if (response.retryAfter != null && !response.retryAfter.contains(":")) {
|
||||
resultBundle.putLong(EXTRA_RETRY_AFTER, Long.parseLong(response.retryAfter));
|
||||
}
|
||||
}
|
||||
return resultBundle;
|
||||
}
|
||||
|
||||
public static String attachRequestId(String msg, String requestId) {
|
||||
if (requestId == null) return msg;
|
||||
return "|ID|" + requestId + "|" + msg;
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.gcm;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.v4.content.WakefulBroadcastReceiver;
|
||||
|
||||
import static org.microg.gms.gcm.GcmConstants.ACTION_C2DM_REGISTER;
|
||||
import static org.microg.gms.gcm.GcmConstants.ACTION_C2DM_UNREGISTER;
|
||||
|
||||
public class PushRegisterReceiver extends WakefulBroadcastReceiver {
|
||||
private static final String TAG = "GmsGcmRegisterRcv";
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Intent intent2 = new Intent(context, PushRegisterService.class);
|
||||
if (intent.getExtras().get("delete") != null) {
|
||||
intent2.setAction(ACTION_C2DM_UNREGISTER);
|
||||
} else {
|
||||
intent2.setAction(ACTION_C2DM_REGISTER);
|
||||
}
|
||||
intent2.putExtras(intent.getExtras());
|
||||
startWakefulService(context, intent2);
|
||||
}
|
||||
}
|
@ -22,15 +22,11 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.os.RemoteException;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.WakefulBroadcastReceiver;
|
||||
import android.util.Log;
|
||||
|
||||
import org.microg.gms.checkin.CheckinService;
|
||||
@ -39,8 +35,6 @@ import org.microg.gms.common.PackageUtils;
|
||||
import org.microg.gms.common.Utils;
|
||||
import org.microg.gms.ui.AskPushPermission;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.microg.gms.gcm.GcmConstants.ACTION_C2DM_REGISTER;
|
||||
import static org.microg.gms.gcm.GcmConstants.ACTION_C2DM_REGISTRATION;
|
||||
import static org.microg.gms.gcm.GcmConstants.ACTION_C2DM_UNREGISTER;
|
||||
@ -51,10 +45,7 @@ import static org.microg.gms.gcm.GcmConstants.EXTRA_ERROR;
|
||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_KID;
|
||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_MESSENGER;
|
||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_PENDING_INTENT;
|
||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_REGISTRATION_ID;
|
||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_RETRY_AFTER;
|
||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_SENDER;
|
||||
import static org.microg.gms.gcm.GcmConstants.EXTRA_UNREGISTERED;
|
||||
|
||||
public class PushRegisterService extends IntentService {
|
||||
private static final String TAG = "GmsGcmRegisterSvc";
|
||||
@ -80,33 +71,9 @@ public class PushRegisterService extends IntentService {
|
||||
database.close();
|
||||
}
|
||||
|
||||
public static RegisterResponse register(Context context, String packageName, String pkgSignature, String sender, String info) {
|
||||
GcmDatabase database = new GcmDatabase(context);
|
||||
RegisterResponse response = register(context, packageName, pkgSignature, sender, info, false);
|
||||
String regId = response.token;
|
||||
if (regId != null) {
|
||||
database.noteAppRegistered(packageName, pkgSignature, regId);
|
||||
} else {
|
||||
database.noteAppRegistrationError(packageName, response.responseText);
|
||||
}
|
||||
database.close();
|
||||
return response;
|
||||
}
|
||||
|
||||
public static RegisterResponse unregister(Context context, String packageName, String pkgSignature, String sender, String info) {
|
||||
GcmDatabase database = new GcmDatabase(context);
|
||||
RegisterResponse response = register(context, packageName, pkgSignature, sender, info, true);
|
||||
if (!packageName.equals(response.deleted)) {
|
||||
database.noteAppRegistrationError(packageName, response.responseText);
|
||||
} else {
|
||||
database.noteAppUnregistered(packageName, pkgSignature);
|
||||
}
|
||||
database.close();
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHandleIntent(Intent intent) {
|
||||
WakefulBroadcastReceiver.completeWakefulIntent(intent);
|
||||
Log.d(TAG, "onHandleIntent: " + intent);
|
||||
|
||||
String requestId = null;
|
||||
@ -117,42 +84,35 @@ public class PushRegisterService extends IntentService {
|
||||
}
|
||||
}
|
||||
|
||||
if (GcmPrefs.get(this).isEnabled()) {
|
||||
if (LastCheckinInfo.read(this).lastCheckin > 0) {
|
||||
try {
|
||||
if (ACTION_C2DM_UNREGISTER.equals(intent.getAction()) ||
|
||||
(ACTION_C2DM_REGISTER.equals(intent.getAction()) && "1".equals(intent.getStringExtra(EXTRA_DELETE)))) {
|
||||
unregister(intent, requestId);
|
||||
} else if (ACTION_C2DM_REGISTER.equals(intent.getAction())) {
|
||||
register(intent, requestId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, e);
|
||||
if (LastCheckinInfo.read(this).lastCheckin > 0) {
|
||||
try {
|
||||
if (ACTION_C2DM_UNREGISTER.equals(intent.getAction()) ||
|
||||
(ACTION_C2DM_REGISTER.equals(intent.getAction()) && "1".equals(intent.getStringExtra(EXTRA_DELETE)))) {
|
||||
unregister(intent, requestId);
|
||||
} else if (ACTION_C2DM_REGISTER.equals(intent.getAction())) {
|
||||
register(intent, requestId);
|
||||
}
|
||||
} else if (!intent.getBooleanExtra(EXTRA_SKIP_TRY_CHECKIN, false)) {
|
||||
Log.d(TAG, "No checkin yet, trying to checkin");
|
||||
intent.putExtra(EXTRA_SKIP_TRY_CHECKIN, true);
|
||||
Intent subIntent = new Intent(this, CheckinService.class);
|
||||
subIntent.putExtra(CheckinService.EXTRA_FORCE_CHECKIN, true);
|
||||
subIntent.putExtra(CheckinService.EXTRA_CALLBACK_INTENT, intent);
|
||||
startService(subIntent);
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
} else {
|
||||
// GCM is disabled, deny registration
|
||||
replyNotAvailable(this, intent, null, requestId);
|
||||
} else if (!intent.getBooleanExtra(EXTRA_SKIP_TRY_CHECKIN, false)) {
|
||||
Log.d(TAG, "No checkin yet, trying to checkin");
|
||||
intent.putExtra(EXTRA_SKIP_TRY_CHECKIN, true);
|
||||
Intent subIntent = new Intent(this, CheckinService.class);
|
||||
subIntent.putExtra(CheckinService.EXTRA_FORCE_CHECKIN, true);
|
||||
subIntent.putExtra(CheckinService.EXTRA_CALLBACK_INTENT, intent);
|
||||
startService(subIntent);
|
||||
}
|
||||
}
|
||||
|
||||
private void register(final Intent intent, String requestId) {
|
||||
PendingIntent pendingIntent = intent.getParcelableExtra(EXTRA_APP);
|
||||
final String packageName = PackageUtils.packageFromPendingIntent(pendingIntent);
|
||||
Log.d(TAG, "register[req]: " + intent.toString() + " extras=" + intent.getExtras());
|
||||
|
||||
GcmDatabase.App app = database.getApp(packageName);
|
||||
if (app == null && GcmPrefs.get(this).isConfirmNewApps()) {
|
||||
try {
|
||||
PackageManager pm = getPackageManager();
|
||||
ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
|
||||
getPackageManager().getApplicationInfo(packageName, 0); // Check package exists
|
||||
Intent i = new Intent(this, AskPushPermission.class);
|
||||
i.putExtra(EXTRA_PENDING_INTENT, intent);
|
||||
i.putExtra(EXTRA_APP, packageName);
|
||||
@ -161,46 +121,31 @@ public class PushRegisterService extends IntentService {
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
replyNotAvailable(this, intent, packageName, requestId);
|
||||
}
|
||||
} else if (app != null && !app.allowRegister) {
|
||||
replyNotAvailable(this, intent, packageName, requestId);
|
||||
} else {
|
||||
registerAndReply(this, intent, packageName, requestId);
|
||||
registerAndReply(this, database, intent, packageName, requestId);
|
||||
}
|
||||
}
|
||||
|
||||
public static void replyNotAvailable(Context context, Intent intent, String packageName, String requestId) {
|
||||
if (packageName == null) {
|
||||
PendingIntent pendingIntent = intent.getParcelableExtra(EXTRA_APP);
|
||||
packageName = PackageUtils.packageFromPendingIntent(pendingIntent);
|
||||
}
|
||||
if (packageName == null) {
|
||||
// skip reply
|
||||
return;
|
||||
}
|
||||
Intent outIntent = new Intent(ACTION_C2DM_REGISTRATION);
|
||||
outIntent.putExtra(EXTRA_ERROR, attachRequestId(ERROR_SERVICE_NOT_AVAILABLE, requestId));
|
||||
Log.d(TAG, "registration not allowed");
|
||||
outIntent.putExtra(EXTRA_ERROR, PushRegisterManager.attachRequestId(ERROR_SERVICE_NOT_AVAILABLE, requestId));
|
||||
sendReply(context, intent, packageName, outIntent);
|
||||
}
|
||||
|
||||
public static void registerAndReply(Context context, Intent intent, String packageName, String requestId) {
|
||||
String sender = intent.getStringExtra(EXTRA_SENDER);
|
||||
String appSignature = PackageUtils.firstSignatureDigest(context, packageName);
|
||||
String regId = register(context, packageName, appSignature, sender, null).token;
|
||||
Intent outIntent = createRegistrationReply(regId, requestId);
|
||||
|
||||
Log.d(TAG, "register[res]: " + outIntent + " extras=" + outIntent.getExtras());
|
||||
sendReply(context, intent, packageName, outIntent);
|
||||
}
|
||||
|
||||
private static Intent createRegistrationReply(String regId, String requestId) {
|
||||
Intent outIntent = new Intent(ACTION_C2DM_REGISTRATION);
|
||||
if (regId != null) {
|
||||
outIntent.putExtra(EXTRA_REGISTRATION_ID, attachRequestId(regId, requestId));
|
||||
} else {
|
||||
outIntent.putExtra(EXTRA_ERROR, attachRequestId(ERROR_SERVICE_NOT_AVAILABLE, requestId));
|
||||
}
|
||||
return outIntent;
|
||||
public static void registerAndReply(Context context, GcmDatabase database, Intent intent, String packageName, String requestId) {
|
||||
Log.d(TAG, "register[req]: " + intent.toString() + " extras=" + intent.getExtras());
|
||||
PushRegisterManager.completeRegisterRequest(context, database,
|
||||
new RegisterRequest()
|
||||
.build(Utils.getBuild(context))
|
||||
.sender(intent.getStringExtra(EXTRA_SENDER))
|
||||
.checkin(LastCheckinInfo.read(context))
|
||||
.app(packageName),
|
||||
bundle -> {
|
||||
Intent outIntent = new Intent(ACTION_C2DM_REGISTRATION);
|
||||
outIntent.putExtras(bundle);
|
||||
Log.d(TAG, "register[res]: " + outIntent.toString() + " extras=" + outIntent.getExtras());
|
||||
sendReply(context, intent, packageName, outIntent);
|
||||
});
|
||||
}
|
||||
|
||||
private static void sendReply(Context context, Intent intent, String packageName, Intent outIntent) {
|
||||
@ -220,55 +165,23 @@ public class PushRegisterService extends IntentService {
|
||||
context.sendOrderedBroadcast(outIntent, null);
|
||||
}
|
||||
|
||||
public static RegisterResponse register(Context context, String app, String appSignature, String sender, String info, boolean delete) {
|
||||
try {
|
||||
RegisterResponse response = new RegisterRequest()
|
||||
.build(Utils.getBuild(context))
|
||||
.sender(sender)
|
||||
.info(info)
|
||||
.checkin(LastCheckinInfo.read(context))
|
||||
.app(app, appSignature, PackageUtils.versionCode(context, app))
|
||||
.delete(delete)
|
||||
.getResponse();
|
||||
Log.d(TAG, "received response: " + response);
|
||||
return response;
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
|
||||
return new RegisterResponse();
|
||||
}
|
||||
|
||||
private void unregister(Intent intent, String requestId) {
|
||||
PendingIntent pendingIntent = intent.getParcelableExtra(EXTRA_APP);
|
||||
String packageName = PackageUtils.packageFromPendingIntent(pendingIntent);
|
||||
Log.d(TAG, "unregister[req]: " + intent.toString() + " extras=" + intent.getExtras());
|
||||
|
||||
Intent outIntent = new Intent(ACTION_C2DM_REGISTRATION);
|
||||
String appSignature = PackageUtils.firstSignatureDigest(this, packageName);
|
||||
|
||||
if (database.getRegistration(packageName, appSignature) == null) {
|
||||
outIntent.putExtra(EXTRA_UNREGISTERED, attachRequestId(packageName, requestId));
|
||||
} else {
|
||||
RegisterResponse response = unregister(this, packageName, appSignature, null, null);
|
||||
if (!packageName.equals(response.deleted)) {
|
||||
outIntent.putExtra(EXTRA_ERROR, attachRequestId(ERROR_SERVICE_NOT_AVAILABLE, requestId));
|
||||
|
||||
if (response.retryAfter != null && !response.retryAfter.contains(":")) {
|
||||
outIntent.putExtra(EXTRA_RETRY_AFTER, Long.parseLong(response.retryAfter));
|
||||
}
|
||||
} else {
|
||||
outIntent.putExtra(EXTRA_UNREGISTERED, attachRequestId(packageName, requestId));
|
||||
}
|
||||
}
|
||||
|
||||
Log.d(TAG, "unregister[res]: " + outIntent.toString() + " extras=" + outIntent.getExtras());
|
||||
sendReply(this, intent, packageName, outIntent);
|
||||
}
|
||||
|
||||
private static String attachRequestId(String msg, String requestId) {
|
||||
if (requestId == null) return msg;
|
||||
return "|ID|" + requestId + "|" + msg;
|
||||
PushRegisterManager.completeRegisterRequest(this, database,
|
||||
new RegisterRequest()
|
||||
.build(Utils.getBuild(this))
|
||||
.sender(intent.getStringExtra(EXTRA_SENDER))
|
||||
.checkin(LastCheckinInfo.read(this))
|
||||
.app(packageName),
|
||||
bundle -> {
|
||||
Intent outIntent = new Intent(ACTION_C2DM_REGISTRATION);
|
||||
outIntent.putExtras(bundle);
|
||||
Log.d(TAG, "unregister[res]: " + outIntent.toString() + " extras=" + outIntent.getExtras());
|
||||
sendReply(this, intent, packageName, outIntent);
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@ -276,127 +189,10 @@ public class PushRegisterService extends IntentService {
|
||||
public IBinder onBind(Intent intent) {
|
||||
Log.d(TAG, "onBind: " + intent.toString());
|
||||
if (ACTION_C2DM_REGISTER.equals(intent.getAction())) {
|
||||
Messenger messenger = new Messenger(new FcmHandler(this));
|
||||
Messenger messenger = new Messenger(new PushRegisterHandler(this, database));
|
||||
return messenger.getBinder();
|
||||
}
|
||||
return super.onBind(intent);
|
||||
}
|
||||
|
||||
private static class FcmRegisterTask extends AsyncTask<Void, Void, RegisterResponse> {
|
||||
private Context context;
|
||||
private String packageName;
|
||||
private String sender;
|
||||
private Callback callback;
|
||||
|
||||
public FcmRegisterTask(Context context, String packageName, String sender, Callback callback) {
|
||||
this.context = context;
|
||||
this.packageName = packageName;
|
||||
this.sender = sender;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
public interface Callback {
|
||||
void onResult(RegisterResponse registerResponse);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RegisterResponse doInBackground(Void... voids) {
|
||||
return register(context, packageName, PackageUtils.firstSignatureDigest(context, packageName), sender, null, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(RegisterResponse registerResponse) {
|
||||
callback.onResult(registerResponse);
|
||||
}
|
||||
}
|
||||
|
||||
private static class FcmHandler extends Handler {
|
||||
private Context context;
|
||||
private int callingUid;
|
||||
|
||||
public FcmHandler(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
|
||||
this.callingUid = Binder.getCallingUid();
|
||||
return super.sendMessageAtTime(msg, uptimeMillis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
if (msg.what == 0) {
|
||||
if (msg.obj instanceof Intent) {
|
||||
Message nuMsg = Message.obtain();
|
||||
nuMsg.what = msg.what;
|
||||
nuMsg.arg1 = 0;
|
||||
nuMsg.replyTo = null;
|
||||
PendingIntent pendingIntent = ((Intent) msg.obj).getParcelableExtra(EXTRA_APP);
|
||||
String packageName = PackageUtils.packageFromPendingIntent(pendingIntent);
|
||||
Bundle data = new Bundle();
|
||||
data.putBoolean("oneWay", false);
|
||||
data.putString("pkg", packageName);
|
||||
data.putBundle("data", msg.getData());
|
||||
nuMsg.setData(data);
|
||||
msg = nuMsg;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
int what = msg.what;
|
||||
int id = msg.arg1;
|
||||
Messenger replyTo = msg.replyTo;
|
||||
if (replyTo == null) {
|
||||
Log.w(TAG, "replyTo is null");
|
||||
return;
|
||||
}
|
||||
Bundle data = msg.getData();
|
||||
if (data.getBoolean("oneWay", false)) {
|
||||
Log.w(TAG, "oneWay requested");
|
||||
return;
|
||||
}
|
||||
String packageName = data.getString("pkg");
|
||||
Bundle subdata = data.getBundle("data");
|
||||
String sender = subdata.getString("sender");
|
||||
try {
|
||||
PackageUtils.checkPackageUid(context, packageName, callingUid);
|
||||
} catch (SecurityException e) {
|
||||
Log.w(TAG, e);
|
||||
return;
|
||||
}
|
||||
new FcmRegisterTask(context, packageName, sender, registerResponse -> {
|
||||
Bundle data1 = new Bundle();
|
||||
if (registerResponse != null) {
|
||||
data1.putString(EXTRA_REGISTRATION_ID, registerResponse.token);
|
||||
} else {
|
||||
data1.putString(EXTRA_ERROR, ERROR_SERVICE_NOT_AVAILABLE);
|
||||
}
|
||||
|
||||
if (what == 0) {
|
||||
Intent outIntent = new Intent(ACTION_C2DM_REGISTRATION);
|
||||
outIntent.putExtras(data1);
|
||||
Message message = Message.obtain();
|
||||
message.obj = outIntent;
|
||||
try {
|
||||
replyTo.send(message);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
} else {
|
||||
Bundle messageData = new Bundle();
|
||||
messageData.putBundle("data", data1);
|
||||
Message response = Message.obtain();
|
||||
response.what = what;
|
||||
response.arg1 = id;
|
||||
response.setData(messageData);
|
||||
try {
|
||||
replyTo.send(response);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
}).execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ package org.microg.gms.gcm;
|
||||
|
||||
import org.microg.gms.checkin.LastCheckinInfo;
|
||||
import org.microg.gms.common.Build;
|
||||
import org.microg.gms.common.Constants;
|
||||
import org.microg.gms.common.HttpFormClient;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -41,9 +42,11 @@ public class RegisterRequest extends HttpFormClient.Request {
|
||||
public String appSignature;
|
||||
@RequestContent("app_ver")
|
||||
public int appVersion;
|
||||
@RequestContent("app_ver_name")
|
||||
public String appVersionName;
|
||||
@RequestContent("info")
|
||||
public String info;
|
||||
@RequestContent("sender")
|
||||
@RequestContent({"sender", "subtype"})
|
||||
public String sender;
|
||||
@RequestContent({"X-GOOG.USER_AID", "device"})
|
||||
public long androidId;
|
||||
@ -52,11 +55,22 @@ public class RegisterRequest extends HttpFormClient.Request {
|
||||
public long securityToken;
|
||||
public String deviceName;
|
||||
public String buildVersion;
|
||||
@RequestContent("osv")
|
||||
public int sdkVersion;
|
||||
@RequestContent("gmsv")
|
||||
public int gmsVersion;
|
||||
@RequestContent("scope")
|
||||
public String scope = "*";
|
||||
@RequestContent("appid")
|
||||
public String appId;
|
||||
@RequestContent("gmp_app_id")
|
||||
public String gmpAppId;
|
||||
|
||||
@Override
|
||||
public void prepare() {
|
||||
userAgent = String.format(USER_AGENT, deviceName, buildVersion);
|
||||
auth = "AidLogin " + androidId + ":" + securityToken;
|
||||
gmsVersion = Constants.MAX_REFERENCE_VERSION;
|
||||
}
|
||||
|
||||
public RegisterRequest checkin(LastCheckinInfo lastCheckinInfo) {
|
||||
@ -65,10 +79,28 @@ public class RegisterRequest extends HttpFormClient.Request {
|
||||
return this;
|
||||
}
|
||||
|
||||
public RegisterRequest app(String app, String appSignature, int appVersion) {
|
||||
public RegisterRequest app(String app) {
|
||||
this.app = app;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RegisterRequest app(String app, String appSignature) {
|
||||
this.app = app;
|
||||
this.appSignature = appSignature;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RegisterRequest app(String app, String appSignature, int appVersion, String appVersionName) {
|
||||
this.app = app;
|
||||
this.appSignature = appSignature;
|
||||
this.appVersion = appVersion;
|
||||
this.appVersionName = appVersionName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RegisterRequest appid(String appid, String gmpAppId) {
|
||||
this.appId = appid;
|
||||
this.gmpAppId = gmpAppId;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -85,6 +117,7 @@ public class RegisterRequest extends HttpFormClient.Request {
|
||||
public RegisterRequest build(Build build) {
|
||||
deviceName = build.device;
|
||||
buildVersion = build.id;
|
||||
sdkVersion = build.sdk;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ public class UnregisterReceiver extends BroadcastReceiver {
|
||||
List<GcmDatabase.Registration> registrations = database.getRegistrationsByApp(packageName);
|
||||
boolean deletedAll = true;
|
||||
for (GcmDatabase.Registration registration : registrations) {
|
||||
deletedAll &= PushRegisterService.unregister(context, registration.packageName, registration.signature, null, null).deleted != null;
|
||||
deletedAll &= PushRegisterManager.unregister(context, registration.packageName, registration.signature, null, null).deleted != null;
|
||||
}
|
||||
if (deletedAll) {
|
||||
database.removeApp(packageName);
|
||||
|
@ -66,7 +66,7 @@ public class AskPushPermission extends FragmentActivity {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PushRegisterService.registerAndReply(AskPushPermission.this, intent, packageName, requestId);
|
||||
PushRegisterService.registerAndReply(AskPushPermission.this, database, intent, packageName, requestId);
|
||||
}
|
||||
}).start();
|
||||
finish();
|
||||
|
@ -7,7 +7,6 @@ import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.support.annotation.StringRes;
|
||||
import android.support.v14.preference.SwitchPreference;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
@ -21,7 +20,7 @@ import android.widget.TextView;
|
||||
import com.google.android.gms.R;
|
||||
|
||||
import org.microg.gms.gcm.GcmDatabase;
|
||||
import org.microg.gms.gcm.PushRegisterService;
|
||||
import org.microg.gms.gcm.PushRegisterManager;
|
||||
import org.microg.tools.ui.AbstractSettingsActivity;
|
||||
import org.microg.tools.ui.ResourceSettingsFragment;
|
||||
|
||||
@ -185,7 +184,7 @@ public class GcmAppFragment extends ResourceSettingsFragment {
|
||||
@Override
|
||||
public void run() {
|
||||
for (GcmDatabase.Registration registration : registrations) {
|
||||
PushRegisterService.unregister(getContext(), registration.packageName, registration.signature, null, null);
|
||||
PushRegisterManager.unregister(getContext(), registration.packageName, registration.signature, null, null);
|
||||
}
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
|
Loading…
x
Reference in New Issue
Block a user