1b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy/* 2b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy * Copyright (C) 2015 The Android Open Source Project 3b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy * 4b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy * Licensed under the Apache License, Version 2.0 (the "License"); 5b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy * you may not use this file except in compliance with the License. 6b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy * You may obtain a copy of the License at 7b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy * 8b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy * http://www.apache.org/licenses/LICENSE-2.0 9b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy * 10b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy * Unless required by applicable law or agreed to in writing, software 11b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy * distributed under the License is distributed on an "AS IS" BASIS, 12b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy * See the License for the specific language governing permissions and 14b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy * limitations under the License. 15b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy */ 16b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy 17b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedypackage com.android.server.pm; 18b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy 19b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedyimport android.content.ComponentName; 20b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedyimport android.content.Context; 21b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedyimport android.content.Intent; 22b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedyimport android.content.ServiceConnection; 237440f177c3e70da0b883f8abffd6c8fc1d507bb8Todd Kennedyimport android.content.pm.EphemeralResolveInfo; 24b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedyimport android.os.Build; 25b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedyimport android.os.Bundle; 26b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedyimport android.os.IBinder; 27b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedyimport android.os.IRemoteCallback; 28b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedyimport android.os.RemoteException; 29b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedyimport android.os.SystemClock; 30b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedyimport android.os.UserHandle; 31b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedyimport android.util.TimedRemoteCaller; 32b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy 33b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedyimport com.android.internal.app.EphemeralResolverService; 34b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedyimport com.android.internal.app.IEphemeralResolver; 35b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy 36b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedyimport java.io.FileDescriptor; 37b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedyimport java.io.PrintWriter; 38b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedyimport java.util.ArrayList; 39b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedyimport java.util.List; 40b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedyimport java.util.concurrent.TimeoutException; 41b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy 42b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy/** 43b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy * Represents a remote ephemeral resolver. It is responsible for binding to the remote 44b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy * service and handling all interactions in a timely manner. 45b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy * @hide 46b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy */ 47b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedyfinal class EphemeralResolverConnection { 48b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy // This is running in a critical section and the timeout must be sufficiently low 49b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy private static final long BIND_SERVICE_TIMEOUT_MS = 50b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy ("eng".equals(Build.TYPE)) ? 300 : 200; 51b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy 52b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy private final Object mLock = new Object(); 53b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy private final GetEphemeralResolveInfoCaller mGetEphemeralResolveInfoCaller = 54b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy new GetEphemeralResolveInfoCaller(); 55b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy private final ServiceConnection mServiceConnection = new MyServiceConnection(); 56b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy private final Context mContext; 57b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy /** Intent used to bind to the service */ 58b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy private final Intent mIntent; 59b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy 60b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy private IEphemeralResolver mRemoteInstance; 61b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy 62b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy public EphemeralResolverConnection(Context context, ComponentName componentName) { 63b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy mContext = context; 64b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy mIntent = new Intent().setComponent(componentName); 65b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 66b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy 67b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy public final List<EphemeralResolveInfo> getEphemeralResolveInfoList(int hashPrefix) { 68b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy throwIfCalledOnMainThread(); 69b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy try { 70b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy return mGetEphemeralResolveInfoCaller.getEphemeralResolveInfoList( 71b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy getRemoteInstanceLazy(), hashPrefix); 72b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } catch (RemoteException re) { 73b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } catch (TimeoutException te) { 74b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } finally { 75b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy synchronized (mLock) { 76b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy mLock.notifyAll(); 77b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 78b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 79b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy return null; 80b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 81b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy 82b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy public void dump(FileDescriptor fd, PrintWriter pw, String prefix) { 83b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy synchronized (mLock) { 84b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy pw.append(prefix).append("bound=") 85b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy .append((mRemoteInstance != null) ? "true" : "false").println(); 86b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy 87b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy pw.flush(); 88b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy 89b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy try { 90b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy getRemoteInstanceLazy().asBinder().dump(fd, new String[] { prefix }); 91b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } catch (TimeoutException te) { 92b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy /* ignore */ 93b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } catch (RemoteException re) { 94b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy /* ignore */ 95b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 96b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 97b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 98b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy 99b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy private IEphemeralResolver getRemoteInstanceLazy() throws TimeoutException { 100b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy synchronized (mLock) { 101b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy if (mRemoteInstance != null) { 102b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy return mRemoteInstance; 103b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 104b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy bindLocked(); 105b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy return mRemoteInstance; 106b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 107b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 108b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy 109b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy private void bindLocked() throws TimeoutException { 110b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy if (mRemoteInstance != null) { 111b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy return; 112b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 113b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy 114b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy mContext.bindServiceAsUser(mIntent, mServiceConnection, 115b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, UserHandle.SYSTEM); 116b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy 117b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy final long startMillis = SystemClock.uptimeMillis(); 118b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy while (true) { 119b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy if (mRemoteInstance != null) { 120b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy break; 121b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 122b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy final long elapsedMillis = SystemClock.uptimeMillis() - startMillis; 123b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy final long remainingMillis = BIND_SERVICE_TIMEOUT_MS - elapsedMillis; 124b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy if (remainingMillis <= 0) { 125b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy throw new TimeoutException("Didn't bind to resolver in time."); 126b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 127b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy try { 128b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy mLock.wait(remainingMillis); 129b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } catch (InterruptedException ie) { 130b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy /* ignore */ 131b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 132b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 133b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy 134b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy mLock.notifyAll(); 135b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 136b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy 137b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy private void throwIfCalledOnMainThread() { 138b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy if (Thread.currentThread() == mContext.getMainLooper().getThread()) { 139b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy throw new RuntimeException("Cannot invoke on the main thread"); 140b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 141b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 142b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy 143b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy private final class MyServiceConnection implements ServiceConnection { 144b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy @Override 145b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy public void onServiceConnected(ComponentName name, IBinder service) { 146b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy synchronized (mLock) { 147b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy mRemoteInstance = IEphemeralResolver.Stub.asInterface(service); 148b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy mLock.notifyAll(); 149b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 150b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 151b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy 152b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy @Override 153b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy public void onServiceDisconnected(ComponentName name) { 154b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy synchronized (mLock) { 155b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy mRemoteInstance = null; 156b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 157b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 158b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 159b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy 160b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy private static final class GetEphemeralResolveInfoCaller 161b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy extends TimedRemoteCaller<List<EphemeralResolveInfo>> { 162b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy private final IRemoteCallback mCallback; 163b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy 164b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy public GetEphemeralResolveInfoCaller() { 165b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy super(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS); 166b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy mCallback = new IRemoteCallback.Stub() { 167b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy @Override 168b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy public void sendResult(Bundle data) throws RemoteException { 169b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy final ArrayList<EphemeralResolveInfo> resolveList = 170b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy data.getParcelableArrayList( 171b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy EphemeralResolverService.EXTRA_RESOLVE_INFO); 172b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy int sequence = 173b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy data.getInt(EphemeralResolverService.EXTRA_SEQUENCE, -1); 174b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy onRemoteMethodResult(resolveList, sequence); 175b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 176b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy }; 177b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 178b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy 179b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy public List<EphemeralResolveInfo> getEphemeralResolveInfoList( 180b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy IEphemeralResolver target, int hashPrefix) 181b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy throws RemoteException, TimeoutException { 182b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy final int sequence = onBeforeRemoteCall(); 183b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy target.getEphemeralResolveInfoList(mCallback, hashPrefix, sequence); 184b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy return getResultTimed(sequence); 185b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 186b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy } 187b8a279ee838c309a64211a3caa5e5e204250163dTodd Kennedy} 188