/* * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import android.os.Binder; import android.os.RemoteException; import java.util.concurrent.Executor; class IndirectStarvation { static Binder binder; // executors are injected and annotated as to what thread they schedule to @ForUiThread private final Executor mUiThreadExecutor = null; @ForNonUiThread private final Executor mNonUiThreadExecutor = null; // call which should not happen on UI thread private static void doTransact() { try { binder.transact(0, null, null, 0); } catch (RemoteException e) { } } Object monitorA; // starvation via locking on UI thread and doing a transaction under that lock // in a background thread public void postBlockingCallToBackgroundThreadAndLockBad() { mUiThreadExecutor.execute( new Runnable() { @Override public void run() { synchronized (monitorA) { } } }); mNonUiThreadExecutor.execute( new Runnable() { @Override public void run() { synchronized (monitorA) { doTransact(); } } }); } Object monitorB, monitorC; // no starvation, as lock on UI thread is not used for transaction on background thread public void postBlockingCallToBackgroundThreadAndUseOtherLockOk() { mUiThreadExecutor.execute( new Runnable() { @Override public void run() { synchronized (monitorB) { } } }); mNonUiThreadExecutor.execute( new Runnable() { @Override public void run() { synchronized (monitorC) { doTransact(); } } }); } }