Merge "Update ObservableServiceConnection to bind to services as the current user." into udc-dev
This commit is contained in:
@@ -25,6 +25,7 @@ import android.os.IBinder;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.systemui.dagger.qualifiers.Main;
|
import com.android.systemui.dagger.qualifiers.Main;
|
||||||
|
import com.android.systemui.settings.UserTracker;
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
@@ -108,6 +109,7 @@ public class ObservableServiceConnection<T> implements ServiceConnection {
|
|||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final Intent mServiceIntent;
|
private final Intent mServiceIntent;
|
||||||
|
private final UserTracker mUserTracker;
|
||||||
private final int mFlags;
|
private final int mFlags;
|
||||||
private final Executor mExecutor;
|
private final Executor mExecutor;
|
||||||
private final ServiceTransformer<T> mTransformer;
|
private final ServiceTransformer<T> mTransformer;
|
||||||
@@ -127,10 +129,12 @@ public class ObservableServiceConnection<T> implements ServiceConnection {
|
|||||||
*/
|
*/
|
||||||
@Inject
|
@Inject
|
||||||
public ObservableServiceConnection(Context context, Intent serviceIntent,
|
public ObservableServiceConnection(Context context, Intent serviceIntent,
|
||||||
|
UserTracker userTracker,
|
||||||
@Main Executor executor,
|
@Main Executor executor,
|
||||||
ServiceTransformer<T> transformer) {
|
ServiceTransformer<T> transformer) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mServiceIntent = serviceIntent;
|
mServiceIntent = serviceIntent;
|
||||||
|
mUserTracker = userTracker;
|
||||||
mFlags = Context.BIND_AUTO_CREATE;
|
mFlags = Context.BIND_AUTO_CREATE;
|
||||||
mExecutor = executor;
|
mExecutor = executor;
|
||||||
mTransformer = transformer;
|
mTransformer = transformer;
|
||||||
@@ -145,7 +149,8 @@ public class ObservableServiceConnection<T> implements ServiceConnection {
|
|||||||
public boolean bind() {
|
public boolean bind() {
|
||||||
boolean bindResult = false;
|
boolean bindResult = false;
|
||||||
try {
|
try {
|
||||||
bindResult = mContext.bindService(mServiceIntent, mFlags, mExecutor, this);
|
bindResult = mContext.bindServiceAsUser(mServiceIntent, this, mFlags,
|
||||||
|
mUserTracker.getUserHandle());
|
||||||
} catch (SecurityException e) {
|
} catch (SecurityException e) {
|
||||||
Log.d(TAG, "Could not bind to service", e);
|
Log.d(TAG, "Could not bind to service", e);
|
||||||
mContext.unbindService(this);
|
mContext.unbindService(this);
|
||||||
@@ -228,11 +233,13 @@ public class ObservableServiceConnection<T> implements ServiceConnection {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||||
|
mExecutor.execute(() -> {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "onServiceConnected");
|
Log.d(TAG, "onServiceConnected");
|
||||||
}
|
}
|
||||||
mProxy = mTransformer.convert(service);
|
mProxy = mTransformer.convert(service);
|
||||||
applyToCallbacksLocked(callback -> callback.onConnected(this, mProxy));
|
applyToCallbacksLocked(callback -> callback.onConnected(this, mProxy));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyToCallbacksLocked(Consumer<Callback<T>> applicator) {
|
private void applyToCallbacksLocked(Consumer<Callback<T>> applicator) {
|
||||||
@@ -250,16 +257,16 @@ public class ObservableServiceConnection<T> implements ServiceConnection {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceDisconnected(ComponentName name) {
|
public void onServiceDisconnected(ComponentName name) {
|
||||||
onDisconnected(DISCONNECT_REASON_DISCONNECTED);
|
mExecutor.execute(() -> onDisconnected(DISCONNECT_REASON_DISCONNECTED));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindingDied(ComponentName name) {
|
public void onBindingDied(ComponentName name) {
|
||||||
onDisconnected(DISCONNECT_REASON_DISCONNECTED);
|
mExecutor.execute(() -> onDisconnected(DISCONNECT_REASON_BINDING_DIED));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNullBinding(ComponentName name) {
|
public void onNullBinding(ComponentName name) {
|
||||||
onDisconnected(DISCONNECT_REASON_NULL_BINDING);
|
mExecutor.execute(() -> onDisconnected(DISCONNECT_REASON_NULL_BINDING));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,12 +29,15 @@ import static org.mockito.Mockito.when;
|
|||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.pm.UserInfo;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.os.UserHandle;
|
||||||
import android.testing.AndroidTestingRunner;
|
import android.testing.AndroidTestingRunner;
|
||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
|
import com.android.systemui.settings.FakeUserTracker;
|
||||||
import com.android.systemui.util.concurrency.FakeExecutor;
|
import com.android.systemui.util.concurrency.FakeExecutor;
|
||||||
import com.android.systemui.util.time.FakeSystemClock;
|
import com.android.systemui.util.time.FakeSystemClock;
|
||||||
|
|
||||||
@@ -44,6 +47,7 @@ import org.junit.runner.RunWith;
|
|||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@@ -93,15 +97,22 @@ public class ObservableServiceConnectionTest extends SysuiTestCase {
|
|||||||
|
|
||||||
FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
|
FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
|
||||||
|
|
||||||
|
private FakeUserTracker mUserTracker;
|
||||||
|
|
||||||
|
private static final int MAIN_USER_ID = 10;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
|
mUserTracker = new FakeUserTracker();
|
||||||
|
// Set the main user as the current user.
|
||||||
|
mUserTracker.set(List.of(new UserInfo(MAIN_USER_ID, "main", UserInfo.FLAG_MAIN)), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConnect() {
|
public void testConnect() {
|
||||||
ObservableServiceConnection<Foo> connection = new ObservableServiceConnection<>(mContext,
|
ObservableServiceConnection<Foo> connection = new ObservableServiceConnection<>(mContext,
|
||||||
mIntent, mExecutor, mTransformer);
|
mIntent, mUserTracker, mExecutor, mTransformer);
|
||||||
// Register twice to ensure only one callback occurs.
|
// Register twice to ensure only one callback occurs.
|
||||||
connection.addCallback(mCallback);
|
connection.addCallback(mCallback);
|
||||||
connection.addCallback(mCallback);
|
connection.addCallback(mCallback);
|
||||||
@@ -121,15 +132,16 @@ public class ObservableServiceConnectionTest extends SysuiTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testDisconnect() {
|
public void testDisconnect() {
|
||||||
ObservableServiceConnection<Foo> connection = new ObservableServiceConnection<>(mContext,
|
ObservableServiceConnection<Foo> connection = new ObservableServiceConnection<>(mContext,
|
||||||
mIntent, mExecutor, mTransformer);
|
mIntent, mUserTracker, mExecutor, mTransformer);
|
||||||
connection.addCallback(mCallback);
|
connection.addCallback(mCallback);
|
||||||
connection.onServiceDisconnected(mComponentName);
|
connection.onServiceDisconnected(mComponentName);
|
||||||
|
mExecutor.runAllReady();
|
||||||
|
|
||||||
// Disconnects before binds should be ignored.
|
// Disconnects before binds should be ignored.
|
||||||
verify(mCallback, never()).onDisconnected(eq(connection), anyInt());
|
verify(mCallback, never()).onDisconnected(eq(connection), anyInt());
|
||||||
|
|
||||||
when(mContext.bindService(eq(mIntent), anyInt(), eq(mExecutor), eq(connection)))
|
when(mContext.bindServiceAsUser(eq(mIntent), eq(connection), anyInt(),
|
||||||
.thenReturn(true);
|
eq(UserHandle.of(MAIN_USER_ID)))).thenReturn(true);
|
||||||
connection.bind();
|
connection.bind();
|
||||||
connection.onServiceDisconnected(mComponentName);
|
connection.onServiceDisconnected(mComponentName);
|
||||||
|
|
||||||
@@ -151,15 +163,16 @@ public class ObservableServiceConnectionTest extends SysuiTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testUnbind() {
|
public void testUnbind() {
|
||||||
ObservableServiceConnection<Foo> connection = new ObservableServiceConnection<>(mContext,
|
ObservableServiceConnection<Foo> connection = new ObservableServiceConnection<>(mContext,
|
||||||
mIntent, mExecutor, mTransformer);
|
mIntent, mUserTracker, mExecutor, mTransformer);
|
||||||
connection.addCallback(mCallback);
|
connection.addCallback(mCallback);
|
||||||
connection.onServiceDisconnected(mComponentName);
|
connection.onServiceDisconnected(mComponentName);
|
||||||
|
mExecutor.runAllReady();
|
||||||
|
|
||||||
// Disconnects before binds should be ignored.
|
// Disconnects before binds should be ignored.
|
||||||
verify(mCallback, never()).onDisconnected(eq(connection), anyInt());
|
verify(mCallback, never()).onDisconnected(eq(connection), anyInt());
|
||||||
|
|
||||||
when(mContext.bindService(eq(mIntent), anyInt(), eq(mExecutor), eq(connection)))
|
when(mContext.bindServiceAsUser(eq(mIntent), eq(connection), anyInt(),
|
||||||
.thenReturn(true);
|
eq(UserHandle.of(MAIN_USER_ID)))).thenReturn(true);
|
||||||
connection.bind();
|
connection.bind();
|
||||||
|
|
||||||
mExecutor.runAllReady();
|
mExecutor.runAllReady();
|
||||||
@@ -175,10 +188,11 @@ public class ObservableServiceConnectionTest extends SysuiTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testBindServiceThrowsError() {
|
public void testBindServiceThrowsError() {
|
||||||
ObservableServiceConnection<Foo> connection = new ObservableServiceConnection<>(mContext,
|
ObservableServiceConnection<Foo> connection = new ObservableServiceConnection<>(mContext,
|
||||||
mIntent, mExecutor, mTransformer);
|
mIntent, mUserTracker, mExecutor, mTransformer);
|
||||||
connection.addCallback(mCallback);
|
connection.addCallback(mCallback);
|
||||||
|
|
||||||
when(mContext.bindService(eq(mIntent), anyInt(), eq(mExecutor), eq(connection)))
|
when(mContext.bindServiceAsUser(eq(mIntent), eq(connection), anyInt(),
|
||||||
|
eq(UserHandle.of(MAIN_USER_ID))))
|
||||||
.thenThrow(new SecurityException());
|
.thenThrow(new SecurityException());
|
||||||
|
|
||||||
// Verify that the exception was caught and that bind returns false, and we properly
|
// Verify that the exception was caught and that bind returns false, and we properly
|
||||||
|
|||||||
Reference in New Issue
Block a user