/* * 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.common.api; import android.content.Context; import android.os.Bundle; import android.os.Looper; import android.os.Message; import android.support.v4.app.FragmentActivity; import android.util.Log; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.api.AccountInfo; 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.Status; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; public class GoogleApiClientImpl implements GoogleApiClient { private static final String TAG = "GmsApiClientImpl"; private final Context context; private final Looper looper; private final AccountInfo accountInfo; private final Map<Api, Api.ApiOptions> apis = new HashMap<Api, Api.ApiOptions>(); private final Map<Api, ApiConnection> apiConnections = new HashMap<Api, ApiConnection>(); private final Handler handler; private final Set<ConnectionCallbacks> connectionCallbacks = new HashSet<ConnectionCallbacks>(); private final Set<OnConnectionFailedListener> connectionFailedListeners = new HashSet<OnConnectionFailedListener>(); private final int clientId; private final ConnectionCallbacks baseConnectionCallbacks = new ConnectionCallbacks() { @Override public void onConnected(Bundle connectionHint) { Log.d(TAG, "ConnectionCallbacks : onConnected()"); for (ConnectionCallbacks callback : connectionCallbacks) { callback.onConnected(connectionHint); } } @Override public void onConnectionSuspended(int cause) { Log.d(TAG, "ConnectionCallbacks : onConnectionSuspended()"); for (ConnectionCallbacks callback : connectionCallbacks) { callback.onConnectionSuspended(cause); } } }; private final OnConnectionFailedListener baseConnectionFailedListener = new OnConnectionFailedListener() { @Override public void onConnectionFailed(ConnectionResult result) { Log.d(TAG, "OnConnectionFailedListener : onConnectionFailed()"); for (OnConnectionFailedListener listener : connectionFailedListeners) { listener.onConnectionFailed(result); } } }; private int usageCounter = 0; private boolean shouldDisconnect = false; public GoogleApiClientImpl(Context context, Looper looper, AccountInfo accountInfo, Map<Api, Api.ApiOptions> apis, Set<ConnectionCallbacks> connectionCallbacks, Set<OnConnectionFailedListener> connectionFailedListeners, int clientId) { this.context = context; this.looper = looper; this.handler = new Handler(looper); this.accountInfo = accountInfo; this.apis.putAll(apis); this.connectionCallbacks.addAll(connectionCallbacks); this.connectionFailedListeners.addAll(connectionFailedListeners); this.clientId = clientId; for (Api api : apis.keySet()) { apiConnections.put(api, api.getBuilder().build(context, looper, apis.get(api), accountInfo, baseConnectionCallbacks, baseConnectionFailedListener)); } } public synchronized void incrementUsageCounter() { usageCounter++; } public synchronized void decrementUsageCounter() { usageCounter--; if (shouldDisconnect) disconnect(); } public Looper getLooper() { return looper; } public ApiConnection getApiConnection(Api api) { return apiConnections.get(api); } @Override public ConnectionResult blockingConnect() { return null; } @Override public ConnectionResult blockingConnect(long timeout, TimeUnit unit) { return null; } @Override public PendingResult<Status> clearDefaultAccountAndReconnect() { return null; } @Override public synchronized void connect() { Log.d(TAG, "connect()"); if (isConnected() || isConnecting()) { if (shouldDisconnect) { shouldDisconnect = false; return; } Log.d(TAG, "Already connected/connecting, nothing to do"); return; } for (ApiConnection connection : apiConnections.values()) { if (!connection.isConnected()) { connection.connect(); } } } @Override public synchronized void disconnect() { if (usageCounter > 0) { shouldDisconnect = true; } else { Log.d(TAG, "disconnect()"); for (ApiConnection connection : apiConnections.values()) { if (connection.isConnected()) { connection.disconnect(); } } } } @Override public synchronized boolean isConnected() { for (ApiConnection connection : apiConnections.values()) { if (!connection.isConnected()) return false; } return true; } @Override public synchronized boolean isConnecting() { for (ApiConnection connection : apiConnections.values()) { if (connection.isConnecting()) return true; } return false; } @Override public boolean isConnectionCallbacksRegistered(ConnectionCallbacks listener) { return connectionCallbacks.contains(listener); } @Override public boolean isConnectionFailedListenerRegistered( OnConnectionFailedListener listener) { return connectionFailedListeners.contains(listener); } @Override public synchronized void reconnect() { Log.d(TAG, "reconnect()"); disconnect(); connect(); } @Override public void registerConnectionCallbacks(ConnectionCallbacks listener) { connectionCallbacks.add(listener); } @Override public void registerConnectionFailedListener(OnConnectionFailedListener listener) { connectionFailedListeners.add(listener); } @Override public void stopAutoManager(FragmentActivity lifecycleActivity) throws IllegalStateException { } @Override public void unregisterConnectionCallbacks(ConnectionCallbacks listener) { connectionCallbacks.remove(listener); } @Override public void unregisterConnectionFailedListener(OnConnectionFailedListener listener) { connectionFailedListeners.remove(listener); } private class Handler extends android.os.Handler { private Handler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { if (msg.what == 0 && msg.obj instanceof Runnable) { ((Runnable) msg.obj).run(); } else { super.handleMessage(msg); } } public void sendRunnable(Runnable runnable) { sendMessage(obtainMessage(1, runnable)); } } }