2015-01-25 01:11:52 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2014-2015 µg 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.
|
|
|
|
*/
|
|
|
|
|
2015-01-15 19:11:31 +00:00
|
|
|
package org.microg.gms.common;
|
|
|
|
|
|
|
|
import android.content.ComponentName;
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.content.ServiceConnection;
|
|
|
|
import android.os.IBinder;
|
2015-01-22 02:07:09 +00:00
|
|
|
import android.util.Log;
|
2015-01-15 19:11:31 +00:00
|
|
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.HashSet;
|
|
|
|
import java.util.Map;
|
|
|
|
import java.util.Set;
|
|
|
|
|
2015-02-01 23:03:48 +00:00
|
|
|
import static org.microg.gms.common.Constants.GMS_PACKAGE_NAME;
|
2015-01-15 19:11:31 +00:00
|
|
|
|
|
|
|
public class MultiConnectionKeeper {
|
2015-01-22 02:07:09 +00:00
|
|
|
private static final String TAG = "GmsMultiConnectionKeeper";
|
|
|
|
|
2015-01-15 19:11:31 +00:00
|
|
|
private static MultiConnectionKeeper INSTANCE;
|
|
|
|
|
|
|
|
private final Context context;
|
|
|
|
private final Map<String, Connection> connections = new HashMap<>();
|
|
|
|
|
|
|
|
public MultiConnectionKeeper(Context context) {
|
|
|
|
this.context = context;
|
|
|
|
}
|
|
|
|
|
2015-01-24 18:06:41 +00:00
|
|
|
public synchronized static MultiConnectionKeeper getInstance(Context context) {
|
2015-01-15 19:11:31 +00:00
|
|
|
if (INSTANCE == null)
|
|
|
|
INSTANCE = new MultiConnectionKeeper(context);
|
|
|
|
return INSTANCE;
|
|
|
|
}
|
|
|
|
|
2015-02-01 23:03:48 +00:00
|
|
|
public synchronized boolean bind(String action, ServiceConnection connection) {
|
2015-01-24 18:06:41 +00:00
|
|
|
Log.d(TAG, "bind(" + action + ", " + connection + ")");
|
2015-01-15 19:11:31 +00:00
|
|
|
Connection con = connections.get(action);
|
|
|
|
if (con != null) {
|
|
|
|
if (!con.forwardsConnection(connection)) {
|
|
|
|
con.addConnectionForward(connection);
|
|
|
|
if (!con.isBound())
|
|
|
|
con.bind();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
con = new Connection(action);
|
|
|
|
con.addConnectionForward(connection);
|
|
|
|
con.bind();
|
|
|
|
connections.put(action, con);
|
|
|
|
}
|
|
|
|
return con.isBound();
|
|
|
|
}
|
2015-01-22 02:07:09 +00:00
|
|
|
|
2015-02-01 23:03:48 +00:00
|
|
|
public synchronized void unbind(String action, ServiceConnection connection) {
|
2015-01-24 18:06:41 +00:00
|
|
|
Log.d(TAG, "unbind(" + action + ", " + connection + ")");
|
2015-01-15 19:11:31 +00:00
|
|
|
Connection con = connections.get(action);
|
|
|
|
if (con != null) {
|
|
|
|
con.removeConnectionForward(connection);
|
|
|
|
if (!con.hasForwards() && con.isBound()) {
|
|
|
|
con.unbind();
|
2015-01-24 18:06:41 +00:00
|
|
|
connections.remove(action);
|
2015-01-15 19:11:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public class Connection {
|
|
|
|
private final String actionString;
|
|
|
|
private final Set<ServiceConnection> connectionForwards = new HashSet<>();
|
|
|
|
private boolean bound = false;
|
|
|
|
private boolean connected = false;
|
|
|
|
private IBinder binder;
|
|
|
|
private ComponentName component;
|
|
|
|
private ServiceConnection serviceConnection = new ServiceConnection() {
|
|
|
|
@Override
|
|
|
|
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
|
2015-01-24 18:06:41 +00:00
|
|
|
Log.d(TAG, "Connection(" + actionString + ") : ServiceConnection : " +
|
|
|
|
"onServiceConnected("+componentName+")");
|
2015-01-15 19:11:31 +00:00
|
|
|
binder = iBinder;
|
|
|
|
component = componentName;
|
|
|
|
for (ServiceConnection connection : connectionForwards) {
|
|
|
|
connection.onServiceConnected(componentName, iBinder);
|
|
|
|
}
|
|
|
|
connected = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onServiceDisconnected(ComponentName componentName) {
|
2015-01-24 18:06:41 +00:00
|
|
|
Log.d(TAG, "Connection(" + actionString + ") : ServiceConnection : " +
|
|
|
|
"onServiceDisconnected("+componentName+")");
|
2015-01-15 19:11:31 +00:00
|
|
|
binder = null;
|
|
|
|
component = componentName;
|
|
|
|
for (ServiceConnection connection : connectionForwards) {
|
|
|
|
connection.onServiceDisconnected(componentName);
|
|
|
|
}
|
|
|
|
connected = false;
|
2015-02-01 23:03:48 +00:00
|
|
|
bound = false;
|
2015-01-15 19:11:31 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
public Connection(String actionString) {
|
|
|
|
this.actionString = actionString;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void bind() {
|
2015-01-24 18:06:41 +00:00
|
|
|
Log.d(TAG, "Connection(" + actionString + ") : bind()");
|
2015-01-15 19:11:31 +00:00
|
|
|
Intent intent = new Intent(actionString).setPackage(GMS_PACKAGE_NAME);
|
|
|
|
bound = context.bindService(intent, serviceConnection,
|
2015-01-22 02:07:09 +00:00
|
|
|
Context.BIND_ADJUST_WITH_ACTIVITY | Context.BIND_AUTO_CREATE);
|
2015-01-15 19:11:31 +00:00
|
|
|
if (!bound) {
|
|
|
|
context.unbindService(serviceConnection);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isBound() {
|
|
|
|
return bound;
|
|
|
|
}
|
|
|
|
|
|
|
|
public IBinder getBinder() {
|
|
|
|
return binder;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void unbind() {
|
2015-01-24 18:06:41 +00:00
|
|
|
Log.d(TAG, "Connection(" + actionString + ") : unbind()");
|
2015-02-01 23:03:48 +00:00
|
|
|
try {
|
|
|
|
context.unbindService(serviceConnection);
|
|
|
|
} catch (IllegalArgumentException e) { // not bound (whatever reason)
|
|
|
|
Log.w(TAG, e);
|
|
|
|
}
|
2015-01-15 19:11:31 +00:00
|
|
|
bound = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void addConnectionForward(ServiceConnection connection) {
|
|
|
|
connectionForwards.add(connection);
|
|
|
|
if (connected) {
|
|
|
|
connection.onServiceConnected(component, binder);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void removeConnectionForward(ServiceConnection connection) {
|
|
|
|
connectionForwards.remove(connection);
|
|
|
|
if (connected) {
|
|
|
|
connection.onServiceDisconnected(component);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean forwardsConnection(ServiceConnection connection) {
|
|
|
|
return connectionForwards.contains(connection);
|
|
|
|
}
|
2015-01-22 02:07:09 +00:00
|
|
|
|
2015-01-15 19:11:31 +00:00
|
|
|
public boolean hasForwards() {
|
|
|
|
return !connectionForwards.isEmpty();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|