Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1162)

Unified Diff: chrome/android/webapk/libs/client/src/org/chromium/webapk/lib/client/WebApkServiceConnectionManager.java

Issue 2974573002: Refactor WebApkServiceConnectionManager. (Closed)
Patch Set: Call the callback on UI thread if bindService() fails. Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/android/webapk/libs/client/src/org/chromium/webapk/lib/client/WebApkServiceConnectionManager.java
diff --git a/chrome/android/webapk/libs/client/src/org/chromium/webapk/lib/client/WebApkServiceConnectionManager.java b/chrome/android/webapk/libs/client/src/org/chromium/webapk/lib/client/WebApkServiceConnectionManager.java
index 2ef84539ad96a9cd3894c793140645bc647cbfa1..6c2e09f6b371cf2ebfd9fd1c8954251d3a5daa28 100644
--- a/chrome/android/webapk/libs/client/src/org/chromium/webapk/lib/client/WebApkServiceConnectionManager.java
+++ b/chrome/android/webapk/libs/client/src/org/chromium/webapk/lib/client/WebApkServiceConnectionManager.java
@@ -12,90 +12,100 @@ import android.os.AsyncTask;
import android.os.IBinder;
import android.util.Log;
-import org.chromium.webapk.lib.runtime_library.IWebApkApi;
-
import java.util.ArrayList;
import java.util.Hashtable;
+import java.util.Map;
/**
- * Manages static global connections between the Chrome application and "WebAPK services". Each
- * WebAPK has its own "WebAPK service".
+ * Each WebAPK has several services. This class manages static global connections between the
+ * Chrome application and the "WebAPK services."
*/
public class WebApkServiceConnectionManager {
/**
- * Interface for getting notified once Chrome is connected to the WebAPK service.
+ * Interface for getting notified once Chrome is connected to a WebAPK Service.
*/
public interface ConnectionCallback {
/**
* Called once Chrome is connected to the WebAPK service.
- * @param api The WebAPK service API.
+ * @param service The WebAPK service.
*/
- public void onConnected(IWebApkApi api);
+ void onConnected(IBinder service);
}
- /**
- * Managed connection to WebAPK service.
- */
+ /** Managed connection to WebAPK service. */
private static class Connection implements ServiceConnection {
/**
* Whether the connection to the service was established.
+ * Note: this flag cannot be replaced by checking whether iBinder is null, since the iBinder
+ * is null even when a service is connected successfully in Junit tests.
*/
private boolean mHasConnected;
- /**
- * Callbacks to call once the connection is established.
- */
+ /** The connection manager who owns this connection. */
+ private WebApkServiceConnectionManager mConnectionManager;
+
+ /** Callbacks to call once the connection is established. */
private ArrayList<ConnectionCallback> mCallbacks = new ArrayList<ConnectionCallback>();
- /**
- * WebAPK IBinder interface.
- */
- private IWebApkApi mApi;
+ /** WebAPK IBinder interface.*/
+ private IBinder mBinder;
public boolean hasConnected() {
return mHasConnected;
}
- public IWebApkApi getApi() {
- return mApi;
+ public IBinder getService() {
+ return mBinder;
}
public void addCallback(ConnectionCallback callback) {
mCallbacks.add(callback);
}
+ public Connection(WebApkServiceConnectionManager manager) {
+ mConnectionManager = manager;
+ }
+
@Override
- public void onServiceDisconnected(ComponentName name) {}
+ public void onServiceDisconnected(ComponentName name) {
+ mHasConnected = false;
+ mBinder = null;
+ if (name != null) {
+ mConnectionManager.onServiceDisconnected(name.getPackageName());
+ }
+ notifyAndClear();
+ }
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mHasConnected = true;
- mApi = IWebApkApi.Stub.asInterface(service);
- Log.d(TAG, String.format("Got IWebApkApi: %s", mApi));
+ mBinder = service;
+ Log.d(TAG, String.format("Got IBinder Service: %s", mBinder));
+ notifyAndClear();
+ }
+ /** Notifies all the callers either the connection is established or failed to connect. */
+ private void notifyAndClear() {
pkotwicz 2017/07/14 23:20:05 You can inline this method in onServiceConnected()
Xi Han 2017/07/17 20:45:32 Done.
for (ConnectionCallback callback : mCallbacks) {
- callback.onConnected(mApi);
+ callback.onConnected(mBinder);
}
mCallbacks.clear();
}
}
- private static final String CATEGORY_WEBAPK_API = "android.intent.category.WEBAPK_API";
-
- private static final String TAG = "cr_WebApk";
+ private static final String TAG = "cr_WebApkService";
- private static WebApkServiceConnectionManager sInstance;
+ /** The category of the service to connect. */
+ private String mCategory;
- /**
- * Mapping of WebAPK package to WebAPK service connection.
- */
+ /** Mapping of WebAPK package to WebAPK service connection.*/
private Hashtable<String, Connection> mConnections = new Hashtable<String, Connection>();
- public static WebApkServiceConnectionManager getInstance() {
- if (sInstance == null) {
- sInstance = new WebApkServiceConnectionManager();
- }
- return sInstance;
+ /** Called when a WebAPK Service connection is disconnected. */
+ protected void onServiceDisconnected(String webApkName) {
+ // TODO(hanxi): checks whether to kill the corresponding WebApkActivity if the WebAPK's data
+ // is cleared or the WebAPK is uninstalled.
+ mConnections.remove(webApkName);
}
/**
@@ -103,36 +113,60 @@ public class WebApkServiceConnectionManager {
* @param appContext Application context.
* @param webApkPackage WebAPK package to create connection for.
* @param callback Callback to call after connection has been established. Called synchronously
- * if the connection is already established.
*/
public void connect(final Context appContext, final String webApkPackage,
final ConnectionCallback callback) {
Connection connection = mConnections.get(webApkPackage);
if (connection != null) {
if (connection.hasConnected()) {
- callback.onConnected(connection.getApi());
+ callback.onConnected(connection.getService());
} else {
connection.addCallback(callback);
}
return;
}
- new AsyncTask<Void, Void, Void>() {
+ new AsyncTask<Void, Void, Boolean>() {
@Override
- protected Void doInBackground(Void... params) {
- Connection newConnection = new Connection();
+ protected Boolean doInBackground(Void... params) {
+ Connection newConnection = new Connection(WebApkServiceConnectionManager.this);
newConnection.addCallback(callback);
Intent intent = createConnectIntent(webApkPackage);
-
+ boolean success = false;
try {
- appContext.bindService(intent, newConnection, Context.BIND_AUTO_CREATE);
-
+ success =
+ appContext.bindService(intent, newConnection, Context.BIND_AUTO_CREATE);
} catch (SecurityException e) {
Log.w(TAG, "Security failed binding.", e);
- return null;
+ } finally {
pkotwicz 2017/07/14 23:20:05 Does this need to be in a finally{} block?
Xi Han 2017/07/17 20:45:32 Done.
+ if (success) {
+ mConnections.put(webApkPackage, newConnection);
+ }
+ return success;
}
+ }
+
+ @Override
+ protected void onPostExecute(Boolean success) {
+ if (!success) callback.onConnected(null);
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
- mConnections.put(webApkPackage, newConnection);
+ /**
+ * Disconnect from all of the WebAPK services. Can be called from any thread.
+ * @param appContext The application context.
+ */
+ public void disconnect(final Context appContext) {
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... voids) {
+ for (Map.Entry<String, Connection> entry : mConnections.entrySet()) {
+ Connection connection = entry.getValue();
+ if (connection == null || !connection.hasConnected()) continue;
pkotwicz 2017/07/14 23:20:05 - Isn't it impossible for |connection| to be null?
Xi Han 2017/07/17 20:45:32 Removed this check.
+ appContext.unbindService(connection);
+ }
+ mConnections.clear();
return null;
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
@@ -162,16 +196,17 @@ public class WebApkServiceConnectionManager {
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
- WebApkServiceConnectionManager() {
+ WebApkServiceConnectionManager(String category) {
+ mCategory = category;
}
/**
* Creates intent to connect to WebAPK service.
* @param webApkPackage The package name of the WebAPK to connect to.
*/
- private static Intent createConnectIntent(String webApkPackage) {
+ private Intent createConnectIntent(String webApkPackage) {
Intent intent = new Intent();
- intent.addCategory(CATEGORY_WEBAPK_API);
+ intent.addCategory(mCategory);
intent.setPackage(webApkPackage);
return intent;
}

Powered by Google App Engine
This is Rietveld 408576698