Merge "Move event logging to TransportClient and add connection event"
This commit is contained in:
committed by
Android (Google) Code Review
commit
4e588baaa4
@@ -29,14 +29,12 @@ import android.content.pm.ResolveInfo;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.EventLog;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.backup.IBackupTransport;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.server.EventLogTags;
|
||||
import com.android.server.backup.transport.OnTransportRegisteredListener;
|
||||
import com.android.server.backup.transport.TransportClient;
|
||||
import com.android.server.backup.transport.TransportClientManager;
|
||||
@@ -574,8 +572,6 @@ public class TransportManager {
|
||||
return BackupManager.ERROR_TRANSPORT_UNAVAILABLE;
|
||||
}
|
||||
|
||||
EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, transportString, 1);
|
||||
|
||||
int result;
|
||||
try {
|
||||
String transportName = transport.name();
|
||||
@@ -587,7 +583,6 @@ public class TransportManager {
|
||||
result = BackupManager.SUCCESS;
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Transport " + transportString + " died while registering");
|
||||
EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, transportString, 0);
|
||||
result = BackupManager.ERROR_TRANSPORT_UNAVAILABLE;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,12 +29,14 @@ import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.UserHandle;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.EventLog;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.backup.IBackupTransport;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.server.EventLogTags;
|
||||
import com.android.server.backup.TransportManager;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -419,10 +421,45 @@ public class TransportClient {
|
||||
@GuardedBy("mStateLock")
|
||||
private void setStateLocked(@State int state, @Nullable IBackupTransport transport) {
|
||||
log(Log.VERBOSE, "State: " + stateToString(mState) + " => " + stateToString(state));
|
||||
onStateTransition(mState, state);
|
||||
mState = state;
|
||||
mTransport = transport;
|
||||
}
|
||||
|
||||
private void onStateTransition(int oldState, int newState) {
|
||||
String transport = mTransportComponent.flattenToShortString();
|
||||
int bound = transitionThroughState(oldState, newState, State.BOUND_AND_CONNECTING);
|
||||
int connected = transitionThroughState(oldState, newState, State.CONNECTED);
|
||||
if (bound != Transition.NO_TRANSITION) {
|
||||
int value = (bound == Transition.UP) ? 1 : 0; // 1 is bound, 0 is not bound
|
||||
EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, transport, value);
|
||||
}
|
||||
if (connected != Transition.NO_TRANSITION) {
|
||||
int value = (connected == Transition.UP) ? 1 : 0; // 1 is connected, 0 is not connected
|
||||
EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_CONNECTION, transport, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link Transition#UP}, if oldState < stateReference <= newState
|
||||
* <li>{@link Transition#DOWN}, if oldState >= stateReference > newState
|
||||
* <li>{@link Transition#NO_TRANSITION}, otherwise
|
||||
*/
|
||||
@Transition
|
||||
private int transitionThroughState(
|
||||
@State int oldState, @State int newState, @State int stateReference) {
|
||||
if (oldState < stateReference && stateReference <= newState) {
|
||||
return Transition.UP;
|
||||
}
|
||||
if (oldState >= stateReference && stateReference > newState) {
|
||||
return Transition.DOWN;
|
||||
}
|
||||
return Transition.NO_TRANSITION;
|
||||
}
|
||||
|
||||
@GuardedBy("mStateLock")
|
||||
private void checkStateIntegrityLocked() {
|
||||
switch (mState) {
|
||||
@@ -481,6 +518,14 @@ public class TransportClient {
|
||||
// CharSequence time = DateFormat.format("yyyy-MM-dd HH:mm:ss", System.currentTimeMillis());
|
||||
}
|
||||
|
||||
@IntDef({Transition.DOWN, Transition.NO_TRANSITION, Transition.UP})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
private @interface Transition {
|
||||
int DOWN = -1;
|
||||
int NO_TRANSITION = 0;
|
||||
int UP = 1;
|
||||
}
|
||||
|
||||
@IntDef({State.UNUSABLE, State.IDLE, State.BOUND_AND_CONNECTING, State.CONNECTED})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
private @interface State {
|
||||
|
||||
@@ -133,6 +133,7 @@ option java_package com.android.server
|
||||
2846 full_backup_cancelled (Package|3),(Message|3)
|
||||
|
||||
2850 backup_transport_lifecycle (Transport|3),(Bound|1|1)
|
||||
2851 backup_transport_connection (Transport|3),(Connected|1|1)
|
||||
|
||||
|
||||
# ---------------------------
|
||||
|
||||
@@ -35,8 +35,10 @@ import android.os.Looper;
|
||||
import android.os.UserHandle;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import com.android.internal.backup.IBackupTransport;
|
||||
import com.android.server.EventLogTags;
|
||||
import com.android.server.backup.TransportManager;
|
||||
import com.android.server.testing.FrameworkRobolectricTestRunner;
|
||||
import com.android.server.testing.ShadowEventLog;
|
||||
import com.android.server.testing.SystemLoaderClasses;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -48,7 +50,7 @@ import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowLooper;
|
||||
|
||||
@RunWith(FrameworkRobolectricTestRunner.class)
|
||||
@Config(manifest = Config.NONE, sdk = 26)
|
||||
@Config(manifest = Config.NONE, sdk = 26, shadows = {ShadowEventLog.class})
|
||||
@SystemLoaderClasses({TransportManager.class, TransportClient.class})
|
||||
@Presubmit
|
||||
public class TransportClientTest {
|
||||
@@ -60,6 +62,7 @@ public class TransportClientTest {
|
||||
@Mock private IBackupTransport.Stub mIBackupTransport;
|
||||
private TransportClient mTransportClient;
|
||||
private ComponentName mTransportComponent;
|
||||
private String mTransportString;
|
||||
private Intent mBindIntent;
|
||||
private ShadowLooper mShadowLooper;
|
||||
|
||||
@@ -71,6 +74,7 @@ public class TransportClientTest {
|
||||
mShadowLooper = shadowOf(mainLooper);
|
||||
mTransportComponent =
|
||||
new ComponentName(PACKAGE_NAME, PACKAGE_NAME + ".transport.Transport");
|
||||
mTransportString = mTransportComponent.flattenToShortString();
|
||||
mBindIntent = new Intent(SERVICE_ACTION_TRANSPORT_HOST).setComponent(mTransportComponent);
|
||||
mTransportClient =
|
||||
new TransportClient(
|
||||
@@ -161,7 +165,7 @@ public class TransportClientTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectAsync_whenFrameworkDoesntBind_releasesConnection() throws Exception {
|
||||
public void testConnectAsync_whenFrameworkDoesNotBind_releasesConnection() throws Exception {
|
||||
when(mContext.bindServiceAsUser(
|
||||
eq(mBindIntent),
|
||||
any(ServiceConnection.class),
|
||||
@@ -234,6 +238,82 @@ public class TransportClientTest {
|
||||
.onTransportConnectionResult(isNull(), eq(mTransportClient));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectAsync_beforeFrameworkCall_logsBoundTransition() {
|
||||
ShadowEventLog.clearEvents();
|
||||
|
||||
mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
|
||||
|
||||
assertEventLogged(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, mTransportString, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectAsync_afterOnServiceConnected_logsBoundAndConnectedTransitions() {
|
||||
ShadowEventLog.clearEvents();
|
||||
|
||||
mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
|
||||
ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
|
||||
connection.onServiceConnected(mTransportComponent, mIBackupTransport);
|
||||
|
||||
assertEventLogged(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, mTransportString, 1);
|
||||
assertEventLogged(EventLogTags.BACKUP_TRANSPORT_CONNECTION, mTransportString, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectAsync_afterOnBindingDied_logsBoundAndUnboundTransitions() {
|
||||
ShadowEventLog.clearEvents();
|
||||
|
||||
mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
|
||||
ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
|
||||
connection.onBindingDied(mTransportComponent);
|
||||
|
||||
assertEventLogged(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, mTransportString, 1);
|
||||
assertEventLogged(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, mTransportString, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnbind_whenConnected_logsDisconnectedAndUnboundTransitions() {
|
||||
mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
|
||||
ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
|
||||
connection.onServiceConnected(mTransportComponent, mIBackupTransport);
|
||||
ShadowEventLog.clearEvents();
|
||||
|
||||
mTransportClient.unbind("caller1");
|
||||
|
||||
assertEventLogged(EventLogTags.BACKUP_TRANSPORT_CONNECTION, mTransportString, 0);
|
||||
assertEventLogged(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, mTransportString, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnServiceDisconnected_whenConnected_logsDisconnectedAndUnboundTransitions() {
|
||||
mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
|
||||
ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
|
||||
connection.onServiceConnected(mTransportComponent, mIBackupTransport);
|
||||
ShadowEventLog.clearEvents();
|
||||
|
||||
connection.onServiceDisconnected(mTransportComponent);
|
||||
|
||||
assertEventLogged(EventLogTags.BACKUP_TRANSPORT_CONNECTION, mTransportString, 0);
|
||||
assertEventLogged(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, mTransportString, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnBindingDied_whenConnected_logsDisconnectedAndUnboundTransitions() {
|
||||
mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
|
||||
ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
|
||||
connection.onServiceConnected(mTransportComponent, mIBackupTransport);
|
||||
ShadowEventLog.clearEvents();
|
||||
|
||||
connection.onBindingDied(mTransportComponent);
|
||||
|
||||
assertEventLogged(EventLogTags.BACKUP_TRANSPORT_CONNECTION, mTransportString, 0);
|
||||
assertEventLogged(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, mTransportString, 0);
|
||||
}
|
||||
|
||||
private void assertEventLogged(int tag, Object... values) {
|
||||
assertThat(ShadowEventLog.hasEvent(tag, values)).isTrue();
|
||||
}
|
||||
|
||||
private ServiceConnection verifyBindServiceAsUserAndCaptureServiceConnection(Context context) {
|
||||
ArgumentCaptor<ServiceConnection> connectionCaptor =
|
||||
ArgumentCaptor.forClass(ServiceConnection.class);
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.server.testing;
|
||||
|
||||
import android.util.EventLog;
|
||||
|
||||
import org.robolectric.annotation.Implementation;
|
||||
import org.robolectric.annotation.Implements;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
@Implements(EventLog.class)
|
||||
public class ShadowEventLog {
|
||||
private final static LinkedHashSet<Entry> ENTRIES = new LinkedHashSet<>();
|
||||
|
||||
@Implementation
|
||||
public static int writeEvent(int tag, Object... values) {
|
||||
ENTRIES.add(new Entry(tag, Arrays.asList(values)));
|
||||
// Currently we don't care about the return value, if we do, estimate it correctly
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static boolean hasEvent(int tag, Object... values) {
|
||||
return ENTRIES.contains(new Entry(tag, Arrays.asList(values)));
|
||||
}
|
||||
|
||||
public static void clearEvents() {
|
||||
ENTRIES.clear();
|
||||
}
|
||||
|
||||
public static class Entry {
|
||||
public final int tag;
|
||||
public final List<Object> values;
|
||||
|
||||
public Entry(int tag, List<Object> values) {
|
||||
this.tag = tag;
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Entry entry = (Entry) o;
|
||||
return tag == entry.tag && values.equals(entry.values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = tag;
|
||||
result = 31 * result + values.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user