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 @CallbackExecutor Executor executor,
@NonNull Consumer<AppSearchResult<AppSearchSession>> callback) { @NonNull Consumer<AppSearchResult<AppSearchSession>> callback) {
try { try {
mService.initialize(mUserId, new IAppSearchResultCallback.Stub() { mService.initialize(mUserId,
@Override /*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime(),
public void onResult(AppSearchResultParcel resultParcel) { new IAppSearchResultCallback.Stub() {
executor.execute(() -> { @Override
AppSearchResult<Void> result = resultParcel.getResult(); public void onResult(AppSearchResultParcel resultParcel) {
if (result.isSuccess()) { executor.execute(() -> {
callback.accept( AppSearchResult<Void> result = resultParcel.getResult();
AppSearchResult.newSuccessfulResult(AppSearchSession.this)); if (result.isSuccess()) {
} else { callback.accept(
callback.accept(AppSearchResult.newFailedResult(result)); 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.IAppSearchManager;
import android.app.appsearch.aidl.IAppSearchResultCallback; import android.app.appsearch.aidl.IAppSearchResultCallback;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log; import android.util.Log;
import com.android.internal.util.Preconditions; import com.android.internal.util.Preconditions;
@@ -72,17 +73,20 @@ public class GlobalSearchSession implements Closeable {
@NonNull @CallbackExecutor Executor executor, @NonNull @CallbackExecutor Executor executor,
@NonNull Consumer<AppSearchResult<GlobalSearchSession>> callback) { @NonNull Consumer<AppSearchResult<GlobalSearchSession>> callback) {
try { try {
mService.initialize(mUserId, new IAppSearchResultCallback.Stub() { mService.initialize(mUserId,
@Override /*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime(),
public void onResult(AppSearchResultParcel resultParcel) { new IAppSearchResultCallback.Stub() {
executor.execute(() -> { @Override
AppSearchResult<Void> result = resultParcel.getResult(); public void onResult(AppSearchResultParcel resultParcel) {
if (result.isSuccess()) { executor.execute(() -> {
callback.accept( AppSearchResult<Void> result = resultParcel.getResult();
AppSearchResult.newSuccessfulResult(GlobalSearchSession.this)); if (result.isSuccess()) {
} else { callback.accept(
callback.accept(AppSearchResult.newFailedResult(result)); 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. * Creates and initializes AppSearchImpl for the calling app.
* *
* @param userId Id of the calling user * @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 * @param callback {@link IAppSearchResultCallback#onResult} will be called with an
* {@link AppSearchResult}&lt;{@link Void}&gt;. * {@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()) { if (ImplInstanceManager.getAppSearchDir(userId).exists()) {
// Only clear the package's data if AppSearch exists for this user. // Only clear the package's data if AppSearch exists for this user.
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext, PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(mContext,
userId); userId);
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
userId, logger);
//TODO(b/145759910) clear visibility setting for package. //TODO(b/145759910) clear visibility setting for package.
impl.clearPackageData(packageName); impl.clearPackageData(packageName);
logger.removeCachedUidForPackage(packageName);
} }
} catch (Throwable t) { } catch (Throwable t) {
Log.e(TAG, "Unable to remove data for package: " + packageName, t); Log.e(TAG, "Unable to remove data for package: " + packageName, t);
@@ -423,22 +426,22 @@ public class AppSearchManagerService extends SystemService {
invokeCallbackOnError(callback, t); invokeCallbackOnError(callback, t);
} finally { } finally {
if (logger != null) { if (logger != null) {
int estimatedBinderLatencyMillis =
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
int totalLatencyMillis =
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
CallStats.Builder cBuilder = new CallStats.Builder(packageName, CallStats.Builder cBuilder = new CallStats.Builder(packageName,
databaseName) databaseName)
.setCallType(CallStats.CALL_TYPE_PUT_DOCUMENTS) .setCallType(CallStats.CALL_TYPE_PUT_DOCUMENTS)
// TODO(b/173532925) check the existing binder call latency chart // TODO(b/173532925) check the existing binder call latency chart
// is good enough for us: // is good enough for us:
// http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
.setEstimatedBinderLatencyMillis( .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
2 * (int) (totalLatencyStartTimeMillis
- binderCallStartTimeMillis))
.setNumOperationsSucceeded(operationSuccessCount) .setNumOperationsSucceeded(operationSuccessCount)
.setNumOperationsFailed(operationFailureCount); .setNumOperationsFailed(operationFailureCount);
cBuilder.getGeneralStatsBuilder() cBuilder.getGeneralStatsBuilder()
.setStatusCode(statusCode) .setStatusCode(statusCode)
.setTotalLatencyMillis( .setTotalLatencyMillis(totalLatencyMillis);
(int) (SystemClock.elapsedRealtime()
- totalLatencyStartTimeMillis));
logger.logStats(cBuilder.build()); logger.logStats(cBuilder.build());
} }
} }
@@ -913,18 +916,51 @@ public class AppSearchManagerService extends SystemService {
} }
@Override @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); Objects.requireNonNull(callback);
long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid(); int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid); int callingUserId = handleIncomingUser(userId, callingUid);
EXECUTOR.execute(() -> { EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
PlatformLogger logger = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try { try {
verifyUserUnlocked(callingUserId); verifyUserUnlocked(callingUserId);
mImplInstanceManager.getOrCreateAppSearchImpl(mContext, callingUserId); logger = mLoggerInstanceManager.getOrCreatePlatformLogger(mContext,
mLoggerInstanceManager.getOrCreatePlatformLogger(getContext(), callingUserId); callingUserId);
mImplInstanceManager.getOrCreateAppSearchImpl(mContext, callingUserId, logger);
++operationSuccessCount;
invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null)); invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
} catch (Throwable t) { } catch (Throwable t) {
++operationFailureCount;
statusCode = throwableToFailedResult(t).getResultCode();
invokeCallbackOnError(callback, t); 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(); int userId = userHandle.getIdentifier();
try { try {
verifyUserUnlocked(userId); verifyUserUnlocked(userId);
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext, PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(mContext,
userId); userId);
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
userId, logger);
stats.dataSize += impl.getStorageInfoForPackage(packageName).getSizeBytes(); stats.dataSize += impl.getStorageInfoForPackage(packageName).getSizeBytes();
} catch (Throwable t) { } catch (Throwable t) {
Log.e( Log.e(
@@ -1046,8 +1084,10 @@ public class AppSearchManagerService extends SystemService {
if (packagesForUid == null) { if (packagesForUid == null) {
return; return;
} }
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext, PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(mContext,
userId); userId);
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
userId, logger);
for (int i = 0; i < packagesForUid.length; i++) { for (int i = 0; i < packagesForUid.length; i++) {
stats.dataSize += stats.dataSize +=
impl.getStorageInfoForPackage(packagesForUid[i]).getSizeBytes(); impl.getStorageInfoForPackage(packagesForUid[i]).getSizeBytes();
@@ -1073,8 +1113,10 @@ public class AppSearchManagerService extends SystemService {
if (packagesForUser == null) { if (packagesForUser == null) {
return; return;
} }
PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(mContext,
userId);
AppSearchImpl impl = AppSearchImpl impl =
mImplInstanceManager.getOrCreateAppSearchImpl(mContext, userId); mImplInstanceManager.getOrCreateAppSearchImpl(mContext, userId, logger);
for (int i = 0; i < packagesForUser.size(); i++) { for (int i = 0; i < packagesForUser.size(); i++) {
String packageName = packagesForUser.get(i).packageName; String packageName = packagesForUser.get(i).packageName;
stats.dataSize += impl.getStorageInfoForPackage(packageName).getSizeBytes(); 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 static android.content.pm.PackageManager.MATCH_FACTORY_ONLY;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt; import android.annotation.UserIdInt;
import android.app.appsearch.exceptions.AppSearchException; import android.app.appsearch.exceptions.AppSearchException;
import android.content.Context; import android.content.Context;
@@ -30,6 +31,7 @@ import android.util.SparseArray;
import com.android.internal.R; import com.android.internal.R;
import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy;
import com.android.server.appsearch.external.localstorage.AppSearchImpl; import com.android.server.appsearch.external.localstorage.AppSearchImpl;
import com.android.server.appsearch.external.localstorage.AppSearchLogger;
import java.io.File; import java.io.File;
@@ -88,16 +90,17 @@ public final class ImplInstanceManager {
* one will be created. * one will be created.
* *
* @param context The context * @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 * @return An initialized {@link AppSearchImpl} for this user
*/ */
@NonNull @NonNull
public AppSearchImpl getOrCreateAppSearchImpl( public AppSearchImpl getOrCreateAppSearchImpl(
@NonNull Context context, @UserIdInt int userId) throws AppSearchException { @NonNull Context context, @UserIdInt int userId, @Nullable AppSearchLogger logger)
throws AppSearchException {
synchronized (mInstancesLocked) { synchronized (mInstancesLocked) {
AppSearchImpl instance = mInstancesLocked.get(userId); AppSearchImpl instance = mInstancesLocked.get(userId);
if (instance == null) { if (instance == null) {
instance = createImpl(context, userId); instance = createImpl(context, userId, logger);
mInstancesLocked.put(userId, instance); mInstancesLocked.put(userId, instance);
} }
return 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 { throws AppSearchException {
File appSearchDir = getAppSearchDir(userId); File appSearchDir = getAppSearchDir(userId);
return AppSearchImpl.create( 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); context.getString(R.string.config_globalAppSearchDataQuerierPackage);
try { try {
if (context.getPackageManager() if (context.getPackageManager()
.getPackageInfoAsUser( .getPackageInfoAsUser(
globalAppSearchDataQuerierPackage, globalAppSearchDataQuerierPackage,
MATCH_FACTORY_ONLY, MATCH_FACTORY_ONLY,
UserHandle.USER_SYSTEM) UserHandle.USER_SYSTEM)
== null) { == null) {
return ""; return "";
} }

View File

@@ -194,7 +194,12 @@ public final class PlatformLogger implements AppSearchLogger {
@Override @Override
public void logStats(@NonNull InitializeStats stats) throws AppSearchException { 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 @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. * 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 * <p>This method is called by most of logToWestworldLocked functions to reduce code
* duplication. * 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 @VisibleForTesting
@GuardedBy("mLock") @GuardedBy("mLock")
@NonNull @NonNull
ExtraStats createExtraStatsLocked(@NonNull String packageName, ExtraStats createExtraStatsLocked(@Nullable String packageName,
@CallStats.CallType int callType) { @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, int samplingRatio = mConfig.mSamplingRatios.get(callType,
mConfig.mDefaultSamplingRatio); mConfig.mDefaultSamplingRatio);
@@ -400,6 +438,9 @@ public final class PlatformLogger implements AppSearchLogger {
* stats. * stats.
*/ */
@GuardedBy("mLock") @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 @VisibleForTesting
boolean shouldLogForTypeLocked(@CallStats.CallType int callType) { boolean shouldLogForTypeLocked(@CallStats.CallType int callType) {
int samplingRatio = mConfig.mSamplingRatios.get(callType, int samplingRatio = mConfig.mSamplingRatios.get(callType,

View File

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