Merge "Log InitializeStats in the platform" into sc-dev

This commit is contained in:
Xiaoyu Jin
2021-05-14 02:25:22 +00:00
committed by Android (Google) Code Review
7 changed files with 148 additions and 49 deletions

View File

@@ -90,17 +90,20 @@ public final class AppSearchSession implements Closeable {
@NonNull @CallbackExecutor Executor executor,
@NonNull Consumer<AppSearchResult<AppSearchSession>> callback) {
try {
mService.initialize(mUserId, new IAppSearchResultCallback.Stub() {
@Override
public void onResult(AppSearchResultParcel resultParcel) {
executor.execute(() -> {
AppSearchResult<Void> result = resultParcel.getResult();
if (result.isSuccess()) {
callback.accept(
AppSearchResult.newSuccessfulResult(AppSearchSession.this));
} else {
callback.accept(AppSearchResult.newFailedResult(result));
}
mService.initialize(mUserId,
/*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime(),
new IAppSearchResultCallback.Stub() {
@Override
public void onResult(AppSearchResultParcel resultParcel) {
executor.execute(() -> {
AppSearchResult<Void> result = resultParcel.getResult();
if (result.isSuccess()) {
callback.accept(
AppSearchResult.newSuccessfulResult(
AppSearchSession.this));
} else {
callback.accept(AppSearchResult.newFailedResult(result));
}
});
}
});

View File

@@ -23,6 +23,7 @@ import android.app.appsearch.aidl.AppSearchResultParcel;
import android.app.appsearch.aidl.IAppSearchManager;
import android.app.appsearch.aidl.IAppSearchResultCallback;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;
import com.android.internal.util.Preconditions;
@@ -72,17 +73,20 @@ public class GlobalSearchSession implements Closeable {
@NonNull @CallbackExecutor Executor executor,
@NonNull Consumer<AppSearchResult<GlobalSearchSession>> callback) {
try {
mService.initialize(mUserId, new IAppSearchResultCallback.Stub() {
@Override
public void onResult(AppSearchResultParcel resultParcel) {
executor.execute(() -> {
AppSearchResult<Void> result = resultParcel.getResult();
if (result.isSuccess()) {
callback.accept(
AppSearchResult.newSuccessfulResult(GlobalSearchSession.this));
} else {
callback.accept(AppSearchResult.newFailedResult(result));
}
mService.initialize(mUserId,
/*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime(),
new IAppSearchResultCallback.Stub() {
@Override
public void onResult(AppSearchResultParcel resultParcel) {
executor.execute(() -> {
AppSearchResult<Void> result = resultParcel.getResult();
if (result.isSuccess()) {
callback.accept(
AppSearchResult.newSuccessfulResult(
GlobalSearchSession.this));
} else {
callback.accept(AppSearchResult.newFailedResult(result));
}
});
}
});

View File

@@ -335,8 +335,12 @@ interface IAppSearchManager {
* Creates and initializes AppSearchImpl for the calling app.
*
* @param userId Id of the calling user
* @param binderCallStartTimeMillis start timestamp of binder call in Millis
* @param callback {@link IAppSearchResultCallback#onResult} will be called with an
* {@link AppSearchResult}&lt;{@link Void}&gt;.
*/
void initialize(in int userId, in IAppSearchResultCallback callback);
void initialize(
in int userId,
in long binderCallStartTimeMillis,
in IAppSearchResultCallback callback);
}

View File

@@ -217,10 +217,13 @@ public class AppSearchManagerService extends SystemService {
}
if (ImplInstanceManager.getAppSearchDir(userId).exists()) {
// Only clear the package's data if AppSearch exists for this user.
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(mContext,
userId);
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
userId, logger);
//TODO(b/145759910) clear visibility setting for package.
impl.clearPackageData(packageName);
logger.removeCachedUidForPackage(packageName);
}
} catch (Throwable t) {
Log.e(TAG, "Unable to remove data for package: " + packageName, t);
@@ -423,22 +426,22 @@ public class AppSearchManagerService extends SystemService {
invokeCallbackOnError(callback, t);
} finally {
if (logger != null) {
int estimatedBinderLatencyMillis =
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
int totalLatencyMillis =
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
CallStats.Builder cBuilder = new CallStats.Builder(packageName,
databaseName)
.setCallType(CallStats.CALL_TYPE_PUT_DOCUMENTS)
// TODO(b/173532925) check the existing binder call latency chart
// is good enough for us:
// http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
.setEstimatedBinderLatencyMillis(
2 * (int) (totalLatencyStartTimeMillis
- binderCallStartTimeMillis))
.setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
.setNumOperationsSucceeded(operationSuccessCount)
.setNumOperationsFailed(operationFailureCount);
cBuilder.getGeneralStatsBuilder()
.setStatusCode(statusCode)
.setTotalLatencyMillis(
(int) (SystemClock.elapsedRealtime()
- totalLatencyStartTimeMillis));
.setTotalLatencyMillis(totalLatencyMillis);
logger.logStats(cBuilder.build());
}
}
@@ -913,18 +916,51 @@ public class AppSearchManagerService extends SystemService {
}
@Override
public void initialize(@UserIdInt int userId, @NonNull IAppSearchResultCallback callback) {
public void initialize(@UserIdInt int userId,
@ElapsedRealtimeLong long binderCallStartTimeMillis,
@NonNull IAppSearchResultCallback callback) {
Objects.requireNonNull(callback);
long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
PlatformLogger logger = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
verifyUserUnlocked(callingUserId);
mImplInstanceManager.getOrCreateAppSearchImpl(mContext, callingUserId);
mLoggerInstanceManager.getOrCreatePlatformLogger(getContext(), callingUserId);
logger = mLoggerInstanceManager.getOrCreatePlatformLogger(mContext,
callingUserId);
mImplInstanceManager.getOrCreateAppSearchImpl(mContext, callingUserId, logger);
++operationSuccessCount;
invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
} catch (Throwable t) {
++operationFailureCount;
statusCode = throwableToFailedResult(t).getResultCode();
invokeCallbackOnError(callback, t);
} finally {
if (logger != null) {
int estimatedBinderLatencyMillis =
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
int totalLatencyMillis =
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
// TODO(b/173532925) make packageName and database nullable after
// removing generalStats
CallStats.Builder cBuilder = new CallStats.Builder(/*packageName=*/"",
/*database=*/ "")
.setCallType(CallStats.CALL_TYPE_INITIALIZE)
// TODO(b/173532925) check the existing binder call latency chart
// is good enough for us:
// http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
.setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
.setNumOperationsSucceeded(operationSuccessCount)
.setNumOperationsFailed(operationFailureCount);
cBuilder.getGeneralStatsBuilder()
.setStatusCode(statusCode)
.setTotalLatencyMillis(totalLatencyMillis);
logger.logStats(cBuilder.build());
}
}
});
}
@@ -1021,8 +1057,10 @@ public class AppSearchManagerService extends SystemService {
int userId = userHandle.getIdentifier();
try {
verifyUserUnlocked(userId);
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(mContext,
userId);
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
userId, logger);
stats.dataSize += impl.getStorageInfoForPackage(packageName).getSizeBytes();
} catch (Throwable t) {
Log.e(
@@ -1046,8 +1084,10 @@ public class AppSearchManagerService extends SystemService {
if (packagesForUid == null) {
return;
}
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(mContext,
userId);
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
userId, logger);
for (int i = 0; i < packagesForUid.length; i++) {
stats.dataSize +=
impl.getStorageInfoForPackage(packagesForUid[i]).getSizeBytes();
@@ -1073,8 +1113,10 @@ public class AppSearchManagerService extends SystemService {
if (packagesForUser == null) {
return;
}
PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(mContext,
userId);
AppSearchImpl impl =
mImplInstanceManager.getOrCreateAppSearchImpl(mContext, userId);
mImplInstanceManager.getOrCreateAppSearchImpl(mContext, userId, logger);
for (int i = 0; i < packagesForUser.size(); i++) {
String packageName = packagesForUser.get(i).packageName;
stats.dataSize += impl.getStorageInfoForPackage(packageName).getSizeBytes();

View File

@@ -19,6 +19,7 @@ package com.android.server.appsearch;
import static android.content.pm.PackageManager.MATCH_FACTORY_ONLY;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.appsearch.exceptions.AppSearchException;
import android.content.Context;
@@ -30,6 +31,7 @@ import android.util.SparseArray;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.server.appsearch.external.localstorage.AppSearchImpl;
import com.android.server.appsearch.external.localstorage.AppSearchLogger;
import java.io.File;
@@ -88,16 +90,17 @@ public final class ImplInstanceManager {
* one will be created.
*
* @param context The context
* @param userId The multi-user userId of the device user calling AppSearch
* @param userId The multi-user userId of the device user calling AppSearch
* @return An initialized {@link AppSearchImpl} for this user
*/
@NonNull
public AppSearchImpl getOrCreateAppSearchImpl(
@NonNull Context context, @UserIdInt int userId) throws AppSearchException {
@NonNull Context context, @UserIdInt int userId, @Nullable AppSearchLogger logger)
throws AppSearchException {
synchronized (mInstancesLocked) {
AppSearchImpl instance = mInstancesLocked.get(userId);
if (instance == null) {
instance = createImpl(context, userId);
instance = createImpl(context, userId, logger);
mInstancesLocked.put(userId, instance);
}
return instance;
@@ -164,11 +167,12 @@ public final class ImplInstanceManager {
}
}
private AppSearchImpl createImpl(@NonNull Context context, @UserIdInt int userId)
private AppSearchImpl createImpl(@NonNull Context context, @UserIdInt int userId,
@Nullable AppSearchLogger logger)
throws AppSearchException {
File appSearchDir = getAppSearchDir(userId);
return AppSearchImpl.create(
appSearchDir, context, userId, mGlobalQuerierPackage, /*logger=*/ null);
appSearchDir, context, userId, mGlobalQuerierPackage, logger);
}
/**
@@ -182,10 +186,10 @@ public final class ImplInstanceManager {
context.getString(R.string.config_globalAppSearchDataQuerierPackage);
try {
if (context.getPackageManager()
.getPackageInfoAsUser(
globalAppSearchDataQuerierPackage,
MATCH_FACTORY_ONLY,
UserHandle.USER_SYSTEM)
.getPackageInfoAsUser(
globalAppSearchDataQuerierPackage,
MATCH_FACTORY_ONLY,
UserHandle.USER_SYSTEM)
== null) {
return "";
}

View File

@@ -194,7 +194,12 @@ public final class PlatformLogger implements AppSearchLogger {
@Override
public void logStats(@NonNull InitializeStats stats) throws AppSearchException {
// TODO(b/173532925): Implement
Objects.requireNonNull(stats);
synchronized (mLock) {
if (shouldLogForTypeLocked(CallStats.CALL_TYPE_INITIALIZE)) {
logStatsImplLocked(stats);
}
}
}
@Override
@@ -337,6 +342,32 @@ public final class PlatformLogger implements AppSearchLogger {
}
}
@GuardedBy("mLock")
private void logStatsImplLocked(@NonNull InitializeStats stats) {
mLastPushTimeMillisLocked = SystemClock.elapsedRealtime();
ExtraStats extraStats = createExtraStatsLocked(/*packageName=*/ null,
CallStats.CALL_TYPE_INITIALIZE);
FrameworkStatsLog.write(FrameworkStatsLog.APP_SEARCH_INITIALIZE_STATS_REPORTED,
extraStats.mSamplingRatio,
extraStats.mSkippedSampleCount,
extraStats.mPackageUid,
stats.getStatusCode(),
stats.getTotalLatencyMillis(),
stats.hasDeSync(),
stats.getPrepareSchemaAndNamespacesLatencyMillis(),
stats.getPrepareVisibilityStoreLatencyMillis(),
stats.getNativeLatencyMillis(),
stats.getDocumentStoreRecoveryCause(),
stats.getIndexRestorationCause(),
stats.getSchemaStoreRecoveryCause(),
stats.getDocumentStoreRecoveryLatencyMillis(),
stats.getIndexRestorationLatencyMillis(),
stats.getSchemaStoreRecoveryLatencyMillis(),
stats.getDocumentStoreDataStatus(),
stats.getDocumentCount(),
stats.getSchemaTypeCount());
}
/**
* Calculate the hash code as an integer by returning the last four bytes of its MD5.
*
@@ -377,12 +408,19 @@ public final class PlatformLogger implements AppSearchLogger {
* <p>This method is called by most of logToWestworldLocked functions to reduce code
* duplication.
*/
// TODO(b/173532925) Once we add CTS test for logging atoms and can inspect the result, we can
// remove this @VisibleForTesting and directly use PlatformLogger.logStats to test sampling and
// rate limiting.
@VisibleForTesting
@GuardedBy("mLock")
@NonNull
ExtraStats createExtraStatsLocked(@NonNull String packageName,
ExtraStats createExtraStatsLocked(@Nullable String packageName,
@CallStats.CallType int callType) {
int packageUid = getPackageUidAsUserLocked(packageName);
int packageUid = Process.INVALID_UID;
if (packageName != null) {
packageUid = getPackageUidAsUserLocked(packageName);
}
int samplingRatio = mConfig.mSamplingRatios.get(callType,
mConfig.mDefaultSamplingRatio);
@@ -400,6 +438,9 @@ public final class PlatformLogger implements AppSearchLogger {
* stats.
*/
@GuardedBy("mLock")
// TODO(b/173532925) Once we add CTS test for logging atoms and can inspect the result, we can
// remove this @VisibleForTesting and directly use PlatformLogger.logStats to test sampling and
// rate limiting.
@VisibleForTesting
boolean shouldLogForTypeLocked(@CallStats.CallType int callType) {
int samplingRatio = mConfig.mSamplingRatios.get(callType,

View File

@@ -874,7 +874,8 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
}
@Override
public void initialize(int userId, IAppSearchResultCallback callback)
public void initialize(int userId, long binderCallStartTimeMillis,
IAppSearchResultCallback callback)
throws RemoteException {
ignore(callback);
}