diff options
11 files changed, 199 insertions, 37 deletions
@@ -267,6 +267,7 @@ LOCAL_SRC_FILES += \ core/java/com/android/internal/app/IBatteryStats.aidl \ core/java/com/android/internal/app/IProcessStats.aidl \ core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl \ + core/java/com/android/internal/app/IVoiceInteractionSessionShowCallback.aidl \ core/java/com/android/internal/app/IVoiceInteractor.aidl \ core/java/com/android/internal/app/IVoiceInteractorCallback.aidl \ core/java/com/android/internal/app/IVoiceInteractorRequest.aidl \ diff --git a/core/java/android/service/voice/IVoiceInteractionSession.aidl b/core/java/android/service/voice/IVoiceInteractionSession.aidl index 4f4b2d5..7c90261 100644 --- a/core/java/android/service/voice/IVoiceInteractionSession.aidl +++ b/core/java/android/service/voice/IVoiceInteractionSession.aidl @@ -20,11 +20,13 @@ import android.content.Intent; import android.graphics.Bitmap; import android.os.Bundle; +import com.android.internal.app.IVoiceInteractionSessionShowCallback; + /** * @hide */ oneway interface IVoiceInteractionSession { - void show(in Bundle sessionArgs, int flags); + void show(in Bundle sessionArgs, int flags, IVoiceInteractionSessionShowCallback showCallback); void hide(); void handleAssist(in Bundle assistData); void handleScreenshot(in Bitmap screenshot); diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java index 3245f55..bb985b4 100644 --- a/core/java/android/service/voice/VoiceInteractionSession.java +++ b/core/java/android/service/voice/VoiceInteractionSession.java @@ -43,6 +43,7 @@ import android.view.ViewTreeObserver; import android.view.WindowManager; import android.widget.FrameLayout; import com.android.internal.app.IVoiceInteractionManagerService; +import com.android.internal.app.IVoiceInteractionSessionShowCallback; import com.android.internal.app.IVoiceInteractor; import com.android.internal.app.IVoiceInteractorCallback; import com.android.internal.app.IVoiceInteractorRequest; @@ -163,9 +164,10 @@ public abstract class VoiceInteractionSession implements KeyEvent.Callback { final IVoiceInteractionSession mSession = new IVoiceInteractionSession.Stub() { @Override - public void show(Bundle sessionArgs, int flags) { - mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIO(MSG_SHOW, - flags, sessionArgs)); + public void show(Bundle sessionArgs, int flags, + IVoiceInteractionSessionShowCallback showCallback) { + mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIOO(MSG_SHOW, + flags, sessionArgs, showCallback)); } @Override @@ -412,9 +414,12 @@ public abstract class VoiceInteractionSession implements KeyEvent.Callback { onHandleScreenshot((Bitmap) msg.obj); break; case MSG_SHOW: - if (DEBUG) Log.d(TAG, "doShow: args=" + msg.obj - + " flags=" + msg.arg1); - doShow((Bundle) msg.obj, msg.arg1); + args = (SomeArgs)msg.obj; + if (DEBUG) Log.d(TAG, "doShow: args=" + args.arg1 + + " flags=" + msg.arg1 + + " showCallback=" + args.arg2); + doShow((Bundle) args.arg1, msg.arg1, + (IVoiceInteractionSessionShowCallback) args.arg2); break; case MSG_HIDE: if (DEBUG) Log.d(TAG, "doHide"); @@ -523,7 +528,7 @@ public abstract class VoiceInteractionSession implements KeyEvent.Callback { onCreate(args, startFlags); } - void doShow(Bundle args, int flags) { + void doShow(Bundle args, int flags, final IVoiceInteractionSessionShowCallback showCallback) { if (DEBUG) Log.v(TAG, "Showing window: mWindowAdded=" + mWindowAdded + " mWindowVisible=" + mWindowVisible); @@ -548,6 +553,22 @@ public abstract class VoiceInteractionSession implements KeyEvent.Callback { mWindowVisible = true; mWindow.show(); } + if (showCallback != null) { + mRootView.invalidate(); + mRootView.getViewTreeObserver().addOnPreDrawListener( + new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + mRootView.getViewTreeObserver().removeOnPreDrawListener(this); + try { + showCallback.onShown(); + } catch (RemoteException e) { + Log.w(TAG, "Error calling onShown", e); + } + return true; + } + }); + } } finally { mWindowWasVisible = true; mInShowWindow = false; @@ -582,7 +603,8 @@ public abstract class VoiceInteractionSession implements KeyEvent.Callback { mRootView = mInflater.inflate( com.android.internal.R.layout.voice_interaction_session, null); mRootView.setSystemUiVisibility( - View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); + View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); mWindow.setContentView(mRootView); mRootView.getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsComputer); @@ -716,7 +738,9 @@ public abstract class VoiceInteractionSession implements KeyEvent.Callback { mWindow = new SoftInputWindow(mContext, "VoiceInteractionSession", mTheme, mCallbacks, this, mDispatcherState, WindowManager.LayoutParams.TYPE_VOICE_INTERACTION, Gravity.BOTTOM, true); - mWindow.getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); + mWindow.getWindow().addFlags( + WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED | + WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); initViews(); mWindow.getWindow().setLayout(MATCH_PARENT, MATCH_PARENT); mWindow.setToken(mToken); diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 66dae7b..54d78f3 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -223,6 +223,7 @@ public interface WindowManager extends ViewManager { @ViewDebug.IntToString(from = TYPE_MAGNIFICATION_OVERLAY, to = "TYPE_MAGNIFICATION_OVERLAY"), @ViewDebug.IntToString(from = TYPE_PRIVATE_PRESENTATION, to = "TYPE_PRIVATE_PRESENTATION"), @ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION, to = "TYPE_VOICE_INTERACTION"), + @ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION_STARTING, to = "TYPE_VOICE_INTERACTION_STARTING"), }) public int type; @@ -549,6 +550,12 @@ public interface WindowManager extends ViewManager { public static final int TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW+32; /** + * Window type: Starting window for voice interaction layer. + * @hide + */ + public static final int TYPE_VOICE_INTERACTION_STARTING = FIRST_SYSTEM_WINDOW+33; + + /** * End of types of system windows. */ public static final int LAST_SYSTEM_WINDOW = 2999; diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl index 144dca4..d328eaf 100644 --- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl +++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl @@ -16,9 +16,11 @@ package com.android.internal.app; +import android.content.ComponentName; import android.content.Intent; import android.os.Bundle; +import com.android.internal.app.IVoiceInteractionSessionShowCallback; import com.android.internal.app.IVoiceInteractor; import android.hardware.soundtrigger.IRecognitionStatusCallback; import android.hardware.soundtrigger.SoundTrigger; @@ -87,10 +89,17 @@ interface IVoiceInteractionManagerService { boolean isServiceActive(); /** + * @return the component name for the currently active voice interaction service + */ + ComponentName getActiveServiceComponentName(); + + /** * Shows the session for the currently active service. Used to start a new session from system * affordances. + * + * @param showCallback callback to be notified when the session was shown */ - void showSessionForActiveService(); + void showSessionForActiveService(IVoiceInteractionSessionShowCallback showCallback); /** * Indicates whether there is a voice session running (but not necessarily showing). diff --git a/core/java/com/android/internal/app/IVoiceInteractionSessionShowCallback.aidl b/core/java/com/android/internal/app/IVoiceInteractionSessionShowCallback.aidl new file mode 100644 index 0000000..15fa89b --- /dev/null +++ b/core/java/com/android/internal/app/IVoiceInteractionSessionShowCallback.aidl @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * 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 com.android.internal.app; + +oneway interface IVoiceInteractionSessionShowCallback { + void onFailed(); + void onShown(); +} diff --git a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java index f0e6c43..d6f9f6d 100644 --- a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java @@ -122,7 +122,8 @@ public class SearchPanelView extends FrameLayout implements StatusBarPanel { private void startVoiceInteractor() { try { - mVoiceInteractionManagerService.showSessionForActiveService(); + // TODO: Pass show callback + mVoiceInteractionManagerService.showSessionForActiveService(null /* showCallback */); } catch (RemoteException e) { Log.w(TAG, "Failed to call showSessionForActiveService", e); } @@ -137,6 +138,15 @@ public class SearchPanelView extends FrameLayout implements StatusBarPanel { } } + private ComponentName getVoiceInteractorComponentName() { + try { + return mVoiceInteractionManagerService.getActiveServiceComponentName(); + } catch (RemoteException e) { + Log.w(TAG, "Failed to call getActiveServiceComponentName", e); + return null; + } + } + @Override protected void onFinishInflate() { super.onFinishInflate(); @@ -152,25 +162,38 @@ public class SearchPanelView extends FrameLayout implements StatusBarPanel { private void maybeSwapSearchIcon() { Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE)) .getAssistIntent(mContext, false, UserHandle.USER_CURRENT); - if (intent != null) { - ComponentName component = intent.getComponent(); - replaceDrawable(mLogo, component, ASSIST_ICON_METADATA_NAME); + ComponentName component = null; + boolean isService = false; + if (isVoiceInteractorActive()) { + component = getVoiceInteractorComponentName(); + isService = true; + } else if (intent != null) { + component = intent.getComponent(); + } + if (component != null) { + replaceDrawable(mLogo, component, ASSIST_ICON_METADATA_NAME, + isService); } else { mLogo.setImageDrawable(null); } } - public void replaceDrawable(ImageView v, ComponentName component, String name) { + public void replaceDrawable(ImageView v, ComponentName component, String name, + boolean isService) { if (component != null) { try { PackageManager packageManager = mContext.getPackageManager(); // Look for the search icon specified in the activity meta-data - Bundle metaData = packageManager.getActivityInfo( - component, PackageManager.GET_META_DATA).metaData; + Bundle metaData = isService + ? packageManager.getServiceInfo( + component, PackageManager.GET_META_DATA).metaData + : packageManager.getActivityInfo( + component, PackageManager.GET_META_DATA).metaData; if (metaData != null) { int iconResId = metaData.getInt(name); if (iconResId != 0) { - Resources res = packageManager.getResourcesForActivity(component); + Resources res = packageManager.getResourcesForApplication( + component.getPackageName()); v.setImageDrawable(res.getDrawable(iconResId)); return; } diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 958caea..cfea86f 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -1922,6 +1922,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { case TYPE_PHONE: return 3; case TYPE_SEARCH_BAR: + case TYPE_VOICE_INTERACTION_STARTING: return 4; case TYPE_VOICE_INTERACTION: // voice interaction layer is almost immediately above apps. @@ -2270,16 +2271,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar); break; case TYPE_NAVIGATION_BAR_PANEL: - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.STATUS_BAR_SERVICE, - "PhoneWindowManager"); - break; case TYPE_STATUS_BAR_PANEL: - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.STATUS_BAR_SERVICE, - "PhoneWindowManager"); - break; case TYPE_STATUS_BAR_SUB_PANEL: + case TYPE_VOICE_INTERACTION_STARTING: mContext.enforceCallingOrSelfPermission( android.Manifest.permission.STATUS_BAR_SERVICE, "PhoneWindowManager"); @@ -3657,7 +3651,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop + mOverscanScreenHeight; } - } else if (attrs.type == TYPE_INPUT_METHOD || attrs.type == TYPE_VOICE_INTERACTION) { + } else if (attrs.type == TYPE_INPUT_METHOD) { pf.left = df.left = of.left = cf.left = vf.left = mDockLeft; pf.top = df.top = of.top = cf.top = vf.top = mDockTop; pf.right = df.right = of.right = cf.right = vf.right = mDockRight; @@ -3668,6 +3662,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { // IM dock windows always go to the bottom of the screen. attrs.gravity = Gravity.BOTTOM; mDockLayer = win.getSurfaceLayer(); + } else if (attrs.type == TYPE_VOICE_INTERACTION) { + pf.left = df.left = of.left = cf.left = vf.left = mUnrestrictedScreenLeft; + pf.top = df.top = of.top = mUnrestrictedScreenTop; + pf.right = df.right = of.right = cf.right = vf.right = mUnrestrictedScreenLeft + + mUnrestrictedScreenWidth; + pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop + + mUnrestrictedScreenHeight; + cf.bottom = vf.bottom = mStableBottom; + cf.top = vf.top = mStableTop; } else if (win == mStatusBar && (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { pf.left = df.left = of.left = mUnrestrictedScreenLeft; pf.top = df.top = of.top = mUnrestrictedScreenTop; diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java index d8b9140..1203735 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java @@ -26,6 +26,7 @@ import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; +import android.content.pm.PackageParser; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.database.ContentObserver; @@ -50,6 +51,7 @@ import android.text.TextUtils; import android.util.Slog; import com.android.internal.app.IVoiceInteractionManagerService; +import com.android.internal.app.IVoiceInteractionSessionShowCallback; import com.android.internal.app.IVoiceInteractor; import com.android.internal.content.PackageMonitor; import com.android.internal.os.BackgroundThread; @@ -396,7 +398,8 @@ public class VoiceInteractionManagerService extends SystemService { final int callingUid = Binder.getCallingUid(); final long caller = Binder.clearCallingIdentity(); try { - mImpl.showSessionLocked(callingPid, callingUid, args, flags); + mImpl.showSessionLocked(callingPid, callingUid, args, flags, + null /* showCallback */); } finally { Binder.restoreCallingIdentity(caller); } @@ -434,7 +437,8 @@ public class VoiceInteractionManagerService extends SystemService { final int callingUid = Binder.getCallingUid(); final long caller = Binder.clearCallingIdentity(); try { - return mImpl.showSessionLocked(callingPid, callingUid, sessionArgs, flags); + return mImpl.showSessionLocked(callingPid, callingUid, sessionArgs, flags, + null /* showCallback */); } finally { Binder.restoreCallingIdentity(caller); } @@ -720,7 +724,20 @@ public class VoiceInteractionManagerService extends SystemService { } @Override - public void showSessionForActiveService() { + public ComponentName getActiveServiceComponentName() { + synchronized (this) { + if (mContext.checkCallingPermission( + Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Caller does not hold the permission " + + Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE); + } + return mImpl != null ? mImpl.mComponent : null; + } + } + + @Override + public void showSessionForActiveService(IVoiceInteractionSessionShowCallback showCallback) { synchronized (this) { if (mContext.checkCallingPermission( Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE) @@ -740,7 +757,8 @@ public class VoiceInteractionManagerService extends SystemService { mImpl.showSessionLocked(callingPid, callingUid, new Bundle() /* sessionArgs */, VoiceInteractionService.START_SOURCE_SYSTEM | VoiceInteractionService.START_WITH_ASSIST - | VoiceInteractionService.START_WITH_SCREENSHOT); + | VoiceInteractionService.START_WITH_SCREENSHOT, + showCallback); } finally { Binder.restoreCallingIdentity(caller); } diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java index 5a91b88..1aa0d0b 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java @@ -39,6 +39,7 @@ import android.service.voice.VoiceInteractionServiceInfo; import android.util.Slog; import android.view.IWindowManager; +import com.android.internal.app.IVoiceInteractionSessionShowCallback; import com.android.internal.app.IVoiceInteractor; import java.io.FileDescriptor; @@ -134,12 +135,13 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne mContext.registerReceiver(mBroadcastReceiver, filter, null, handler); } - public boolean showSessionLocked(int callingPid, int callingUid, Bundle args, int flags) { + public boolean showSessionLocked(int callingPid, int callingUid, Bundle args, int flags, + IVoiceInteractionSessionShowCallback showCallback) { if (mActiveSession == null) { mActiveSession = new VoiceInteractionSessionConnection(mLock, mSessionComponentName, mUser, mContext, this, callingPid, callingUid); } - return mActiveSession.showLocked(args, flags); + return mActiveSession.showLocked(args, flags, showCallback); } public boolean hideSessionLocked(int callingPid, int callingUid) { diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java index 7a379c2..73c7363 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java @@ -41,10 +41,12 @@ import android.util.Slog; import android.view.IWindowManager; import android.view.WindowManager; import com.android.internal.app.IAssistScreenshotReceiver; +import com.android.internal.app.IVoiceInteractionSessionShowCallback; import com.android.internal.app.IVoiceInteractor; import com.android.internal.os.IResultReceiver; import java.io.PrintWriter; +import java.util.ArrayList; final class VoiceInteractionSessionConnection implements ServiceConnection { final static String TAG = "VoiceInteractionServiceManager"; @@ -74,6 +76,26 @@ final class VoiceInteractionSessionConnection implements ServiceConnection { Bundle mAssistData; boolean mHaveScreenshot; Bitmap mScreenshot; + ArrayList<IVoiceInteractionSessionShowCallback> mPendingShowCallbacks = new ArrayList<>(); + + IVoiceInteractionSessionShowCallback mShowCallback = + new IVoiceInteractionSessionShowCallback.Stub() { + @Override + public void onFailed() throws RemoteException { + synchronized (mLock) { + notifyPendingShowCallbacksFailedLocked(); + } + } + + @Override + public void onShown() throws RemoteException { + synchronized (mLock) { + // TODO: Figure out whether this is good enough or whether we need to hook into + // Window manager to actually wait for the window to be drawn. + notifyPendingShowCallbacksShownLocked(); + } + } + }; public interface Callback { public void sessionConnectionGone(VoiceInteractionSessionConnection connection); @@ -151,7 +173,8 @@ final class VoiceInteractionSessionConnection implements ServiceConnection { } } - public boolean showLocked(Bundle args, int flags) { + public boolean showLocked(Bundle args, int flags, + IVoiceInteractionSessionShowCallback showCallback) { if (mBound) { if (!mFullyBound) { mFullyBound = mContext.bindServiceAsUser(mBindIntent, mFullConnection, @@ -182,15 +205,23 @@ final class VoiceInteractionSessionConnection implements ServiceConnection { } if (mSession != null) { try { - mSession.show(mShowArgs, mShowFlags); + mSession.show(mShowArgs, mShowFlags, showCallback); mShowArgs = null; mShowFlags = 0; } catch (RemoteException e) { } deliverSessionDataLocked(); + } else if (showCallback != null) { + mPendingShowCallbacks.add(showCallback); } return true; } + if (showCallback != null) { + try { + showCallback.onFailed(); + } catch (RemoteException e) { + } + } return false; } @@ -320,7 +351,7 @@ final class VoiceInteractionSessionConnection implements ServiceConnection { mInteractor = interactor; if (mShown) { try { - session.show(mShowArgs, mShowFlags); + session.show(mShowArgs, mShowFlags, mShowCallback); mShowArgs = null; mShowFlags = 0; } catch (RemoteException e) { @@ -330,6 +361,26 @@ final class VoiceInteractionSessionConnection implements ServiceConnection { return true; } + private void notifyPendingShowCallbacksShownLocked() { + for (int i = 0; i < mPendingShowCallbacks.size(); i++) { + try { + mPendingShowCallbacks.get(i).onShown(); + } catch (RemoteException e) { + } + } + mPendingShowCallbacks.clear(); + } + + private void notifyPendingShowCallbacksFailedLocked() { + for (int i = 0; i < mPendingShowCallbacks.size(); i++) { + try { + mPendingShowCallbacks.get(i).onFailed(); + } catch (RemoteException e) { + } + } + mPendingShowCallbacks.clear(); + } + @Override public void onServiceConnected(ComponentName name, IBinder service) { synchronized (mLock) { |