1e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk/** 2e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Copyright (c) 2016, The Android Open Source Project 3e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * 4e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Licensed under the Apache License, Version 2.0 (the "License"); 5e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * you may not use this file except in compliance with the License. 6e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * You may obtain a copy of the License at 7e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * 8e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * http://www.apache.org/licenses/LICENSE-2.0 9e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * 10e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Unless required by applicable law or agreed to in writing, software 11e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * distributed under the License is distributed on an "AS IS" BASIS, 12e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * See the License for the specific language governing permissions and 14e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * limitations under the License. 15e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 16e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkpackage com.android.server.utils; 17e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 18e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.annotation.NonNull; 19e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.app.PendingIntent; 20e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.content.ComponentName; 21e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.content.Context; 22e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.content.Intent; 23e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.content.ServiceConnection; 24e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.IBinder; 25e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.IBinder.DeathRecipient; 26e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.IInterface; 27e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.RemoteException; 28e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.UserHandle; 29e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.util.Slog; 30e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 31e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport java.util.Objects; 32e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 33e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk/** 34e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Manages the lifecycle of an application-provided service bound from system server. 35e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * 36e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @hide 37e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 38e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkpublic class ManagedApplicationService { 39e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private final String TAG = getClass().getSimpleName(); 40e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 41e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private final Context mContext; 42e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private final int mUserId; 43e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private final ComponentName mComponent; 44e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private final int mClientLabel; 45e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private final String mSettingsAction; 46e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private final BinderChecker mChecker; 47e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 48e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private final DeathRecipient mDeathRecipient = new DeathRecipient() { 49e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @Override 50e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public void binderDied() { 51e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk synchronized (mLock) { 52e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mBoundInterface = null; 53e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 54e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 55e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk }; 56e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 57e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private final Object mLock = new Object(); 58e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 59e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk // State protected by mLock 60e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private ServiceConnection mPendingConnection; 61e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private ServiceConnection mConnection; 62e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private IInterface mBoundInterface; 63c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk private PendingEvent mPendingEvent; 64c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk 65e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private ManagedApplicationService(final Context context, final ComponentName component, 66e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk final int userId, int clientLabel, String settingsAction, 67e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk BinderChecker binderChecker) { 68e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mContext = context; 69e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mComponent = component; 70e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mUserId = userId; 71e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mClientLabel = clientLabel; 72e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mSettingsAction = settingsAction; 73e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mChecker = binderChecker; 74e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 75e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 76e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk /** 77e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Implement to validate returned IBinder instance. 78e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 79e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public interface BinderChecker { 80e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk IInterface asInterface(IBinder binder); 81e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk boolean checkType(IInterface service); 82e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 83e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 84e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk /** 85c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk * Implement to call IInterface methods after service is connected. 86c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk */ 87c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk public interface PendingEvent { 88c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk void runEvent(IInterface service) throws RemoteException; 89c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk } 90c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk 91c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk /** 92e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Create a new ManagedApplicationService object but do not yet bind to the user service. 93e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * 94e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param context a Context to use for binding the application service. 95e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param component the {@link ComponentName} of the application service to bind. 96e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param userId the user ID of user to bind the application service as. 97e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param clientLabel the resource ID of a label displayed to the user indicating the 98e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * binding service. 99e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param settingsAction an action that can be used to open the Settings UI to enable/disable 100e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * binding to these services. 101e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param binderChecker an interface used to validate the returned binder object. 102e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @return a ManagedApplicationService instance. 103e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 104e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public static ManagedApplicationService build(@NonNull final Context context, 105e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @NonNull final ComponentName component, final int userId, @NonNull int clientLabel, 106e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @NonNull String settingsAction, @NonNull BinderChecker binderChecker) { 107e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk return new ManagedApplicationService(context, component, userId, clientLabel, 108e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk settingsAction, binderChecker); 109e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 110e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 111e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk /** 112e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @return the user ID of the user that owns the bound service. 113e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 114e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public int getUserId() { 115e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk return mUserId; 116e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 117e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 118e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk /** 119e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @return the component of the bound service. 120e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 121e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public ComponentName getComponent() { 122e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk return mComponent; 123e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 124e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 125e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk /** 126e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Asynchronously unbind from the application service if the bound service component and user 127e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * does not match the given signature. 128e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * 129e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param componentName the component that must match. 130e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param userId the user ID that must match. 131e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @return {@code true} if not matching. 132e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 133e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public boolean disconnectIfNotMatching(final ComponentName componentName, final int userId) { 134e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk if (matches(componentName, userId)) { 135e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk return false; 136e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 137e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk disconnect(); 138e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk return true; 139e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 140e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 141c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk 142c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk /** 143c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk * Send an event to run as soon as the binder interface is available. 144c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk * 145c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk * @param event a {@link PendingEvent} to send. 146c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk */ 147c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk public void sendEvent(@NonNull PendingEvent event) { 148c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk IInterface iface; 149c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk synchronized (mLock) { 150c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk iface = mBoundInterface; 151c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk if (iface == null) { 152c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk mPendingEvent = event; 153c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk } 154c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk } 155c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk 156c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk if (iface != null) { 157c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk try { 158c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk event.runEvent(iface); 159c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk } catch (RuntimeException | RemoteException ex) { 160c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk Slog.e(TAG, "Received exception from user service: ", ex); 161c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk } 162c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk } 163c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk } 164c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk 165e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk /** 166e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Asynchronously unbind from the application service if bound. 167e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 168e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public void disconnect() { 169e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk synchronized (mLock) { 170e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk // Wipe out pending connections 171e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mPendingConnection = null; 172e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 173e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk // Unbind existing connection, if it exists 174e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk if (mConnection != null) { 175e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mContext.unbindService(mConnection); 176e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mConnection = null; 177e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 178e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 179e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mBoundInterface = null; 180e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 181e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 182e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 183e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk /** 184e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Asynchronously bind to the application service if not bound. 185e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 186e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public void connect() { 187e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk synchronized (mLock) { 188e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk if (mConnection != null || mPendingConnection != null) { 189e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk // We're already connected or are trying to connect 190e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk return; 191e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 192e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 193e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk final PendingIntent pendingIntent = PendingIntent.getActivity( 194e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mContext, 0, new Intent(mSettingsAction), 0); 195e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk final Intent intent = new Intent().setComponent(mComponent). 196e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk putExtra(Intent.EXTRA_CLIENT_LABEL, mClientLabel). 197e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk putExtra(Intent.EXTRA_CLIENT_INTENT, pendingIntent); 198e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 199e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk final ServiceConnection serviceConnection = new ServiceConnection() { 200e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @Override 201e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public void onServiceConnected(ComponentName componentName, IBinder iBinder) { 202c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk IInterface iface = null; 203c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk PendingEvent pendingEvent = null; 204e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk synchronized (mLock) { 205e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk if (mPendingConnection == this) { 206e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk // No longer pending, remove from pending connection 207e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mPendingConnection = null; 208e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mConnection = this; 209e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } else { 210e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk // Service connection wasn't pending, must have been disconnected 211e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mContext.unbindService(this); 2124beb6be3538f8da2a8206917cf17d9d5dd4d34acRuben Brunk return; 213e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 214e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 215e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk try { 216e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk iBinder.linkToDeath(mDeathRecipient, 0); 217e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mBoundInterface = mChecker.asInterface(iBinder); 218e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk if (!mChecker.checkType(mBoundInterface)) { 219e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk // Received an invalid binder, disconnect 220e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mContext.unbindService(this); 221e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mBoundInterface = null; 222e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 223c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk iface = mBoundInterface; 224c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk pendingEvent = mPendingEvent; 225c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk mPendingEvent = null; 226e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } catch (RemoteException e) { 227e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk // DOA 228e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk Slog.w(TAG, "Unable to bind service: " + intent, e); 229e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mBoundInterface = null; 230e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 231e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 232c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk if (iface != null && pendingEvent != null) { 233c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk try { 234c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk pendingEvent.runEvent(iface); 235c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk } catch (RuntimeException | RemoteException ex) { 236c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk Slog.e(TAG, "Received exception from user service: ", ex); 237c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk } 238c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk } 239e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 240e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 241e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @Override 242e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public void onServiceDisconnected(ComponentName componentName) { 243e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk Slog.w(TAG, "Service disconnected: " + intent); 2444beb6be3538f8da2a8206917cf17d9d5dd4d34acRuben Brunk mConnection = null; 2454beb6be3538f8da2a8206917cf17d9d5dd4d34acRuben Brunk mBoundInterface = null; 246e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 247e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk }; 248e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 249e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mPendingConnection = serviceConnection; 250e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 251e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk try { 252e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk if (!mContext.bindServiceAsUser(intent, serviceConnection, 253e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, 254e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk new UserHandle(mUserId))) { 255e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk Slog.w(TAG, "Unable to bind service: " + intent); 256e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 257e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } catch (SecurityException e) { 258e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk Slog.w(TAG, "Unable to bind service: " + intent, e); 259e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 260e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 261e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 262e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 263e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private boolean matches(final ComponentName component, final int userId) { 264e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk return Objects.equals(mComponent, component) && mUserId == userId; 265e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 266e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk} 267