From 6429c006f4491594cd47567bc68fc3c2a7afe89b Mon Sep 17 00:00:00 2001
From: Venny
Date: Sun, 19 Jul 2020 22:56:15 +0200
Subject: [PATCH 1/3] Fix grammar
---
.../java/org/microg/gms/common/ForegroundServiceContext.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/play-services-base-core/src/main/java/org/microg/gms/common/ForegroundServiceContext.java b/play-services-base-core/src/main/java/org/microg/gms/common/ForegroundServiceContext.java
index 539f4ed4..9fd66d7d 100644
--- a/play-services-base-core/src/main/java/org/microg/gms/common/ForegroundServiceContext.java
+++ b/play-services-base-core/src/main/java/org/microg/gms/common/ForegroundServiceContext.java
@@ -75,7 +75,7 @@ public class ForegroundServiceContext extends ContextWrapper {
return new Notification.Builder(context, channel.getId())
.setOngoing(true)
.setContentTitle("Running in background")
- .setContentText("This notification ensures, that microG does not get killed.")
+ .setContentText("This notification ensures that microG does not get killed.")
.setSmallIcon(R.drawable.ic_foreground_notification)
.setColor(0xFFFFFF)
.build();
From 2d5e3ef7427f9261d2f6c623e687b04e9d41bab8 Mon Sep 17 00:00:00 2001
From: Venny
Date: Sun, 19 Jul 2020 23:19:41 +0200
Subject: [PATCH 2/3] Remove useless folders
---
play-services-cast/build.gradle | 47 --
play-services-cast/gradle.properties | 34 --
.../src/main/AndroidManifest.xml | 18 -
.../com/google/android/gms/cast/Cast.java | 223 ---------
.../android/gms/cast/CastPresentation.java | 33 --
.../android/gms/cast/CastRemoteDisplay.java | 76 ----
.../gms/cast/CastRemoteDisplayApi.java | 26 --
.../cast/CastRemoteDisplayLocalService.java | 28 --
.../org/microg/gms/cast/CastApiBuilder.java | 34 --
.../java/org/microg/gms/cast/CastApiImpl.java | 134 ------
.../org/microg/gms/cast/CastClientImpl.java | 29 --
.../gms/cast/CastRemoteDisplayApiBuilder.java | 35 --
.../gms/cast/CastRemoteDisplayApiImpl.java | 34 --
play-services-gcm/build.gradle | 47 --
play-services-gcm/gradle.properties | 34 --
.../src/main/AndroidManifest.xml | 27 --
.../android/gms/gcm/GcmListenerService.java | 194 --------
.../android/gms/gcm/GcmNetworkManager.java | 244 ----------
.../com/google/android/gms/gcm/GcmPubSub.java | 121 -----
.../google/android/gms/gcm/GcmReceiver.java | 127 ------
.../android/gms/gcm/GcmTaskService.java | 149 ------
.../android/gms/gcm/GoogleCloudMessaging.java | 322 -------------
.../google/android/gms/gcm/OneoffTask.java | 221 ---------
.../android/gms/gcm/PendingCallback.java | 59 ---
.../google/android/gms/gcm/PeriodicTask.java | 235 ----------
.../java/com/google/android/gms/gcm/Task.java | 271 -----------
.../google/android/gms/gcm/TaskParams.java | 49 --
.../org/microg/gms/gcm/CloudMessagingRpc.java | 165 -------
play-services-iid/build.gradle | 47 --
play-services-iid/gradle.properties | 34 --
.../src/main/AndroidManifest.xml | 24 -
.../google/android/gms/iid/InstanceID.java | 275 ------------
.../gms/iid/InstanceIDListenerService.java | 138 ------
.../org/microg/gms/iid/InstanceIdRpc.java | 423 ------------------
.../org/microg/gms/iid/InstanceIdStore.java | 111 -----
play-services/build.gradle | 54 ---
play-services/gradle.properties | 34 --
play-services/src/main/AndroidManifest.xml | 22 -
38 files changed, 4178 deletions(-)
delete mode 100644 play-services-cast/build.gradle
delete mode 100644 play-services-cast/gradle.properties
delete mode 100644 play-services-cast/src/main/AndroidManifest.xml
delete mode 100644 play-services-cast/src/main/java/com/google/android/gms/cast/Cast.java
delete mode 100644 play-services-cast/src/main/java/com/google/android/gms/cast/CastPresentation.java
delete mode 100644 play-services-cast/src/main/java/com/google/android/gms/cast/CastRemoteDisplay.java
delete mode 100644 play-services-cast/src/main/java/com/google/android/gms/cast/CastRemoteDisplayApi.java
delete mode 100644 play-services-cast/src/main/java/com/google/android/gms/cast/CastRemoteDisplayLocalService.java
delete mode 100644 play-services-cast/src/main/java/org/microg/gms/cast/CastApiBuilder.java
delete mode 100644 play-services-cast/src/main/java/org/microg/gms/cast/CastApiImpl.java
delete mode 100644 play-services-cast/src/main/java/org/microg/gms/cast/CastClientImpl.java
delete mode 100644 play-services-cast/src/main/java/org/microg/gms/cast/CastRemoteDisplayApiBuilder.java
delete mode 100644 play-services-cast/src/main/java/org/microg/gms/cast/CastRemoteDisplayApiImpl.java
delete mode 100644 play-services-gcm/build.gradle
delete mode 100644 play-services-gcm/gradle.properties
delete mode 100644 play-services-gcm/src/main/AndroidManifest.xml
delete mode 100644 play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmListenerService.java
delete mode 100644 play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmNetworkManager.java
delete mode 100644 play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmPubSub.java
delete mode 100644 play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmReceiver.java
delete mode 100644 play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmTaskService.java
delete mode 100644 play-services-gcm/src/main/java/com/google/android/gms/gcm/GoogleCloudMessaging.java
delete mode 100644 play-services-gcm/src/main/java/com/google/android/gms/gcm/OneoffTask.java
delete mode 100644 play-services-gcm/src/main/java/com/google/android/gms/gcm/PendingCallback.java
delete mode 100644 play-services-gcm/src/main/java/com/google/android/gms/gcm/PeriodicTask.java
delete mode 100644 play-services-gcm/src/main/java/com/google/android/gms/gcm/Task.java
delete mode 100644 play-services-gcm/src/main/java/com/google/android/gms/gcm/TaskParams.java
delete mode 100644 play-services-gcm/src/main/java/org/microg/gms/gcm/CloudMessagingRpc.java
delete mode 100644 play-services-iid/build.gradle
delete mode 100644 play-services-iid/gradle.properties
delete mode 100644 play-services-iid/src/main/AndroidManifest.xml
delete mode 100644 play-services-iid/src/main/java/com/google/android/gms/iid/InstanceID.java
delete mode 100644 play-services-iid/src/main/java/com/google/android/gms/iid/InstanceIDListenerService.java
delete mode 100644 play-services-iid/src/main/java/org/microg/gms/iid/InstanceIdRpc.java
delete mode 100644 play-services-iid/src/main/java/org/microg/gms/iid/InstanceIdStore.java
delete mode 100644 play-services/build.gradle
delete mode 100644 play-services/gradle.properties
delete mode 100644 play-services/src/main/AndroidManifest.xml
diff --git a/play-services-cast/build.gradle b/play-services-cast/build.gradle
deleted file mode 100644
index 85ea138a..00000000
--- a/play-services-cast/build.gradle
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2013-2015 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.
- */
-
-apply plugin: 'com.android.library'
-
-String getMyVersionName() {
- def stdout = new ByteArrayOutputStream()
- if (rootProject.file("gradlew").exists())
- exec { commandLine 'git', 'describe', '--tags', '--always', '--dirty'; standardOutput = stdout }
- else // automatic build system, don't tag dirty
- exec { commandLine 'git', 'describe', '--tags', '--always'; standardOutput = stdout }
- return stdout.toString().trim().substring(1)
-}
-
-android {
- compileSdkVersion androidCompileSdk()
- buildToolsVersion "$androidBuildVersionTools"
-
- defaultConfig {
- versionName getMyVersionName()
- minSdkVersion androidMinSdk()
- targetSdkVersion androidTargetSdk()
- }
-
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
-}
-
-dependencies {
- api project(':play-services-base')
- api project(':play-services-cast-api')
-}
diff --git a/play-services-cast/gradle.properties b/play-services-cast/gradle.properties
deleted file mode 100644
index 937fcc06..00000000
--- a/play-services-cast/gradle.properties
+++ /dev/null
@@ -1,34 +0,0 @@
-#
-# Copyright 2013-2016 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.
-#
-
-POM_NAME=Play Services Cast Library
-POM_DESCRIPTION=The Play Services Library module to access the Cast API
-
-POM_PACKAGING=aar
-
-POM_URL=https://github.com/microg/android_external_GmsLib
-
-POM_SCM_URL=https://github.com/microg/android_external_GmsLib
-POM_SCM_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
-POM_SCM_DEV_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
-
-POM_LICENCE_NAME=The Apache Software License, Version 2.0
-POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
-POM_LICENCE_DIST=repo
-
-POM_DEVELOPER_ID=mar-v-in
-POM_DEVELOPER_NAME=Marvin W
-
diff --git a/play-services-cast/src/main/AndroidManifest.xml b/play-services-cast/src/main/AndroidManifest.xml
deleted file mode 100644
index 7e14f394..00000000
--- a/play-services-cast/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
diff --git a/play-services-cast/src/main/java/com/google/android/gms/cast/Cast.java b/play-services-cast/src/main/java/com/google/android/gms/cast/Cast.java
deleted file mode 100644
index b223b584..00000000
--- a/play-services-cast/src/main/java/com/google/android/gms/cast/Cast.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) 2013-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 com.google.android.gms.cast;
-
-import android.os.Bundle;
-
-import com.google.android.gms.common.api.Api;
-import com.google.android.gms.common.api.GoogleApiClient;
-import com.google.android.gms.common.api.PendingResult;
-import com.google.android.gms.common.api.Result;
-import com.google.android.gms.common.api.Status;
-
-import org.microg.gms.cast.CastApiBuilder;
-import org.microg.gms.cast.CastApiImpl;
-import org.microg.gms.common.PublicApi;
-
-import java.io.IOException;
-
-@PublicApi
-public final class Cast {
-
- /**
- * A constant indicating that the Google Cast device is not the currently active video input.
- */
- public static final int ACTIVE_INPUT_STATE_NO = 0;
-
- /**
- * A constant indicating that it is not known (and/or not possible to know) whether the Google Cast device is
- * the currently active video input. Active input state can only be reported when the Google Cast device is
- * connected to a TV or AVR with CEC support.
- */
- public static final int ACTIVE_INPUT_STATE_UNKNOWN = -1;
-
- /**
- * A constant indicating that the Google Cast device is the currently active video input.
- */
- public static final int ACTIVE_INPUT_STATE_YES = 1;
-
- /**
- * A boolean extra for the connection hint bundle passed to
- * {@link GoogleApiClient.ConnectionCallbacks#onConnected(Bundle)} that indicates that the connection was
- * re-established, but the receiver application that was in use at the time of the connection loss is no longer
- * running on the receiver.
- */
- public static final String EXTRA_APP_NO_LONGER_RUNNING = "com.google.android.gms.cast.EXTRA_APP_NO_LONGER_RUNNING";
-
- /**
- * The maximum raw message length (in bytes) that is supported by a Cast channel.
- */
- public static final int MAX_MESSAGE_LENGTH = 65536;
-
- /**
- * The maximum length (in characters) of a namespace name.
- */
- public static final int MAX_NAMESPACE_LENGTH = 128;
-
- /**
- * A constant indicating that the Google Cast device is not currently in standby.
- */
- public static final int STANDBY_STATE_NO = 0;
-
- /**
- * A constant indicating that it is not known (and/or not possible to know) whether the Google Cast device is
- * currently in standby. Standby state can only be reported when the Google Cast device is connected to a TV or
- * AVR with CEC support.
- */
- public static final int STANDBY_STATE_UNKNOWN = -1;
-
- /**
- * A constant indicating that the Google Cast device is currently in standby.
- */
- public static final int STANDBY_STATE_YES = 1;
-
-
- /**
- * Token to pass to {@link GoogleApiClient.Builder#addApi(Api)} to enable the Cast features.
- */
- public static final Api API = new Api(new CastApiBuilder());
-
- /**
- * An implementation of the CastApi interface. The interface is used to interact with a cast device.
- */
- public static final Cast.CastApi CastApi = new CastApiImpl();
-
- private Cast() {
- }
-
- public interface ApplicationConnectionResult extends Result {
- ApplicationMetadata getApplicationMetadata();
-
- String getApplicationStatus();
-
- String getSessionId();
-
- boolean getWasLaunched();
- }
-
- public interface CastApi {
- int getActiveInputState(GoogleApiClient client);
-
- ApplicationMetadata getApplicationMetadata(GoogleApiClient client);
-
- String getApplicationStatus(GoogleApiClient client);
-
- int getStandbyState(GoogleApiClient client);
-
- double getVolume(GoogleApiClient client);
-
- boolean isMute(GoogleApiClient client);
-
- PendingResult joinApplication(GoogleApiClient client);
-
- PendingResult joinApplication(GoogleApiClient client, String applicationId, String sessionId);
-
- PendingResult joinApplication(GoogleApiClient client, String applicationId);
-
- PendingResult launchApplication(GoogleApiClient client, String applicationId, LaunchOptions launchOptions);
-
- PendingResult launchApplication(GoogleApiClient client, String applicationId);
-
- @Deprecated
- PendingResult launchApplication(GoogleApiClient client, String applicationId, boolean relaunchIfRunning);
-
- PendingResult leaveApplication(GoogleApiClient client);
-
- void removeMessageReceivedCallbacks(GoogleApiClient client, String namespace) throws IOException;
-
- void requestStatus(GoogleApiClient client) throws IOException;
-
- PendingResult sendMessage(GoogleApiClient client, String namespace, String message);
-
- void setMessageReceivedCallbacks(GoogleApiClient client, String namespace, Cast.MessageReceivedCallback callbacks) throws IOException;
-
- void setMute(GoogleApiClient client, boolean mute) throws IOException;
-
- void setVolume(GoogleApiClient client, double volume) throws IOException;
-
- PendingResult stopApplication(GoogleApiClient client);
-
- PendingResult stopApplication(GoogleApiClient client, String sessionId);
- }
-
- public static class CastOptions implements Api.ApiOptions.HasOptions {
- private final CastDevice castDevice;
- private final Listener castListener;
- private final boolean verboseLoggingEnabled;
-
- public CastOptions(CastDevice castDevice, Listener castListener, boolean verboseLoggingEnabled) {
- this.castDevice = castDevice;
- this.castListener = castListener;
- this.verboseLoggingEnabled = verboseLoggingEnabled;
- }
-
- @Deprecated
- public static Builder builder(CastDevice castDevice, Listener castListener) {
- return new Builder(castDevice, castListener);
- }
-
- public static class Builder {
- private final CastDevice castDevice;
- private final Listener castListener;
- private boolean verboseLoggingEnabled;
-
- public Builder(CastDevice castDevice, Listener castListener) {
- this.castDevice = castDevice;
- this.castListener = castListener;
- }
-
- public CastOptions build() {
- return new CastOptions(castDevice, castListener, verboseLoggingEnabled);
- }
-
- public Builder setVerboseLoggingEnabled(boolean verboseLoggingEnabled) {
- this.verboseLoggingEnabled = verboseLoggingEnabled;
- return this;
- }
- }
- }
-
- public static class Listener {
- public void onActiveInputStateChanged(int activeInputState) {
-
- }
-
- public void onApplicationDisconnected(int statusCode) {
-
- }
-
- public void onApplicationMetadataChanged(ApplicationMetadata applicationMetadata) {
-
- }
-
- public void onApplicationStatusChanged() {
-
- }
-
- public void onStandbyStateChanged(int standbyState) {
-
- }
-
- public void onVolumeChanged() {
-
- }
- }
-
- public interface MessageReceivedCallback {
- void onMessageReceived(CastDevice castDevice, String namespace, String message);
- }
-}
diff --git a/play-services-cast/src/main/java/com/google/android/gms/cast/CastPresentation.java b/play-services-cast/src/main/java/com/google/android/gms/cast/CastPresentation.java
deleted file mode 100644
index cfc55685..00000000
--- a/play-services-cast/src/main/java/com/google/android/gms/cast/CastPresentation.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2013-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 com.google.android.gms.cast;
-
-import android.annotation.TargetApi;
-import android.app.Presentation;
-import android.content.Context;
-import android.view.Display;
-
-@TargetApi(17)
-public class CastPresentation extends Presentation {
- public CastPresentation(Context outerContext, Display display) {
- super(outerContext, display);
- }
-
- public CastPresentation(Context outerContext, Display display, int theme) {
- super(outerContext, display, theme);
- }
-}
diff --git a/play-services-cast/src/main/java/com/google/android/gms/cast/CastRemoteDisplay.java b/play-services-cast/src/main/java/com/google/android/gms/cast/CastRemoteDisplay.java
deleted file mode 100644
index ddb5d53c..00000000
--- a/play-services-cast/src/main/java/com/google/android/gms/cast/CastRemoteDisplay.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2013-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 com.google.android.gms.cast;
-
-import android.view.Display;
-
-import com.google.android.gms.common.api.Api;
-import com.google.android.gms.common.api.GoogleApiClient;
-import com.google.android.gms.common.api.Result;
-import com.google.android.gms.common.api.Status;
-
-import org.microg.gms.cast.CastRemoteDisplayApiBuilder;
-import org.microg.gms.cast.CastRemoteDisplayApiImpl;
-import org.microg.gms.common.PublicApi;
-
-@PublicApi
-public final class CastRemoteDisplay {
- /**
- * Token to pass to {@link GoogleApiClient.Builder#addApi(Api)} to enable the CastRemoteDisplay features.
- */
- public static final Api API = new Api(new CastRemoteDisplayApiBuilder());
-
- /**
- * An implementation of the CastRemoteDisplayAPI interface. The interface is used to interact with a cast device.
- */
- public static final CastRemoteDisplayApi CastApi = new CastRemoteDisplayApiImpl();
-
- private CastRemoteDisplay() {
- }
-
- public static final class CastRemoteDisplayOptions implements Api.ApiOptions.HasOptions {
- private CastDevice castDevice;
- private CastRemoteDisplaySessionCallbacks callbacks;
-
- private CastRemoteDisplayOptions(CastDevice castDevice, CastRemoteDisplaySessionCallbacks callbacks) {
- this.castDevice = castDevice;
- this.callbacks = callbacks;
- }
-
- public static final class Builder {
- private CastDevice castDevice;
- private CastRemoteDisplaySessionCallbacks callbacks;
-
- public Builder(CastDevice castDevice, CastRemoteDisplaySessionCallbacks callbacks) {
- this.castDevice = castDevice;
- this.callbacks = callbacks;
- }
-
- public CastRemoteDisplayOptions build() {
- return new CastRemoteDisplayOptions(castDevice, callbacks);
- }
- }
- }
-
- public interface CastRemoteDisplaySessionCallbacks {
- void onRemoteDisplayEnded(Status status);
- }
-
- public interface CastRemoteDisplaySessionResult extends Result {
- Display getPresentationDisplay();
- }
-}
diff --git a/play-services-cast/src/main/java/com/google/android/gms/cast/CastRemoteDisplayApi.java b/play-services-cast/src/main/java/com/google/android/gms/cast/CastRemoteDisplayApi.java
deleted file mode 100644
index 5c053581..00000000
--- a/play-services-cast/src/main/java/com/google/android/gms/cast/CastRemoteDisplayApi.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2013-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 com.google.android.gms.cast;
-
-import com.google.android.gms.common.api.GoogleApiClient;
-import com.google.android.gms.common.api.PendingResult;
-
-public interface CastRemoteDisplayApi {
- PendingResult startRemoteDisplay(GoogleApiClient apiClient, String applicationId);
-
- PendingResult stopRemoteDisplay(GoogleApiClient apiClient);
-}
diff --git a/play-services-cast/src/main/java/com/google/android/gms/cast/CastRemoteDisplayLocalService.java b/play-services-cast/src/main/java/com/google/android/gms/cast/CastRemoteDisplayLocalService.java
deleted file mode 100644
index dbc4108a..00000000
--- a/play-services-cast/src/main/java/com/google/android/gms/cast/CastRemoteDisplayLocalService.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2013-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 com.google.android.gms.cast;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.IBinder;
-
-public class CastRemoteDisplayLocalService extends Service {
- @Override
- public IBinder onBind(Intent intent) {
- return null;
- }
-}
diff --git a/play-services-cast/src/main/java/org/microg/gms/cast/CastApiBuilder.java b/play-services-cast/src/main/java/org/microg/gms/cast/CastApiBuilder.java
deleted file mode 100644
index cc40793f..00000000
--- a/play-services-cast/src/main/java/org/microg/gms/cast/CastApiBuilder.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2013-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.cast;
-
-import android.content.Context;
-import android.os.Looper;
-
-import com.google.android.gms.cast.Cast;
-import com.google.android.gms.common.api.AccountInfo;
-import com.google.android.gms.common.api.GoogleApiClient;
-
-import org.microg.gms.common.api.ApiBuilder;
-import org.microg.gms.common.api.ApiConnection;
-
-public class CastApiBuilder implements ApiBuilder{
- @Override
- public ApiConnection build(Context context, Looper looper, Cast.CastOptions options, AccountInfo accountInfo, GoogleApiClient.ConnectionCallbacks callbacks, GoogleApiClient.OnConnectionFailedListener connectionFailedListener) {
- return new CastClientImpl(context, options, callbacks, connectionFailedListener);
- }
-}
diff --git a/play-services-cast/src/main/java/org/microg/gms/cast/CastApiImpl.java b/play-services-cast/src/main/java/org/microg/gms/cast/CastApiImpl.java
deleted file mode 100644
index bb95565e..00000000
--- a/play-services-cast/src/main/java/org/microg/gms/cast/CastApiImpl.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2013-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.cast;
-
-import com.google.android.gms.cast.ApplicationMetadata;
-import com.google.android.gms.cast.Cast;
-import com.google.android.gms.cast.LaunchOptions;
-import com.google.android.gms.common.api.GoogleApiClient;
-import com.google.android.gms.common.api.PendingResult;
-import com.google.android.gms.common.api.Status;
-
-import java.io.IOException;
-
-// TODO
-public class CastApiImpl implements Cast.CastApi {
- @Override
- public int getActiveInputState(GoogleApiClient client) {
- return 0;
- }
-
- @Override
- public ApplicationMetadata getApplicationMetadata(GoogleApiClient client) {
- return null;
- }
-
- @Override
- public String getApplicationStatus(GoogleApiClient client) {
- return null;
- }
-
- @Override
- public int getStandbyState(GoogleApiClient client) {
- return 0;
- }
-
- @Override
- public double getVolume(GoogleApiClient client) {
- return 0;
- }
-
- @Override
- public boolean isMute(GoogleApiClient client) {
- return false;
- }
-
- @Override
- public PendingResult joinApplication(GoogleApiClient client) {
- return null;
- }
-
- @Override
- public PendingResult joinApplication(GoogleApiClient client, String applicationId, String sessionId) {
- return null;
- }
-
- @Override
- public PendingResult joinApplication(GoogleApiClient client, String applicationId) {
- return null;
- }
-
- @Override
- public PendingResult launchApplication(GoogleApiClient client, String applicationId, LaunchOptions launchOptions) {
- return null;
- }
-
- @Override
- public PendingResult launchApplication(GoogleApiClient client, String applicationId) {
- return null;
- }
-
- @Override
- public PendingResult launchApplication(GoogleApiClient client, String applicationId, boolean relaunchIfRunning) {
- return null;
- }
-
- @Override
- public PendingResult leaveApplication(GoogleApiClient client) {
- return null;
- }
-
- @Override
- public void removeMessageReceivedCallbacks(GoogleApiClient client, String namespace) throws IOException {
-
- }
-
- @Override
- public void requestStatus(GoogleApiClient client) throws IOException {
-
- }
-
- @Override
- public PendingResult sendMessage(GoogleApiClient client, String namespace, String message) {
- return null;
- }
-
- @Override
- public void setMessageReceivedCallbacks(GoogleApiClient client, String namespace, Cast.MessageReceivedCallback callbacks) throws IOException {
-
- }
-
- @Override
- public void setMute(GoogleApiClient client, boolean mute) throws IOException {
-
- }
-
- @Override
- public void setVolume(GoogleApiClient client, double volume) throws IOException {
-
- }
-
- @Override
- public PendingResult stopApplication(GoogleApiClient client) {
- return null;
- }
-
- @Override
- public PendingResult stopApplication(GoogleApiClient client, String sessionId) {
- return null;
- }
-}
diff --git a/play-services-cast/src/main/java/org/microg/gms/cast/CastClientImpl.java b/play-services-cast/src/main/java/org/microg/gms/cast/CastClientImpl.java
deleted file mode 100644
index 1f80aa1f..00000000
--- a/play-services-cast/src/main/java/org/microg/gms/cast/CastClientImpl.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2013-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.cast;
-
-import android.content.Context;
-
-import com.google.android.gms.cast.Cast;
-import com.google.android.gms.common.api.GoogleApiClient;
-
-import org.microg.gms.common.DummyApiConnection;
-
-public class CastClientImpl extends DummyApiConnection {
- public CastClientImpl(Context context, Cast.CastOptions options, GoogleApiClient.ConnectionCallbacks callbacks, GoogleApiClient.OnConnectionFailedListener connectionFailedListener) {
- }
-}
diff --git a/play-services-cast/src/main/java/org/microg/gms/cast/CastRemoteDisplayApiBuilder.java b/play-services-cast/src/main/java/org/microg/gms/cast/CastRemoteDisplayApiBuilder.java
deleted file mode 100644
index 048afd15..00000000
--- a/play-services-cast/src/main/java/org/microg/gms/cast/CastRemoteDisplayApiBuilder.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2013-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.cast;
-
-import android.content.Context;
-import android.os.Looper;
-
-import com.google.android.gms.cast.CastRemoteDisplay;
-import com.google.android.gms.common.api.AccountInfo;
-import com.google.android.gms.common.api.GoogleApiClient;
-
-import org.microg.gms.common.DummyApiConnection;
-import org.microg.gms.common.api.ApiBuilder;
-import org.microg.gms.common.api.ApiConnection;
-
-public class CastRemoteDisplayApiBuilder implements ApiBuilder {
- @Override
- public ApiConnection build(Context context, Looper looper, CastRemoteDisplay.CastRemoteDisplayOptions options, AccountInfo accountInfo, GoogleApiClient.ConnectionCallbacks callbacks, GoogleApiClient.OnConnectionFailedListener connectionFailedListener) {
- return new DummyApiConnection();
- }
-}
diff --git a/play-services-cast/src/main/java/org/microg/gms/cast/CastRemoteDisplayApiImpl.java b/play-services-cast/src/main/java/org/microg/gms/cast/CastRemoteDisplayApiImpl.java
deleted file mode 100644
index 4f47a90d..00000000
--- a/play-services-cast/src/main/java/org/microg/gms/cast/CastRemoteDisplayApiImpl.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2013-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.cast;
-
-import com.google.android.gms.cast.CastRemoteDisplay;
-import com.google.android.gms.cast.CastRemoteDisplayApi;
-import com.google.android.gms.common.api.GoogleApiClient;
-import com.google.android.gms.common.api.PendingResult;
-
-public class CastRemoteDisplayApiImpl implements CastRemoteDisplayApi {
- @Override
- public PendingResult startRemoteDisplay(GoogleApiClient apiClient, String applicationId) {
- return null;
- }
-
- @Override
- public PendingResult stopRemoteDisplay(GoogleApiClient apiClient) {
- return null;
- }
-}
diff --git a/play-services-gcm/build.gradle b/play-services-gcm/build.gradle
deleted file mode 100644
index fc2881e0..00000000
--- a/play-services-gcm/build.gradle
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2013-2015 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.
- */
-
-apply plugin: 'com.android.library'
-
-String getMyVersionName() {
- def stdout = new ByteArrayOutputStream()
- if (rootProject.file("gradlew").exists())
- exec { commandLine 'git', 'describe', '--tags', '--always', '--dirty'; standardOutput = stdout }
- else // automatic build system, don't tag dirty
- exec { commandLine 'git', 'describe', '--tags', '--always'; standardOutput = stdout }
- return stdout.toString().trim().substring(1)
-}
-
-android {
- compileSdkVersion androidCompileSdk()
- buildToolsVersion "$androidBuildVersionTools"
-
- defaultConfig {
- versionName getMyVersionName()
- minSdkVersion androidMinSdk()
- targetSdkVersion androidTargetSdk()
- }
-
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
-}
-
-dependencies {
- api project(':play-services-iid')
- // compile project(':play-services-measurement')
-}
\ No newline at end of file
diff --git a/play-services-gcm/gradle.properties b/play-services-gcm/gradle.properties
deleted file mode 100644
index 2265b126..00000000
--- a/play-services-gcm/gradle.properties
+++ /dev/null
@@ -1,34 +0,0 @@
-#
-# Copyright 2013-2016 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.
-#
-
-POM_NAME=Play Services GCM Library
-POM_DESCRIPTION=The Play Services Library module to access Google Cloud Messaging
-
-POM_PACKAGING=aar
-
-POM_URL=https://github.com/microg/android_external_GmsLib
-
-POM_SCM_URL=https://github.com/microg/android_external_GmsLib
-POM_SCM_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
-POM_SCM_DEV_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
-
-POM_LICENCE_NAME=The Apache Software License, Version 2.0
-POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
-POM_LICENCE_DIST=repo
-
-POM_DEVELOPER_ID=mar-v-in
-POM_DEVELOPER_NAME=Marvin W
-
diff --git a/play-services-gcm/src/main/AndroidManifest.xml b/play-services-gcm/src/main/AndroidManifest.xml
deleted file mode 100644
index ca9ea221..00000000
--- a/play-services-gcm/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmListenerService.java b/play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmListenerService.java
deleted file mode 100644
index ccf99acf..00000000
--- a/play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmListenerService.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (C) 2013-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 com.google.android.gms.gcm;
-
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.Intent;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.util.Log;
-
-import org.microg.gms.common.PublicApi;
-
-import static org.microg.gms.gcm.GcmConstants.ACTION_C2DM_RECEIVE;
-import static org.microg.gms.gcm.GcmConstants.ACTION_NOTIFICATION_OPEN;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_ERROR;
-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_TYPE;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_PENDING_INTENT;
-import static org.microg.gms.gcm.GcmConstants.MESSAGE_TYPE_DELETED_MESSAGE;
-import static org.microg.gms.gcm.GcmConstants.MESSAGE_TYPE_GCM;
-import static org.microg.gms.gcm.GcmConstants.MESSAGE_TYPE_SEND_ERROR;
-import static org.microg.gms.gcm.GcmConstants.MESSAGE_TYPE_SEND_EVENT;
-
-/**
- * Base class for communicating with Google Cloud Messaging.
- *
- * It also provides functionality such as automatically displaying
- * notifications when requested by app server.
- *
- * Override base class methods to handle any events required by the application.
- * Methods are invoked asynchronously.
- *
- * Include the following in the manifest:
- *
- *
- *
- *
- *
- *
- */
-@PublicApi
-public abstract class GcmListenerService extends Service {
- private static final String TAG = "GcmListenerService";
-
- private final Object lock = new Object();
- private int startId;
- private int counter = 0;
-
- public final IBinder onBind(Intent intent) {
- return null;
- }
-
- /**
- * Called when GCM server deletes pending messages due to exceeded
- * storage limits, for example, when the device cannot be reached
- * for an extended period of time.
- *
- * It is recommended to retrieve any missing messages directly from the
- * app server.
- */
- public void onDeletedMessages() {
- // To be overwritten
- }
-
- /**
- * Called when a message is received.
- *
- * @param from describes message sender.
- * @param data message data as String key/value pairs.
- */
- public void onMessageReceived(String from, Bundle data) {
- // To be overwritten
- }
-
- /**
- * Called when an upstream message has been successfully sent to the
- * GCM connection server.
- *
- * @param msgId of the upstream message sent using
- * {@link com.google.android.gms.gcm.GoogleCloudMessaging#send(java.lang.String, java.lang.String, android.os.Bundle)}.
- */
- public void onMessageSent(String msgId) {
- // To be overwritten
- }
-
- /**
- * Called when there was an error sending an upstream message.
- *
- * @param msgId of the upstream message sent using
- * {@link com.google.android.gms.gcm.GoogleCloudMessaging#send(java.lang.String, java.lang.String, android.os.Bundle)}.
- * @param error description of the error.
- */
- public void onSendError(String msgId, String error) {
- // To be overwritten
- }
-
- public final int onStartCommand(final Intent intent, int flags, int startId) {
- synchronized (lock) {
- this.startId = startId;
- this.counter++;
- }
-
- if (intent != null) {
- if (ACTION_NOTIFICATION_OPEN.equals(intent.getAction())) {
- handlePendingNotification(intent);
- finishCounter();
- GcmReceiver.completeWakefulIntent(intent);
- } else if (ACTION_C2DM_RECEIVE.equals(intent.getAction())) {
- new AsyncTask() {
- @Override
- protected Void doInBackground(Void... params) {
- handleC2dmMessage(intent);
- return null;
- }
- }.execute();
- } else {
- Log.w(TAG, "Unknown intent action: " + intent.getAction());
-
- }
-
- return START_REDELIVER_INTENT;
- } else {
- finishCounter();
- return START_NOT_STICKY;
- }
- }
-
- private void handleC2dmMessage(Intent intent) {
- try {
- String messageType = intent.getStringExtra(EXTRA_MESSAGE_TYPE);
- if (messageType == null || MESSAGE_TYPE_GCM.equals(messageType)) {
- String from = intent.getStringExtra(EXTRA_FROM);
- Bundle data = intent.getExtras();
- data.remove(EXTRA_MESSAGE_TYPE);
- data.remove("android.support.content.wakelockid"); // WakefulBroadcastReceiver.EXTRA_WAKE_LOCK_ID
- data.remove(EXTRA_FROM);
- onMessageReceived(from, data);
- } else if (MESSAGE_TYPE_DELETED_MESSAGE.equals(messageType)) {
- onDeletedMessages();
- } else if (MESSAGE_TYPE_SEND_EVENT.equals(messageType)) {
- onMessageSent(intent.getStringExtra(EXTRA_MESSAGE_ID));
- } else if (MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
- onSendError(intent.getStringExtra(EXTRA_MESSAGE_ID), intent.getStringExtra(EXTRA_ERROR));
- } else {
- Log.w(TAG, "Unknown message type: " + messageType);
- }
- finishCounter();
- } finally {
- GcmReceiver.completeWakefulIntent(intent);
- }
- }
-
- private void handlePendingNotification(Intent intent) {
- PendingIntent pendingIntent = intent.getParcelableExtra(EXTRA_PENDING_INTENT);
- if (pendingIntent != null) {
- try {
- pendingIntent.send();
- } catch (PendingIntent.CanceledException e) {
- Log.w(TAG, "Notification cancelled", e);
- }
- } else {
- Log.w(TAG, "Notification was null");
- }
- }
-
- private void finishCounter() {
- synchronized (lock) {
- this.counter--;
- if (counter == 0) {
- stopSelfResult(startId);
- }
- }
- }
-
-}
diff --git a/play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmNetworkManager.java b/play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmNetworkManager.java
deleted file mode 100644
index a7ee9a89..00000000
--- a/play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmNetworkManager.java
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright (C) 2013-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 com.google.android.gms.gcm;
-
-import android.app.PendingIntent;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.os.Bundle;
-import android.text.TextUtils;
-
-import java.util.List;
-
-import static org.microg.gms.common.Constants.GMS_PACKAGE_NAME;
-import static org.microg.gms.gcm.GcmConstants.ACTION_SCHEDULE;
-import static org.microg.gms.gcm.GcmConstants.ACTION_TASK_READY;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_COMPONENT;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_SCHEDULER_ACTION;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_TAG;
-import static org.microg.gms.gcm.GcmConstants.SCHEDULER_ACTION_CANCEL;
-import static org.microg.gms.gcm.GcmConstants.SCHEDULER_ACTION_CANCEL_ALL;
-import static org.microg.gms.gcm.GcmConstants.SCHEDULER_ACTION_SCHEDULE;
-
-/**
- * Class to create apps with robust "send-to-sync", which is the mechanism to sync data with
- * servers where new information is available.
- *
- * You can use the API to schedule network-oriented tasks, and let Google Play services batch
- * network operations across the system. This greatly simplifies the implementation of common
- * patterns, such as waiting for network connectivity, network retries, and backoff.
- *
- * Tasks must be scheduled based on an execution window in time. During this execution window
- * the scheduler will use its discretion in picking an optimal execution time, based on network
- * availability (whether the device has connectivity), network activity (whether packages are
- * actively being transferred). and load (how many other pending tasks are available for
- * execution at that point in time). If none of these factors are influential, the
- * scheduler will always wait until the end of the specified window.
- *
- * To receive the notification from the scheduler that a task is ready to be executed, your
- * client app must implement a {@link com.google.android.gms.gcm.GcmTaskService} and filter
- * on the action {@link com.google.android.gms.gcm.GcmTaskService#SERVICE_ACTION_EXECUTE_TASK}.
- *
- * Note that tags of arbitrary length are not allowed; if the tag you
- * provide is greater than 100 characters an exception will be thrown when you try to create your
- * {@link com.google.android.gms.gcm.Task} object.
- *
- * The service should be protected by the permission
- * com.google.android.gms.permission.BIND_NETWORK_TASK_SERVICE which is used by Google Play
- * Services. This prevents other code from invoking the broadcast receiver. Here is an excerpt from
- * a sample manifest:
- *
- *
- *
- *
- *
- *
- *
- * An execution contains the tag identifier which your client app provides. This identifies
- * one "task", or piece of work, that you mean to perform. Consider the tag to be the key to which
- * your task logic is paired.
- *
- * // Schedule a task to occur between five and fifteen seconds from now:
- * OneoffTask myTask = new OneoffTask.Builder()
- * .setService(MyGcmTaskService.class)
- * .setExecutionWindow(
- * 5 * DateUtil.MINUTE_IN_SECONDS, 15 * DateUtil.MINUTE_IN_SECONDS)
- * .setTag("test-upload")
- * .build();
- * GcmNetworkManager.get(this).schedule(myTask);
- * ...
- * // Implement service logic to be notified when the task elapses:
- * MyUploadService extends GcmTaskService {
- *
- * @Override public int onRunTask(TaskParams params) {
- * // Do some upload work.
- * return GcmNetworkManager.RESULT_SUCCESS;
- * }
- * }
- *
- * To help in debugging your tasks, run
- * adb shell dumpsys activity service GcmService --endpoints [...]
- * If you want to execute your task immediately (for debugging) you can execute tasks from the
- * command line via:
- * adb shell am broadcast -a "com.google.android.gms.gcm.ACTION_TRIGGER_TASK" \
- * -e component -e tag
- * Where COMPONENT_NAME: The full
- * {@link ComponentName#flattenToString()} returned for your implementation of
- * {@link com.google.android.gms.gcm.GcmTaskService}.
- * TAG: the tag you want to have land in
- * {@link com.google.android.gms.gcm.GcmTaskService#onRunTask(com.google.android.gms.gcm.TaskParams)}
- * Example usage for the gradle target GcmTestProxy service:
- * adb shell am broadcast -a "com.google.android.gms.gcm.ACTION_TRIGGER_TASK" \
- * -e component "com.google.android.gms.gcm.test.proxy/.internal.nstest.TestNetworkTaskService" \
- * -e tag "upload"
- * This is only available if the device is a test-keys build. This will replace any
- * previously scheduled task with the same tag! This will have especially awkward effects
- * if your original task was a periodic, because the debug task is scheduled as a one-off.
- */
-public class GcmNetworkManager {
- /**
- * Indicates a task has failed, but not to reschedule.
- */
- public static final int RESULT_FAILURE = 2;
-
- /**
- * Indicates a task has failed to execute, and must be retried with back-off.
- */
- public static final int RESULT_RESCHEDULE = 1;
-
- /**
- * Indicates a task has successfully been executed, and can be removed from the queue.
- */
- public static final int RESULT_SUCCESS = 0;
-
- private static GcmNetworkManager INSTANCE;
-
- private final Context context;
-
- private GcmNetworkManager(Context context) {
- this.context = context;
- }
-
- /**
- * Cancels all tasks previously scheduled against the provided GcmTaskService. Note that a
- * cancel will have no effect on an in-flight task.
- *
- * @param gcmTaskService The endpoint for which you want to cancel all outstanding tasks.
- */
- public void cancelAllTasks(Class extends GcmTaskService> gcmTaskService) {
- validateService(gcmTaskService.getName());
- Intent scheduleIntent = createScheduleIntent();
- if (scheduleIntent != null) {
- scheduleIntent.putExtra(EXTRA_SCHEDULER_ACTION, SCHEDULER_ACTION_CANCEL_ALL);
- scheduleIntent.putExtra(EXTRA_COMPONENT, new ComponentName(context, gcmTaskService));
- context.sendBroadcast(scheduleIntent);
- }
- }
-
- /**
- * Cancel a task, specified by tag. Note that a cancel will have no effect on an in-flight
- * task.
- *
- * @param tag The tag to uniquely identify this task on this endpoint.
- * @param gcmTaskService The endpoint for which you want to cancel all outstanding tasks.
- */
- public void cancelTask(String tag, Class extends GcmTaskService> gcmTaskService) {
- if (TextUtils.isEmpty(tag) || tag.length() < 100) throw new IllegalArgumentException("tag invalid");
- validateService(gcmTaskService.getName());
- Intent scheduleIntent = createScheduleIntent();
- if (scheduleIntent != null) {
- scheduleIntent.putExtra(EXTRA_SCHEDULER_ACTION, SCHEDULER_ACTION_CANCEL);
- scheduleIntent.putExtra(EXTRA_TAG, tag);
- scheduleIntent.putExtra(EXTRA_COMPONENT, new ComponentName(context, gcmTaskService));
- context.sendBroadcast(scheduleIntent);
- }
- }
-
- /**
- * Use this function to access the GcmNetworkManager API.
- *
- * @param context Context of the calling app.
- * @return GcmNetworkManager object.
- */
- public static GcmNetworkManager getInstance(Context context) {
- synchronized (GcmNetworkManager.class) {
- if (INSTANCE == null) {
- INSTANCE = new GcmNetworkManager(context);
- }
- return INSTANCE;
- }
- }
-
- /**
- * Entry point to schedule a task with the network manager.
- *
- * If GooglePlayServices is unavailable (upgrading, missing, etc). This call will fail silently.
- * You should wrap it in a call to {@link com.google.android.gms.common.GooglePlayServicesUtil#isGooglePlayServicesAvailable(android.content.Context)}
- *
- * @param task Task constructed using {@link com.google.android.gms.gcm.Task.Builder}. Can be
- * an instance of {@link com.google.android.gms.gcm.PeriodicTask} or
- * {@link com.google.android.gms.gcm.OneoffTask}.
- */
- public void schedule(Task task) {
- validateService(task.getServiceName());
- Intent scheduleIntent = createScheduleIntent();
- if (scheduleIntent != null) {
- Bundle extras = scheduleIntent.getExtras();
- extras.putString(EXTRA_SCHEDULER_ACTION, SCHEDULER_ACTION_SCHEDULE);
- task.toBundle(extras);
- scheduleIntent.putExtras(extras);
- context.sendBroadcast(scheduleIntent);
- }
- }
-
- private Intent createScheduleIntent() {
- if (!packageExists(GMS_PACKAGE_NAME)) return null;
- Intent scheduleIntent = new Intent(ACTION_SCHEDULE);
- scheduleIntent.setPackage(GMS_PACKAGE_NAME);
- scheduleIntent.putExtra("app", PendingIntent.getBroadcast(context, 0, new Intent(), 0));
- return scheduleIntent;
- }
-
- private boolean packageExists(String packageName) {
- try {
- PackageManager pm = context.getPackageManager();
- pm.getPackageInfo(packageName, 0);
- return true;
- } catch (PackageManager.NameNotFoundException e) {
- return false;
- }
- }
-
- private void validateService(String serviceName) {
- if (serviceName == null) throw new NullPointerException("No service provided");
- Intent taskIntent = new Intent(ACTION_TASK_READY);
- taskIntent.setPackage(context.getPackageName());
- PackageManager pm = context.getPackageManager();
- List serviceResolves = pm.queryIntentServices(taskIntent, 0);
- if (serviceResolves == null || serviceResolves.isEmpty())
- throw new IllegalArgumentException("No service found");
- for (ResolveInfo info : serviceResolves) {
- if (serviceName.equals(info.serviceInfo.name)) return;
- }
- throw new IllegalArgumentException("Service not supported.");
- }
-}
diff --git a/play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmPubSub.java b/play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmPubSub.java
deleted file mode 100644
index 07c9f4a5..00000000
--- a/play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmPubSub.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2013-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 com.google.android.gms.gcm;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.text.TextUtils;
-
-import com.google.android.gms.iid.InstanceID;
-
-import java.io.IOException;
-import java.util.regex.Pattern;
-
-import static org.microg.gms.gcm.GcmConstants.EXTRA_TOPIC;
-
-/**
- * GcmPubSub provides a publish-subscribe model for sending GCM topic messages.
- *
- * An app can subscribe to different topics defined by the
- * developer. The app server can then send messages to the subscribed devices
- * without having to maintain topic-subscribers mapping. Topics do not
- * need to be explicitly created before subscribing or publishing—they
- * are automatically created when publishing or subscribing.
- *
- * String topic = "/topics/myTopic";
- * String registrationToken = InstanceID.getInstance(context)
- * .getToken(SENDER_ID, GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
- * GcmPubSub.getInstance(context).subscribe(registrationToken, topic, null);
- * // Messages published to the topic will be received as regular GCM messages
- * // with 'from' set to "/topics/myTopic"
- * To publish to a topic, see
- * GCM server documentation.
- */
-public class GcmPubSub {
-
- private static final Pattern topicPattern = Pattern.compile("/topics/[a-zA-Z0-9-_.~%]{1,900}");
- private static GcmPubSub INSTANCE;
-
- private final InstanceID instanceId;
-
- public GcmPubSub(Context context) {
- this.instanceId = InstanceID.getInstance(context);
- }
-
- /**
- * Returns an instance of GCM PubSub.
- *
- * @return GcmPubSub instance
- */
- public static synchronized GcmPubSub getInstance(Context context) {
- if (INSTANCE == null) {
- INSTANCE = new GcmPubSub(context);
- }
- return INSTANCE;
- }
-
- /**
- * Subscribes an app instance to a topic, enabling it to receive messages
- * sent to that topic.
- *
- * The topic sender must be authorized to send messages to the
- * app instance. To authorize it, call {@link com.google.android.gms.iid.InstanceID#getToken(java.lang.String, java.lang.String)}
- * with the sender ID and {@link com.google.android.gms.gcm.GoogleCloudMessaging#INSTANCE_ID_SCOPE}
- *
- * Do not call this function on the main thread.
- *
- * @param registrationToken {@link com.google.android.gms.iid.InstanceID} token that authorizes topic
- * sender to send messages to the app instance.
- * @param topic developer defined topic name.
- * Must match the following regular expression:
- * "/topics/[a-zA-Z0-9-_.~%]{1,900}".
- * @param extras (optional) additional information.
- * @throws IOException if the request fails.
- */
- public void subscribe(String registrationToken, String topic, Bundle extras) throws IOException {
- if (TextUtils.isEmpty(registrationToken))
- throw new IllegalArgumentException("No registration token!");
- if (TextUtils.isEmpty(topic) || !topicPattern.matcher(topic).matches())
- throw new IllegalArgumentException("Invalid topic: " + topic);
-
- if (extras == null) extras = new Bundle();
- extras.putString(EXTRA_TOPIC, topic);
- instanceId.getToken(registrationToken, topic, extras);
- }
-
- /**
- * Unsubscribes an app instance from a topic, stopping it from receiving
- * any further messages sent to that topic.
- *
- * Do not call this function on the main thread.
- *
- * @param registrationToken {@link com.google.android.gms.iid.InstanceID} token
- * for the same sender and scope that was previously
- * used for subscribing to the topic.
- * @param topic from which to stop receiving messages.
- * @throws IOException if the request fails.
- */
- public void unsubscribe(String registrationToken, String topic) throws IOException {
- if (TextUtils.isEmpty(topic) || !topicPattern.matcher(topic).matches())
- throw new IllegalArgumentException("Invalid topic: " + topic);
-
- Bundle extras = new Bundle();
- extras.putString(EXTRA_TOPIC, topic);
- instanceId.deleteToken(registrationToken, topic, extras);
- }
-
-}
\ No newline at end of file
diff --git a/play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmReceiver.java b/play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmReceiver.java
deleted file mode 100644
index d160f42b..00000000
--- a/play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmReceiver.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2013-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 com.google.android.gms.gcm;
-
-import android.Manifest;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.os.Build;
-import android.support.v4.content.WakefulBroadcastReceiver;
-import android.util.Base64;
-import android.util.Log;
-
-import static org.microg.gms.gcm.GcmConstants.ACTION_C2DM_REGISTRATION;
-import static org.microg.gms.gcm.GcmConstants.ACTION_INSTANCE_ID;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_FROM;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_RAWDATA;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_RAWDATA_BASE64;
-import static org.microg.gms.gcm.GcmConstants.GCMID_INSTANCE_ID;
-import static org.microg.gms.gcm.GcmConstants.GCMID_REFRESH;
-
-/**
- * WakefulBroadcastReceiver
that receives GCM messages and delivers them to an
- * application-specific {@link com.google.android.gms.gcm.GcmListenerService} subclass.
- *
- * This receiver should be declared in your application's manifest file as follows:
- *
- *
- *
- *
- *
- *
- *
- *
- *
- * The com.google.android.c2dm.permission.SEND
permission is held by Google Play
- * services. This prevents other apps from invoking the broadcast receiver.
- */
-public class GcmReceiver extends WakefulBroadcastReceiver {
- private static final String TAG = "GcmReceiver";
-
- public void onReceive(Context context, Intent intent) {
- sanitizeIntent(context, intent);
- enforceIntentClassName(context, intent);
- sendIntent(context, intent);
- if (getResultCode() == 0) setResultCodeIfOrdered(-1);
- }
-
- private void sanitizeIntent(Context context, Intent intent) {
- intent.setComponent(null);
- intent.setPackage(context.getPackageName());
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
- intent.removeCategory(context.getPackageName());
- }
- String from = intent.getStringExtra(EXTRA_FROM);
- if (ACTION_C2DM_REGISTRATION.equals(intent.getAction()) || GCMID_INSTANCE_ID.equals(from) || GCMID_REFRESH.equals(from)) {
- intent.setAction(ACTION_INSTANCE_ID);
- }
- String base64encoded = intent.getStringExtra(EXTRA_RAWDATA_BASE64);
- if (base64encoded != null) {
- intent.putExtra(EXTRA_RAWDATA, Base64.decode(base64encoded, Base64.DEFAULT));
- intent.removeExtra(EXTRA_RAWDATA_BASE64);
- }
- }
-
- private void enforceIntentClassName(Context context, Intent intent) {
- ResolveInfo resolveInfo = context.getPackageManager().resolveService(intent, 0);
- if (resolveInfo == null || resolveInfo.serviceInfo == null) {
- Log.e(TAG, "Failed to resolve target intent service, skipping classname enforcement");
- return;
- }
- ServiceInfo serviceInfo = resolveInfo.serviceInfo;
- if (!context.getPackageName().equals(serviceInfo.packageName) || serviceInfo.name == null) {
- Log.e(TAG, "Error resolving target intent service, skipping classname enforcement. Resolved service was: " + serviceInfo.packageName + "/" + serviceInfo.name);
- return;
- }
- intent.setClassName(context, serviceInfo.name.startsWith(".") ? (context.getPackageName() + serviceInfo.name) : serviceInfo.name);
- }
-
- private void sendIntent(Context context, Intent intent) {
- setResultCodeIfOrdered(500);
- try {
- ComponentName startedComponent;
- if (context.checkCallingOrSelfPermission(Manifest.permission.WAKE_LOCK) == PackageManager.PERMISSION_GRANTED) {
- startedComponent = startWakefulService(context, intent);
- } else {
- Log.d(TAG, "Missing wake lock permission, service start may be delayed");
- startedComponent = context.startService(intent);
- }
- if (startedComponent == null) {
- Log.e(TAG, "Error while delivering the message: ServiceIntent not found.");
- setResultCodeIfOrdered(404);
- } else {
- setResultCodeIfOrdered(-1);
- }
- } catch (SecurityException e) {
- Log.e(TAG, "Error while delivering the message to the serviceIntent", e);
- setResultCodeIfOrdered(401);
- }
- }
-
- private void setResultCodeIfOrdered(int code) {
- if (isOrderedBroadcast()) {
- setResultCode(code);
- }
- }
-}
\ No newline at end of file
diff --git a/play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmTaskService.java b/play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmTaskService.java
deleted file mode 100644
index 0d790589..00000000
--- a/play-services-gcm/src/main/java/com/google/android/gms/gcm/GcmTaskService.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) 2013-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 com.google.android.gms.gcm;
-
-import android.app.Service;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.Parcelable;
-import android.os.PowerManager;
-import android.util.Log;
-
-import org.microg.gms.common.PublicApi;
-import org.microg.gms.gcm.GcmConstants;
-
-/**
- * Implemented by the client application to provide an endpoint for the {@link com.google.android.gms.gcm.GcmNetworkManager}
- * to call back to when a task is ready to be executed.
- *
- * Clients must add this service to their manifest and implement
- * {@link com.google.android.gms.gcm.GcmTaskService#onRunTask(com.google.android.gms.gcm.TaskParams)}.
- * This service must provide an {@link IntentFilter} on the action
- * {@link com.google.android.gms.gcm.GcmTaskService#SERVICE_ACTION_EXECUTE_TASK}. Here's an example:
- *
- *
- *
- *
- *
- *
- *
- * The return value of onRunTask(TaskParams) will determine what the manager does with subsequent
- * executions of this task. Specifically you can return {@link com.google.android.gms.gcm.GcmNetworkManager#RESULT_RESCHEDULE}
- * to have this task be re-executed again shortly subject to exponential back-off. Returning
- * {@link com.google.android.gms.gcm.GcmNetworkManager#RESULT_FAILURE} for a periodic task will only affect the executing
- * instance of the task, and future tasks will be executed as normal.
- *
- * Once a task is running it will not be cancelled, however a newly scheduled task with the same
- * tag will not be executed until the active task has completed. This newly scheduled task will
- * replace the previous task, regardless of whether the previous task returned
- * {@link com.google.android.gms.gcm.GcmNetworkManager#RESULT_RESCHEDULE}.
- *
- * Bear in mind that your service may receive multiple calls from the scheduler at once
- * (specifically if you've made multiple schedule requests that overlap). If this is the case, your
- * implementation of {@link com.google.android.gms.gcm.GcmTaskService#onRunTask(com.google.android.gms.gcm.TaskParams)} must be thread-safe.
- *
- * The scheduler will hold a {@link PowerManager.WakeLock} for your service, however
- * after three minutes of execution if your task has not returned it will be considered to
- * have timed out, and the wakelock will be released. Rescheduling your task at this point
- * will have no effect.
- * If you suspect your task will run longer than this you should start your own service
- * explicitly or use some other mechanism; this API is intended for relatively quick network
- * operations.
- *
- * Your task will run at priority Process.THREAD_PRIORITY_BACKGROUND. If this
- * is not appropriate, you should start your own service with suitably
- * conditioned threads.
- */
-@PublicApi
-public abstract class GcmTaskService extends Service {
- private static final String TAG = "GcmTaskService";
-
- /**
- * Action broadcast by the GcmNetworkManager to the requesting package when
- * a scheduled task is ready for execution.
- */
- public static final String SERVICE_ACTION_EXECUTE_TASK = GcmConstants.ACTION_TASK_READY;
-
- /**
- * Action that a {@link com.google.android.gms.gcm.GcmTaskService} is started with when the service needs to initialize
- * its tasks.
- */
- public static final String SERVICE_ACTION_INITIALIZE = GcmConstants.ACTION_TASK_INITIALZE;
-
- /**
- * You must protect your service with this permission to avoid being bound to by an
- * application other than Google Play Services.
- */
- public static final String SERVICE_PERMISSION = GcmConstants.PERMISSION_NETWORK_TASK;
-
- public IBinder onBind(Intent intent) {
- return null;
- }
-
- /**
- * When your package is removed or updated, all of its network tasks are cleared by the
- * GcmNetworkManager. You can override this method to reschedule them in the case of an
- * updated package. This is not called when your application is first installed.
- *
- * This is called on your application's main thread.
- */
- public void onInitializeTasks() {
- // To be overwritten
- }
-
- /**
- * Override this function to provide the logic for your task execution.
- *
- * @param params Parameters provided at schedule time with
- * {@link com.google.android.gms.gcm.OneoffTask.Builder#setTag(java.lang.String)}
- * @return One of {@link com.google.android.gms.gcm.GcmNetworkManager#RESULT_SUCCESS},
- * {@link com.google.android.gms.gcm.GcmNetworkManager#RESULT_RESCHEDULE}, or
- * {@link com.google.android.gms.gcm.GcmNetworkManager#RESULT_FAILURE}.
- */
- public abstract int onRunTask(TaskParams params);
-
- /**
- * Receives the command to begin doing work, for which it spawns another thread.
- */
- public int onStartCommand(Intent intent, int flags, int startId) {
- intent.setExtrasClassLoader(PendingCallback.class.getClassLoader());
- if (SERVICE_ACTION_EXECUTE_TASK.equals(intent.getAction())) {
- String tag = intent.getStringExtra("tag");
- Parcelable callback = intent.getParcelableExtra("callback");
- Bundle extras = intent.getBundleExtra("extras");
- if (callback == null || !(callback instanceof PendingCallback)) {
- Log.w(TAG, tag + ": Invalid callback!");
- return START_NOT_STICKY;
- }
-
- // TODO ensure single instance
-
- // TODO run task in new thread
- } else if (SERVICE_ACTION_INITIALIZE.equals(intent.getAction())) {
- this.onInitializeTasks();
-
- // TODO ensure single instance
- }
-
- return START_NOT_STICKY;
- }
-
-}
diff --git a/play-services-gcm/src/main/java/com/google/android/gms/gcm/GoogleCloudMessaging.java b/play-services-gcm/src/main/java/com/google/android/gms/gcm/GoogleCloudMessaging.java
deleted file mode 100644
index 06546d7b..00000000
--- a/play-services-gcm/src/main/java/com/google/android/gms/gcm/GoogleCloudMessaging.java
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Copyright (C) 2013-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 com.google.android.gms.gcm;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Looper;
-import android.text.TextUtils;
-
-import com.google.android.gms.iid.InstanceID;
-
-import org.microg.gms.common.PublicApi;
-import org.microg.gms.gcm.CloudMessagingRpc;
-import org.microg.gms.gcm.GcmConstants;
-
-import java.io.IOException;
-
-import static org.microg.gms.common.Constants.GMS_PACKAGE_NAME;
-import static org.microg.gms.gcm.GcmConstants.ACTION_C2DM_RECEIVE;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_DELAY;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_ERROR;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_MESSAGE_ID;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_MESSAGE_TYPE;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_REGISTRATION_ID;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_SENDER;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_SENDER_LEGACY;
-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_TTL;
-
-/**
- * GoogleCloudMessaging (GCM) enables apps to communicate with their app servers
- * using simple messages.
- *
- * To send or receive messages, the app must get a
- * registrationToken from {@link com.google.android.gms.iid.InstanceID#getToken(java.lang.String, java.lang.String)}, which authorizes an
- * app server to send messages to an app instance. Pass sender ID and
- * {@link com.google.android.gms.gcm.GoogleCloudMessaging#INSTANCE_ID_SCOPE} as parameters to the method.
- * A sender ID is a project number acquired from the API console, as described in
- * Getting Started.
- *
- * In order to receive GCM messages, declare {@link com.google.android.gms.gcm.GcmReceiver}
- * and an implementation of {@link com.google.android.gms.gcm.GcmListenerService} in the app manifest.
- * {@link com.google.android.gms.gcm.GcmReceiver} will pass the incoming messages to the implementation
- * of {@link com.google.android.gms.gcm.GcmListenerService}. To process messages, override base class
- * methods to handle any events required by the application.
- *
- * Client apps can send upstream messages back to the app server using the XMPP-based
- * Cloud Connection Server,
- * For example:
- *
- * gcm.send(SENDER_ID + "@gcm.googleapis.com", id, data);
- * See Implementing GCM Client on Android for more details.
- */
-@PublicApi
-public class GoogleCloudMessaging {
- /**
- * The GCM {@link com.google.android.gms.gcm.GoogleCloudMessaging#register(java.lang.String...)} and {@link com.google.android.gms.gcm.GoogleCloudMessaging#unregister()} methods are
- * blocking. Blocking methods must not be called on the main thread.
- */
- public static final String ERROR_MAIN_THREAD = "MAIN_THREAD";
-
- /**
- * The device can't read the response, or there was a 500/503 from the
- * server that can be retried later. The application should use exponential
- * back off and retry.
- */
- public static final String ERROR_SERVICE_NOT_AVAILABLE = GcmConstants.ERROR_SERVICE_NOT_AVAILABLE;
-
- /**
- * Specifies scope used in obtaining GCM registrationToken when calling
- * {@link com.google.android.gms.iid.InstanceID#getToken(java.lang.String, java.lang.String)}
- */
- public static final String INSTANCE_ID_SCOPE = GcmConstants.INSTANCE_ID_SCOPE_GCM;
-
- /**
- * Returned by {@link com.google.android.gms.gcm.GoogleCloudMessaging#getMessageType(android.content.Intent)} to indicate that the server deleted
- * some pending messages because they exceeded the storage limits. The
- * application should contact the server to retrieve the discarded messages.
- *
- * @deprecated Instead implement {@link com.google.android.gms.gcm.GcmListenerService#onDeletedMessages()}
- */
- @Deprecated
- public static final String MESSAGE_TYPE_DELETED = GcmConstants.MESSAGE_TYPE_DELETED_MESSAGE;
-
- /**
- * Returned by {@link com.google.android.gms.gcm.GoogleCloudMessaging#getMessageType(android.content.Intent)} to indicate a regular message.
- *
- * @deprecated Instead implement {@link com.google.android.gms.gcm.GcmListenerService#onMessageReceived(java.lang.String, android.os.Bundle)}
- */
- @Deprecated
- public static final String MESSAGE_TYPE_MESSAGE = GcmConstants.MESSAGE_TYPE_GCM;
-
- /**
- * Returned by {@link com.google.android.gms.gcm.GoogleCloudMessaging#getMessageType(android.content.Intent)} to indicate a send error.
- * The intent includes the message ID of the message and an error code.
- *
- * @deprecated Instead implement {@link com.google.android.gms.gcm.GcmListenerService#onSendError(java.lang.String, java.lang.String)}
- */
- @Deprecated
- public static final String MESSAGE_TYPE_SEND_ERROR = GcmConstants.MESSAGE_TYPE_SEND_ERROR;
-
- /**
- * Returned by {@link com.google.android.gms.gcm.GoogleCloudMessaging#getMessageType(android.content.Intent)} to indicate a sent message has been received by the GCM
- * server. The intent includes the message ID of the message.
- *
- * @deprecated Instead implement {@link com.google.android.gms.gcm.GcmListenerService#onMessageSent(java.lang.String)}
- */
- @Deprecated
- public static final String MESSAGE_TYPE_SEND_EVENT = GcmConstants.MESSAGE_TYPE_SEND_EVENT;
-
- private static GoogleCloudMessaging instance;
-
- private CloudMessagingRpc rpc;
- private Context context;
-
- public GoogleCloudMessaging() {
- }
-
- /**
- * Must be called when your application is done using GCM, to release
- * internal resources.
- */
- public synchronized void close() {
- instance = null;
- rpc.close();
- }
-
- /**
- * Return the singleton instance of GCM.
- */
- public static GoogleCloudMessaging getInstance(Context context) {
- if (instance == null) {
- instance = new GoogleCloudMessaging();
- instance.context = context.getApplicationContext();
- instance.rpc = new CloudMessagingRpc(instance.context);
- }
- return instance;
- }
-
- /**
- * Return the message type from an intent passed into a client app's broadcast receiver. There
- * are two general categories of messages passed from the server: regular GCM messages,
- * and special GCM status messages.
- *
- * The possible types are:
- * {@link #MESSAGE_TYPE_MESSAGE}, {@link #MESSAGE_TYPE_DELETED}, {@link #MESSAGE_TYPE_SEND_EVENT} and {@link #MESSAGE_TYPE_SEND_ERROR}
- *
- * You can use this method to filter based on message type. Since it is likely that GCM will
- * be extended in the future with new message types, just ignore any message types you're not
- * interested in, or that you don't recognize.
- *
- * @return The message type or null if the intent is not a GCM intent
- */
- public String getMessageType(Intent intent) {
- if (intent == null || !ACTION_C2DM_RECEIVE.equals(intent.getAction())) return null;
- if (!intent.hasExtra(EXTRA_MESSAGE_TYPE)) return MESSAGE_TYPE_MESSAGE;
- return intent.getStringExtra(EXTRA_MESSAGE_TYPE);
- }
-
- /**
- * Register the application for GCM and return the registration ID. You must call this once,
- * when your application is installed, and send the returned registration ID to the server.
- *
- * Repeated calls to this method will return the original registration ID.
- *
- * If you want to modify the list of senders, you must call unregister()
first.
- *
- * Most applications use a single sender ID. You may use multiple senders if different
- * servers may send messages to the app or for testing.
- *
- * @param senderIds list of project numbers or Google accounts identifying who is allowed to
- * send messages to this application.
- * @return registration id
- * @throws IOException
- * @deprecated Instead, for GCM registration, use
- * {@link com.google.android.gms.iid.InstanceID#getToken(java.lang.String, java.lang.String)}.
- * Set authorizedEntity to a sender ID and scope to {@link com.google.android.gms.gcm.GoogleCloudMessaging#INSTANCE_ID_SCOPE}.
- */
- @Deprecated
- public String register(String... senderIds) throws IOException {
- if (Looper.getMainLooper() == Looper.myLooper()) throw new IOException(ERROR_MAIN_THREAD);
-
- if (senderIds == null || senderIds.length == 0) throw new IllegalArgumentException("No sender ids");
- StringBuilder sb = new StringBuilder(senderIds[0]);
- for (int i = 1; i < senderIds.length; i++) {
- sb.append(',').append(senderIds[i]);
- }
- String sender = sb.toString();
-
- if (isLegacyFallback()) {
- Bundle extras = new Bundle();
- extras.putString(EXTRA_SENDER_LEGACY, sender);
- return InstanceID.getInstance(context).getToken(sb.toString(), INSTANCE_ID_SCOPE, extras);
- } else {
- Bundle extras = new Bundle();
- extras.putString(EXTRA_SENDER, sender);
- return rpc.handleRegisterMessageResult(rpc.sendRegisterMessageBlocking(extras));
- }
- }
-
- /**
- * Send an upstream ("device to cloud") message. You can only use the upstream feature
- * if your GCM implementation uses the XMPP-based
- * Cloud Connection Server.
- *
- * The current limits for max storage time and number of outstanding messages per
- * application are documented in the
- * GCM Developers Guide.
- *
- * @param to string identifying the receiver of the message in the format of
- * SENDER_ID@gcm.googleapis.com
. The SENDER_ID
should be one of the sender
- * IDs used when calling {@link com.google.android.gms.iid.InstanceID#getToken(java.lang.String, java.lang.String)}
- * @param msgId ID of the message. This is generated by the application. It must be
- * unique for each message. This allows error callbacks and debugging.
- * @param timeToLive If 0, we'll attempt to send immediately and return an
- * error if we're not connected. Otherwise, the message will be queued.
- * As for server-side messages, we don't return an error if the message has been
- * dropped because of TTL—this can happen on the server side, and it would require
- * extra communication.
- * @param data key/value pairs to be sent. Values must be String, any other type will
- * be ignored.
- * @throws IllegalArgumentException
- * @throws IOException
- */
- public void send(String to, String msgId, long timeToLive, Bundle data) throws IOException {
- if (TextUtils.isEmpty(to)) throw new IllegalArgumentException("Invalid 'to'");
-
- if (isLegacyFallback()) {
- Bundle extras = new Bundle();
- for (String key : data.keySet()) {
- Object o = extras.get(key);
- if (o instanceof String) {
- extras.putString("gcm." + key, (String) o);
- }
- }
- extras.putString(EXTRA_SEND_TO, to);
- extras.putString(EXTRA_MESSAGE_ID, msgId);
- InstanceID.getInstance(context).requestToken("GCM", "upstream", extras);
- } else {
- Bundle extras = data != null ? new Bundle(data) : new Bundle();
- extras.putString(EXTRA_SEND_TO, to);
- extras.putString(EXTRA_SEND_FROM, getFrom(to));
- extras.putString(EXTRA_MESSAGE_ID, msgId);
- extras.putLong(EXTRA_TTL, timeToLive);
- extras.putInt(EXTRA_DELAY, -1);
- rpc.sendGcmMessage(extras);
- }
- }
-
- /**
- * Send an upstream ("device to cloud") message. You can only use the upstream feature
- * if your GCM implementation uses the XMPP-based
- * Cloud Connection Server.
- *
- * When there is an active connection the message will be sent immediately, otherwise the
- * message will be queued for the maximum interval.
- *
- * @param to string identifying the receiver of the message in the format of
- * SENDER_ID@gcm.googleapis.com
. The SENDER_ID
should be one of the sender
- * IDs used when calling {@link com.google.android.gms.iid.InstanceID#getToken(java.lang.String, java.lang.String)}
- * @param msgId ID of the message. This is generated by the application. It must be
- * unique for each message. This allows error callbacks and debugging.
- * @param data key/value pairs to be sent. Values must be String—any other type will
- * be ignored.
- * @throws IllegalArgumentException
- * @throws IOException
- */
- public void send(String to, String msgId, Bundle data) throws IOException {
- send(to, msgId, -1, data);
- }
-
- /**
- * Unregister the application. Calling unregister()
stops any
- * messages from the server. This is a blocking call—you shouldn't call
- * it from the UI thread.
- *
- * You should rarely (if ever) need to call this method. Not only is it
- * expensive in terms of resources, but it invalidates all your registration IDs
- * returned from register() or subscribe(). This should not be done
- * unnecessarily. A better approach is to simply have your server stop
- * sending messages.
- *
- * @throws IOException if we can't connect to server to unregister.
- * @deprecated Instead use
- * {@link com.google.android.gms.iid.InstanceID#deleteToken(java.lang.String, java.lang.String)} or
- * {@link com.google.android.gms.iid.InstanceID#deleteInstanceID()}.
- */
- @Deprecated
- public void unregister() throws IOException {
- if (Looper.getMainLooper() == Looper.myLooper()) throw new IOException(ERROR_MAIN_THREAD);
- InstanceID.getInstance(context).deleteInstanceID();
- }
-
- private boolean isLegacyFallback() {
- String gcmPackageName = CloudMessagingRpc.getGcmPackageName(context);
- return gcmPackageName != null && gcmPackageName.endsWith(".gsf");
- }
-
- private String getFrom(String to) {
- int i = to.indexOf('@');
- if (i > 0) {
- to = to.substring(0, i);
- }
- return InstanceID.getInstance(context).getStore().get("", to, INSTANCE_ID_SCOPE);
- }
-}
diff --git a/play-services-gcm/src/main/java/com/google/android/gms/gcm/OneoffTask.java b/play-services-gcm/src/main/java/com/google/android/gms/gcm/OneoffTask.java
deleted file mode 100644
index 5e56cb12..00000000
--- a/play-services-gcm/src/main/java/com/google/android/gms/gcm/OneoffTask.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (C) 2013-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 com.google.android.gms.gcm;
-
-import android.os.Bundle;
-import android.os.Parcel;
-
-import org.microg.gms.common.PublicApi;
-
-/**
- * A task that will execute once,at some point within the specified window.
- * If one of {@link com.google.android.gms.gcm.GcmNetworkManager#cancelTask(java.lang.String, java.lang.Class extends com.google.android.gms.gcm.GcmTaskService>)} or
- * {@link com.google.android.gms.gcm.GcmNetworkManager#cancelAllTasks(java.lang.Class extends com.google.android.gms.gcm.GcmTaskService>)} is called before this
- * executes it will be cancelled.
- *
- * Note that you can request a one-off task to be executed at any point in the future, but to
- * prevent abuse the scheduler will only set an alarm at a minimum of 30 seconds in the
- * future. Your task can still be run earlier than this if some network event occurs to wake up
- * the scheduler.
- */
-@PublicApi
-public class OneoffTask extends com.google.android.gms.gcm.Task {
- private final long windowStart;
- private final long windowEnd;
-
- private OneoffTask(Builder builder) {
- super(builder);
- this.windowStart = builder.windowStart;
- this.windowEnd = builder.windowEnd;
- }
-
- private OneoffTask(Parcel source) {
- super(source);
- this.windowStart = source.readLong();
- this.windowEnd = source.readLong();
- }
-
- /**
- * @return The number of seconds from now by which this task must have executed.
- */
- public long getWindowEnd() {
- return windowEnd;
- }
-
- /**
- * @return The number of seconds from now at which this task is eligible for execution.
- */
- public long getWindowStart() {
- return windowStart;
- }
-
- /**
- * Insert the task object into the provided bundle for IPC. Use #fromBundle to recreate the
- * object on the other side.
- */
- public void toBundle(Bundle bundle) {
- super.toBundle(bundle);
- bundle.putLong("window_start", this.windowStart);
- bundle.putLong("window_end", this.windowEnd);
- }
-
- public String toString() {
- return super.toString()
- + " windowStart=" + this.getWindowStart()
- + " windowEnd=" + this.getWindowEnd();
- }
-
- public void writeToParcel(Parcel parcel, int flags) {
- super.writeToParcel(parcel, flags);
- parcel.writeLong(this.windowStart);
- parcel.writeLong(this.windowEnd);
- }
-
- public static final Creator CREATOR = new Creator() {
- @Override
- public OneoffTask createFromParcel(Parcel source) {
- return new OneoffTask(source);
- }
-
- @Override
- public OneoffTask[] newArray(int size) {
- return new OneoffTask[size];
- }
- };
-
- public static class Builder extends Task.Builder {
- private long windowStart = -1;
- private long windowEnd = -1;
-
- public Builder() {
- this.isPersisted = false;
- }
-
- public OneoffTask build() {
- return new OneoffTask(this);
- }
-
- /**
- * Mandatory setter for creating a one-off task. You specify the earliest point in
- * time in the future from which your task might start executing, as well as the
- * latest point in time in the future at which your task must have executed.
- *
- * @param windowStartDelaySeconds Earliest point from which your task is eligible to
- * run.
- * @param windowEndDelaySeconds Latest point at which your task must be run.
- */
- public OneoffTask.Builder setExecutionWindow(long windowStartDelaySeconds, long windowEndDelaySeconds) {
- this.windowEnd = windowEndDelaySeconds;
- this.windowStart = windowStartDelaySeconds;
- return this;
- }
-
- /**
- * Optional setter for specifying any extra parameters necessary for the task.
- */
- public OneoffTask.Builder setExtras(Bundle extras) {
- this.extras = extras;
- return this;
- }
-
- /**
- * Optional setter to specify whether this task should be persisted across reboots..
- * Callers must hold the permission
- * android.Manifest.permission.RECEIVE_BOOT_COMPLETED, otherwise this setter is
- * ignored.
- *
- * @param isPersisted True if this task should be persisted across device reboots.
- */
- public OneoffTask.Builder setPersisted(boolean isPersisted) {
- this.isPersisted = isPersisted;
- return this;
- }
-
- /**
- * Set the network state your task requires to run. If the specified network is
- * unavailable your task will not be executed until it becomes available.
- *
- * The default for either a periodic or one-off task is
- * {@link com.google.android.gms.gcm.Task#NETWORK_STATE_CONNECTED}. Note that changing this to
- * {@link com.google.android.gms.gcm.Task#NETWORK_STATE_ANY} means there is no guarantee that data will be available
- * when your task executes.
- *
- * In addition, the only guarantee for connectivity is at the moment of execution - it is
- * possible for the device to lose data shortly after your task begins executing.
- */
- public OneoffTask.Builder setRequiredNetwork(int requiredNetworkState) {
- this.requiredNetworkState = requiredNetworkState;
- return this;
- }
-
- /**
- * Set whether your task requires that the device be connected to power in order to
- * execute.
- *
- * Use this to defer nonessential operations whenever possible. Note that if you set this
- * field and the device is not connected to power your task will not run
- * until the device is plugged in.
- *
- * One way to deal with your task not executing until the constraint is met is to schedule
- * another task without the constraints that is subject to some deadline that you can abide.
- * This task would be responsible for executing your fallback logic.
- */
- public OneoffTask.Builder setRequiresCharging(boolean requiresCharging) {
- this.requiresCharging = requiresCharging;
- return this;
- }
-
- /**
- * Set whichever {@link com.google.android.gms.gcm.GcmTaskService} you implement to execute the logic for this task.
- *
- * @param gcmTaskService Endpoint against which you're scheduling this task.
- */
- public OneoffTask.Builder setService(Class extends GcmTaskService> gcmTaskService) {
- this.gcmTaskService = gcmTaskService.getName();
- return this;
- }
-
- /**
- * Mandatory setter for specifying the tag identifer for this task. This tag will be
- * returned at execution time to your endpoint. See
- * {@link com.google.android.gms.gcm.GcmTaskService#onRunTask(com.google.android.gms.gcm.TaskParams)}
- * Maximum tag length is 100.<
- *
- * @param tag String identifier for this task. Consecutive schedule calls for the same
- * tag will update any preexisting task with the same tag.
- */
- public OneoffTask.Builder setTag(String tag) {
- this.tag = tag;
- return this;
- }
-
- /**
- * Optional setter to specify whether this task should override any preexisting tasks
- * with the same tag. This defaults to false, which means that a new task will not
- * override an existing one.
- *
- * @param updateCurrent True to update the current task with the parameters of the new.
- * Default false.
- */
- public OneoffTask.Builder setUpdateCurrent(boolean updateCurrent) {
- this.updateCurrent = updateCurrent;
- return this;
- }
-
- }
-
-}
\ No newline at end of file
diff --git a/play-services-gcm/src/main/java/com/google/android/gms/gcm/PendingCallback.java b/play-services-gcm/src/main/java/com/google/android/gms/gcm/PendingCallback.java
deleted file mode 100644
index a6527ac9..00000000
--- a/play-services-gcm/src/main/java/com/google/android/gms/gcm/PendingCallback.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2013-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 com.google.android.gms.gcm;
-
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-public class PendingCallback implements Parcelable {
- private final IBinder binder;
-
- public PendingCallback(IBinder binder) {
- this.binder = binder;
- }
-
- private PendingCallback(Parcel in) {
- this.binder = in.readStrongBinder();
- }
-
- public IBinder getBinder() {
- return binder;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeStrongBinder(binder);
- }
-
- public static final Creator CREATOR = new Creator() {
- @Override
- public PendingCallback createFromParcel(Parcel source) {
- return new PendingCallback(source);
- }
-
- @Override
- public PendingCallback[] newArray(int size) {
- return new PendingCallback[size];
- }
- };
-}
diff --git a/play-services-gcm/src/main/java/com/google/android/gms/gcm/PeriodicTask.java b/play-services-gcm/src/main/java/com/google/android/gms/gcm/PeriodicTask.java
deleted file mode 100644
index 37aefe95..00000000
--- a/play-services-gcm/src/main/java/com/google/android/gms/gcm/PeriodicTask.java
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Copyright (C) 2013-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 com.google.android.gms.gcm;
-
-import android.os.Bundle;
-import android.os.Parcel;
-
-import org.microg.gms.common.PublicApi;
-
-/**
- * A periodic task is one that will recur at the specified interval, without needing to be
- * rescheduled.
- * Schedule a task that will recur until the user calls one of
- * {@link com.google.android.gms.gcm.GcmNetworkManager#cancelAllTasks(java.lang.Class extends com.google.android.gms.gcm.GcmTaskService>)}, or
- * {@link com.google.android.gms.gcm.GcmNetworkManager#cancelTask(java.lang.String, java.lang.Class extends com.google.android.gms.gcm.GcmTaskService>)} with
- * an identifying tag.
- *
- * Periodic tasks will not be scheduled if their period is below a certain minimum
- * (currently 30 seconds).
- */
-@PublicApi
-public class PeriodicTask extends com.google.android.gms.gcm.Task {
-
- protected long mFlexInSeconds;
-
- protected long mIntervalInSeconds;
-
- private PeriodicTask(Builder builder) {
- super(builder);
- this.mIntervalInSeconds = builder.periodInSeconds;
- this.mFlexInSeconds = Math.min(builder.flexInSeconds, mIntervalInSeconds);
- }
-
- private PeriodicTask(Parcel source) {
- super(source);
- mIntervalInSeconds = source.readLong();
- mFlexInSeconds = Math.min(source.readLong(), mIntervalInSeconds);
- }
-
-
- /**
- * @return The number of seconds before the end of the period returned via
- * {@link com.google.android.gms.gcm.PeriodicTask#getPeriod()} that this periodic task can be executed early.
- */
- public long getFlex() {
- return mFlexInSeconds;
- }
-
- /**
- * @return The period for this task. The number of seconds between subsequent executions.
- */
- public long getPeriod() {
- return mIntervalInSeconds;
- }
-
- /**
- * Insert the task object into the provided bundle for IPC. Use #fromBundle to recreate the
- * object on the other side.
- */
- public void toBundle(Bundle bundle) {
- super.toBundle(bundle);
- bundle.putLong("period", this.mIntervalInSeconds);
- bundle.putLong("period_flex", this.mFlexInSeconds);
- }
-
- public String toString() {
- return super.toString() + " period=" + this.getPeriod() + " flex=" + this.getFlex();
- }
-
- public void writeToParcel(Parcel parcel, int flags) {
- super.writeToParcel(parcel, flags);
- parcel.writeLong(this.mIntervalInSeconds);
- parcel.writeLong(this.mFlexInSeconds);
- }
-
- public static final Creator CREATOR = new Creator() {
- @Override
- public PeriodicTask createFromParcel(Parcel source) {
- return new PeriodicTask(source);
- }
-
- @Override
- public PeriodicTask[] newArray(int size) {
- return new PeriodicTask[size];
- }
- };
-
- public static class Builder extends com.google.android.gms.gcm.Task.Builder {
- private long flexInSeconds = -1;
- private long periodInSeconds = -1;
-
- public Builder() {
- isPersisted = true;
- }
-
- public PeriodicTask build() {
- return new PeriodicTask(this);
- }
-
- /**
- * Optional setter for specifying any extra parameters necessary for the task.
- */
- public PeriodicTask.Builder setExtras(Bundle extras) {
- this.extras = extras;
- return this;
- }
-
- /**
- * Optional setter for specifying how close to the end of the period set in
- * {@link com.google.android.gms.gcm.PeriodicTask.Builder#setPeriod(long)} you are willing to execute.
- *
- * For example, specifying a period of 30 seconds, with a flex value of 10 seconds
- * will allow the scheduler to determine the best moment between the 20th and 30th
- * second at which to execute your task.
- */
- public PeriodicTask.Builder setFlex(long flexInSeconds) {
- this.flexInSeconds = flexInSeconds;
- return this;
- }
-
- /**
- * Mandatory setter for creating a periodic task. This specifies that you would like
- * this task to recur at most once every mIntervalInSeconds.
- *
- * By default you have no control over where within this period the task will execute.
- * If you want to restrict the task to run within a certain timeframe from the end of
- * the period, use {@link com.google.android.gms.gcm.PeriodicTask.Builder#setFlex(long)}
- */
- public PeriodicTask.Builder setPeriod(long periodInSeconds) {
- this.periodInSeconds = periodInSeconds;
- return this;
- }
-
- /**
- * Optional setter to specify whether this task should be persisted across reboots. This
- * defaults to true for periodic tasks,
- *
- * Callers must hold the permission
- * android.Manifest.permission.RECEIVE_BOOT_COMPLETED, otherwise this setter is
- * ignored.
- *
- * @param isPersisted True if this task should be persisted across device reboots.
- */
- public PeriodicTask.Builder setPersisted(boolean isPersisted) {
- this.isPersisted = isPersisted;
- return this;
- }
-
- /**
- * Set the network state your task requires to run. If the specified network is
- * unavailable your task will not be executed until it becomes available.
- *
- * The default for either a periodic or one-off task is
- * {@link com.google.android.gms.gcm.Task#NETWORK_STATE_CONNECTED}. Note that changing this to
- * {@link com.google.android.gms.gcm.Task#NETWORK_STATE_ANY} means there is no guarantee that data will be available
- * when your task executes.
- *
- * In addition, the only guarantee for connectivity is at the moment of execution - it is
- * possible for the device to lose data shortly after your task begins executing.
- */
- public PeriodicTask.Builder setRequiredNetwork(int requiredNetworkState) {
- this.requiredNetworkState = requiredNetworkState;
- return this;
- }
-
- /**
- * Set whether your task requires that the device be connected to power in order to
- * execute.
- *
- * Use this to defer nonessential operations whenever possible. Note that if you set this
- * field and the device is not connected to power your task will not run
- * until the device is plugged in.
- *
- * One way to deal with your task not executing until the constraint is met is to schedule
- * another task without the constraints that is subject to some deadline that you can abide.
- * This task would be responsible for executing your fallback logic.
- */
- public PeriodicTask.Builder setRequiresCharging(boolean requiresCharging) {
- this.requiresCharging = requiresCharging;
- return this;
- }
-
- /**
- * Set whichever {@link com.google.android.gms.gcm.GcmTaskService} you implement to execute the logic for this task.
- *
- * @param gcmTaskService Endpoint against which you're scheduling this task.
- */
- public PeriodicTask.Builder setService(Class extends GcmTaskService> gcmTaskService) {
- this.gcmTaskService = gcmTaskService.getName();
- return this;
- }
-
- /**
- * Mandatory setter for specifying the tag identifer for this task. This tag will be
- * returned at execution time to your endpoint. See
- * {@link com.google.android.gms.gcm.GcmTaskService#onRunTask(com.google.android.gms.gcm.TaskParams)}
- *
- * Maximum tag length is 100.
- *
- * @param tag String identifier for this task. Consecutive schedule calls for the same
- * tag will update any preexisting task with the same tag.
- */
- public PeriodicTask.Builder setTag(String tag) {
- this.tag = tag;
- return this;
- }
-
- /**
- * Optional setter to specify whether this task should override any preexisting tasks
- * with the same tag. This defaults to false, which means that a new task will not
- * override an existing one.
- *
- * @param updateCurrent True to update the current task with the parameters of the new.
- * Default false.
- */
- public PeriodicTask.Builder setUpdateCurrent(boolean updateCurrent) {
- this.updateCurrent = updateCurrent;
- return this;
- }
- }
-}
\ No newline at end of file
diff --git a/play-services-gcm/src/main/java/com/google/android/gms/gcm/Task.java b/play-services-gcm/src/main/java/com/google/android/gms/gcm/Task.java
deleted file mode 100644
index 6f30caed..00000000
--- a/play-services-gcm/src/main/java/com/google/android/gms/gcm/Task.java
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright (C) 2013-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 com.google.android.gms.gcm;
-
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import org.microg.gms.common.PublicApi;
-
-/**
- * Encapsulates the parameters of a task that you will schedule on the
- * {@link com.google.android.gms.gcm.GcmNetworkManager}.
- *
- * Construct instances of either {@link com.google.android.gms.gcm.PeriodicTask} or
- * {@link com.google.android.gms.gcm.OneoffTask} with the desired parameters/behaviour and
- * schedule them using {@link com.google.android.gms.gcm.GcmNetworkManager#schedule(com.google.android.gms.gcm.Task)}.
- */
-@PublicApi
-public abstract class Task implements Parcelable {
-
- /**
- * The maximum size allowed for extras bundle in bytes.
- *
- */
- public static final int EXTRAS_LIMIT_BYTES = 10240;
-
- /**
- * Specify using {@link com.google.android.gms.gcm.Task.Builder#setRequiredNetwork(int)}
- * that your task will execute [...] of whether network is available.
- *
- */
- public static final int NETWORK_STATE_ANY = 2;
-
- /**
- * Specify using {@link com.google.android.gms.gcm.Task.Builder#setRequiredNetwork(int)}
- * that your task will only execute if [...] sort of data connection is available -
- * either metered or unmetered. This is the default.
- */
- public static final int NETWORK_STATE_CONNECTED = 0;
-
- /**
- * Specify using {@link com.google.android.gms.gcm.Task.Builder#setRequiredNetwork(int)}
- * that your task will only execute if there is an unmetered network connection available.
- *
- */
- public static final int NETWORK_STATE_UNMETERED = 1;
-
- protected static final long UNINITIALIZED = -1;
-
- private final String serviceName;
- private final String tag;
- private final boolean updateCurrent;
- private final boolean persisted;
- private final int requiredNetwork;
- private final boolean requiresCharging;
- private final Bundle extras;
-
- Task(Builder builder) {
- this.serviceName = builder.gcmTaskService;
- this.tag = builder.tag;
- this.updateCurrent = builder.updateCurrent;
- this.persisted = builder.isPersisted;
- this.requiredNetwork = builder.requiredNetworkState;
- this.requiresCharging = builder.requiresCharging;
- this.extras = builder.extras;
- }
-
- Task(Parcel in) {
- this.serviceName = in.readString();
- this.tag = in.readString();
- this.updateCurrent = in.readInt() == 1;
- this.persisted = in.readInt() == 1;
- this.requiredNetwork = NETWORK_STATE_ANY;
- this.requiresCharging = false;
- this.extras = null;
- }
-
- public int describeContents() {
- return 0;
- }
-
- /**
- * @return The extra parameters for the task set by the client.
- */
- public Bundle getExtras() {
- return extras;
- }
-
- /**
- * If the specified network is unavailable, your task will not be run until
- * it is.
- *
- * @return The network type that this task requires in order to run. See the NETWORK_TYPE_*
- * flavours for an explanation of what this value can be.
- */
- public int getRequiredNetwork() {
- return requiredNetwork;
- }
-
- /**
- * If the device is not charging and this is set to true, your task will not be run
- * until it is.
- *
- * @return Whether or not this task depends on the device being connected to power in order to
- * execute.
- */
- public boolean getRequiresCharging() {
- return requiresCharging;
- }
-
- /**
- * @return The {@link com.google.android.gms.gcm.GcmTaskService} component that this task
- * will execute on.
- */
- public String getServiceName() {
- return serviceName;
- }
-
- /**
- * @return The String identifier for this task, that is returned to
- * {@link com.google.android.gms.gcm.GcmTaskService#onRunTask(com.google.android.gms.gcm.TaskParams)}
- * when this task executes.
- */
- public String getTag() {
- return tag;
- }
-
- /**
- * @return Whether this task will be persisted across devices restarts or Google Play Services
- * crashes.
- */
- public boolean isPersisted() {
- return persisted;
- }
-
- /**
- * @return Whether or not this task will update a pre-existing task in the scheduler queue.
- */
- public boolean isUpdateCurrent() {
- return updateCurrent;
- }
-
- public void toBundle(Bundle bundle) {
- bundle.putString("tag", this.tag);
- bundle.putBoolean("update_current", this.updateCurrent);
- bundle.putBoolean("persisted", this.persisted);
- bundle.putString("service", this.serviceName);
- bundle.putInt("requiredNetwork", this.requiredNetwork);
- bundle.putBoolean("requiresCharging", this.requiresCharging);
- bundle.putBundle("retryStrategy", null); // TODO
- bundle.putBundle("extras", this.extras);
- }
-
- public void writeToParcel(Parcel parcel, int i) {
- parcel.writeString(serviceName);
- parcel.writeString(tag);
- parcel.writeInt(updateCurrent ? 1 : 0);
- parcel.writeInt(persisted ? 1 : 0);
- }
-
-
- /**
- * Builder object to construct these tasks before sending them to the network manager. Use
- * either {@link com.google.android.gms.gcm.PeriodicTask.Builder} or
- * {@link com.google.android.gms.gcm.Task.Builder}
- */
- public abstract static class Builder {
- protected Bundle extras;
- protected String gcmTaskService;
- protected boolean isPersisted;
- protected int requiredNetworkState;
- protected boolean requiresCharging;
- protected String tag;
- protected boolean updateCurrent;
-
- public Builder() {
- throw new UnsupportedOperationException();
- }
-
- public abstract Task build();
-
- /**
- * Optional setter for specifying any extra parameters necessary for the task.
- */
- public abstract Task.Builder setExtras(Bundle extras);
-
- /**
- * Optional setter to specify whether this task should be persisted across reboots. This
- * defaults to true for periodic tasks, and is not supported for one-off tasks.
- *
- * Callers must hold the permission
- * android.Manifest.permission.RECEIVE_BOOT_COMPLETED, otherwise this setter is
- * ignored.
- *
- * @param isPersisted True if this task should be persisted across device reboots.
- */
- public abstract Task.Builder setPersisted(boolean isPersisted);
-
- /**
- * Set the network state your task requires to run. If the specified network is
- * unavailable your task will not be executed until it becomes available.
- *
- * The default for either a periodic or one-off task is
- * {@link com.google.android.gms.gcm.Task#NETWORK_STATE_CONNECTED}. Note that changing this to
- * {@link com.google.android.gms.gcm.Task#NETWORK_STATE_ANY} means there is no guarantee that data will be available
- * when your task executes.
- *
- * In addition, the only guarantee for connectivity is at the moment of execution - it is
- * possible for the device to lose data shortly after your task begins executing.
- */
- public abstract Task.Builder setRequiredNetwork(int requiredNetworkState);
-
- /**
- * Set whether your task requires that the device be connected to power in order to
- * execute.
- *
- * Use this to defer nonessential operations whenever possible. Note that if you set this
- * field and the device is not connected to power your task will not run
- * until the device is plugged in.
- *
- * One way to deal with your task not executing until the constraint is met is to schedule
- * another task without the constraints that is subject to some deadline that you can abide.
- * This task would be responsible for executing your fallback logic.
- */
- public abstract Task.Builder setRequiresCharging(boolean requiresCharging);
-
- /**
- * Set whichever {@link com.google.android.gms.gcm.GcmTaskService} you implement to execute the logic for this task.
- *
- * @param gcmTaskService Endpoint against which you're scheduling this task.
- */
- public abstract Task.Builder setService(Class extends GcmTaskService> gcmTaskService);
-
- /**
- * Mandatory setter for specifying the tag identifer for this task. This tag will be
- * returned at execution time to your endpoint. See
- * {@link com.google.android.gms.gcm.GcmTaskService#onRunTask(com.google.android.gms.gcm.TaskParams)}
- *
- * Maximum tag length is 100.
- *
- * @param tag String identifier for this task. Consecutive schedule calls for the same tag
- * will update any preexisting task with the same tag.
- */
- public abstract Task.Builder setTag(String tag);
-
- /**
- * Optional setter to specify whether this task should override any preexisting tasks with
- * the same tag. This defaults to false, which means that a new task will not override an
- * existing one.
- *
- * @param updateCurrent True to update the current task with the parameters of the new.
- * Default false.
- */
- public abstract Task.Builder setUpdateCurrent(boolean updateCurrent);
- }
-}
\ No newline at end of file
diff --git a/play-services-gcm/src/main/java/com/google/android/gms/gcm/TaskParams.java b/play-services-gcm/src/main/java/com/google/android/gms/gcm/TaskParams.java
deleted file mode 100644
index 0fb0940a..00000000
--- a/play-services-gcm/src/main/java/com/google/android/gms/gcm/TaskParams.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2013-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 com.google.android.gms.gcm;
-
-import android.os.Bundle;
-
-import org.microg.gms.common.PublicApi;
-
-/**
- * Container of parameters handed off to the client app in
- * {@link com.google.android.gms.gcm.GcmTaskService#onRunTask(com.google.android.gms.gcm.TaskParams)}.
- */
-@PublicApi
-public class TaskParams {
- private final String tag;
- private final Bundle extras;
-
- public TaskParams(String tag) {
- this(tag, null);
- }
-
- public TaskParams(String tag, Bundle extras) {
- this.tag = tag;
- this.extras = extras;
- }
-
- public Bundle getExtras() {
- return extras;
- }
-
- public String getTag() {
- return tag;
- }
-
-}
diff --git a/play-services-gcm/src/main/java/org/microg/gms/gcm/CloudMessagingRpc.java b/play-services-gcm/src/main/java/org/microg/gms/gcm/CloudMessagingRpc.java
deleted file mode 100644
index 4496af3e..00000000
--- a/play-services-gcm/src/main/java/org/microg/gms/gcm/CloudMessagingRpc.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2013-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.gcm;
-
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Messenger;
-import android.util.Log;
-
-import com.google.android.gms.iid.InstanceID;
-
-import java.io.IOException;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static com.google.android.gms.gcm.GoogleCloudMessaging.ERROR_SERVICE_NOT_AVAILABLE;
-import static org.microg.gms.common.Constants.GMS_PACKAGE_NAME;
-import static org.microg.gms.common.Constants.GSF_PACKAGE_NAME;
-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_GCM_SEND;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_APP;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_ERROR;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_MESSAGE_ID;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_MESSENGER;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_REGISTRATION_ID;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_UNREGISTERED;
-import static org.microg.gms.gcm.GcmConstants.PERMISSION_GTALK;
-import static org.microg.gms.gcm.GcmConstants.PERMISSION_RECEIVE;
-
-public class CloudMessagingRpc {
- private static final AtomicInteger messageIdCounter = new AtomicInteger(1);
- private static String gcmPackageName;
-
- private final BlockingQueue messengerResponseQueue = new LinkedBlockingQueue();
- private final Messenger messenger = new Messenger(new Handler(Looper.getMainLooper()) {
- @Override
- public void handleMessage(Message msg) {
- if (msg == null || !(msg.obj instanceof Intent)) {
- // Invalid message -> drop
- return;
- }
- Intent intent = (Intent) msg.obj;
- if (ACTION_C2DM_REGISTRATION.equals(intent.getAction())) {
- messengerResponseQueue.add(intent);
- }
- }
- });
-
- /**
- * Due to it's nature of being a monitored reference, Intents can be used to authenticate a package source.
- */
- private PendingIntent selfAuthIntent;
- private Context context;
-
- public CloudMessagingRpc(Context context) {
- this.context = context;
- }
-
- public static String getGcmPackageName(Context context) {
- if (gcmPackageName != null) {
- return gcmPackageName;
- }
- PackageManager packageManager = context.getPackageManager();
- for (ResolveInfo resolveInfo : packageManager.queryIntentServices(new Intent(ACTION_C2DM_REGISTER), 0)) {
- if (packageManager.checkPermission(PERMISSION_RECEIVE, resolveInfo.serviceInfo.packageName) == PERMISSION_GRANTED) {
- return gcmPackageName = resolveInfo.serviceInfo.packageName;
- }
- }
- try {
- ApplicationInfo appInfo = packageManager.getApplicationInfo(GMS_PACKAGE_NAME, 0);
- return gcmPackageName = appInfo.packageName;
- } catch (PackageManager.NameNotFoundException ignored) {
- }
- try {
- ApplicationInfo appInfo = packageManager.getApplicationInfo(GSF_PACKAGE_NAME, 0);
- return gcmPackageName = appInfo.packageName;
- } catch (PackageManager.NameNotFoundException ex3) {
- return null;
- }
- }
-
- public void close() {
- // Cancel the authentication
- if (selfAuthIntent != null) {
- selfAuthIntent.cancel();
- selfAuthIntent = null;
- }
- }
-
- private PendingIntent getSelfAuthIntent() {
- if (selfAuthIntent == null) {
- Intent intent = new Intent();
- intent.setPackage("com.google.example.invalidpackage");
- selfAuthIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
- }
- return selfAuthIntent;
- }
-
- public Intent sendRegisterMessageBlocking(Bundle extras) throws IOException {
- sendRegisterMessage(extras);
- Intent resultIntent;
- try {
- resultIntent = messengerResponseQueue.poll(30, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- throw new IOException(e.getMessage());
- }
- if (resultIntent == null) {
- throw new IOException(ERROR_SERVICE_NOT_AVAILABLE);
- }
- return resultIntent;
- }
-
- private void sendRegisterMessage(Bundle extras) {
- Intent intent = new Intent(ACTION_C2DM_REGISTER);
- intent.setPackage(getGcmPackageName(context));
- extras.putString(EXTRA_MESSAGE_ID, "google.rpc" + messageIdCounter.getAndIncrement());
- intent.putExtras(extras);
- intent.putExtra(EXTRA_MESSENGER, messenger);
- intent.putExtra(EXTRA_APP, getSelfAuthIntent());
- context.startService(intent);
- }
-
- public void sendGcmMessage(Bundle extras) {
- Intent intent = new Intent(ACTION_GCM_SEND);
- intent.setPackage(GMS_PACKAGE_NAME);
- intent.putExtras(extras);
- intent.putExtra(EXTRA_APP, getSelfAuthIntent());
- context.sendOrderedBroadcast(intent, PERMISSION_GTALK);
- }
-
- public String handleRegisterMessageResult(Intent resultIntent) throws IOException {
- if (resultIntent == null) throw new IOException(InstanceID.ERROR_SERVICE_NOT_AVAILABLE);
- String result = resultIntent.getStringExtra(EXTRA_REGISTRATION_ID);
- if (result == null) result = resultIntent.getStringExtra(EXTRA_UNREGISTERED);
- if (result != null) return result;
- result = resultIntent.getStringExtra(EXTRA_ERROR);
- throw new IOException(result != null ? result : InstanceID.ERROR_SERVICE_NOT_AVAILABLE);
- }
-}
diff --git a/play-services-iid/build.gradle b/play-services-iid/build.gradle
deleted file mode 100644
index c8960415..00000000
--- a/play-services-iid/build.gradle
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2013-2015 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.
- */
-
-apply plugin: 'com.android.library'
-
-String getMyVersionName() {
- def stdout = new ByteArrayOutputStream()
- if (rootProject.file("gradlew").exists())
- exec { commandLine 'git', 'describe', '--tags', '--always', '--dirty'; standardOutput = stdout }
- else // automatic build system, don't tag dirty
- exec { commandLine 'git', 'describe', '--tags', '--always'; standardOutput = stdout }
- return stdout.toString().trim().substring(1)
-}
-
-android {
- compileSdkVersion androidCompileSdk()
- buildToolsVersion "$androidBuildVersionTools"
-
- defaultConfig {
- versionName getMyVersionName()
- minSdkVersion androidMinSdk()
- targetSdkVersion androidTargetSdk()
- }
-
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
-}
-
-dependencies {
- api project(':play-services-base')
- api project(':play-services-iid-api')
-}
diff --git a/play-services-iid/gradle.properties b/play-services-iid/gradle.properties
deleted file mode 100644
index 2e179864..00000000
--- a/play-services-iid/gradle.properties
+++ /dev/null
@@ -1,34 +0,0 @@
-#
-# Copyright 2013-2016 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.
-#
-
-POM_NAME=Play Services IID Library
-POM_DESCRIPTION=The Play Services Library module to access the InstanceID API
-
-POM_PACKAGING=aar
-
-POM_URL=https://github.com/microg/android_external_GmsLib
-
-POM_SCM_URL=https://github.com/microg/android_external_GmsLib
-POM_SCM_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
-POM_SCM_DEV_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
-
-POM_LICENCE_NAME=The Apache Software License, Version 2.0
-POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
-POM_LICENCE_DIST=repo
-
-POM_DEVELOPER_ID=mar-v-in
-POM_DEVELOPER_NAME=Marvin W
-
diff --git a/play-services-iid/src/main/AndroidManifest.xml b/play-services-iid/src/main/AndroidManifest.xml
deleted file mode 100644
index 67377ff0..00000000
--- a/play-services-iid/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/play-services-iid/src/main/java/com/google/android/gms/iid/InstanceID.java b/play-services-iid/src/main/java/com/google/android/gms/iid/InstanceID.java
deleted file mode 100644
index 8a4dbefa..00000000
--- a/play-services-iid/src/main/java/com/google/android/gms/iid/InstanceID.java
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Copyright (C) 2013-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 com.google.android.gms.iid;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.os.Looper;
-import android.text.TextUtils;
-import android.util.Base64;
-import android.util.Log;
-
-import org.microg.gms.common.PublicApi;
-import org.microg.gms.gcm.GcmConstants;
-import org.microg.gms.iid.InstanceIdRpc;
-import org.microg.gms.iid.InstanceIdStore;
-
-import java.io.IOException;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.microg.gms.gcm.GcmConstants.EXTRA_DELETE;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_SCOPE;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_SENDER;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_SUBSCIPTION;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_SUBTYPE;
-
-/**
- * Instance ID provides a unique identifier for each app instance and a mechanism
- * to authenticate and authorize actions (for example, sending a GCM message).
- *
- * Instance ID is stable but may become invalid, if:
- *
- * - App deletes Instance ID
- * - Device is factory reset
- * - User uninstalls the app
- * - User clears app data
- *
- * If Instance ID has become invalid, the app can call {@link com.google.android.gms.iid.InstanceID#getId()}
- * to request a new Instance ID.
- * To prove ownership of Instance ID and to allow servers to access data or
- * services associated with the app, call {@link com.google.android.gms.iid.InstanceID#getToken(java.lang.String, java.lang.String)}.
- */
-@PublicApi
-public class InstanceID {
- /**
- * Error returned when failed requests are retried too often. Use
- * exponential backoff when retrying requests
- */
- public static final String ERROR_BACKOFF = "RETRY_LATER";
-
- /**
- * Blocking methods must not be called on the main thread.
- */
- public static final String ERROR_MAIN_THREAD = "MAIN_THREAD";
-
- /**
- * Tokens can't be generated. Only devices with Google Play are supported.
- */
- public static final String ERROR_MISSING_INSTANCEID_SERVICE = "MISSING_INSTANCEID_SERVICE";
-
- /**
- * The device cannot read the response, or there was a server error.
- * Application should retry the request later using exponential backoff
- * and retry (on each subsequent failure increase delay before retrying).
- */
- public static final String ERROR_SERVICE_NOT_AVAILABLE = GcmConstants.ERROR_SERVICE_NOT_AVAILABLE;
-
- /**
- * Timeout waiting for a response.
- */
- public static final String ERROR_TIMEOUT = "TIMEOUT";
-
- private static final int RSA_KEY_SIZE = 2048;
- private static final String TAG = "InstanceID";
-
- private static InstanceIdStore storeInstance;
- private static InstanceIdRpc rpc;
- private static Map instances = new HashMap();
-
- private final String subtype;
- private KeyPair keyPair;
- private long creationTime;
-
- private InstanceID(String subtype) {
- this.subtype = subtype == null ? "" : subtype;
- }
-
- /**
- * Resets Instance ID and revokes all tokens.
- *
- * @throws IOException
- */
- public void deleteInstanceID() throws IOException {
- deleteToken("*", "*");
- creationTime = 0;
- storeInstance.delete(subtype + "|");
- keyPair = null;
- }
-
- /**
- * Revokes access to a scope (action) for an entity previously
- * authorized by {@link com.google.android.gms.iid.InstanceID#getToken(java.lang.String, java.lang.String)}.
- *
- * Do not call this function on the main thread.
- *
- * @param authorizedEntity Entity that must no longer have access.
- * @param scope Action that entity is no longer authorized to perform.
- * @throws IOException if the request fails.
- */
- public void deleteToken(String authorizedEntity, String scope) throws IOException {
- deleteToken(authorizedEntity, scope, null);
- }
-
- @PublicApi(exclude = true)
- public void deleteToken(String authorizedEntity, String scope, Bundle extras) throws IOException {
- if (Looper.getMainLooper() == Looper.myLooper()) throw new IOException(ERROR_MAIN_THREAD);
-
- storeInstance.delete(subtype, authorizedEntity, scope);
-
- if (extras == null) extras = new Bundle();
- extras.putString(EXTRA_SENDER, authorizedEntity);
- extras.putString(EXTRA_SUBSCIPTION, authorizedEntity);
- extras.putString(EXTRA_DELETE, "1");
- extras.putString("X-" + EXTRA_DELETE, "1");
- extras.putString(EXTRA_SUBTYPE, TextUtils.isEmpty(subtype) ? authorizedEntity : subtype);
- extras.putString("X-" + EXTRA_SUBTYPE, TextUtils.isEmpty(subtype) ? authorizedEntity : subtype);
- if (scope != null) extras.putString(EXTRA_SCOPE, scope);
-
- rpc.handleRegisterMessageResult(rpc.sendRegisterMessageBlocking(extras, getKeyPair()));
- }
-
- /**
- * Returns time when instance ID was created.
- *
- * @return Time when instance ID was created (milliseconds since Epoch).
- */
- public long getCreationTime() {
- if (creationTime == 0) {
- String s = storeInstance.get(subtype, "cre");
- if (s != null) {
- creationTime = Long.parseLong(s);
- }
- }
- return creationTime;
- }
-
- /**
- * Returns a stable identifier that uniquely identifies the app instance.
- *
- * @return The identifier for the application instance.
- */
- public String getId() {
- return sha1KeyPair(getKeyPair());
- }
-
- /**
- * Returns an instance of this class.
- *
- * @return InstanceID instance.
- */
- public static InstanceID getInstance(Context context) {
- String subtype = "";
- if (storeInstance == null) {
- storeInstance = new InstanceIdStore(context.getApplicationContext());
- rpc = new InstanceIdRpc(context.getApplicationContext());
- }
- InstanceID instance = instances.get(subtype);
- if (instance == null) {
- instance = new InstanceID(subtype);
- instances.put(subtype, instance);
- }
- return instance;
- }
-
- /**
- * Returns a token that authorizes an Entity (example: cloud service) to perform
- * an action on behalf of the application identified by Instance ID.
- *
- * This is similar to an OAuth2 token except, it applies to the
- * application instance instead of a user.
- *
- * Do not call this function on the main thread.
- *
- * @param authorizedEntity Entity authorized by the token.
- * @param scope Action authorized for authorizedEntity.
- * @param extras additional parameters specific to each token scope.
- * Bundle keys starting with 'GCM.' and 'GOOGLE.' are
- * reserved.
- * @return a token that can identify and authorize the instance of the
- * application on the device.
- * @throws IOException if the request fails.
- */
- public String getToken(String authorizedEntity, String scope, Bundle extras) throws IOException {
- if (Looper.getMainLooper() == Looper.myLooper()) throw new IOException(ERROR_MAIN_THREAD);
-
- throw new UnsupportedOperationException();
- }
-
- /**
- * Returns a token that authorizes an Entity (example: cloud service) to perform
- * an action on behalf of the application identified by Instance ID.
- *
- * This is similar to an OAuth2 token except, it applies to the
- * application instance instead of a user.
- *
- * Do not call this function on the main thread.
- *
- * @param authorizedEntity Entity authorized by the token.
- * @param scope Action authorized for authorizedEntity.
- * @return a token that can identify and authorize the instance of the
- * application on the device.
- * @throws IOException if the request fails.
- */
- public String getToken(String authorizedEntity, String scope) throws IOException {
- return getToken(authorizedEntity, scope, null);
- }
-
- @PublicApi(exclude = true)
- public InstanceIdStore getStore() {
- return storeInstance;
- }
-
- @PublicApi(exclude = true)
- public String requestToken(String authorizedEntity, String scope, Bundle extras) {
- throw new UnsupportedOperationException();
- }
-
- private synchronized KeyPair getKeyPair() {
- if (keyPair == null) {
- keyPair = storeInstance.getKeyPair(subtype);
- if (keyPair == null) {
- try {
- KeyPairGenerator rsaGenerator = KeyPairGenerator.getInstance("RSA");
- rsaGenerator.initialize(RSA_KEY_SIZE);
- keyPair = rsaGenerator.generateKeyPair();
- creationTime = System.currentTimeMillis();
- storeInstance.put(subtype, keyPair, creationTime);
- } catch (NoSuchAlgorithmException e) {
- Log.w(TAG, e);
- }
- }
- }
- return keyPair;
- }
-
- @PublicApi(exclude = true)
- public static String sha1KeyPair(KeyPair keyPair) {
- try {
- byte[] digest = MessageDigest.getInstance("SHA1").digest(keyPair.getPublic().getEncoded());
- digest[0] = (byte) (112 + (0xF & digest[0]) & 0xFF);
- return Base64.encodeToString(digest, 0, 8, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING);
- } catch (NoSuchAlgorithmException e) {
- Log.w(TAG, e);
- return null;
- }
- }
-}
\ No newline at end of file
diff --git a/play-services-iid/src/main/java/com/google/android/gms/iid/InstanceIDListenerService.java b/play-services-iid/src/main/java/com/google/android/gms/iid/InstanceIDListenerService.java
deleted file mode 100644
index a15baa0f..00000000
--- a/play-services-iid/src/main/java/com/google/android/gms/iid/InstanceIDListenerService.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2013-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 com.google.android.gms.iid;
-
-import android.app.Service;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.support.v4.content.WakefulBroadcastReceiver;
-
-import static org.microg.gms.gcm.GcmConstants.ACTION_C2DM_REGISTRATION;
-import static org.microg.gms.gcm.GcmConstants.ACTION_INSTANCE_ID;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_FROM;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_GSF_INTENT;
-
-/**
- * Base class to handle Instance ID service notifications on token
- * refresh.
- *
- * Any app using Instance ID or GCM must include a class extending
- * InstanceIDListenerService and implement {@link com.google.android.gms.iid.InstanceIDListenerService#onTokenRefresh()}.
- *
- * Include the following in the manifest:
- *
- *
- *
- *
- *
- *
- * Do not export this service. Instead, keep it private to prevent other apps
- * accessing your service.
- */
-public class InstanceIDListenerService extends Service {
-
- private BroadcastReceiver registrationReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- handleIntent(intent);
- stop();
- }
- };
- private MessengerCompat messengerCompat = new MessengerCompat(new Handler(Looper.getMainLooper()) {
- @Override
- public void handleMessage(Message msg) {
- handleIntent((Intent) msg.obj);
- }
- });
-
- private int counter = 0;
- private int startId = -1;
-
- private void handleIntent(Intent intent) {
- // TODO
- }
-
- public IBinder onBind(Intent intent) {
- if (intent != null && ACTION_INSTANCE_ID.equals(intent.getAction())) {
- return messengerCompat.getBinder();
- }
- return null;
- }
-
- public void onCreate() {
- IntentFilter filter = new IntentFilter(ACTION_C2DM_REGISTRATION);
- filter.addCategory(getPackageName());
- registerReceiver(registrationReceiver, filter);
- }
-
- public void onDestroy() {
- unregisterReceiver(registrationReceiver);
- }
-
- public int onStartCommand(Intent intent, int flags, int startId) {
- synchronized (this) {
- this.counter++;
- if (startId > this.startId) this.startId = startId;
- }
- try {
- if (intent != null) {
- if (ACTION_INSTANCE_ID.equals(intent.getAction()) && intent.hasExtra(EXTRA_GSF_INTENT)) {
- startService((Intent) intent.getParcelableExtra(EXTRA_GSF_INTENT));
- return START_STICKY;
- }
-
- handleIntent(intent);
-
- if (intent.hasExtra(EXTRA_FROM))
- WakefulBroadcastReceiver.completeWakefulIntent(intent);
- }
- } finally {
- stop();
- }
- return START_NOT_STICKY;
- }
-
- /**
- * Called when the system determines that the tokens need to be refreshed. The application
- * should call getToken() and send the tokens to all application servers.
- *
- * This will not be called very frequently, it is needed for key rotation and to handle special
- * cases.
- *
- * The system will throttle the refresh event across all devices to avoid overloading
- * application servers with token updates.
- */
- public void onTokenRefresh() {
- // To be overwritten
- }
-
- private void stop() {
- synchronized (this) {
- counter--;
- if (counter <= 0) {
- stopSelf(startId);
- }
- }
- }
-
-}
\ No newline at end of file
diff --git a/play-services-iid/src/main/java/org/microg/gms/iid/InstanceIdRpc.java b/play-services-iid/src/main/java/org/microg/gms/iid/InstanceIdRpc.java
deleted file mode 100644
index 77f65f5e..00000000
--- a/play-services-iid/src/main/java/org/microg/gms/iid/InstanceIdRpc.java
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * Copyright (C) 2013-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.iid;
-
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.ConditionVariable;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.text.TextUtils;
-import android.util.Base64;
-import android.util.Log;
-
-import com.google.android.gms.iid.InstanceID;
-import com.google.android.gms.iid.MessengerCompat;
-
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.security.GeneralSecurityException;
-import java.security.KeyPair;
-import java.security.PrivateKey;
-import java.security.Signature;
-import java.security.interfaces.RSAPrivateKey;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Random;
-
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static com.google.android.gms.iid.InstanceID.ERROR_BACKOFF;
-import static com.google.android.gms.iid.InstanceID.ERROR_MISSING_INSTANCEID_SERVICE;
-import static com.google.android.gms.iid.InstanceID.ERROR_SERVICE_NOT_AVAILABLE;
-import static com.google.android.gms.iid.InstanceID.ERROR_TIMEOUT;
-import static org.microg.gms.common.Constants.GMS_PACKAGE_NAME;
-import static org.microg.gms.common.Constants.GSF_PACKAGE_NAME;
-import static org.microg.gms.common.Constants.MAX_REFERENCE_VERSION;
-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_INSTANCE_ID;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_APP;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_APP_ID;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_APP_VERSION_CODE;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_APP_VERSION_NAME;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_CLIENT_VERSION;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_ERROR;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_GMS_VERSION;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_GSF_INTENT;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_IS_MESSENGER2;
-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_OS_VERSION;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_PUBLIC_KEY;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_REGISTRATION_ID;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_SIGNATURE;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_UNREGISTERED;
-import static org.microg.gms.gcm.GcmConstants.EXTRA_USE_GSF;
-import static org.microg.gms.gcm.GcmConstants.PERMISSION_RECEIVE;
-
-public class InstanceIdRpc {
- private static final String TAG = "InstanceID/Rpc";
-
- private static final int BLOCKING_WAIT_TIME = 30000;
-
- private static String iidPackageName;
- private static int lastRequestId;
- private static int retryCount;
- private static Map blockingResponses = new HashMap();
-
- private long nextAttempt;
- private int interval;
- private Context context;
- private PendingIntent selfAuthToken;
- private Messenger messenger;
- private Messenger myMessenger;
- private MessengerCompat messengerCompat;
-
- public InstanceIdRpc(Context context) {
- this.context = context;
- }
-
- public static String getIidPackageName(Context context) {
- if (iidPackageName != null) {
- return iidPackageName;
- }
- PackageManager packageManager = context.getPackageManager();
- for (ResolveInfo resolveInfo : packageManager.queryIntentServices(new Intent(ACTION_C2DM_REGISTER), 0)) {
- if (packageManager.checkPermission(PERMISSION_RECEIVE, resolveInfo.serviceInfo.packageName) == PERMISSION_GRANTED) {
- return iidPackageName = resolveInfo.serviceInfo.packageName;
- }
- }
- try {
- ApplicationInfo appInfo = packageManager.getApplicationInfo(GMS_PACKAGE_NAME, 0);
- return iidPackageName = appInfo.packageName;
- } catch (PackageManager.NameNotFoundException ignored) {
- }
- try {
- ApplicationInfo appInfo = packageManager.getApplicationInfo(GSF_PACKAGE_NAME, 0);
- return iidPackageName = appInfo.packageName;
- } catch (PackageManager.NameNotFoundException ex3) {
- Log.w(TAG, "Both Google Play Services and legacy GSF package are missing");
- return null;
- }
- }
-
- private static int getGmsVersionCode(final Context context) {
- final PackageManager packageManager = context.getPackageManager();
- try {
- return packageManager.getPackageInfo(getIidPackageName(context), 0).versionCode;
- } catch (PackageManager.NameNotFoundException ex) {
- return -1;
- }
- }
-
- private static int getSelfVersionCode(final Context context) {
- try {
- return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode;
- } catch (PackageManager.NameNotFoundException neverHappens) {
- return 0;
- }
- }
-
- private static String getSelfVersionName(final Context context) {
- try {
- return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
- } catch (PackageManager.NameNotFoundException neverHappens) {
- return null;
- }
- }
-
- void initialize() {
- if (myMessenger != null) return;
- getIidPackageName(context);
- myMessenger = new Messenger(new Handler(Looper.getMainLooper()) {
- @Override
- public void handleMessage(Message msg) {
- if (msg == null) {
- return;
- }
- if (msg.obj instanceof Intent) {
- Intent intent = (Intent) msg.obj;
- intent.setExtrasClassLoader(MessengerCompat.class.getClassLoader());
- if (intent.hasExtra(EXTRA_MESSENGER)) {
- Parcelable messengerCandidate = intent.getParcelableExtra(EXTRA_MESSENGER);
- if (messengerCandidate instanceof MessengerCompat) {
- messengerCompat = (MessengerCompat) messengerCandidate;
- } else if (messengerCandidate instanceof Messenger) {
- messenger = (Messenger) messengerCandidate;
- }
- }
- handleResponseInternal(intent);
- } else {
- Log.w(TAG, "Dropping invalid message");
- }
- }
- });
- }
-
- public void handleResponseInternal(Intent resultIntent) {
- if (resultIntent == null) return;
- if (!ACTION_C2DM_REGISTRATION.equals(resultIntent.getAction()) && !ACTION_INSTANCE_ID.equals(resultIntent.getAction()))
- return;
- String result = resultIntent.getStringExtra(EXTRA_REGISTRATION_ID);
- if (result == null) result = resultIntent.getStringExtra(EXTRA_UNREGISTERED);
- if (result == null) {
- handleError(resultIntent);
- return;
- }
- retryCount = 0;
- nextAttempt = 0;
- interval = 0;
-
- String requestId = null;
- if (result.startsWith("|")) {
- // parse structured response
- String[] split = result.split("\\|");
- if (!"ID".equals(split[1])) {
- Log.w(TAG, "Unexpected structured response " + result);
- }
- requestId = split[2];
- if (split.length > 4) {
- if ("SYNC".equals(split[3])) {
- // TODO: sync
- } else if("RST".equals(split[3])) {
- // TODO: rst
- resultIntent.removeExtra(EXTRA_REGISTRATION_ID);
- return;
- }
- }
- result = split[split.length-1];
- if (result.startsWith(":"))
- result = result.substring(1);
- resultIntent.putExtra(EXTRA_REGISTRATION_ID, result);
- }
- setResponse(requestId, resultIntent);
- }
-
- private void handleError(Intent resultIntent) {
- String error = resultIntent.getStringExtra("error");
- if (error == null) return;
- String requestId = null;
- if (error.startsWith("|")) {
- // parse structured error message
- String[] split = error.split("\\|");
- if (!"ID".equals(split[1])) {
- Log.w(TAG, "Unexpected structured response " + error);
- }
- if (split.length > 2) {
- requestId = split[2];
- error = split[3];
- if (error.startsWith(":"))
- error = error.substring(1);
- } else {
- error = "UNKNOWN";
- }
- resultIntent.putExtra("error", error);
- }
- setResponse(requestId, resultIntent);
- long retryAfter = resultIntent.getLongExtra("Retry-After", 0);
- if (retryAfter > 0) {
- interval = (int) (retryAfter * 1000);
- nextAttempt = SystemClock.elapsedRealtime() + interval;
- Log.d(TAG, "Server requested retry delay: " + interval);
- } else if (ERROR_SERVICE_NOT_AVAILABLE.equals(error) || "AUTHENTICATION_FAILED".equals(error)
- && GSF_PACKAGE_NAME.equals(getIidPackageName(context))) {
- retryCount++;
- if (retryCount < 3) return;
- if (retryCount == 3) interval = 1000 + new Random().nextInt(1000);
- interval = interval * 2;
- nextAttempt = SystemClock.elapsedRealtime() + interval;
- Log.d(TAG, "Setting retry delay to " + interval);
- }
- }
-
- private synchronized PendingIntent getSelfAuthToken() {
- if (selfAuthToken == null) {
- Intent intent = new Intent();
- intent.setPackage("com.google.example.invalidpackage");
- selfAuthToken = PendingIntent.getBroadcast(context, 0, intent, 0);
- }
- return selfAuthToken;
- }
-
- private static synchronized String getRequestId() {
- return Integer.toString(lastRequestId++);
- }
-
- private void sendRegisterMessage(Bundle data, KeyPair keyPair, String requestId) throws IOException {
- long elapsedRealtime = SystemClock.elapsedRealtime();
- if (nextAttempt != 0 && elapsedRealtime <= nextAttempt) {
- Log.w(TAG, "Had to wait for " + interval + ", that's still " + (nextAttempt - elapsedRealtime));
- throw new IOException(ERROR_BACKOFF);
- }
- initialize();
- if (iidPackageName == null) {
- throw new IOException(ERROR_MISSING_INSTANCEID_SERVICE);
- }
- Intent intent = new Intent(ACTION_C2DM_REGISTER);
- intent.setPackage(iidPackageName);
- data.putString(EXTRA_GMS_VERSION, Integer.toString(getGmsVersionCode(context)));
- data.putString(EXTRA_OS_VERSION, Integer.toString(Build.VERSION.SDK_INT));
- data.putString(EXTRA_APP_VERSION_CODE, Integer.toString(getSelfVersionCode(context)));
- data.putString(EXTRA_APP_VERSION_NAME, getSelfVersionName(context));
- data.putString(EXTRA_CLIENT_VERSION, "iid-" + MAX_REFERENCE_VERSION);
- data.putString(EXTRA_APP_ID, InstanceID.sha1KeyPair(keyPair));
- String pub = base64encode(keyPair.getPublic().getEncoded());
- data.putString(EXTRA_PUBLIC_KEY, pub);
- data.putString(EXTRA_SIGNATURE, sign(keyPair, context.getPackageName(), pub));
- intent.putExtras(data);
- intent.putExtra(EXTRA_APP, getSelfAuthToken());
- sendRequest(intent, requestId);
- }
-
- private static String sign(KeyPair keyPair, String... payload) {
- byte[] bytes;
- try {
- bytes = TextUtils.join("\n", payload).getBytes("UTF-8");
- } catch (UnsupportedEncodingException e) {
- Log.e(TAG, "Unable to encode", e);
- return null;
- }
- PrivateKey privateKey = keyPair.getPrivate();
- try {
- Signature signature = Signature.getInstance(privateKey instanceof RSAPrivateKey ? "SHA256withRSA" : "SHA256withECDSA");
- signature.initSign(privateKey);
- signature.update(bytes);
- return base64encode(signature.sign());
- } catch (GeneralSecurityException e) {
- Log.e(TAG, "Unable to sign", e);
- return null;
- }
- }
-
- private static String base64encode(byte[] bytes) {
- return Base64.encodeToString(bytes, Base64.URL_SAFE + Base64.NO_PADDING + Base64.NO_WRAP);
- }
-
- private void sendRequest(Intent intent, String requestId) {
- intent.putExtra(EXTRA_KID, "|ID|" + requestId + "|");
- intent.putExtra("X-" + EXTRA_KID, "|ID|" + requestId + "|");
- Log.d(TAG, "Sending " + intent.getExtras());
- if (messenger != null) {
- intent.putExtra(EXTRA_MESSENGER, myMessenger);
- Message msg = Message.obtain();
- msg.obj = intent;
- try {
- messenger.send(msg);
- return;
- } catch (RemoteException e) {
- Log.d(TAG, "Messenger failed, falling back to service");
- }
- }
-
- boolean useGsf = iidPackageName.endsWith(".gsf");
- if (intent.hasExtra(EXTRA_USE_GSF))
- useGsf = "1".equals(intent.getStringExtra(EXTRA_USE_GSF));
-
- if (useGsf) {
- Intent holder = new Intent(ACTION_INSTANCE_ID);
- holder.setPackage(context.getPackageName());
- holder.putExtra(EXTRA_GSF_INTENT, intent);
- context.startService(holder);
- } else {
- intent.putExtra(EXTRA_MESSENGER, myMessenger);
- intent.putExtra(EXTRA_IS_MESSENGER2, "1");
- if (messengerCompat != null) {
- Message msg = Message.obtain();
- msg.obj = intent;
- try {
- messengerCompat.send(msg);
- return;
- } catch (RemoteException e) {
- Log.d(TAG, "Messenger failed, falling back to service");
- }
- }
- context.startService(intent);
- }
- }
-
- public Intent sendRegisterMessageBlocking(Bundle data, KeyPair keyPair) throws IOException {
- Intent intent = sendRegisterMessageBlockingInternal(data, keyPair);
- if (intent != null && intent.hasExtra(EXTRA_MESSENGER)) {
- // Now with a messenger
- intent = sendRegisterMessageBlockingInternal(data, keyPair);
- }
- return intent;
- }
-
- private Intent sendRegisterMessageBlockingInternal(Bundle data, KeyPair keyPair) throws IOException {
- ConditionVariable cv = new ConditionVariable();
- String requestId = getRequestId();
- synchronized (InstanceIdRpc.class) {
- blockingResponses.put(requestId, cv);
- }
-
- sendRegisterMessage(data, keyPair, requestId);
-
- cv.block(BLOCKING_WAIT_TIME);
- synchronized (InstanceIdRpc.class) {
- Object res = blockingResponses.remove(requestId);
- if (res instanceof Intent) {
- return (Intent) res;
- } else if (res instanceof String) {
- throw new IOException((String) res);
- }
- Log.w(TAG, "No response " + res);
- throw new IOException(ERROR_TIMEOUT);
- }
- }
-
- public String handleRegisterMessageResult(Intent resultIntent) throws IOException {
- if (resultIntent == null) throw new IOException(ERROR_SERVICE_NOT_AVAILABLE);
- String result = resultIntent.getStringExtra(EXTRA_REGISTRATION_ID);
- if (result == null) result = resultIntent.getStringExtra(EXTRA_UNREGISTERED);
- if (result != null) return result;
- result = resultIntent.getStringExtra(EXTRA_ERROR);
- throw new IOException(result != null ? result : ERROR_SERVICE_NOT_AVAILABLE);
- }
-
- private void setResponse(String requestId, Object response) {
- if (requestId == null) {
- for (String r : blockingResponses.keySet()) {
- setResponse(r, response);
- }
- }
- Object old = blockingResponses.get(requestId);
- blockingResponses.put(requestId, response);
- if (old instanceof ConditionVariable) {
- ((ConditionVariable) old).open();
- } else if (old instanceof Messenger) {
- Message msg = Message.obtain();
- msg.obj = response;
- try {
- ((Messenger) old).send(msg);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to send response", e);
- }
- }
- }
-}
diff --git a/play-services-iid/src/main/java/org/microg/gms/iid/InstanceIdStore.java b/play-services-iid/src/main/java/org/microg/gms/iid/InstanceIdStore.java
deleted file mode 100644
index 65778936..00000000
--- a/play-services-iid/src/main/java/org/microg/gms/iid/InstanceIdStore.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2013-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.iid;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.util.Base64;
-import android.util.Log;
-
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.security.spec.X509EncodedKeySpec;
-
-public class InstanceIdStore {
- private static final String TAG = "InstanceID/Store";
- private static final String PREF_NAME = "com.google.android.gms.appid";
-
- private Context context;
- private SharedPreferences sharedPreferences;
-
- public InstanceIdStore(Context context) {
- this.context = context;
- this.sharedPreferences = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
- }
-
- public synchronized String get(String key) {
- return sharedPreferences.getString(key, null);
- }
-
- public String get(String subtype, String key) {
- return get(subtype + "|S|" + key);
- }
-
- public String get(String subtype, String authorizedEntity, String scope) {
- return get(subtype + "|T|" + authorizedEntity + "|" + scope);
- }
-
- public KeyPair getKeyPair(String subtype) {
- String pub = get(subtype, "|P|");
- String priv = get(subtype, "|K|");
- if (pub == null || priv == null) {
- return null;
- }
- try {
- byte[] pubKey = Base64.decode(pub, Base64.URL_SAFE);
- byte[] privKey = Base64.decode(priv, Base64.URL_SAFE);
- KeyFactory rsaFactory = KeyFactory.getInstance("RSA");
- return new KeyPair(rsaFactory.generatePublic(new X509EncodedKeySpec(pubKey)), rsaFactory.generatePrivate(new PKCS8EncodedKeySpec(privKey)));
- } catch (Exception e) {
- Log.w(TAG, "Invalid key stored " + e);
- return null;
- }
- }
-
- public synchronized void put(String key, String value) {
- SharedPreferences.Editor editor = sharedPreferences.edit();
- editor.putString(key, value);
- editor.apply();
- }
-
- public void put(String subtype, String key, String value) {
- put(subtype + "|S|" + key, value);
- }
-
- public void put(String subtype, String authorizedEntity, String scope, String value) {
- put(subtype + "|T|" + authorizedEntity + "|" + scope, value);
- }
-
- public synchronized void put(String subtype, KeyPair keyPair, long timestamp) {
- put(subtype, "|P|", Base64.encodeToString(keyPair.getPublic().getEncoded(), Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING));
- put(subtype, "|K|", Base64.encodeToString(keyPair.getPrivate().getEncoded(), Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING));
- put(subtype, "cre", Long.toString(timestamp));
- }
-
- public synchronized void delete() {
- SharedPreferences.Editor editor = sharedPreferences.edit();
- editor.clear();
- editor.apply();
- }
-
- public synchronized void delete(String prefix) {
- SharedPreferences.Editor editor = sharedPreferences.edit();
- for (String key : sharedPreferences.getAll().keySet()) {
- if (key.startsWith(prefix)) {
- editor.remove(key);
- }
- }
- editor.apply();
- }
-
- public synchronized void delete(String subtype, String authorizedEntity, String scope) {
- SharedPreferences.Editor editor = sharedPreferences.edit();
- editor.remove(subtype + "|T|" + authorizedEntity + "|" + scope);
- editor.apply();
- }
-}
diff --git a/play-services/build.gradle b/play-services/build.gradle
deleted file mode 100644
index 488c0632..00000000
--- a/play-services/build.gradle
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2013-2015 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.
- */
-
-apply plugin: 'com.android.library'
-
-String getMyVersionName() {
- def stdout = new ByteArrayOutputStream()
- if (rootProject.file("gradlew").exists())
- exec { commandLine 'git', 'describe', '--tags', '--always', '--dirty'; standardOutput = stdout }
- else // automatic build system, don't tag dirty
- exec { commandLine 'git', 'describe', '--tags', '--always'; standardOutput = stdout }
- return stdout.toString().trim().substring(1)
-}
-
-android {
- compileSdkVersion androidCompileSdk()
- buildToolsVersion "$androidBuildVersionTools"
-
- defaultConfig {
- versionName getMyVersionName()
- minSdkVersion androidMinSdk()
- targetSdkVersion androidTargetSdk()
- }
-
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
-
- lintOptions {
- disable 'InvalidPackage'
- }
-}
-
-dependencies {
- api project(':play-services-base')
- api project(':play-services-cast')
- api project(':play-services-gcm')
- api project(':play-services-location')
- api project(':play-services-wearable')
-}
diff --git a/play-services/gradle.properties b/play-services/gradle.properties
deleted file mode 100644
index b8e4412a..00000000
--- a/play-services/gradle.properties
+++ /dev/null
@@ -1,34 +0,0 @@
-#
-# Copyright 2013-2016 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.
-#
-
-POM_NAME=Play Services Library
-POM_DESCRIPTION=The whole package of Play Services libraries. Use play-services-* artifacts if you only need certain parts
-
-POM_PACKAGING=aar
-
-POM_URL=https://github.com/microg/android_external_GmsLib
-
-POM_SCM_URL=https://github.com/microg/android_external_GmsLib
-POM_SCM_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
-POM_SCM_DEV_CONNECTION=scm:git@github.com:microg/android_external_GmsLib.git
-
-POM_LICENCE_NAME=The Apache Software License, Version 2.0
-POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
-POM_LICENCE_DIST=repo
-
-POM_DEVELOPER_ID=mar-v-in
-POM_DEVELOPER_NAME=Marvin W
-
diff --git a/play-services/src/main/AndroidManifest.xml b/play-services/src/main/AndroidManifest.xml
deleted file mode 100644
index a18fdb94..00000000
--- a/play-services/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
-
From 03e0051d63279170f06abb1a8676decf67535829 Mon Sep 17 00:00:00 2001
From: X1nto
Date: Mon, 20 Jul 2020 14:07:15 +0400
Subject: [PATCH 3/3] changed launcher icon and removed old microg icons
---
.../gms/common/ForegroundServiceContext.java | 3 +--
.../src/main/AndroidManifest.xml | 7 ++++---
.../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 5612 -> 5619 bytes
.../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 2962 -> 2806 bytes
.../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 7539 -> 7815 bytes
.../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 14450 -> 12421 bytes
.../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 19647 -> 16984 bytes
.../src/main/res/values-de/strings.xml | 1 -
.../src/main/res/values-es/strings.xml | 1 -
.../src/main/res/values-fr/strings.xml | 1 -
.../src/main/res/values-pl/strings.xml | 1 -
.../src/main/res/values-pt-rBR/strings.xml | 1 -
.../src/main/res/values-ro/strings.xml | 1 -
.../src/main/res/values-ru/strings.xml | 1 -
.../src/main/res/values-sr/strings.xml | 1 -
.../src/main/res/values-uk/strings.xml | 1 -
.../src/main/res/values-zh-rTW/strings.xml | 1 -
.../src/main/res/values/strings.xml | 1 -
.../src/main/res/xml/authenticator.xml | 7 ++++---
19 files changed, 9 insertions(+), 19 deletions(-)
diff --git a/play-services-base-core/src/main/java/org/microg/gms/common/ForegroundServiceContext.java b/play-services-base-core/src/main/java/org/microg/gms/common/ForegroundServiceContext.java
index 539f4ed4..d21dd612 100644
--- a/play-services-base-core/src/main/java/org/microg/gms/common/ForegroundServiceContext.java
+++ b/play-services-base-core/src/main/java/org/microg/gms/common/ForegroundServiceContext.java
@@ -67,7 +67,7 @@ public class ForegroundServiceContext extends ContextWrapper {
@RequiresApi(api = Build.VERSION_CODES.O)
private static Notification buildForegroundNotification(Context context) {
- NotificationChannel channel = new NotificationChannel("foreground-service", "Foreground Service", NotificationManager.IMPORTANCE_NONE);
+ NotificationChannel channel = new NotificationChannel("foreground-service", "Foreground Service", NotificationManager.IMPORTANCE_MIN);
channel.setShowBadge(false);
channel.setLockscreenVisibility(0);
channel.setVibrationPattern(new long[0]);
@@ -77,7 +77,6 @@ public class ForegroundServiceContext extends ContextWrapper {
.setContentTitle("Running in background")
.setContentText("This notification ensures, that microG does not get killed.")
.setSmallIcon(R.drawable.ic_foreground_notification)
- .setColor(0xFFFFFF)
.build();
}
}
diff --git a/play-services-core/src/main/AndroidManifest.xml b/play-services-core/src/main/AndroidManifest.xml
index 093a47b5..375af576 100644
--- a/play-services-core/src/main/AndroidManifest.xml
+++ b/play-services-core/src/main/AndroidManifest.xml
@@ -34,7 +34,8 @@
+ android:icon="@mipmap/ic_launcher"
+ android:label="Vanced microG"/>
+ android:label="Vanced microG">
@@ -276,7 +277,7 @@
diff --git a/play-services-core/src/main/res/mipmap-hdpi/ic_launcher.png b/play-services-core/src/main/res/mipmap-hdpi/ic_launcher.png
index bbac7d455a62b53b1a01be88e97e8cb7e397bb88..25d30beaa772d49a670026ebacc06bb04163f352 100644
GIT binary patch
literal 5619
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
Z`#;9Ty}~`?#{d8T002ovPDHLkV1n8)@SFeu
literal 7539
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