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