Merge "Add dumpsys support to RulesManagerService"
This commit is contained in:
@@ -125,4 +125,8 @@ public final class DistroRulesVersion implements Parcelable {
|
|||||||
+ ", mRevision='" + mRevision + '\''
|
+ ", mRevision='" + mRevision + '\''
|
||||||
+ '}';
|
+ '}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toDumpString() {
|
||||||
|
return mRulesVersion + "," + mRevision;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import java.io.FileOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
import static com.android.server.timezone.PackageStatus.CHECK_COMPLETED_FAILURE;
|
import static com.android.server.timezone.PackageStatus.CHECK_COMPLETED_FAILURE;
|
||||||
import static com.android.server.timezone.PackageStatus.CHECK_COMPLETED_SUCCESS;
|
import static com.android.server.timezone.PackageStatus.CHECK_COMPLETED_SUCCESS;
|
||||||
@@ -375,4 +376,8 @@ final class PackageStatusStorage {
|
|||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void dump(PrintWriter printWriter) {
|
||||||
|
printWriter.println("Package status: " + getPackageStatus());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import android.provider.TimeZoneRulesDataContract;
|
|||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Monitors the installed applications associated with time zone updates. If the app packages are
|
* Monitors the installed applications associated with time zone updates. If the app packages are
|
||||||
@@ -510,4 +511,23 @@ public class PackageTracker implements IntentHelper.Listener {
|
|||||||
Slog.wtf(TAG, message, cause);
|
Slog.wtf(TAG, message, cause);
|
||||||
throw new RuntimeException(message, cause);
|
throw new RuntimeException(message, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void dump(PrintWriter fout) {
|
||||||
|
fout.println("PackageTrackerState: " + toString());
|
||||||
|
mPackageStatusStorage.dump(fout);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "PackageTracker{" +
|
||||||
|
"mTrackingEnabled=" + mTrackingEnabled +
|
||||||
|
", mUpdateAppPackageName='" + mUpdateAppPackageName + '\'' +
|
||||||
|
", mDataAppPackageName='" + mDataAppPackageName + '\'' +
|
||||||
|
", mCheckTimeAllowedMillis=" + mCheckTimeAllowedMillis +
|
||||||
|
", mFailedCheckRetryCount=" + mFailedCheckRetryCount +
|
||||||
|
", mLastTriggerTimestamp=" + mLastTriggerTimestamp +
|
||||||
|
", mCheckTriggered=" + mCheckTriggered +
|
||||||
|
", mCheckFailureCount=" + mCheckFailureCount +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,14 @@
|
|||||||
|
|
||||||
package com.android.server.timezone;
|
package com.android.server.timezone;
|
||||||
|
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An easy-to-mock interface around permission checks for use by {@link RulesManagerService}.
|
* An easy-to-mock interface around permission checks for use by {@link RulesManagerService}.
|
||||||
*/
|
*/
|
||||||
public interface PermissionHelper {
|
public interface PermissionHelper {
|
||||||
|
|
||||||
void enforceCallerHasPermission(String requiredPermission) throws SecurityException;
|
void enforceCallerHasPermission(String requiredPermission) throws SecurityException;
|
||||||
|
|
||||||
|
boolean checkDumpPermission(String tag, PrintWriter printWriter);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,12 +37,24 @@ import android.os.RemoteException;
|
|||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileDescriptor;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.PrintWriter;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import libcore.icu.ICU;
|
||||||
|
import libcore.util.ZoneInfoDB;
|
||||||
|
|
||||||
|
import static android.app.timezone.RulesState.DISTRO_STATUS_INSTALLED;
|
||||||
|
import static android.app.timezone.RulesState.DISTRO_STATUS_NONE;
|
||||||
|
import static android.app.timezone.RulesState.DISTRO_STATUS_UNKNOWN;
|
||||||
|
import static android.app.timezone.RulesState.STAGED_OPERATION_INSTALL;
|
||||||
|
import static android.app.timezone.RulesState.STAGED_OPERATION_NONE;
|
||||||
|
import static android.app.timezone.RulesState.STAGED_OPERATION_UNINSTALL;
|
||||||
|
import static android.app.timezone.RulesState.STAGED_OPERATION_UNKNOWN;
|
||||||
|
|
||||||
// TODO(nfuller) Add EventLog calls where useful in the system server.
|
// TODO(nfuller) Add EventLog calls where useful in the system server.
|
||||||
// TODO(nfuller) Check logging best practices in the system server.
|
// TODO(nfuller) Check logging best practices in the system server.
|
||||||
@@ -113,6 +125,11 @@ public final class RulesManagerService extends IRulesManager.Stub {
|
|||||||
public RulesState getRulesState() {
|
public RulesState getRulesState() {
|
||||||
mPermissionHelper.enforceCallerHasPermission(REQUIRED_UPDATER_PERMISSION);
|
mPermissionHelper.enforceCallerHasPermission(REQUIRED_UPDATER_PERMISSION);
|
||||||
|
|
||||||
|
return getRulesStateInternal();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Like {@link #getRulesState()} without the permission check. */
|
||||||
|
private RulesState getRulesStateInternal() {
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
String systemRulesVersion;
|
String systemRulesVersion;
|
||||||
try {
|
try {
|
||||||
@@ -126,18 +143,18 @@ public final class RulesManagerService extends IRulesManager.Stub {
|
|||||||
|
|
||||||
// Determine the staged operation status, if possible.
|
// Determine the staged operation status, if possible.
|
||||||
DistroRulesVersion stagedDistroRulesVersion = null;
|
DistroRulesVersion stagedDistroRulesVersion = null;
|
||||||
int stagedOperationStatus = RulesState.STAGED_OPERATION_UNKNOWN;
|
int stagedOperationStatus = STAGED_OPERATION_UNKNOWN;
|
||||||
if (!operationInProgress) {
|
if (!operationInProgress) {
|
||||||
StagedDistroOperation stagedDistroOperation;
|
StagedDistroOperation stagedDistroOperation;
|
||||||
try {
|
try {
|
||||||
stagedDistroOperation = mInstaller.getStagedDistroOperation();
|
stagedDistroOperation = mInstaller.getStagedDistroOperation();
|
||||||
if (stagedDistroOperation == null) {
|
if (stagedDistroOperation == null) {
|
||||||
stagedOperationStatus = RulesState.STAGED_OPERATION_NONE;
|
stagedOperationStatus = STAGED_OPERATION_NONE;
|
||||||
} else if (stagedDistroOperation.isUninstall) {
|
} else if (stagedDistroOperation.isUninstall) {
|
||||||
stagedOperationStatus = RulesState.STAGED_OPERATION_UNINSTALL;
|
stagedOperationStatus = STAGED_OPERATION_UNINSTALL;
|
||||||
} else {
|
} else {
|
||||||
// Must be an install.
|
// Must be an install.
|
||||||
stagedOperationStatus = RulesState.STAGED_OPERATION_INSTALL;
|
stagedOperationStatus = STAGED_OPERATION_INSTALL;
|
||||||
DistroVersion stagedDistroVersion = stagedDistroOperation.distroVersion;
|
DistroVersion stagedDistroVersion = stagedDistroOperation.distroVersion;
|
||||||
stagedDistroRulesVersion = new DistroRulesVersion(
|
stagedDistroRulesVersion = new DistroRulesVersion(
|
||||||
stagedDistroVersion.rulesVersion,
|
stagedDistroVersion.rulesVersion,
|
||||||
@@ -150,16 +167,16 @@ public final class RulesManagerService extends IRulesManager.Stub {
|
|||||||
|
|
||||||
// Determine the installed distro state, if possible.
|
// Determine the installed distro state, if possible.
|
||||||
DistroVersion installedDistroVersion;
|
DistroVersion installedDistroVersion;
|
||||||
int distroStatus = RulesState.DISTRO_STATUS_UNKNOWN;
|
int distroStatus = DISTRO_STATUS_UNKNOWN;
|
||||||
DistroRulesVersion installedDistroRulesVersion = null;
|
DistroRulesVersion installedDistroRulesVersion = null;
|
||||||
if (!operationInProgress) {
|
if (!operationInProgress) {
|
||||||
try {
|
try {
|
||||||
installedDistroVersion = mInstaller.getInstalledDistroVersion();
|
installedDistroVersion = mInstaller.getInstalledDistroVersion();
|
||||||
if (installedDistroVersion == null) {
|
if (installedDistroVersion == null) {
|
||||||
distroStatus = RulesState.DISTRO_STATUS_NONE;
|
distroStatus = DISTRO_STATUS_NONE;
|
||||||
installedDistroRulesVersion = null;
|
installedDistroRulesVersion = null;
|
||||||
} else {
|
} else {
|
||||||
distroStatus = RulesState.DISTRO_STATUS_INSTALLED;
|
distroStatus = DISTRO_STATUS_INSTALLED;
|
||||||
installedDistroRulesVersion = new DistroRulesVersion(
|
installedDistroRulesVersion = new DistroRulesVersion(
|
||||||
installedDistroVersion.rulesVersion,
|
installedDistroVersion.rulesVersion,
|
||||||
installedDistroVersion.revision);
|
installedDistroVersion.revision);
|
||||||
@@ -358,6 +375,87 @@ public final class RulesManagerService extends IRulesManager.Stub {
|
|||||||
mPackageTracker.recordCheckResult(checkToken, success);
|
mPackageTracker.recordCheckResult(checkToken, success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||||
|
if (!mPermissionHelper.checkDumpPermission(TAG, pw)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RulesState rulesState = getRulesStateInternal();
|
||||||
|
if (args != null && args.length == 2) {
|
||||||
|
// Formatting options used for automated tests. The format is less free-form than
|
||||||
|
// the -format options, which are intended to be easier to parse.
|
||||||
|
if ("-format_state".equals(args[0]) && args[1] != null) {
|
||||||
|
for (char c : args[1].toCharArray()) {
|
||||||
|
switch (c) {
|
||||||
|
case 'p': // Report operation in progress
|
||||||
|
pw.println("Operation in progress: "
|
||||||
|
+ rulesState.isOperationInProgress());
|
||||||
|
break;
|
||||||
|
case 's': // Report system image rules version
|
||||||
|
pw.println("System rules version: "
|
||||||
|
+ rulesState.getSystemRulesVersion());
|
||||||
|
break;
|
||||||
|
case 'c': // Report current installation state
|
||||||
|
pw.println("Current install state: "
|
||||||
|
+ distroStatusToString(rulesState.getDistroStatus()));
|
||||||
|
break;
|
||||||
|
case 'i': // Report currently installed version
|
||||||
|
DistroRulesVersion installedRulesVersion =
|
||||||
|
rulesState.getInstalledDistroRulesVersion();
|
||||||
|
pw.print("Installed rules version: ");
|
||||||
|
if (installedRulesVersion == null) {
|
||||||
|
pw.println("<None>");
|
||||||
|
} else {
|
||||||
|
pw.println(installedRulesVersion.toDumpString());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'o': // Report staged operation type
|
||||||
|
int stagedOperationType = rulesState.getStagedOperationType();
|
||||||
|
pw.println("Staged operation: "
|
||||||
|
+ stagedOperationToString(stagedOperationType));
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
// Report staged version (i.e. the one that will be installed next boot
|
||||||
|
// if the staged operation is an install).
|
||||||
|
pw.print("Staged rules version: ");
|
||||||
|
DistroRulesVersion stagedDistroRulesVersion =
|
||||||
|
rulesState.getStagedDistroRulesVersion();
|
||||||
|
if (stagedDistroRulesVersion == null) {
|
||||||
|
pw.println("<None>");
|
||||||
|
} else {
|
||||||
|
pw.println("Staged install version: "
|
||||||
|
+ stagedDistroRulesVersion.toDumpString());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
// Report the active rules version (i.e. the rules in use by the current
|
||||||
|
// process).
|
||||||
|
pw.println("Active rules version (ICU, libcore): "
|
||||||
|
+ ICU.getTZDataVersion() + ","
|
||||||
|
+ ZoneInfoDB.getInstance().getVersion());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pw.println("Unknown option: " + c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pw.println("RulesManagerService state: " + toString());
|
||||||
|
pw.println("Active rules version (ICU, libcore): " + ICU.getTZDataVersion() + ","
|
||||||
|
+ ZoneInfoDB.getInstance().getVersion());
|
||||||
|
mPackageTracker.dump(pw);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "RulesManagerService{" +
|
||||||
|
"mOperationInProgress=" + mOperationInProgress +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
private static CheckToken createCheckTokenOrThrow(byte[] checkTokenBytes) {
|
private static CheckToken createCheckTokenOrThrow(byte[] checkTokenBytes) {
|
||||||
CheckToken checkToken;
|
CheckToken checkToken;
|
||||||
try {
|
try {
|
||||||
@@ -368,4 +466,30 @@ public final class RulesManagerService extends IRulesManager.Stub {
|
|||||||
}
|
}
|
||||||
return checkToken;
|
return checkToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String distroStatusToString(int distroStatus) {
|
||||||
|
switch(distroStatus) {
|
||||||
|
case DISTRO_STATUS_NONE:
|
||||||
|
return "None";
|
||||||
|
case DISTRO_STATUS_INSTALLED:
|
||||||
|
return "Installed";
|
||||||
|
case DISTRO_STATUS_UNKNOWN:
|
||||||
|
default:
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String stagedOperationToString(int stagedOperationType) {
|
||||||
|
switch(stagedOperationType) {
|
||||||
|
case STAGED_OPERATION_NONE:
|
||||||
|
return "None";
|
||||||
|
case STAGED_OPERATION_UNINSTALL:
|
||||||
|
return "Uninstall";
|
||||||
|
case STAGED_OPERATION_INSTALL:
|
||||||
|
return "Install";
|
||||||
|
case STAGED_OPERATION_UNKNOWN:
|
||||||
|
default:
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,10 +17,13 @@
|
|||||||
package com.android.server.timezone;
|
package com.android.server.timezone;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.Binder;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import libcore.io.Streams;
|
import libcore.io.Streams;
|
||||||
|
|
||||||
@@ -40,6 +43,19 @@ final class RulesManagerServiceHelperImpl implements PermissionHelper, Executor
|
|||||||
mContext.enforceCallingPermission(requiredPermission, null /* message */);
|
mContext.enforceCallingPermission(requiredPermission, null /* message */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkDumpPermission(String tag, PrintWriter pw) {
|
||||||
|
// TODO(nfuller): Switch to DumpUtils.checkDumpPermission() when it is available in AOSP.
|
||||||
|
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
|
||||||
|
!= PackageManager.PERMISSION_GRANTED) {
|
||||||
|
pw.println("Permission Denial: can't dump LocationManagerService from from pid="
|
||||||
|
+ Binder.getCallingPid()
|
||||||
|
+ ", uid=" + Binder.getCallingUid());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO Wake lock required?
|
// TODO Wake lock required?
|
||||||
@Override
|
@Override
|
||||||
public void execute(Runnable runnable) {
|
public void execute(Runnable runnable) {
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import android.support.test.InstrumentationRegistry;
|
|||||||
import android.support.test.filters.SmallTest;
|
import android.support.test.filters.SmallTest;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
|
||||||
import static junit.framework.Assert.assertTrue;
|
import static junit.framework.Assert.assertTrue;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
@@ -228,4 +230,27 @@ public class PackageStatusStorageTest {
|
|||||||
assertFalse(writeOk2);
|
assertFalse(writeOk2);
|
||||||
assertEquals(expectedPackageStatus, mPackageStatusStorage.getPackageStatus());
|
assertEquals(expectedPackageStatus, mPackageStatusStorage.getPackageStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void dump() {
|
||||||
|
StringWriter stringWriter = new StringWriter();
|
||||||
|
PrintWriter printWriter = new PrintWriter(stringWriter);
|
||||||
|
|
||||||
|
// Dump initial state.
|
||||||
|
mPackageStatusStorage.dump(printWriter);
|
||||||
|
|
||||||
|
// No crash and it does something.
|
||||||
|
assertFalse(stringWriter.toString().isEmpty());
|
||||||
|
|
||||||
|
// Reset
|
||||||
|
stringWriter.getBuffer().setLength(0);
|
||||||
|
assertTrue(stringWriter.toString().isEmpty());
|
||||||
|
|
||||||
|
// Store something.
|
||||||
|
mPackageStatusStorage.generateCheckToken(VALID_PACKAGE_VERSIONS);
|
||||||
|
|
||||||
|
mPackageStatusStorage.dump(printWriter);
|
||||||
|
|
||||||
|
assertFalse(stringWriter.toString().isEmpty());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ import android.provider.TimeZoneRulesDataContract;
|
|||||||
import android.support.test.InstrumentationRegistry;
|
import android.support.test.InstrumentationRegistry;
|
||||||
import android.support.test.filters.SmallTest;
|
import android.support.test.filters.SmallTest;
|
||||||
|
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
@@ -1174,6 +1177,16 @@ public class PackageTrackerTest {
|
|||||||
assertFalse(token1.equals(token2));
|
assertFalse(token1.equals(token2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void dump() {
|
||||||
|
StringWriter stringWriter = new StringWriter();
|
||||||
|
PrintWriter printWriter = new PrintWriter(stringWriter);
|
||||||
|
|
||||||
|
mPackageTracker.dump(printWriter);
|
||||||
|
|
||||||
|
assertFalse(stringWriter.toString().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
private void simulatePackageInstallation(PackageVersions packageVersions) throws Exception {
|
private void simulatePackageInstallation(PackageVersions packageVersions) throws Exception {
|
||||||
configureApplicationsValidManifests(packageVersions);
|
configureApplicationsValidManifests(packageVersions);
|
||||||
|
|
||||||
|
|||||||
@@ -32,11 +32,15 @@ import android.app.timezone.RulesState;
|
|||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileDescriptor;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import libcore.io.IoUtils;
|
||||||
|
|
||||||
import static com.android.server.timezone.RulesManagerService.REQUIRED_UPDATER_PERMISSION;
|
import static com.android.server.timezone.RulesManagerService.REQUIRED_UPDATER_PERMISSION;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
@@ -52,6 +56,7 @@ import static org.mockito.Mockito.mock;
|
|||||||
import static org.mockito.Mockito.reset;
|
import static org.mockito.Mockito.reset;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
|
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -724,6 +729,97 @@ public class RulesManagerServiceTest {
|
|||||||
verifyPackageTrackerCalled(null /* token */, true /* success */);
|
verifyPackageTrackerCalled(null /* token */, true /* success */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void dump_noPermission() throws Exception {
|
||||||
|
when(mMockPermissionHelper.checkDumpPermission(any(String.class), any(PrintWriter.class)))
|
||||||
|
.thenReturn(false);
|
||||||
|
|
||||||
|
doDumpCallAndCapture(mRulesManagerService, null);
|
||||||
|
verifyZeroInteractions(mMockPackageTracker, mMockTimeZoneDistroInstaller);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void dump_emptyArgs() throws Exception {
|
||||||
|
doSuccessfulDumpCall(mRulesManagerService, new String[0]);
|
||||||
|
|
||||||
|
// Verify the package tracker was consulted.
|
||||||
|
verify(mMockPackageTracker).dump(any(PrintWriter.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void dump_nullArgs() throws Exception {
|
||||||
|
doSuccessfulDumpCall(mRulesManagerService, null);
|
||||||
|
// Verify the package tracker was consulted.
|
||||||
|
verify(mMockPackageTracker).dump(any(PrintWriter.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void dump_unknownArgs() throws Exception {
|
||||||
|
String dumpedTextUnknownArgs = doSuccessfulDumpCall(
|
||||||
|
mRulesManagerService, new String[] { "foo", "bar"});
|
||||||
|
|
||||||
|
// Verify the package tracker was consulted.
|
||||||
|
verify(mMockPackageTracker).dump(any(PrintWriter.class));
|
||||||
|
|
||||||
|
String dumpedTextZeroArgs = doSuccessfulDumpCall(mRulesManagerService, null);
|
||||||
|
assertEquals(dumpedTextZeroArgs, dumpedTextUnknownArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void dump_formatState() throws Exception {
|
||||||
|
// Just expect these to not throw exceptions, not return nothing, and not interact with the
|
||||||
|
// package tracker.
|
||||||
|
doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("p"));
|
||||||
|
doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("s"));
|
||||||
|
doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("c"));
|
||||||
|
doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("i"));
|
||||||
|
doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("o"));
|
||||||
|
doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("t"));
|
||||||
|
doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("a"));
|
||||||
|
doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("z" /* Unknown */));
|
||||||
|
doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("piscotz"));
|
||||||
|
|
||||||
|
verifyZeroInteractions(mMockPackageTracker);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String[] dumpFormatArgs(String argsString) {
|
||||||
|
return new String[] { "-format_state", argsString};
|
||||||
|
}
|
||||||
|
|
||||||
|
private String doSuccessfulDumpCall(RulesManagerService rulesManagerService, String[] args)
|
||||||
|
throws Exception {
|
||||||
|
when(mMockPermissionHelper.checkDumpPermission(any(String.class), any(PrintWriter.class)))
|
||||||
|
.thenReturn(true);
|
||||||
|
|
||||||
|
// Set up the mocks to return (arbitrary) information about the current device state.
|
||||||
|
when(mMockTimeZoneDistroInstaller.getSystemRulesVersion()).thenReturn("2017a");
|
||||||
|
when(mMockTimeZoneDistroInstaller.getInstalledDistroVersion()).thenReturn(
|
||||||
|
new DistroVersion(2, 3, "2017b", 4));
|
||||||
|
when(mMockTimeZoneDistroInstaller.getStagedDistroOperation()).thenReturn(
|
||||||
|
StagedDistroOperation.install(new DistroVersion(5, 6, "2017c", 7)));
|
||||||
|
|
||||||
|
// Do the dump call.
|
||||||
|
String dumpedOutput = doDumpCallAndCapture(rulesManagerService, args);
|
||||||
|
|
||||||
|
assertFalse(dumpedOutput.isEmpty());
|
||||||
|
|
||||||
|
return dumpedOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String doDumpCallAndCapture(
|
||||||
|
RulesManagerService rulesManagerService, String[] args) throws IOException {
|
||||||
|
File file = File.createTempFile("dump", null);
|
||||||
|
try {
|
||||||
|
try (FileOutputStream fos = new FileOutputStream(file)) {
|
||||||
|
FileDescriptor fd = fos.getFD();
|
||||||
|
rulesManagerService.dump(fd, args);
|
||||||
|
}
|
||||||
|
return IoUtils.readFileAsString(file.getAbsolutePath());
|
||||||
|
} finally {
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void verifyNoPackageTrackerCallsMade() {
|
private void verifyNoPackageTrackerCallsMade() {
|
||||||
verifyNoMoreInteractions(mMockPackageTracker);
|
verifyNoMoreInteractions(mMockPackageTracker);
|
||||||
reset(mMockPackageTracker);
|
reset(mMockPackageTracker);
|
||||||
|
|||||||
Reference in New Issue
Block a user