mirror of
https://github.com/YTVanced/VancedMicroG
synced 2024-11-24 12:15:12 +00:00
Complete play-services-tasks implementation
This commit is contained in:
parent
0522ed41fb
commit
aae974ec5b
29 changed files with 1071 additions and 132 deletions
|
@ -1,17 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2013-2015 microG Project Team
|
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
*
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
* 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'
|
apply plugin: 'com.android.library'
|
||||||
|
|
|
@ -1,18 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
<!--
|
||||||
~ Copyright (C) 2013-2017 microG Project Team
|
~ SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
~
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
~ 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.
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<manifest package="org.microg.gms.tasks"/>
|
<manifest package="org.microg.gms.tasks"/>
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.0
|
||||||
|
* Notice: Portions of this file are reproduced from work created and shared by Google and used
|
||||||
|
* according to terms described in the Creative Commons 4.0 Attribution License.
|
||||||
|
* See https://developers.google.com/readme/policies for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.android.gms.tasks;
|
||||||
|
|
||||||
|
import org.microg.gms.common.PublicApi;
|
||||||
|
|
||||||
|
@PublicApi
|
||||||
|
public abstract class CancellationToken {
|
||||||
|
/**
|
||||||
|
* Checks if cancellation has been requested from the {@link CancellationTokenSource}.
|
||||||
|
*
|
||||||
|
* @return {@code true} if cancellation is requested, {@code false} otherwise
|
||||||
|
*/
|
||||||
|
public abstract boolean isCancellationRequested();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an {@link OnTokenCanceledListener} to this {@link CancellationToken}.
|
||||||
|
*
|
||||||
|
* @param listener the listener that will fire once the cancellation request succeeds.
|
||||||
|
*/
|
||||||
|
public abstract CancellationToken onCanceledRequested(OnTokenCanceledListener listener);
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.0
|
||||||
|
* Notice: Portions of this file are reproduced from work created and shared by Google and used
|
||||||
|
* according to terms described in the Creative Commons 4.0 Attribution License.
|
||||||
|
* See https://developers.google.com/readme/policies for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.android.gms.tasks;
|
||||||
|
|
||||||
|
import org.microg.gms.common.PublicApi;
|
||||||
|
import org.microg.gms.tasks.CancellationTokenImpl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link CancellationToken} or cancels one that has already created. There is a 1:1 {@link CancellationTokenSource} to {@link CancellationToken} relationship.
|
||||||
|
* <p>
|
||||||
|
* To create a {@link CancellationToken}, create a {@link CancellationTokenSource} first and then call {@link #getToken()} to get the {@link CancellationToken} for this {@link CancellationTokenSource}.
|
||||||
|
*
|
||||||
|
* @see CancellationToken
|
||||||
|
*/
|
||||||
|
@PublicApi
|
||||||
|
public class CancellationTokenSource {
|
||||||
|
private CancellationTokenImpl token = new CancellationTokenImpl();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link CancellationTokenSource} instance.
|
||||||
|
*/
|
||||||
|
public CancellationTokenSource() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels the {@link CancellationToken} if cancellation has not been requested yet.
|
||||||
|
*/
|
||||||
|
public void cancel() {
|
||||||
|
token.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the {@link CancellationToken} for this {@link CancellationTokenSource}.
|
||||||
|
*
|
||||||
|
* @return the {@link CancellationToken} that can be passed to asynchronous {@link Task} to cancel the Task.
|
||||||
|
*/
|
||||||
|
public CancellationToken getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,17 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2013-2017 microG Project Team
|
* SPDX-FileCopyrightText: 2016, microG Project Team
|
||||||
*
|
* SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.0
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Notice: Portions of this file are reproduced from work created and shared by Google and used
|
||||||
* you may not use this file except in compliance with the License.
|
* according to terms described in the Creative Commons 4.0 Attribution License.
|
||||||
* You may obtain a copy of the License at
|
* See https://developers.google.com/readme/policies for details.
|
||||||
*
|
|
||||||
* 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.tasks;
|
package com.google.android.gms.tasks;
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.0
|
||||||
|
* Notice: Portions of this file are reproduced from work created and shared by Google and used
|
||||||
|
* according to terms described in the Creative Commons 4.0 Attribution License.
|
||||||
|
* See https://developers.google.com/readme/policies for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.android.gms.tasks;
|
||||||
|
|
||||||
|
import org.microg.gms.common.PublicApi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An exception indicating that something attempted to set a result, exception, or cancellation on a {@link Task} that was already completed.
|
||||||
|
*/
|
||||||
|
@PublicApi
|
||||||
|
public class DuplicateTaskCompletionException extends IllegalStateException {
|
||||||
|
|
||||||
|
private DuplicateTaskCompletionException(String s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a DuplicateTaskCompletionException from a {@link Task}.
|
||||||
|
*
|
||||||
|
* The {@link Task} must be complete.
|
||||||
|
*/
|
||||||
|
public static DuplicateTaskCompletionException of(Task<?> task) {
|
||||||
|
if (!task.isComplete()) throw new IllegalStateException("Task is not yet completed");
|
||||||
|
return new DuplicateTaskCompletionException("Task is already completed");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.0
|
||||||
|
* Notice: Portions of this file are reproduced from work created and shared by Google and used
|
||||||
|
* according to terms described in the Creative Commons 4.0 Attribution License.
|
||||||
|
* See https://developers.google.com/readme/policies for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.android.gms.tasks;
|
||||||
|
|
||||||
|
import org.microg.gms.common.PublicApi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listener called when a {@link Task} is canceled.
|
||||||
|
*/
|
||||||
|
@PublicApi
|
||||||
|
public interface OnCanceledListener {
|
||||||
|
/**
|
||||||
|
* Called when the Task is canceled successfully.
|
||||||
|
*/
|
||||||
|
public abstract void onCanceled();
|
||||||
|
}
|
|
@ -1,17 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2013-2017 microG Project Team
|
* SPDX-FileCopyrightText: 2016, microG Project Team
|
||||||
*
|
* SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.0
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Notice: Portions of this file are reproduced from work created and shared by Google and used
|
||||||
* you may not use this file except in compliance with the License.
|
* according to terms described in the Creative Commons 4.0 Attribution License.
|
||||||
* You may obtain a copy of the License at
|
* See https://developers.google.com/readme/policies for details.
|
||||||
*
|
|
||||||
* 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.tasks;
|
package com.google.android.gms.tasks;
|
||||||
|
|
|
@ -1,17 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2013-2017 microG Project Team
|
* SPDX-FileCopyrightText: 2016, microG Project Team
|
||||||
*
|
* SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.0
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Notice: Portions of this file are reproduced from work created and shared by Google and used
|
||||||
* you may not use this file except in compliance with the License.
|
* according to terms described in the Creative Commons 4.0 Attribution License.
|
||||||
* You may obtain a copy of the License at
|
* See https://developers.google.com/readme/policies for details.
|
||||||
*
|
|
||||||
* 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.tasks;
|
package com.google.android.gms.tasks;
|
||||||
|
|
|
@ -1,17 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2013-2017 microG Project Team
|
* SPDX-FileCopyrightText: 2016, microG Project Team
|
||||||
*
|
* SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.0
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Notice: Portions of this file are reproduced from work created and shared by Google and used
|
||||||
* you may not use this file except in compliance with the License.
|
* according to terms described in the Creative Commons 4.0 Attribution License.
|
||||||
* You may obtain a copy of the License at
|
* See https://developers.google.com/readme/policies for details.
|
||||||
*
|
|
||||||
* 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.tasks;
|
package com.google.android.gms.tasks;
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.0
|
||||||
|
* Notice: Portions of this file are reproduced from work created and shared by Google and used
|
||||||
|
* according to terms described in the Creative Commons 4.0 Attribution License.
|
||||||
|
* See https://developers.google.com/readme/policies for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.android.gms.tasks;
|
||||||
|
|
||||||
|
import org.microg.gms.common.PublicApi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listener called when a {@link CancellationToken} is canceled successfully.
|
||||||
|
*
|
||||||
|
* @see CancellationToken#onCanceledRequested(OnTokenCanceledListener)
|
||||||
|
*/
|
||||||
|
@PublicApi
|
||||||
|
public interface OnTokenCanceledListener {
|
||||||
|
/**
|
||||||
|
* Called when the {@link CancellationToken} is canceled successfully.
|
||||||
|
*/
|
||||||
|
void onCanceled();
|
||||||
|
}
|
|
@ -1,17 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2013-2017 microG Project Team
|
* SPDX-FileCopyrightText: 2016, microG Project Team
|
||||||
*
|
* SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.0
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Notice: Portions of this file are reproduced from work created and shared by Google and used
|
||||||
* you may not use this file except in compliance with the License.
|
* according to terms described in the Creative Commons 4.0 Attribution License.
|
||||||
* You may obtain a copy of the License at
|
* See https://developers.google.com/readme/policies for details.
|
||||||
*
|
|
||||||
* 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.tasks;
|
package com.google.android.gms.tasks;
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.0
|
||||||
|
* Notice: Portions of this file are reproduced from work created and shared by Google and used
|
||||||
|
* according to terms described in the Creative Commons 4.0 Attribution License.
|
||||||
|
* See https://developers.google.com/readme/policies for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.android.gms.tasks;
|
||||||
|
|
||||||
|
import org.microg.gms.common.PublicApi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A function that is called to continue execution then a {@link Task} succeeds.
|
||||||
|
* @see Task#onSuccessTask
|
||||||
|
*/
|
||||||
|
@PublicApi
|
||||||
|
public interface SuccessContinuation<TResult, TContinuationResult> {
|
||||||
|
/**
|
||||||
|
* Returns the result of applying this SuccessContinuation to Task.
|
||||||
|
* <p>
|
||||||
|
* The SuccessContinuation only happens then the Task is successful. If the previous Task fails, the onSuccessTask continuation will be skipped and failure listeners will be invoked.
|
||||||
|
*
|
||||||
|
* @param result the result of completed Task
|
||||||
|
* @throws Exception if the result couldn't be produced
|
||||||
|
*/
|
||||||
|
Task<TContinuationResult> then(TResult result) throws Exception;
|
||||||
|
}
|
|
@ -1,17 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2013-2017 microG Project Team
|
* SPDX-FileCopyrightText: 2016, microG Project Team
|
||||||
*
|
* SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.0
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Notice: Portions of this file are reproduced from work created and shared by Google and used
|
||||||
* you may not use this file except in compliance with the License.
|
* according to terms described in the Creative Commons 4.0 Attribution License.
|
||||||
* You may obtain a copy of the License at
|
* See https://developers.google.com/readme/policies for details.
|
||||||
*
|
|
||||||
* 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.tasks;
|
package com.google.android.gms.tasks;
|
||||||
|
@ -31,6 +23,42 @@ public abstract class Task<TResult> {
|
||||||
public Task() {
|
public Task() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a listener that is called if the Task is canceled.
|
||||||
|
* <p>
|
||||||
|
* The listener will be called on main application thread. If the Task has already been canceled, a call to the listener will be immediately scheduled. If multiple listeners are added, they will be called in the order in which they were added.
|
||||||
|
*
|
||||||
|
* @return this Task
|
||||||
|
*/
|
||||||
|
public Task<TResult> addOnCanceledListener(OnCanceledListener listener) {
|
||||||
|
throw new UnsupportedOperationException("addOnCanceledListener is not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a listener that is called if the Task is canceled.
|
||||||
|
* <p>
|
||||||
|
* If the Task has already been canceled, a call to the listener will be immediately scheduled. If multiple listeners are added, they will be called in the order in which they were added.
|
||||||
|
*
|
||||||
|
* @param executor the executor to use to call the listener
|
||||||
|
* @return this Task
|
||||||
|
*/
|
||||||
|
public Task<TResult> addOnCanceledListener(Executor executor, OnCanceledListener listener) {
|
||||||
|
throw new UnsupportedOperationException("addOnCanceledListener is not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an Activity-scoped listener that is called if the Task is canceled.
|
||||||
|
* <p>
|
||||||
|
* The listener will be called on main application thread. If the Task has already been canceled, a call to the listener will be immediately scheduled. If multiple listeners are added, they will be called in the order in which they were added.
|
||||||
|
* <p>
|
||||||
|
* The listener will be automatically removed during {@link Activity#onStop()}.
|
||||||
|
*
|
||||||
|
* @return this Task
|
||||||
|
*/
|
||||||
|
public Task<TResult> addOnCanceledListener(Activity activity, OnCanceledListener listener) {
|
||||||
|
throw new UnsupportedOperationException("addOnCanceledListener is not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a listener that is called when the Task completes.
|
* Adds a listener that is called when the Task completes.
|
||||||
* <p/>
|
* <p/>
|
||||||
|
@ -184,7 +212,7 @@ public abstract class Task<TResult> {
|
||||||
* @param executor the executor to use to call the Continuation
|
* @param executor the executor to use to call the Continuation
|
||||||
* @see Continuation#then(Task)
|
* @see Continuation#then(Task)
|
||||||
*/
|
*/
|
||||||
public <TContinuationResult> Task<TContinuationResult> continueWithTask(Executor executor, Continuation<TResult, Task<TContinuationResult>> var2) {
|
public <TContinuationResult> Task<TContinuationResult> continueWithTask(Executor executor, Continuation<TResult, Task<TContinuationResult>> continuation) {
|
||||||
throw new UnsupportedOperationException("continueWithTask is not implemented");
|
throw new UnsupportedOperationException("continueWithTask is not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,6 +239,11 @@ public abstract class Task<TResult> {
|
||||||
*/
|
*/
|
||||||
public abstract <X extends Throwable> TResult getResult(Class<X> exceptionType) throws X;
|
public abstract <X extends Throwable> TResult getResult(Class<X> exceptionType) throws X;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code true} if the Task is canceled; {@code false} otherwise.
|
||||||
|
*/
|
||||||
|
public abstract boolean isCanceled();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@code true} if the Task is complete; {@code false} otherwise.
|
* Returns {@code true} if the Task is complete; {@code false} otherwise.
|
||||||
*/
|
*/
|
||||||
|
@ -221,4 +254,29 @@ public abstract class Task<TResult> {
|
||||||
*/
|
*/
|
||||||
public abstract boolean isSuccessful();
|
public abstract boolean isSuccessful();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new Task that will be completed with the result of applying the specified SuccessContinuation to this Task when this Task completes successfully. If the previous Task fails, the onSuccessTask completion will be skipped and failure listeners will be invoked.
|
||||||
|
* <p>
|
||||||
|
* The SuccessContinuation will be called on the main application thread.
|
||||||
|
* <p>
|
||||||
|
* If the previous Task is canceled, the returned Task will also be canceled and the SuccessContinuation would not execute.
|
||||||
|
*
|
||||||
|
* @see SuccessContinuation#then
|
||||||
|
*/
|
||||||
|
public <TContinuationResult> Task<TContinuationResult> onSuccessTask(SuccessContinuation<TResult, TContinuationResult> successContinuation) {
|
||||||
|
throw new UnsupportedOperationException("onSuccessTask is not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new Task that will be completed with the result of applying the specified SuccessContinuation to this Task when this Task completes successfully. If the previous Task fails, the onSuccessTask completion will be skipped and failure listeners will be invoked.
|
||||||
|
* <p>
|
||||||
|
* If the previous Task is canceled, the returned Task will also be canceled and the SuccessContinuation would not execute.
|
||||||
|
*
|
||||||
|
* @param executor the executor to use to call the SuccessContinuation
|
||||||
|
* @see SuccessContinuation#then
|
||||||
|
*/
|
||||||
|
public <TContinuationResult> Task<TContinuationResult> onSuccessTask(Executor executor, SuccessContinuation<TResult, TContinuationResult> successContinuation) {
|
||||||
|
throw new UnsupportedOperationException("onSuccessTask is not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,15 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2013-2017 microG Project Team
|
* SPDX-FileCopyrightText: 2016, microG Project Team
|
||||||
*
|
* SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.0
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Notice: Portions of this file are reproduced from work created and shared by Google and used
|
||||||
* you may not use this file except in compliance with the License.
|
* according to terms described in the Creative Commons 4.0 Attribution License.
|
||||||
* You may obtain a copy of the License at
|
* See https://developers.google.com/readme/policies for details.
|
||||||
*
|
|
||||||
* 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.tasks;
|
package com.google.android.gms.tasks;
|
||||||
|
|
||||||
import org.microg.gms.common.PublicApi;
|
import org.microg.gms.common.PublicApi;
|
||||||
|
import org.microg.gms.tasks.TaskImpl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the ability to create an incomplete {@link Task} and later complete it by either
|
* Provides the ability to create an incomplete {@link Task} and later complete it by either
|
||||||
|
@ -24,29 +17,78 @@ import org.microg.gms.common.PublicApi;
|
||||||
*/
|
*/
|
||||||
@PublicApi
|
@PublicApi
|
||||||
public class TaskCompletionSource<TResult> {
|
public class TaskCompletionSource<TResult> {
|
||||||
|
private TaskImpl<TResult> task = new TaskImpl<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance of {@link TaskCompletionSource}.
|
||||||
|
*/
|
||||||
public TaskCompletionSource() {
|
public TaskCompletionSource() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance of {@link TaskCompletionSource} with a {@link CancellationToken} so that the Task can be set to canceled when {@link CancellationToken} is canceled.
|
||||||
|
*/
|
||||||
|
public TaskCompletionSource(CancellationToken token) {
|
||||||
|
token.onCanceledRequested(() -> {
|
||||||
|
try {
|
||||||
|
task.cancel();
|
||||||
|
} catch (DuplicateTaskCompletionException ignored) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Task.
|
* Returns the Task.
|
||||||
*/
|
*/
|
||||||
public Task<TResult> getTask() {
|
public Task<TResult> getTask() {
|
||||||
return null;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Completes the Task with the specified exception.
|
* Completes the Task with the specified exception.
|
||||||
|
*
|
||||||
* @throws IllegalStateException if the Task is already complete
|
* @throws IllegalStateException if the Task is already complete
|
||||||
*/
|
*/
|
||||||
public void setException(Exception e) {
|
public void setException(Exception e) {
|
||||||
|
task.setException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Completes the Task with the specified exception, unless the Task has already completed.
|
||||||
|
* If the Task has already completed, the call does nothing.
|
||||||
|
*
|
||||||
|
* @return {@code true} if the exception was set successfully, {@code false} otherwise
|
||||||
|
*/
|
||||||
|
public boolean trySetException(Exception e) {
|
||||||
|
try {
|
||||||
|
setException(e);
|
||||||
|
return true;
|
||||||
|
} catch (DuplicateTaskCompletionException ignored) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Completes the Task with the specified result.
|
* Completes the Task with the specified result.
|
||||||
|
*
|
||||||
* @throws IllegalStateException if the Task is already complete
|
* @throws IllegalStateException if the Task is already complete
|
||||||
*/
|
*/
|
||||||
public void setResult(TResult result) {
|
public void setResult(TResult result) {
|
||||||
|
task.setResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Completes the Task with the specified result, unless the Task has already completed.
|
||||||
|
* If the Task has already completed, the call does nothing.
|
||||||
|
*
|
||||||
|
* @return {@code true} if the result was set successfully, {@code false} otherwise
|
||||||
|
*/
|
||||||
|
public boolean trySetResult(TResult result) {
|
||||||
|
try {
|
||||||
|
setResult(result);
|
||||||
|
return true;
|
||||||
|
} catch (DuplicateTaskCompletionException ignored) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.0
|
||||||
|
* Notice: Portions of this file are reproduced from work created and shared by Google and used
|
||||||
|
* according to terms described in the Creative Commons 4.0 Attribution License.
|
||||||
|
* See https://developers.google.com/readme/policies for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.android.gms.tasks;
|
||||||
|
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
|
||||||
|
import org.microg.gms.common.PublicApi;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Standard {@link Executor} instances for use with {@link Task}.
|
||||||
|
*/
|
||||||
|
@PublicApi
|
||||||
|
public final class TaskExecutors {
|
||||||
|
/**
|
||||||
|
* An Executor that uses the main application thread.
|
||||||
|
*/
|
||||||
|
public static final Executor MAIN_THREAD = new Executor() {
|
||||||
|
private Handler handler = new Handler(Looper.getMainLooper());
|
||||||
|
@Override
|
||||||
|
public void execute(Runnable command) {
|
||||||
|
handler.post(command);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,17 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2013-2017 microG Project Team
|
* SPDX-FileCopyrightText: 2016, microG Project Team
|
||||||
*
|
* SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.0
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Notice: Portions of this file are reproduced from work created and shared by Google and used
|
||||||
* you may not use this file except in compliance with the License.
|
* according to terms described in the Creative Commons 4.0 Attribution License.
|
||||||
* You may obtain a copy of the License at
|
* See https://developers.google.com/readme/policies for details.
|
||||||
*
|
|
||||||
* 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.tasks;
|
package com.google.android.gms.tasks;
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.gms.tasks;
|
||||||
|
|
||||||
|
import com.google.android.gms.tasks.CancellationToken;
|
||||||
|
import com.google.android.gms.tasks.DuplicateTaskCompletionException;
|
||||||
|
import com.google.android.gms.tasks.OnTokenCanceledListener;
|
||||||
|
|
||||||
|
public class CancellationTokenImpl extends CancellationToken {
|
||||||
|
private TaskImpl<Void> task = new TaskImpl<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCancellationRequested() {
|
||||||
|
return task.isComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CancellationToken onCanceledRequested(OnTokenCanceledListener listener) {
|
||||||
|
task.addOnSuccessListener(aVoid -> listener.onCanceled());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancel() {
|
||||||
|
try {
|
||||||
|
task.cancel();
|
||||||
|
} catch (DuplicateTaskCompletionException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.gms.tasks;
|
||||||
|
|
||||||
|
import com.google.android.gms.tasks.OnCanceledListener;
|
||||||
|
import com.google.android.gms.tasks.Task;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
public class CancelledExecutor<TResult> extends UpdateExecutor<TResult> {
|
||||||
|
private OnCanceledListener listener;
|
||||||
|
|
||||||
|
public CancelledExecutor(Executor executor, OnCanceledListener listener) {
|
||||||
|
super(executor);
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTaskUpdate(Task<TResult> task) {
|
||||||
|
if (task.isCanceled()) {
|
||||||
|
execute(() -> listener.onCanceled());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
super.cancel();
|
||||||
|
listener = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.gms.tasks;
|
||||||
|
|
||||||
|
import com.google.android.gms.tasks.OnCompleteListener;
|
||||||
|
import com.google.android.gms.tasks.Task;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
public class CompletedExecutor<TResult> extends UpdateExecutor<TResult> {
|
||||||
|
private OnCompleteListener<TResult> listener;
|
||||||
|
|
||||||
|
public CompletedExecutor(Executor executor, OnCompleteListener<TResult> listener) {
|
||||||
|
super(executor);
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTaskUpdate(Task<TResult> task) {
|
||||||
|
if (task.isComplete()) {
|
||||||
|
execute(() -> listener.onComplete(task));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
super.cancel();
|
||||||
|
listener = null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.gms.tasks;
|
||||||
|
|
||||||
|
import com.google.android.gms.tasks.Continuation;
|
||||||
|
import com.google.android.gms.tasks.Task;
|
||||||
|
import com.google.android.gms.tasks.TaskCompletionSource;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
public class ContinuationExecutor<TResult, TContinuationResult> extends UpdateExecutor<TResult> {
|
||||||
|
private Continuation<TResult, TContinuationResult> continuation;
|
||||||
|
private TaskCompletionSource<TContinuationResult> completionSource = new TaskCompletionSource<>();
|
||||||
|
|
||||||
|
public ContinuationExecutor(Executor executor, Continuation<TResult, TContinuationResult> continuation) {
|
||||||
|
super(executor);
|
||||||
|
this.continuation = continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTaskUpdate(Task<TResult> task) {
|
||||||
|
if (task.isComplete()) {
|
||||||
|
execute(() -> {
|
||||||
|
try {
|
||||||
|
completionSource.setResult(continuation.then(task));
|
||||||
|
} catch (Exception e) {
|
||||||
|
completionSource.setException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<TContinuationResult> getTask() {
|
||||||
|
return completionSource.getTask();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
super.cancel();
|
||||||
|
continuation = null;
|
||||||
|
completionSource = null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.gms.tasks;
|
||||||
|
|
||||||
|
import com.google.android.gms.tasks.Continuation;
|
||||||
|
import com.google.android.gms.tasks.Task;
|
||||||
|
import com.google.android.gms.tasks.TaskCompletionSource;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
public class ContinuationWithExecutor<TResult, TContinuationResult> extends UpdateExecutor<TResult> {
|
||||||
|
private Continuation<TResult, Task<TContinuationResult>> continuation;
|
||||||
|
private TaskCompletionSource<TContinuationResult> completionSource = new TaskCompletionSource<>();
|
||||||
|
|
||||||
|
public ContinuationWithExecutor(Executor executor, Continuation<TResult, Task<TContinuationResult>> continuation) {
|
||||||
|
super(executor);
|
||||||
|
this.continuation = continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTaskUpdate(Task<TResult> task) {
|
||||||
|
if (task.isComplete()) {
|
||||||
|
execute(() -> {
|
||||||
|
try {
|
||||||
|
continuation.then(task).addOnCompleteListener(this, (subTask) -> {
|
||||||
|
if (subTask.isSuccessful()) {
|
||||||
|
completionSource.setResult(subTask.getResult());
|
||||||
|
} else {
|
||||||
|
completionSource.setException(subTask.getException());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
completionSource.setException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<TContinuationResult> getTask() {
|
||||||
|
return completionSource.getTask();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
super.cancel();
|
||||||
|
continuation = null;
|
||||||
|
completionSource = null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.gms.tasks;
|
||||||
|
|
||||||
|
import com.google.android.gms.tasks.OnFailureListener;
|
||||||
|
import com.google.android.gms.tasks.Task;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
public class FailureExecutor<TResult> extends UpdateExecutor<TResult> {
|
||||||
|
private OnFailureListener listener;
|
||||||
|
|
||||||
|
public FailureExecutor(Executor executor, OnFailureListener listener) {
|
||||||
|
super(executor);
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTaskUpdate(Task<TResult> task) {
|
||||||
|
if (task.isComplete() && !task.isSuccessful() && !task.isCanceled()) {
|
||||||
|
execute(() -> listener.onFailure(task.getException()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
super.cancel();
|
||||||
|
listener = null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.gms.tasks;
|
||||||
|
|
||||||
|
import com.google.android.gms.tasks.SuccessContinuation;
|
||||||
|
import com.google.android.gms.tasks.Task;
|
||||||
|
import com.google.android.gms.tasks.TaskCompletionSource;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
public class SuccessContinuationExecutor<TResult, TContinuationResult> extends UpdateExecutor<TResult> {
|
||||||
|
private SuccessContinuation<TResult, TContinuationResult> continuation;
|
||||||
|
private TaskCompletionSource<TContinuationResult> completionSource = new TaskCompletionSource<>();
|
||||||
|
|
||||||
|
public SuccessContinuationExecutor(Executor executor, SuccessContinuation<TResult, TContinuationResult> continuation) {
|
||||||
|
super(executor);
|
||||||
|
this.continuation = continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTaskUpdate(Task<TResult> task) {
|
||||||
|
if (task.isSuccessful()) {
|
||||||
|
execute(() -> {
|
||||||
|
try {
|
||||||
|
continuation.then(task.getResult()).addOnCompleteListener(this, (subTask) -> {
|
||||||
|
if (subTask.isSuccessful()) {
|
||||||
|
completionSource.setResult(subTask.getResult());
|
||||||
|
} else {
|
||||||
|
completionSource.setException(subTask.getException());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
completionSource.setException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
completionSource.setException(task.getException());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<TContinuationResult> getTask() {
|
||||||
|
return completionSource.getTask();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
super.cancel();
|
||||||
|
continuation = null;
|
||||||
|
completionSource = null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.gms.tasks;
|
||||||
|
|
||||||
|
import com.google.android.gms.tasks.OnSuccessListener;
|
||||||
|
import com.google.android.gms.tasks.Task;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
public class SuccessExecutor<TResult> extends UpdateExecutor<TResult> {
|
||||||
|
private OnSuccessListener<? super TResult> listener;
|
||||||
|
|
||||||
|
public SuccessExecutor(Executor executor, OnSuccessListener<? super TResult> listener) {
|
||||||
|
super(executor);
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTaskUpdate(Task<TResult> task) {
|
||||||
|
if (task.isSuccessful()) {
|
||||||
|
execute(() -> listener.onSuccess(task.getResult()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
super.cancel();
|
||||||
|
listener = null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,240 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.gms.tasks;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
|
||||||
|
import com.google.android.gms.tasks.Continuation;
|
||||||
|
import com.google.android.gms.tasks.DuplicateTaskCompletionException;
|
||||||
|
import com.google.android.gms.tasks.OnCanceledListener;
|
||||||
|
import com.google.android.gms.tasks.OnCompleteListener;
|
||||||
|
import com.google.android.gms.tasks.OnFailureListener;
|
||||||
|
import com.google.android.gms.tasks.OnSuccessListener;
|
||||||
|
import com.google.android.gms.tasks.RuntimeExecutionException;
|
||||||
|
import com.google.android.gms.tasks.SuccessContinuation;
|
||||||
|
import com.google.android.gms.tasks.Task;
|
||||||
|
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
|
import static com.google.android.gms.tasks.TaskExecutors.MAIN_THREAD;
|
||||||
|
|
||||||
|
public class TaskImpl<TResult> extends Task<TResult> {
|
||||||
|
private final Object lock = new Object();
|
||||||
|
private boolean completed;
|
||||||
|
private boolean cancelled;
|
||||||
|
private TResult result;
|
||||||
|
private Exception exception;
|
||||||
|
private Queue<UpdateListener<TResult>> completionQueue = new LinkedBlockingQueue<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Task<TResult> addOnCanceledListener(OnCanceledListener listener) {
|
||||||
|
return addOnCanceledListener(MAIN_THREAD, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Task<TResult> addOnCanceledListener(Executor executor, OnCanceledListener listener) {
|
||||||
|
return enqueueOrInvoke(new CancelledExecutor<>(executor, listener));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Task<TResult> addOnCanceledListener(Activity activity, OnCanceledListener listener) {
|
||||||
|
return enqueueOrInvoke(activity, new CancelledExecutor<>(MAIN_THREAD, listener));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Task<TResult> addOnCompleteListener(OnCompleteListener<TResult> listener) {
|
||||||
|
return addOnCompleteListener(MAIN_THREAD, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Task<TResult> addOnCompleteListener(Executor executor, OnCompleteListener<TResult> listener) {
|
||||||
|
return enqueueOrInvoke(new CompletedExecutor<>(executor, listener));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Task<TResult> addOnCompleteListener(Activity activity, OnCompleteListener<TResult> listener) {
|
||||||
|
return enqueueOrInvoke(activity, new CompletedExecutor<>(MAIN_THREAD, listener));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Task<TResult> addOnFailureListener(OnFailureListener listener) {
|
||||||
|
return addOnFailureListener(MAIN_THREAD, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Task<TResult> addOnFailureListener(Executor executor, OnFailureListener listener) {
|
||||||
|
return enqueueOrInvoke(new FailureExecutor<>(executor, listener));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Task<TResult> addOnFailureListener(Activity activity, OnFailureListener listener) {
|
||||||
|
return enqueueOrInvoke(activity, new FailureExecutor<>(MAIN_THREAD, listener));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Task<TResult> addOnSuccessListener(OnSuccessListener<? super TResult> listener) {
|
||||||
|
return addOnSuccessListener(MAIN_THREAD, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Task<TResult> addOnSuccessListener(Executor executor, OnSuccessListener<? super TResult> listener) {
|
||||||
|
return enqueueOrInvoke(new SuccessExecutor<>(executor, listener));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Task<TResult> addOnSuccessListener(Activity activity, OnSuccessListener<? super TResult> listener) {
|
||||||
|
return enqueueOrInvoke(activity, new SuccessExecutor<>(MAIN_THREAD, listener));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <TContinuationResult> Task<TContinuationResult> continueWith(Continuation<TResult, TContinuationResult> continuation) {
|
||||||
|
return continueWith(MAIN_THREAD, continuation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <TContinuationResult> Task<TContinuationResult> continueWith(Executor executor, Continuation<TResult, TContinuationResult> continuation) {
|
||||||
|
ContinuationExecutor<TResult, TContinuationResult> c = new ContinuationExecutor<>(executor, continuation);
|
||||||
|
enqueueOrInvoke(c);
|
||||||
|
return c.getTask();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <TContinuationResult> Task<TContinuationResult> continueWithTask(Continuation<TResult, Task<TContinuationResult>> continuation) {
|
||||||
|
return continueWithTask(MAIN_THREAD, continuation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <TContinuationResult> Task<TContinuationResult> continueWithTask(Executor executor, Continuation<TResult, Task<TContinuationResult>> continuation) {
|
||||||
|
ContinuationWithExecutor<TResult, TContinuationResult> c = new ContinuationWithExecutor<>(executor, continuation);
|
||||||
|
enqueueOrInvoke(c);
|
||||||
|
return c.getTask();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Exception getException() {
|
||||||
|
synchronized (lock) {
|
||||||
|
return exception;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TResult getResult() {
|
||||||
|
synchronized (lock) {
|
||||||
|
if (!completed) throw new IllegalStateException("Task is not yet complete");
|
||||||
|
if (cancelled) throw new CancellationException("Task is canceled");
|
||||||
|
if (exception != null) throw new RuntimeExecutionException(exception);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <X extends Throwable> TResult getResult(Class<X> exceptionType) throws X {
|
||||||
|
synchronized (lock) {
|
||||||
|
if (!completed) throw new IllegalStateException("Task is not yet complete");
|
||||||
|
if (cancelled) throw new CancellationException("Task is canceled");
|
||||||
|
if (exceptionType.isInstance(exception)) throw exceptionType.cast(exception);
|
||||||
|
if (exception != null) throw new RuntimeExecutionException(exception);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCanceled() {
|
||||||
|
synchronized (lock) {
|
||||||
|
return cancelled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isComplete() {
|
||||||
|
synchronized (lock) {
|
||||||
|
return completed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSuccessful() {
|
||||||
|
synchronized (lock) {
|
||||||
|
return completed && !cancelled && exception == null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerActivityStop(Activity activity, UpdateListener<TResult> listener) {
|
||||||
|
UpdateListenerLifecycleObserver.getObserverForActivity(activity).registerActivityStopListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task<TResult> enqueueOrInvoke(Activity activity, UpdateListener<TResult> listener) {
|
||||||
|
synchronized (lock) {
|
||||||
|
if (completed) {
|
||||||
|
listener.onTaskUpdate(this);
|
||||||
|
} else {
|
||||||
|
completionQueue.offer(listener);
|
||||||
|
registerActivityStop(activity, listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task<TResult> enqueueOrInvoke(UpdateListener<TResult> listener) {
|
||||||
|
synchronized (lock) {
|
||||||
|
if (completed) {
|
||||||
|
listener.onTaskUpdate(this);
|
||||||
|
} else {
|
||||||
|
completionQueue.offer(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyQueue() {
|
||||||
|
UpdateListener<TResult> listener;
|
||||||
|
while ((listener = completionQueue.poll()) != null) {
|
||||||
|
listener.onTaskUpdate(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancel() {
|
||||||
|
synchronized (lock) {
|
||||||
|
if (completed) throw DuplicateTaskCompletionException.of(this);
|
||||||
|
this.completed = true;
|
||||||
|
this.cancelled = true;
|
||||||
|
notifyQueue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResult(TResult result) {
|
||||||
|
synchronized (lock) {
|
||||||
|
if (completed) throw DuplicateTaskCompletionException.of(this);
|
||||||
|
this.completed = true;
|
||||||
|
this.result = result;
|
||||||
|
notifyQueue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setException(Exception exception) {
|
||||||
|
synchronized (lock) {
|
||||||
|
if (completed) throw DuplicateTaskCompletionException.of(this);
|
||||||
|
this.completed = true;
|
||||||
|
this.exception = exception;
|
||||||
|
notifyQueue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <TContinuationResult> Task<TContinuationResult> onSuccessTask(SuccessContinuation<TResult, TContinuationResult> successContinuation) {
|
||||||
|
return onSuccessTask(MAIN_THREAD, successContinuation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <TContinuationResult> Task<TContinuationResult> onSuccessTask(Executor executor, SuccessContinuation<TResult, TContinuationResult> successContinuation) {
|
||||||
|
SuccessContinuationExecutor<TResult, TContinuationResult> c = new SuccessContinuationExecutor<>(executor, successContinuation);
|
||||||
|
enqueueOrInvoke(c);
|
||||||
|
return c.getTask();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.gms.tasks;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
public abstract class UpdateExecutor<TResult> implements UpdateListener<TResult>, Executor {
|
||||||
|
private Executor executor;
|
||||||
|
|
||||||
|
public UpdateExecutor(Executor executor) {
|
||||||
|
this.executor = executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Runnable runnable) {
|
||||||
|
if (executor == null) return;
|
||||||
|
executor.execute(runnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
executor = null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.gms.tasks;
|
||||||
|
|
||||||
|
import com.google.android.gms.tasks.Task;
|
||||||
|
|
||||||
|
public interface UpdateListener<TResult> {
|
||||||
|
void onTaskUpdate(Task<TResult> task);
|
||||||
|
|
||||||
|
void cancel();
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.microg.gms.tasks;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.Application;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
|
public class UpdateListenerLifecycleObserver {
|
||||||
|
private static WeakHashMap<Activity, WeakReference<UpdateListenerLifecycleObserver>> map = new WeakHashMap<>();
|
||||||
|
private static boolean activityLifecycleCallbacksRegistered = false;
|
||||||
|
private List<WeakReference<UpdateListener<?>>> list = new ArrayList<>();
|
||||||
|
|
||||||
|
public synchronized static UpdateListenerLifecycleObserver getObserverForActivity(Activity activity) {
|
||||||
|
WeakReference<UpdateListenerLifecycleObserver> ref = map.get(activity);
|
||||||
|
if (ref != null) {
|
||||||
|
UpdateListenerLifecycleObserver observer = ref.get();
|
||||||
|
if (observer != null) {
|
||||||
|
return observer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!activityLifecycleCallbacksRegistered) {
|
||||||
|
activity.getApplication().registerActivityLifecycleCallbacks(new MyActivityLifecycleCallbacks());
|
||||||
|
activityLifecycleCallbacksRegistered = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateListenerLifecycleObserver newInstance = new UpdateListenerLifecycleObserver();
|
||||||
|
map.put(activity, new WeakReference<>(newInstance));
|
||||||
|
return newInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private UpdateListenerLifecycleObserver() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void registerActivityStopListener(UpdateListener<?> listener) {
|
||||||
|
list.add(new WeakReference<>(listener));
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void onStop() {
|
||||||
|
for (WeakReference<UpdateListener<?>> ref : list) {
|
||||||
|
UpdateListener<?> listener = ref.get();
|
||||||
|
listener.cancel();
|
||||||
|
}
|
||||||
|
list.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MyActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
|
||||||
|
@Override
|
||||||
|
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityStarted(Activity activity) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityResumed(Activity activity) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityPaused(Activity activity) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityStopped(Activity activity) {
|
||||||
|
WeakReference<UpdateListenerLifecycleObserver> ref = map.get(activity);
|
||||||
|
if (ref != null) {
|
||||||
|
UpdateListenerLifecycleObserver observer = ref.get();
|
||||||
|
if (observer != null) {
|
||||||
|
observer.onStop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityDestroyed(Activity activity) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue