1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.phone.vvm.omtp.sync;
18
19import android.net.Network;
20import android.support.annotation.NonNull;
21import android.telecom.PhoneAccountHandle;
22import com.android.phone.VoicemailStatus;
23import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
24import com.android.phone.vvm.omtp.VvmLog;
25import java.io.Closeable;
26import java.util.concurrent.CompletableFuture;
27import java.util.concurrent.ExecutionException;
28import java.util.concurrent.Future;
29
30/**
31 * Class to retrieve a {@link Network} synchronously. {@link #getNetwork(OmtpVvmCarrierConfigHelper,
32 * PhoneAccountHandle)} will block until a suitable network is retrieved or it has failed.
33 */
34public class VvmNetworkRequest {
35
36    private static final String TAG = "VvmNetworkRequest";
37
38    /**
39     * A wrapper around a Network returned by a {@link VvmNetworkRequestCallback}, which should be
40     * closed once not needed anymore.
41     */
42    public static class NetworkWrapper implements Closeable {
43
44        private final Network mNetwork;
45        private final VvmNetworkRequestCallback mCallback;
46
47        private NetworkWrapper(Network network, VvmNetworkRequestCallback callback) {
48            mNetwork = network;
49            mCallback = callback;
50        }
51
52        public Network get() {
53            return mNetwork;
54        }
55
56        @Override
57        public void close() {
58            mCallback.releaseNetwork();
59        }
60    }
61
62    public static class RequestFailedException extends Exception {
63
64        private RequestFailedException(Throwable cause) {
65            super(cause);
66        }
67    }
68
69    @NonNull
70    public static NetworkWrapper getNetwork(OmtpVvmCarrierConfigHelper config,
71        PhoneAccountHandle handle, VoicemailStatus.Editor status) throws RequestFailedException {
72        FutureNetworkRequestCallback callback = new FutureNetworkRequestCallback(config, handle,
73            status);
74        callback.requestNetwork();
75        try {
76            return callback.getFuture().get();
77        } catch (InterruptedException | ExecutionException e) {
78            callback.releaseNetwork();
79            VvmLog.e(TAG, "can't get future network", e);
80            throw new RequestFailedException(e);
81        }
82    }
83
84    private static class FutureNetworkRequestCallback extends VvmNetworkRequestCallback {
85
86        /**
87         * {@link CompletableFuture#get()} will block until {@link CompletableFuture#
88         * complete(Object) } has been called on the other thread.
89         */
90        private final CompletableFuture<NetworkWrapper> mFuture = new CompletableFuture<>();
91
92        public FutureNetworkRequestCallback(OmtpVvmCarrierConfigHelper config,
93            PhoneAccountHandle phoneAccount, VoicemailStatus.Editor status) {
94            super(config, phoneAccount, status);
95        }
96
97        public Future<NetworkWrapper> getFuture() {
98            return mFuture;
99        }
100
101        @Override
102        public void onAvailable(Network network) {
103            super.onAvailable(network);
104            mFuture.complete(new NetworkWrapper(network, this));
105        }
106
107        @Override
108        public void onFailed(String reason) {
109            super.onFailed(reason);
110            mFuture.complete(null);
111        }
112
113    }
114}
115