MicroG 0.2.16.204713

This commit is contained in:
Oizaro 2020-12-23 03:12:18 +01:00
parent 6bfd8eb982
commit 3a06aa7c15
30 changed files with 435 additions and 211 deletions

View File

@ -45,8 +45,8 @@ allprojects {
apply plugin: 'idea'
group = 'org.microg.gms'
version = "0.2.14.204218"
ext.appVersionCode = 204215004
version = "0.2.16.204713"
ext.appVersionCode = 204713001
ext.isReleaseVersion = false
}

View File

@ -19,7 +19,7 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
dependencies {
api "org.microg:safe-parcel:$safeParcelVersion"
api "org.microg:safe-parcel:1.7.0"
implementation "androidx.annotation:annotation:$annotationVersion"
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.21'

View File

@ -46,6 +46,7 @@ public enum GmsService {
CREDENTIALS(68, "com.google.android.gms.auth.api.credentials.service.START"),
MEASUREMENT(93, "com.google.android.gms.measurement.START"),
GASS(116, "com.google.android.gms.gass.START"),
IDENTITY_SIGN_IN(212, "com.google.android.gms.auth.api.identity.service.signin.START"),
;
public int SERVICE_ID;
@ -65,6 +66,15 @@ public enum GmsService {
return UNKNOWN;
}
public static GmsService byAction(String action) {
for (GmsService service : values()) {
for (String serviceAction : service.SECONDARY_ACTIONS) {
if (serviceAction.equals(action)) return service;
}
}
return UNKNOWN;
}
public static String nameFromServiceId(int serviceId) {
return byServiceId(serviceId).toString(serviceId);
}

View File

@ -80,9 +80,10 @@
tools:ignore="ProtectedPermissions" />
<application
android:forceQueryable="true"
android:allowBackup="false"
android:allowBackup="true"
android:fullBackupOnly="true"
android:extractNativeLibs="true"
android:forceQueryable="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config">
@ -144,7 +145,8 @@
<!-- Cloud Messaging -->
<service
android:name="org.microg.gms.gcm.PushRegisterService">
android:name="org.microg.gms.gcm.PushRegisterService"
android:process=":persistent">
<intent-filter>
<action android:name="com.mgoogle.android.c2dm.intent.REGISTER" />
<action android:name="com.mgoogle.android.c2dm.intent.UNREGISTER" />
@ -153,24 +155,33 @@
</intent-filter>
</service>
<receiver android:name="org.microg.gms.gcm.PushRegisterReceiver">
<receiver
android:name="org.microg.gms.gcm.PushRegisterReceiver"
android:process=":persistent">
<intent-filter>
<action android:name="com.mgoogle.iid.TOKEN_REQUEST" />
</intent-filter>
</receiver>
<service android:name="org.microg.gms.gcm.McsService" />
<service
android:name="org.microg.gms.gcm.McsService"
android:process=":persistent" />
<receiver
android:name="org.microg.gms.gcm.SendReceiver">
android:name="org.microg.gms.gcm.SendReceiver"
android:process=":persistent">
<intent-filter>
<action android:name="com.google.android.gcm.intent.SEND" />
</intent-filter>
</receiver>
<receiver android:name="org.microg.gms.gcm.ServiceInfoReceiver" />
<receiver
android:name="org.microg.gms.gcm.ServiceInfoReceiver"
android:process=":persistent" />
<receiver android:name="org.microg.gms.gcm.TriggerReceiver">
<receiver
android:name="org.microg.gms.gcm.TriggerReceiver"
android:process=":persistent">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.AIRPLANE_MODE" />
@ -191,7 +202,9 @@
</intent-filter>
</receiver>
<receiver android:name="org.microg.gms.gcm.UnregisterReceiver">
<receiver
android:name="org.microg.gms.gcm.UnregisterReceiver"
android:process=":persistent">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_DATA_CLEARED" />
<action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />

View File

@ -22,9 +22,7 @@ public class CheckinPrefs implements SharedPreferences.OnSharedPreferenceChangeL
public static CheckinPrefs get(Context context) {
if (INSTANCE == null) {
if (!context.getPackageName().equals(PackageUtils.getProcessName())) {
Log.w("Preferences", CheckinPrefs.class.getName() + " initialized outside main process", new RuntimeException());
}
PackageUtils.warnIfNotMainProcess(context, CheckinPrefs.class);
if (context == null) return new CheckinPrefs(null);
INSTANCE = new CheckinPrefs(context.getApplicationContext());
}

View File

@ -32,13 +32,16 @@ import android.util.Log;
import androidx.legacy.content.WakefulBroadcastReceiver;
import com.mgoogle.android.gms.R;
import com.google.android.gms.checkin.internal.ICheckinService;
import org.microg.gms.auth.AuthConstants;
import org.microg.gms.common.ForegroundServiceInfo;
import org.microg.gms.common.ForegroundServiceContext;
import org.microg.gms.gcm.McsService;
import org.microg.gms.people.PeopleManager;
@ForegroundServiceInfo(value = "Google device registration", res = R.string.service_name_checkin)
public class CheckinService extends IntentService {
private static final String TAG = "GmsCheckinSvc";
public static final long MAX_VALID_CHECKIN_AGE = 24 * 60 * 60 * 1000; // 12 hours

View File

@ -48,16 +48,46 @@ public class ForegroundServiceContext extends ContextWrapper {
return powerManager.isIgnoringBatteryOptimizations(getPackageName());
}
private static String getServiceName(Service service) {
String serviceName = null;
try {
ForegroundServiceInfo annotation = service.getClass().getAnnotation(ForegroundServiceInfo.class);
if (annotation != null) {
if (annotation.res() != 0) {
try {
serviceName = service.getString(annotation.res());
} catch (Exception ignored) {
}
}
if (serviceName == null) {
serviceName = annotation.value();
}
}
} catch (Exception ignored) {
}
if (serviceName == null) {
serviceName = service.getClass().getSimpleName();
}
return serviceName;
}
public static void completeForegroundService(Service service, Intent intent, String tag) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& intent != null
&& intent.getBooleanExtra(EXTRA_FOREGROUND, false)) {
Log.d(tag, "Started in foreground mode.");
service.startForeground(tag.hashCode(), buildForegroundNotification(service));
String serviceName = getServiceName(service);
Log.d(tag, "Started " + serviceName + " in foreground mode.");
try {
Notification notification = buildForegroundNotification(service, serviceName);
service.startForeground(serviceName.hashCode(), notification);
Log.d(tag, "Notification: " + notification.toString());
} catch (Exception e) {
Log.w(tag, e);
}
}
}
private static Notification buildForegroundNotification(Context context) {
private static Notification buildForegroundNotification(Context context, String serviceName) {
Intent notificationIntent = new Intent();
notificationIntent.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@ -70,6 +100,7 @@ public class ForegroundServiceContext extends ContextWrapper {
context.getResources().getString(R.string.notification_service_name),
NotificationManager.IMPORTANCE_LOW);
Channel.setShowBadge(false);
Channel.setVibrationPattern(new long[]{0});
Channel.setLockscreenVisibility(0);
context.getSystemService(NotificationManager.class).createNotificationChannel(Channel);
}

View File

@ -0,0 +1,18 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.common;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ForegroundServiceInfo {
String value();
int res() default 0;
}

View File

@ -24,6 +24,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.os.Binder;
import android.util.Log;
import androidx.annotation.Nullable;
@ -255,6 +256,36 @@ public class PackageUtils {
}
}
public static boolean isPersistentProcess() {
String processName = getProcessName();
if (processName == null) {
Log.w("GmsPackageUtils", "Can't determine process name of current process");
return false;
}
return processName.endsWith(":persistent");
}
public static boolean isMainProcess(Context context) {
String processName = getProcessName();
if (processName == null) {
Log.w("GmsPackageUtils", "Can't determine process name of current process");
return false;
}
return processName.equals(context.getPackageName());
}
public static void warnIfNotPersistentProcess(Class<?> clazz) {
if (!isPersistentProcess()) {
Log.w("GmsPackageUtils", clazz.getSimpleName() + " initialized outside persistent process", new RuntimeException());
}
}
public static void warnIfNotMainProcess(Context context, Class<?> clazz) {
if (!isMainProcess(context)) {
Log.w("GmsPackageUtils", clazz.getSimpleName() + " initialized outside main process", new RuntimeException());
}
}
public static String sha1sum(byte[] bytes) {
MessageDigest md;
try {

View File

@ -53,10 +53,7 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe
public static GcmPrefs get(Context context) {
if (INSTANCE == null) {
if (!context.getPackageName().equals(PackageUtils.getProcessName())) {
Log.w("Preferences", GcmPrefs.class.getName() + " initialized outside main process", new RuntimeException());
}
if (context == null) return new GcmPrefs(null);
PackageUtils.warnIfNotPersistentProcess(GcmPrefs.class);
INSTANCE = new GcmPrefs(context.getApplicationContext());
}
return INSTANCE;
@ -64,7 +61,6 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe
private boolean gcmLogEnabled = true;
private String lastPersistedId = "";
private boolean confirmNewApps = false;
private boolean gcmEnabled = false;
private int networkMobile = 0;
@ -76,19 +72,19 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe
private int learntMobile = 300000;
private int learntOther = 300000;
private final Context context;
private SharedPreferences preferences;
private SharedPreferences systemDefaultPreferences;
private GcmPrefs(Context context) {
if (context != null) {
preferences = PreferenceManager.getDefaultSharedPreferences(context);
preferences.registerOnSharedPreferenceChangeListener(this);
try {
systemDefaultPreferences = (SharedPreferences) Context.class.getDeclaredMethod("getSharedPreferences", File.class, int.class).invoke(context, new File("/system/etc/microg.xml"), Context.MODE_PRIVATE);
} catch (Exception ignored) {
}
update();
this.context = context;
preferences = PreferenceManager.getDefaultSharedPreferences(context);
preferences.registerOnSharedPreferenceChangeListener(this);
try {
systemDefaultPreferences = (SharedPreferences) Context.class.getDeclaredMethod("getSharedPreferences", File.class, int.class).invoke(context, new File("/system/etc/microg.xml"), Context.MODE_PRIVATE);
} catch (Exception ignored) {
}
update();
}
private boolean getSettingsBoolean(String key, boolean def) {
@ -101,7 +97,6 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe
public void update() {
gcmEnabled = getSettingsBoolean(PREF_ENABLE_GCM, true);
gcmLogEnabled = getSettingsBoolean(PREF_FULL_LOG, true);
confirmNewApps = getSettingsBoolean(PREF_CONFIRM_NEW_APPS, false);
lastPersistedId = preferences.getString(PREF_LAST_PERSISTENT_ID, "");
@ -129,12 +124,49 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe
}
public int getHeartbeatMsFor(NetworkInfo info) {
return getHeartbeatMsFor(getNetworkPrefForInfo(info), false);
return getHeartbeatMsFor(getNetworkPrefForInfo(info));
}
public int getHeartbeatMsFor(String pref, boolean rawRoaming) {
if (PREF_NETWORK_ROAMING.equals(pref) && (rawRoaming || networkRoaming != 0)) {
return networkRoaming * 60000;
public int getMobileInterval() {
return networkMobile;
}
public int getWifiInterval() {
return networkWifi;
}
public int getRoamingInterval() {
return networkRoaming;
}
public int getOtherInterval() {
return networkOther;
}
public void setMobileInterval(int value) {
this.networkMobile = value;
preferences.edit().putString(PREF_NETWORK_MOBILE, Integer.toString(networkMobile)).apply();
}
public void setWifiInterval(int value) {
this.networkWifi = value;
preferences.edit().putString(PREF_NETWORK_WIFI, Integer.toString(networkWifi)).apply();
}
public void setRoamingInterval(int value) {
this.networkRoaming = value;
preferences.edit().putString(PREF_NETWORK_ROAMING, Integer.toString(networkRoaming)).apply();
}
public void setOtherInterval(int value) {
this.networkOther = value;
preferences.edit().putString(PREF_NETWORK_OTHER, Integer.toString(networkOther)).apply();
}
public int getHeartbeatMsFor(String pref) {
if (PREF_NETWORK_ROAMING.equals(pref)) {
if (networkRoaming != 0) return networkRoaming * 60000;
else return learntMobile;
} else if (PREF_NETWORK_MOBILE.equals(pref)) {
if (networkMobile != 0) return networkMobile * 60000;
else return learntMobile;
@ -201,6 +233,18 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe
preferences.edit().putInt(PREF_LEARNT_MOBILE, INTERVAL).putInt(PREF_LEARNT_WIFI, INTERVAL).putInt(PREF_LEARNT_OTHER, INTERVAL).apply();
}
public int getLearntMobileInterval() {
return learntMobile;
}
public int getLearntWifiInterval() {
return learntWifi;
}
public int getLearntOtherInterval() {
return learntOther;
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
update();
@ -210,27 +254,23 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe
return gcmEnabled;
}
public boolean isEnabledFor(NetworkInfo info) {
return isEnabled() && info != null && getHeartbeatMsFor(info) >= 0;
}
public static void setEnabled(Context context, boolean newStatus) {
boolean changed = GcmPrefs.get(context).isEnabled() != newStatus;
PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(GcmPrefs.PREF_ENABLE_GCM, newStatus).apply();
public void setEnabled(boolean value) {
boolean changed = gcmEnabled != value;
preferences.edit().putBoolean(GcmPrefs.PREF_ENABLE_GCM, value).apply();
if (!changed) return;
if (!newStatus) {
if (!value) {
McsService.stop(context);
} else {
context.sendBroadcast(new Intent(TriggerReceiver.FORCE_TRY_RECONNECT, null, context, TriggerReceiver.class));
}
}
public boolean isGcmLogEnabled() {
return gcmLogEnabled;
public boolean isEnabledFor(NetworkInfo info) {
return isEnabled() && info != null && getHeartbeatMsFor(info) >= 0;
}
public boolean isConfirmNewApps() {
return confirmNewApps;
public boolean isGcmLogEnabled() {
return gcmLogEnabled;
}
public List<String> getLastPersistedIds() {

View File

@ -40,10 +40,12 @@ import android.util.Log;
import androidx.legacy.content.WakefulBroadcastReceiver;
import com.mgoogle.android.gms.R;
import com.squareup.wire.Message;
import org.microg.gms.checkin.LastCheckinInfo;
import org.microg.gms.common.ForegroundServiceContext;
import org.microg.gms.common.ForegroundServiceInfo;
import org.microg.gms.common.PackageUtils;
import org.microg.gms.gcm.mcs.AppData;
import org.microg.gms.gcm.mcs.Close;
@ -106,6 +108,7 @@ import static org.microg.gms.gcm.McsConstants.MSG_OUTPUT_ERROR;
import static org.microg.gms.gcm.McsConstants.MSG_OUTPUT_READY;
import static org.microg.gms.gcm.McsConstants.MSG_TEARDOWN;
@ForegroundServiceInfo(value = "Cloud messaging", res = R.string.service_name_mcs)
public class McsService extends Service implements Handler.Callback {
private static final String TAG = "GmsGcmMcsSvc";
@ -236,7 +239,7 @@ public class McsService extends Service implements Handler.Callback {
return false;
}
// consider connection to be dead if we did not receive an ack within twice the heartbeat interval
int heartbeatMs = GcmPrefs.get(context).getHeartbeatMsFor(activeNetworkPref, false);
int heartbeatMs = GcmPrefs.get(context).getHeartbeatMsFor(activeNetworkPref);
if (heartbeatMs < 0) {
closeAll();
} else if (SystemClock.elapsedRealtime() - lastHeartbeatAckElapsedRealtime > 2 * heartbeatMs) {
@ -266,7 +269,7 @@ public class McsService extends Service implements Handler.Callback {
public void scheduleHeartbeat(Context context) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
int heartbeatMs = GcmPrefs.get(this).getHeartbeatMsFor(activeNetworkPref, false);
int heartbeatMs = GcmPrefs.get(this).getHeartbeatMsFor(activeNetworkPref);
if (heartbeatMs < 0) {
closeAll();
}

View File

@ -87,8 +87,7 @@ public class PushRegisterManager {
if (!request.delete) {
if (!prefs.isEnabled() ||
(app != null && !app.allowRegister) ||
LastCheckinInfo.read(context).lastCheckin <= 0 ||
(app == null && prefs.isConfirmNewApps())) {
LastCheckinInfo.read(context).lastCheckin <= 0) {
Bundle bundle = new Bundle();
bundle.putString(EXTRA_ERROR, ERROR_SERVICE_NOT_AVAILABLE);
callback.onResult(bundle);

View File

@ -55,8 +55,6 @@ public class GServicesProvider extends ContentProvider {
@Override
public boolean onCreate() {
databaseHelper = new DatabaseHelper(getContext());
if (CheckinPrefs.get(getContext()).isEnabled()) {
getContext().sendOrderedBroadcast(new Intent(getContext(), org.microg.gms.checkin.TriggerReceiver.class), null);
}
@ -64,6 +62,7 @@ public class GServicesProvider extends ContentProvider {
getContext().sendBroadcast(new Intent(org.microg.gms.gcm.TriggerReceiver.FORCE_TRY_RECONNECT, null, getContext(), org.microg.gms.gcm.TriggerReceiver.class));
}
databaseHelper = new DatabaseHelper(getContext());
return true;
}

View File

@ -1,90 +0,0 @@
/*
* Copyright (C) 2017 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.ui;
import android.content.Intent;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.preference.Preference;
import com.mgoogle.android.gms.R;
import org.microg.gms.gcm.GcmPrefs;
import org.microg.gms.gcm.McsService;
import org.microg.gms.gcm.TriggerReceiver;
import org.microg.tools.ui.ResourceSettingsFragment;
public class GcmAdvancedFragment extends ResourceSettingsFragment {
private static String[] HEARTBEAT_PREFS = new String[]{GcmPrefs.PREF_NETWORK_MOBILE, GcmPrefs.PREF_NETWORK_ROAMING, GcmPrefs.PREF_NETWORK_WIFI, GcmPrefs.PREF_NETWORK_OTHER};
public GcmAdvancedFragment() {
preferencesResource = R.xml.preferences_gcm_advanced;
}
@Override
public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) {
super.onCreatePreferences(savedInstanceState, rootKey);
for (String pref : HEARTBEAT_PREFS) {
findPreference(pref).setOnPreferenceChangeListener((preference, newValue) -> {
getPreferenceManager().getSharedPreferences().edit().putString(preference.getKey(), (String) newValue).apply();
updateContent();
if (newValue.equals("-1") && preference.getKey().equals(McsService.activeNetworkPref)) {
McsService.stop(getContext());
} else if (!McsService.isConnected(getContext())) {
getContext().sendBroadcast(new Intent(TriggerReceiver.FORCE_TRY_RECONNECT, null, getContext(), TriggerReceiver.class));
}
return true;
});
}
updateContent();
}
@Override
public void onResume() {
super.onResume();
updateContent();
}
private void updateContent() {
GcmPrefs prefs = GcmPrefs.get(getContext());
for (String pref : HEARTBEAT_PREFS) {
Preference preference = findPreference(pref);
int state = prefs.getNetworkValue(pref);
if (state == 0) {
int heartbeat = prefs.getHeartbeatMsFor(preference.getKey(), true);
if (heartbeat == 0) {
preference.setSummary(getString(R.string.service_status_enabled_short) + " / " + getString(R.string.gcm_status_pref_default));
} else {
preference.setSummary(getString(R.string.service_status_enabled_short) + " / " + getString(R.string.gcm_status_pref_default) + ": " + getHeartbeatString(heartbeat));
}
} else if (state == -1) {
preference.setSummary(getString(R.string.service_status_disabled_short));
} else {
preference.setSummary(getString(R.string.service_status_enabled_short) + " / " + getString(R.string.gcm_status_pref_manual) + ": " + getHeartbeatString(state * 60000));
}
}
}
private String getHeartbeatString(int heartbeatMs) {
if (heartbeatMs < 120000) {
return (heartbeatMs / 1000) + " " + getString(R.string.gcm_status_pref_sec);
}
return (heartbeatMs / 60000) + " " + getString(R.string.gcm_status_pref_min);
}
}

View File

@ -0,0 +1,84 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.chimera
import android.content.ContentProvider
import android.content.ContentValues
import android.content.Context
import android.content.Intent
import android.database.Cursor
import android.database.MatrixCursor
import android.net.Uri
import android.os.Bundle
import android.util.Log
import androidx.core.os.bundleOf
import org.microg.gms.DummyService
import org.microg.gms.common.GmsService
import org.microg.gms.common.RemoteListenerProxy
class ServiceProvider : ContentProvider() {
override fun onCreate(): Boolean {
Log.d(TAG, "onCreate")
return true
}
override fun call(method: String, arg: String?, extras: Bundle?): Bundle? {
when (method) {
"serviceIntentCall" -> {
val serviceAction = extras?.getString("serviceActionBundleKey") ?: return null
val ourServiceAction = GmsService.byAction(serviceAction)?.takeIf { it.SERVICE_ID > 0 }?.ACTION ?: serviceAction
val context = context!!
val intent = Intent(ourServiceAction).apply { `package` = context.packageName }
val resolveInfo = context.packageManager.resolveService(intent, 0)
if (resolveInfo != null) {
intent.setClassName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name)
} else {
intent.setClass(context, DummyService::class.java)
}
Log.d(TAG, "$method: $serviceAction -> $intent")
return bundleOf(
"serviceResponseIntentKey" to intent
)
}
else -> {
Log.d(TAG, "$method: $arg, $extras")
return super.call(method, arg, extras)
}
}
}
override fun query(uri: Uri, projection: Array<out String>?, selection: String?, selectionArgs: Array<out String>?, sortOrder: String?): Cursor? {
val cursor = MatrixCursor(COLUMNS)
Log.d(TAG, "query: $uri")
return cursor
}
override fun insert(uri: Uri, values: ContentValues?): Uri? {
Log.d(TAG, "insert: $uri, $values")
return uri
}
override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<out String>?): Int {
Log.d(TAG, "update: $uri, $values, $selection, $selectionArgs")
return 0
}
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int {
Log.d(TAG, "delete: $uri, $selection, $selectionArgs")
return 0
}
override fun getType(uri: Uri): String {
Log.d(TAG, "getType: $uri")
return "vnd.android.cursor.item/com.google.android.gms.chimera"
}
companion object {
private const val TAG = "ChimeraServiceProvider"
private val COLUMNS = arrayOf("version", "apkPath", "loaderPath", "apkDescStr")
}
}

View File

@ -57,24 +57,7 @@ private suspend fun ensureCheckinIsUpToDate(context: Context) {
private suspend fun ensureAppRegistrationAllowed(context: Context, database: GcmDatabase, packageName: String) {
if (!GcmPrefs.get(context).isEnabled) throw RuntimeException("GCM disabled")
val app = database.getApp(packageName)
if (app == null && GcmPrefs.get(context).isConfirmNewApps) {
val accepted: Boolean = suspendCoroutine { continuation ->
val i = Intent(context, AskPushPermission::class.java)
i.putExtra(AskPushPermission.EXTRA_REQUESTED_PACKAGE, packageName)
i.putExtra(AskPushPermission.EXTRA_RESULT_RECEIVER, object : ResultReceiver(null) {
override fun onReceiveResult(resultCode: Int, resultData: Bundle?) {
continuation.resume(resultCode == Activity.RESULT_OK)
}
})
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
i.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
i.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT)
context.startActivity(i)
}
if (!accepted) {
throw RuntimeException("Push permission not granted to app")
}
} else if (app?.allowRegister == false) {
if (app?.allowRegister == false) {
throw RuntimeException("Push permission not granted to app")
}
}

View File

@ -22,23 +22,29 @@ private const val EXTRA_SERVICE_INFO = "org.microg.gms.gcm.SERVICE_INFO"
private const val EXTRA_CONFIGURATION = "org.microg.gms.gcm.CONFIGURATION"
private const val TAG = "GmsGcmStatusInfo"
data class ServiceInfo(val configuration: ServiceConfiguration, val connected: Boolean, val startTimestamp: Long) : Serializable
data class ServiceInfo(val configuration: ServiceConfiguration, val connected: Boolean, val startTimestamp: Long, val learntMobileInterval: Int, val learntWifiInterval: Int, val learntOtherInterval: Int) : Serializable
// TODO: Intervals
data class ServiceConfiguration(val enabled: Boolean, val confirmNewApps: Boolean) : Serializable {
data class ServiceConfiguration(val enabled: Boolean, val mobile: Int, val wifi: Int, val roaming: Int, val other: Int) : Serializable {
fun saveToPrefs(context: Context) {
GcmPrefs.setEnabled(context, enabled)
// TODO: confirm new apps
GcmPrefs.get(context).apply {
isEnabled = enabled
mobileInterval = mobile
wifiInterval = wifi
roamingInterval = roaming
otherInterval = other
}
}
}
private fun GcmPrefs.toConfiguration(): ServiceConfiguration = ServiceConfiguration(isEnabled, isConfirmNewApps)
private fun GcmPrefs.toConfiguration(): ServiceConfiguration = ServiceConfiguration(isEnabled, mobileInterval, wifiInterval, roamingInterval, otherInterval)
class ServiceInfoReceiver : BroadcastReceiver() {
private fun sendInfoResponse(context: Context) {
context.sendOrderedBroadcast(Intent(ACTION_SERVICE_INFO_RESPONSE).apply {
setPackage(context.packageName)
putExtra(EXTRA_SERVICE_INFO, ServiceInfo(GcmPrefs.get(context).toConfiguration(), McsService.isConnected(context), McsService.getStartTimestamp()))
val prefs = GcmPrefs.get(context)
putExtra(EXTRA_SERVICE_INFO, ServiceInfo(prefs.toConfiguration(), McsService.isConnected(context), McsService.getStartTimestamp(), prefs.learntMobileInterval, prefs.learntWifiInterval, prefs.learntOtherInterval))
}, null)
}

View File

@ -14,6 +14,8 @@ import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.delay
import org.microg.gms.checkin.CheckinPrefs
import org.microg.gms.gcm.GcmPrefs
import org.microg.gms.gcm.getGcmServiceInfo
import org.microg.gms.gcm.setGcmServiceConfiguration
class ProvisionService : LifecycleService() {
private fun Bundle.getBooleanOrNull(key: String): Boolean? {
@ -29,7 +31,7 @@ class ProvisionService : LifecycleService() {
}
intent?.extras?.getBooleanOrNull("checkin_enabled")?.let { CheckinPrefs.setEnabled(this@ProvisionService, it) }
intent?.extras?.getBooleanOrNull("gcm_enabled")?.let { GcmPrefs.setEnabled(this@ProvisionService, it) }
intent?.extras?.getBooleanOrNull("gcm_enabled")?.let { setGcmServiceConfiguration(this@ProvisionService, getGcmServiceInfo(this@ProvisionService).configuration.copy(enabled = it)) }
// What else?
delay(2 * 1000) // Wait 2 seconds to give provisioning some extra time

View File

@ -0,0 +1,104 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.ui
import android.os.Bundle
import androidx.lifecycle.lifecycleScope
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.TwoStatePreference
import com.mgoogle.android.gms.R
import org.microg.gms.gcm.*
class PushNotificationAdvancedFragment : PreferenceFragmentCompat() {
private lateinit var networkMobile: ListPreference
private lateinit var networkWifi: ListPreference
private lateinit var networkRoaming: ListPreference
private lateinit var networkOther: ListPreference
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.preferences_gcm_advanced)
}
override fun onBindPreferences() {
networkMobile = preferenceScreen.findPreference(GcmPrefs.PREF_NETWORK_MOBILE) ?: networkMobile
networkWifi = preferenceScreen.findPreference(GcmPrefs.PREF_NETWORK_WIFI) ?: networkWifi
networkRoaming = preferenceScreen.findPreference(GcmPrefs.PREF_NETWORK_ROAMING) ?: networkRoaming
networkOther = preferenceScreen.findPreference(GcmPrefs.PREF_NETWORK_OTHER) ?: networkOther
networkMobile.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
lifecycleScope.launchWhenResumed {
(newValue as? String)?.toIntOrNull()?.let {
setGcmServiceConfiguration(requireContext(), getGcmServiceInfo(requireContext()).configuration.copy(mobile = it))
}
updateContent()
}
true
}
networkWifi.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
lifecycleScope.launchWhenResumed {
(newValue as? String)?.toIntOrNull()?.let {
setGcmServiceConfiguration(requireContext(), getGcmServiceInfo(requireContext()).configuration.copy(wifi = it))
}
updateContent()
}
true
}
networkRoaming.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
lifecycleScope.launchWhenResumed {
(newValue as? String)?.toIntOrNull()?.let {
setGcmServiceConfiguration(requireContext(), getGcmServiceInfo(requireContext()).configuration.copy(roaming = it))
}
updateContent()
}
true
}
networkOther.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
lifecycleScope.launchWhenResumed {
(newValue as? String)?.toIntOrNull()?.let {
setGcmServiceConfiguration(requireContext(), getGcmServiceInfo(requireContext()).configuration.copy(other = it))
}
updateContent()
}
true
}
}
override fun onResume() {
super.onResume()
updateContent()
}
private fun updateContent() {
lifecycleScope.launchWhenResumed {
val serviceInfo = getGcmServiceInfo(requireContext())
networkMobile.value = serviceInfo.configuration.mobile.toString()
networkMobile.summary = getSummaryString(serviceInfo.configuration.mobile, serviceInfo.learntMobileInterval)
networkWifi.value = serviceInfo.configuration.wifi.toString()
networkWifi.summary = getSummaryString(serviceInfo.configuration.wifi, serviceInfo.learntWifiInterval)
networkRoaming.value = serviceInfo.configuration.roaming.toString()
networkRoaming.summary = getSummaryString(serviceInfo.configuration.roaming, serviceInfo.learntMobileInterval)
networkOther.value = serviceInfo.configuration.other.toString()
networkOther.summary = getSummaryString(serviceInfo.configuration.other, serviceInfo.learntOtherInterval)
}
}
private fun getSummaryString(value: Int, learnt: Int): String = when (value) {
-1 -> getString(R.string.service_status_disabled_short)
0 -> getString(R.string.service_status_enabled_short) + " / " + getString(R.string.gcm_status_pref_default) + ": " + getHeartbeatString(learnt)
else -> getString(R.string.service_status_enabled_short) + " / " + getString(R.string.gcm_status_pref_manual) + ": " + getHeartbeatString(value * 60000)
}
private fun getHeartbeatString(heartbeatMs: Int): String {
return if (heartbeatMs < 120000) {
(heartbeatMs / 1000).toString() + " " + getString(R.string.gcm_status_pref_sec)
} else (heartbeatMs / 60000).toString() + " " + getString(R.string.gcm_status_pref_min)
}
companion object {
private val HEARTBEAT_PREFS = arrayOf(GcmPrefs.PREF_NETWORK_MOBILE, GcmPrefs.PREF_NETWORK_ROAMING, GcmPrefs.PREF_NETWORK_WIFI, GcmPrefs.PREF_NETWORK_OTHER)
}
}

View File

@ -52,7 +52,7 @@
</fragment>
<fragment
android:id="@+id/gcmAdvancedFragment"
android:name="org.microg.gms.ui.GcmAdvancedFragment"
android:name="org.microg.gms.ui.PushNotificationAdvancedFragment"
android:label="@string/service_name_mcs" />
<fragment

View File

@ -18,14 +18,14 @@
<resources>
<string-array name="gcm_network_config_names" translatables="false">
<item>@string/service_status_disabled</item>
<item>@string/service_status_default</item>
<item>Intervalo de ping: 2 minutos</item>
<item>Intervalo de ping: 5 minutos</item>
<item>Intervalo de ping: 10 minutos</item>
<item>Intervalo de ping: 15 minutos</item>
<item>Intervalo de ping: 20 minutos</item>
<item>Intervalo de ping: 30 minutos</item>
<item>@string/service_status_disabled_short</item>
<item>@string/gcm_status_pref_default</item>
<item>Intervalo de ping: 2 minutos</item>
<item>Intervalo de ping: 5 minutos</item>
<item>Intervalo de ping: 10 minutos</item>
<item>Intervalo de ping: 15 minutos</item>
<item>Intervalo de ping: 20 minutos</item>
<item>Intervalo de ping: 30 minutos</item>
</string-array>
</resources>

View File

@ -59,10 +59,8 @@ Esto puede tardar unos minutos."</string>
<string name="perm_extended_access_label">Acceso extendido a los servicios de Google</string>
<string name="service_name_checkin">Registro de dispositivos Google</string>
<string name="service_name_mcs">Google Cloud Messaging</string>
<string name="service_name_mcs">Cloud Messaging</string>
<string name="service_status_disabled">Deshabilitado</string>
<string name="service_status_default">Por Defecto</string>
<string name="service_status_enabled_short">Encendido</string>
<string name="service_status_disabled_short">Apagado</string>
@ -85,7 +83,7 @@ Esto puede tardar unos minutos."</string>
<string name="checkin_last_registration">Ultimo registro: <xliff:g example="Yesterday, 02:20 PM">%1$s</xliff:g></string>
<string name="cond_gcm_bat_title">Optimizaciones de bateria habilitadas</string>
<string name="cond_gcm_bat_summary">Has habilitado Google Cloud Messaging pero tienes las optimizacion de bateria activada para los servicios de microG. Para que lleguen las notificaciones deberás deshabilitar la optimización de batería para microG.</string>
<string name="cond_gcm_bat_summary">Has habilitado Cloud Messaging pero tienes las optimizacion de bateria activada para los servicios de microG. Para que lleguen las notificaciones deberás deshabilitar la optimización de batería para microG.</string>
<string name="cond_gcm_bat_action">Deshabilitar optimizaciones</string>
<string name="prefs_account">Preferencias de Cuenta</string>
@ -100,7 +98,7 @@ Esto puede tardar unos minutos."</string>
<string name="pref_add_account_title">Cuenta</string>
<string name="pref_add_account_summary">Añadir cuenta de Google</string>
<string name="pref_gcm_switcher_title">Recibir notificaciones push</string>
<string name="pref_gcm_enable_mcs_summary">Google Cloud Messaging es un proveedor de notificaciónes push usado por muchas aplicaciones de terceros. Pará usarlo tienes que activar registro de dispositivos.</string>
<string name="pref_gcm_enable_mcs_summary">Cloud Messaging es un proveedor de notificaciónes push usado por muchas aplicaciones de terceros. Pará usarlo tienes que activar registro de dispositivos.</string>
<string name="pref_about_title">Acerca de Vanced microG</string>
<string name="pref_cast_double_fix">Solucion para Cast duplicado</string>

View File

@ -18,8 +18,8 @@
<resources>
<string-array name="gcm_network_config_names" translatables="false">
<item>@string/service_status_disabled</item>
<item>@string/service_status_default</item>
<item>@string/service_status_disabled_short</item>
<item>@string/gcm_status_pref_default</item>
<item>Ping interval: 2 menit</item>
<item>Ping interval: 5 menit</item>
<item>Ping interval: 10 menit</item>

View File

@ -59,10 +59,8 @@ Ini bisa berlangsung beberapa menit."</string>
<string name="perm_extended_access_label">Akses lebih ke layanan Google</string>
<string name="service_name_checkin">Google device registration</string>
<string name="service_name_mcs">Google Cloud Messaging</string>
<string name="service_name_mcs">Cloud Messaging</string>
<string name="service_status_disabled">Dinonaktifkan</string>
<string name="service_status_default">Default</string>
<string name="service_status_enabled_short">Hidup</string>
<string name="service_status_disabled_short">Mati</string>
@ -85,7 +83,7 @@ Ini bisa berlangsung beberapa menit."</string>
<string name="checkin_last_registration">Registrasi terakhir: <xliff:g example="Yesterday, 02:20 PM">%1$s</xliff:g></string>
<string name="cond_gcm_bat_title">Optimisasi baterai diaktifkan</string>
<string name="cond_gcm_bat_summary">Anda mengaktifkan Google Cloud Messaging namun mengaktifkan optimisasi baterai untuk layanan utama microG. Untuk mendapatkan notifikasi push anda harus menonaktifkan optimisasi baterai.</string>
<string name="cond_gcm_bat_summary">Anda mengaktifkan Cloud Messaging namun mengaktifkan optimisasi baterai untuk layanan utama microG. Untuk mendapatkan notifikasi push anda harus menonaktifkan optimisasi baterai.</string>
<string name="cond_gcm_bat_action">Nonaktifkan optimisasi</string>
<string name="prefs_account">Preferensi akun</string>
@ -100,7 +98,7 @@ Ini bisa berlangsung beberapa menit."</string>
<string name="pref_add_account_title">Akun</string>
<string name="pref_add_account_summary">Tambahkan akun Google</string>
<string name="pref_gcm_switcher_title">Terima notifikasi push</string>
<string name="pref_gcm_enable_mcs_summary">Google Cloud Messaging adalah penyedia notifikasi push yang digunakan pada banyak aplikasi pihak ketiga. Untuk menggunakannya anda harus mengaktifkan device registration.</string>
<string name="pref_gcm_enable_mcs_summary">Cloud Messaging adalah penyedia notifikasi push yang digunakan pada banyak aplikasi pihak ketiga. Untuk menggunakannya anda harus mengaktifkan device registration.</string>
<string name="pref_about_title">Tentang Vanced microG</string>
<string name="pref_cast_double_fix">Perbaikan Cast terduplikasi</string>

View File

@ -18,8 +18,8 @@
<resources>
<string-array name="gcm_network_config_names" translatables="false">
<item>@string/service_status_disabled</item>
<item>@string/service_status_default</item>
<item>@string/service_status_disabled_short</item>
<item>@string/gcm_status_pref_default</item>
<item>Intervallo ping: 2 minuti</item>
<item>Intervallo ping: 5 minuti</item>
<item>Intervallo ping: 10 minuti</item>

View File

@ -59,10 +59,8 @@ Questo potrà richiedere un paio di minuti"</string>
<string name="perm_extended_access_label">Estendi accesso ai servizi Google</string>
<string name="service_name_checkin">Registrazione dispositivo Google</string>
<string name="service_name_mcs">Messaggistica Cloud Google</string>
<string name="service_name_mcs">Messaggistica Cloud</string>
<string name="service_status_disabled">Disattivata</string>
<string name="service_status_default">Predefinito</string>
<string name="service_status_enabled_short">Attiva</string>
<string name="service_status_disabled_short">Disattivata</string>
@ -85,7 +83,7 @@ Questo potrà richiedere un paio di minuti"</string>
<string name="checkin_last_registration">Ultima registrazione: <xliff:g example="Yesterday, 02:20 PM">%1$s</xliff:g></string>
<string name="cond_gcm_bat_title">Ottimizzazione batteria attivata</string>
<string name="cond_gcm_bat_summary">Hai attivato l\'opzione Messaggistica Cloud Google ma i Servizi Vanced microG risultano al momento limitati dall\'ottimizzazione energetica di sistema. Se desideri ricevere le notifiche push, escludi i microG da questa ottimizzazione.</string>
<string name="cond_gcm_bat_summary">Hai attivato l\'opzione Messaggistica Cloud ma i Servizi Vanced microG risultano al momento limitati dall\'ottimizzazione energetica di sistema. Se desideri ricevere le notifiche push, escludi i microG da questa ottimizzazione.</string>
<string name="cond_gcm_bat_action">Disattiva ottimizzazione</string>
<string name="prefs_account">Preferenze account</string>
@ -100,7 +98,7 @@ Questo potrà richiedere un paio di minuti"</string>
<string name="pref_add_account_title">Account</string>
<string name="pref_add_account_summary">Aggiungi account Google</string>
<string name="pref_gcm_switcher_title">Ricevi notifiche push</string>
<string name="pref_gcm_enable_mcs_summary">Messaggistica Cloud Google è un fornitore di notifiche push presente in molte applicazioni di terze parti. Per utilizzarlo è necessario attivare la registrazione del dispositivo.</string>
<string name="pref_gcm_enable_mcs_summary">Messaggistica Cloud è un fornitore di notifiche push presente in molte applicazioni di terze parti. Per utilizzarlo è necessario attivare la registrazione del dispositivo.</string>
<string name="pref_about_title">Informazioni su Vanced microG</string>
<string name="pref_cast_double_fix">Correzione cast duplicato</string>

View File

@ -18,8 +18,8 @@
<resources>
<string-array name="gcm_network_config_names" translatables="false">
<item>@string/service_status_disabled</item>
<item>@string/service_status_default</item>
<item>@string/service_status_disabled_short</item>
<item>@string/gcm_status_pref_default</item>
<item>Интервал пинга: 2 минуты</item>
<item>Интервал пинга: 5 минут</item>
<item>Интервал пинга: 10 минут</item>

View File

@ -59,10 +59,8 @@
<string name="perm_extended_access_label">Расширенный доступ к сервисам Google</string>
<string name="service_name_checkin">Регистрация устройства в Google</string>
<string name="service_name_mcs">Google Cloud Messaging</string>
<string name="service_name_mcs">Cloud Messaging</string>
<string name="service_status_disabled">Отключен</string>
<string name="service_status_default">По умолчанию</string>
<string name="service_status_enabled_short">Вкл</string>
<string name="service_status_disabled_short">Выкл</string>
@ -85,7 +83,7 @@
<string name="checkin_last_registration">Последняя регистрация: <xliff:g example="Yesterday, 02:20 PM">%1$s</xliff:g></string>
<string name="cond_gcm_bat_title">Включена экономия заряда батареи</string>
<string name="cond_gcm_bat_summary">Вы включили Google Cloud Messaging, но не отключили экономию заряда батареи для Vanced microG. Для корректной работы уведомлений вам нужно отключить экономию заряда батареи.</string>
<string name="cond_gcm_bat_summary">Вы включили Cloud Messaging, но не отключили экономию заряда батареи для Vanced microG. Для корректной работы уведомлений вам нужно отключить экономию заряда батареи.</string>
<string name="cond_gcm_bat_action">Отключить экономию</string>
<string name="prefs_account">Настройки аккаунта</string>
@ -100,7 +98,7 @@
<string name="pref_add_account_title">Аккаунт</string>
<string name="pref_add_account_summary">Добавить аккаунт Google</string>
<string name="pref_gcm_switcher_title">Получать push-уведомления</string>
<string name="pref_gcm_enable_mcs_summary">Google Cloud Messaging позволяет получать уведомления от многих приложений. Чтобы использовать GCM, включите регистрацию устройства в Google.</string>
<string name="pref_gcm_enable_mcs_summary">Cloud Messaging позволяет получать уведомления от многих приложений. Чтобы использовать GCM, включите регистрацию устройства в Google.</string>
<string name="pref_about_title">О Vanced microG</string>
<string name="pref_cast_double_fix">Исправление двух кнопок трансляции</string>

View File

@ -29,8 +29,8 @@
</string-array>
<string-array name="gcm_network_config_names" translatables="false">
<item>@string/service_status_disabled</item>
<item>@string/service_status_default</item>
<item>@string/service_status_disabled_short</item>
<item>@string/gcm_status_pref_default</item>
<item>Ping interval: 2 minutes</item>
<item>Ping interval: 5 minutes</item>
<item>Ping interval: 10 minutes</item>

View File

@ -59,10 +59,8 @@ This can take a couple of minutes."</string>
<string name="perm_extended_access_label">Extended access to Google services</string>
<string name="service_name_checkin">Google device registration</string>
<string name="service_name_mcs">Google Cloud Messaging</string>
<string name="service_name_mcs">Cloud Messaging</string>
<string name="service_status_disabled">Disabled</string>
<string name="service_status_default">Default</string>
<string name="service_status_enabled_short">On</string>
<string name="service_status_disabled_short">Off</string>
@ -85,7 +83,7 @@ This can take a couple of minutes."</string>
<string name="checkin_last_registration">Last registration: <xliff:g example="Yesterday, 02:20 PM">%1$s</xliff:g></string>
<string name="cond_gcm_bat_title">Battery optimizations enabled</string>
<string name="cond_gcm_bat_summary">You enabled Google Cloud Messaging but have battery optimizations active for microG Services Core. For push notifications to arrive you should disable battery optimizations.</string>
<string name="cond_gcm_bat_summary">You enabled Cloud Messaging but have battery optimizations active for microG Services Core. For push notifications to arrive you should disable battery optimizations.</string>
<string name="cond_gcm_bat_action">Disable optimization</string>
<string name="prefs_account">Account preferences</string>
@ -100,7 +98,7 @@ This can take a couple of minutes."</string>
<string name="pref_add_account_title">Account</string>
<string name="pref_add_account_summary">Add Google account</string>
<string name="pref_gcm_switcher_title">Receive push notifications</string>
<string name="pref_gcm_enable_mcs_summary">Google Cloud Messaging is a push notification provider used by many third-party applications. To use it you must enable device registration.</string>
<string name="pref_gcm_enable_mcs_summary">Cloud Messaging is a push notification provider used by many third-party applications. To use it you must enable device registration.</string>
<string name="pref_about_title">About Vanced microG</string>
<string name="pref_cast_double_fix">Cast duplication fix</string>