Merge "Guard system usage reporting by checking the caller has system access." into sc-dev am: e5a810e1d4
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14987453 Change-Id: Idfa5501e55b059c42f7367f2adb11af943b2cb89
This commit is contained in:
committed by
Automerger Merge Worker
commit
56ebe0fee4
@@ -37,6 +37,7 @@ import android.app.appsearch.aidl.AppSearchResultParcel;
|
|||||||
import android.app.appsearch.aidl.IAppSearchBatchResultCallback;
|
import android.app.appsearch.aidl.IAppSearchBatchResultCallback;
|
||||||
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.app.appsearch.exceptions.AppSearchException;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -58,10 +59,7 @@ import android.util.Log;
|
|||||||
import com.android.internal.annotations.GuardedBy;
|
import com.android.internal.annotations.GuardedBy;
|
||||||
import com.android.server.LocalManagerRegistry;
|
import com.android.server.LocalManagerRegistry;
|
||||||
import com.android.server.SystemService;
|
import com.android.server.SystemService;
|
||||||
import com.android.server.appsearch.external.localstorage.AppSearchImpl;
|
|
||||||
import com.android.server.appsearch.external.localstorage.stats.CallStats;
|
import com.android.server.appsearch.external.localstorage.stats.CallStats;
|
||||||
import com.android.server.appsearch.stats.LoggerInstanceManager;
|
|
||||||
import com.android.server.appsearch.stats.PlatformLogger;
|
|
||||||
import com.android.server.appsearch.util.PackageUtil;
|
import com.android.server.appsearch.util.PackageUtil;
|
||||||
import com.android.server.appsearch.visibilitystore.VisibilityStore;
|
import com.android.server.appsearch.visibilitystore.VisibilityStore;
|
||||||
import com.android.server.usage.StorageStatsManagerLocal;
|
import com.android.server.usage.StorageStatsManagerLocal;
|
||||||
@@ -89,9 +87,8 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
private static final String TAG = "AppSearchManagerService";
|
private static final String TAG = "AppSearchManagerService";
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private PackageManager mPackageManager;
|
private PackageManager mPackageManager;
|
||||||
private ImplInstanceManager mImplInstanceManager;
|
|
||||||
private UserManager mUserManager;
|
private UserManager mUserManager;
|
||||||
private LoggerInstanceManager mLoggerInstanceManager;
|
private AppSearchUserInstanceManager mAppSearchUserInstanceManager;
|
||||||
|
|
||||||
// Never call shutdownNow(). It will cancel the futures it's returned. And since
|
// Never call shutdownNow(). It will cancel the futures it's returned. And since
|
||||||
// Executor#execute won't return anything, we will hang forever waiting for the execution.
|
// Executor#execute won't return anything, we will hang forever waiting for the execution.
|
||||||
@@ -116,9 +113,8 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
public void onStart() {
|
public void onStart() {
|
||||||
publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
|
publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
|
||||||
mPackageManager = getContext().getPackageManager();
|
mPackageManager = getContext().getPackageManager();
|
||||||
mImplInstanceManager = ImplInstanceManager.getInstance(mContext);
|
mAppSearchUserInstanceManager = AppSearchUserInstanceManager.getInstance();
|
||||||
mUserManager = mContext.getSystemService(UserManager.class);
|
mUserManager = mContext.getSystemService(UserManager.class);
|
||||||
mLoggerInstanceManager = LoggerInstanceManager.getInstance();
|
|
||||||
registerReceivers();
|
registerReceivers();
|
||||||
LocalManagerRegistry.getManager(StorageStatsManagerLocal.class)
|
LocalManagerRegistry.getManager(StorageStatsManagerLocal.class)
|
||||||
.registerStorageStatsAugmenter(new AppSearchStorageStatsAugmenter(), TAG);
|
.registerStorageStatsAugmenter(new AppSearchStorageStatsAugmenter(), TAG);
|
||||||
@@ -180,8 +176,7 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
*/
|
*/
|
||||||
private void handleUserRemoved(@NonNull UserHandle userHandle) {
|
private void handleUserRemoved(@NonNull UserHandle userHandle) {
|
||||||
try {
|
try {
|
||||||
mImplInstanceManager.closeAndRemoveAppSearchImplForUser(userHandle);
|
mAppSearchUserInstanceManager.closeAndRemoveUserInstance(userHandle);
|
||||||
mLoggerInstanceManager.removePlatformLoggerForUser(userHandle);
|
|
||||||
Log.i(TAG, "Removed AppSearchImpl instance for: " + userHandle);
|
Log.i(TAG, "Removed AppSearchImpl instance for: " + userHandle);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
Log.e(TAG, "Unable to remove data for: " + userHandle, t);
|
Log.e(TAG, "Unable to remove data for: " + userHandle, t);
|
||||||
@@ -224,14 +219,13 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Only clear the package's data if AppSearch exists for this user.
|
// Only clear the package's data if AppSearch exists for this user.
|
||||||
if (ImplInstanceManager.getAppSearchDir(userHandle).exists()) {
|
if (AppSearchUserInstanceManager.getAppSearchDir(userHandle).exists()) {
|
||||||
PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(mContext,
|
AppSearchUserInstance instance =
|
||||||
userHandle, AppSearchConfig.getInstance(EXECUTOR));
|
mAppSearchUserInstanceManager.getOrCreateUserInstance(
|
||||||
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
|
mContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
|
||||||
userHandle, logger);
|
|
||||||
//TODO(b/145759910) clear visibility setting for package.
|
//TODO(b/145759910) clear visibility setting for package.
|
||||||
impl.clearPackageData(packageName);
|
instance.getAppSearchImpl().clearPackageData(packageName);
|
||||||
logger.removeCachedUidForPackage(packageName);
|
instance.getLogger().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);
|
||||||
@@ -248,11 +242,10 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
EXECUTOR.execute(() -> {
|
EXECUTOR.execute(() -> {
|
||||||
try {
|
try {
|
||||||
// Only clear the package's data if AppSearch exists for this user.
|
// Only clear the package's data if AppSearch exists for this user.
|
||||||
if (ImplInstanceManager.getAppSearchDir(userHandle).exists()) {
|
if (AppSearchUserInstanceManager.getAppSearchDir(userHandle).exists()) {
|
||||||
PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(
|
AppSearchUserInstance instance =
|
||||||
|
mAppSearchUserInstanceManager.getOrCreateUserInstance(
|
||||||
mContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
|
mContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
|
||||||
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
|
|
||||||
userHandle, logger);
|
|
||||||
List<PackageInfo> installedPackageInfos = mContext
|
List<PackageInfo> installedPackageInfos = mContext
|
||||||
.createContextAsUser(userHandle, /*flags=*/0)
|
.createContextAsUser(userHandle, /*flags=*/0)
|
||||||
.getPackageManager()
|
.getPackageManager()
|
||||||
@@ -263,7 +256,7 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
}
|
}
|
||||||
packagesToKeep.add(VisibilityStore.PACKAGE_NAME);
|
packagesToKeep.add(VisibilityStore.PACKAGE_NAME);
|
||||||
//TODO(b/145759910) clear visibility setting for package.
|
//TODO(b/145759910) clear visibility setting for package.
|
||||||
impl.prunePackageData(packagesToKeep);
|
instance.getAppSearchImpl().prunePackageData(packagesToKeep);
|
||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
Log.e(TAG, "Unable to prune packages for " + user, t);
|
Log.e(TAG, "Unable to prune packages for " + user, t);
|
||||||
@@ -279,7 +272,7 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
UserHandle userHandle = user.getUserHandle();
|
UserHandle userHandle = user.getUserHandle();
|
||||||
mUnlockedUsersLocked.remove(userHandle);
|
mUnlockedUsersLocked.remove(userHandle);
|
||||||
try {
|
try {
|
||||||
mImplInstanceManager.closeAndRemoveAppSearchImplForUser(userHandle);
|
mAppSearchUserInstanceManager.closeAndRemoveUserInstance(userHandle);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
Log.e(TAG, "Error handling user stopping.", t);
|
Log.e(TAG, "Error handling user stopping.", t);
|
||||||
}
|
}
|
||||||
@@ -311,7 +304,7 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
@NonNull String databaseName,
|
@NonNull String databaseName,
|
||||||
@NonNull List<Bundle> schemaBundles,
|
@NonNull List<Bundle> schemaBundles,
|
||||||
@NonNull List<String> schemasNotDisplayedBySystem,
|
@NonNull List<String> schemasNotDisplayedBySystem,
|
||||||
@NonNull Map<String, List<Bundle>> schemasPackageAccessibleBundles,
|
@NonNull Map<String, List<Bundle>> schemasVisibleToPackagesBundles,
|
||||||
boolean forceOverride,
|
boolean forceOverride,
|
||||||
int schemaVersion,
|
int schemaVersion,
|
||||||
@NonNull UserHandle userHandle,
|
@NonNull UserHandle userHandle,
|
||||||
@@ -321,7 +314,7 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
Objects.requireNonNull(databaseName);
|
Objects.requireNonNull(databaseName);
|
||||||
Objects.requireNonNull(schemaBundles);
|
Objects.requireNonNull(schemaBundles);
|
||||||
Objects.requireNonNull(schemasNotDisplayedBySystem);
|
Objects.requireNonNull(schemasNotDisplayedBySystem);
|
||||||
Objects.requireNonNull(schemasPackageAccessibleBundles);
|
Objects.requireNonNull(schemasVisibleToPackagesBundles);
|
||||||
Objects.requireNonNull(userHandle);
|
Objects.requireNonNull(userHandle);
|
||||||
Objects.requireNonNull(callback);
|
Objects.requireNonNull(callback);
|
||||||
|
|
||||||
@@ -330,7 +323,7 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
|
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
|
||||||
EXECUTOR.execute(() -> {
|
EXECUTOR.execute(() -> {
|
||||||
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
|
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
|
||||||
PlatformLogger logger = null;
|
AppSearchUserInstance instance = null;
|
||||||
int operationSuccessCount = 0;
|
int operationSuccessCount = 0;
|
||||||
int operationFailureCount = 0;
|
int operationFailureCount = 0;
|
||||||
try {
|
try {
|
||||||
@@ -341,9 +334,9 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
schemas.add(new AppSearchSchema(schemaBundles.get(i)));
|
schemas.add(new AppSearchSchema(schemaBundles.get(i)));
|
||||||
}
|
}
|
||||||
Map<String, List<PackageIdentifier>> schemasPackageAccessible =
|
Map<String, List<PackageIdentifier>> schemasPackageAccessible =
|
||||||
new ArrayMap<>(schemasPackageAccessibleBundles.size());
|
new ArrayMap<>(schemasVisibleToPackagesBundles.size());
|
||||||
for (Map.Entry<String, List<Bundle>> entry :
|
for (Map.Entry<String, List<Bundle>> entry :
|
||||||
schemasPackageAccessibleBundles.entrySet()) {
|
schemasVisibleToPackagesBundles.entrySet()) {
|
||||||
List<PackageIdentifier> packageIdentifiers =
|
List<PackageIdentifier> packageIdentifiers =
|
||||||
new ArrayList<>(entry.getValue().size());
|
new ArrayList<>(entry.getValue().size());
|
||||||
for (int i = 0; i < entry.getValue().size(); i++) {
|
for (int i = 0; i < entry.getValue().size(); i++) {
|
||||||
@@ -352,12 +345,12 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
}
|
}
|
||||||
schemasPackageAccessible.put(entry.getKey(), packageIdentifiers);
|
schemasPackageAccessible.put(entry.getKey(), packageIdentifiers);
|
||||||
}
|
}
|
||||||
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
|
instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
|
||||||
logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
|
SetSchemaResponse setSchemaResponse = instance.getAppSearchImpl().setSchema(
|
||||||
SetSchemaResponse setSchemaResponse = impl.setSchema(
|
|
||||||
packageName,
|
packageName,
|
||||||
databaseName,
|
databaseName,
|
||||||
schemas,
|
schemas,
|
||||||
|
instance.getVisibilityStore(),
|
||||||
schemasNotDisplayedBySystem,
|
schemasNotDisplayedBySystem,
|
||||||
schemasPackageAccessible,
|
schemasPackageAccessible,
|
||||||
forceOverride,
|
forceOverride,
|
||||||
@@ -370,12 +363,12 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
statusCode = throwableToFailedResult(t).getResultCode();
|
statusCode = throwableToFailedResult(t).getResultCode();
|
||||||
invokeCallbackOnError(callback, t);
|
invokeCallbackOnError(callback, t);
|
||||||
} finally {
|
} finally {
|
||||||
if (logger != null) {
|
if (instance != null) {
|
||||||
int estimatedBinderLatencyMillis =
|
int estimatedBinderLatencyMillis =
|
||||||
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
|
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
|
||||||
int totalLatencyMillis =
|
int totalLatencyMillis =
|
||||||
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
|
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
|
||||||
logger.logStats(new CallStats.Builder()
|
instance.getLogger().logStats(new CallStats.Builder()
|
||||||
.setPackageName(packageName)
|
.setPackageName(packageName)
|
||||||
.setDatabase(databaseName)
|
.setDatabase(databaseName)
|
||||||
.setStatusCode(statusCode)
|
.setStatusCode(statusCode)
|
||||||
@@ -410,8 +403,10 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
try {
|
try {
|
||||||
verifyUserUnlocked(callingUser);
|
verifyUserUnlocked(callingUser);
|
||||||
verifyCallingPackage(callingUser, callingUid, packageName);
|
verifyCallingPackage(callingUser, callingUid, packageName);
|
||||||
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
|
AppSearchUserInstance instance =
|
||||||
GetSchemaResponse response = impl.getSchema(packageName, databaseName);
|
mAppSearchUserInstanceManager.getUserInstance(callingUser);
|
||||||
|
GetSchemaResponse response =
|
||||||
|
instance.getAppSearchImpl().getSchema(packageName, databaseName);
|
||||||
invokeCallbackOnResult(
|
invokeCallbackOnResult(
|
||||||
callback,
|
callback,
|
||||||
AppSearchResult.newSuccessfulResult(response.getBundle()));
|
AppSearchResult.newSuccessfulResult(response.getBundle()));
|
||||||
@@ -438,10 +433,12 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
try {
|
try {
|
||||||
verifyUserUnlocked(callingUser);
|
verifyUserUnlocked(callingUser);
|
||||||
verifyCallingPackage(callingUser, callingUid, packageName);
|
verifyCallingPackage(callingUser, callingUid, packageName);
|
||||||
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
|
AppSearchUserInstance instance =
|
||||||
List<String> namespaces = impl.getNamespaces(packageName, databaseName);
|
mAppSearchUserInstanceManager.getUserInstance(callingUser);
|
||||||
invokeCallbackOnResult(callback,
|
List<String> namespaces =
|
||||||
AppSearchResult.newSuccessfulResult(namespaces));
|
instance.getAppSearchImpl().getNamespaces(packageName, databaseName);
|
||||||
|
invokeCallbackOnResult(
|
||||||
|
callback, AppSearchResult.newSuccessfulResult(namespaces));
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
invokeCallbackOnError(callback, t);
|
invokeCallbackOnError(callback, t);
|
||||||
}
|
}
|
||||||
@@ -467,7 +464,7 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
|
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
|
||||||
EXECUTOR.execute(() -> {
|
EXECUTOR.execute(() -> {
|
||||||
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
|
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
|
||||||
PlatformLogger logger = null;
|
AppSearchUserInstance instance = null;
|
||||||
int operationSuccessCount = 0;
|
int operationSuccessCount = 0;
|
||||||
int operationFailureCount = 0;
|
int operationFailureCount = 0;
|
||||||
try {
|
try {
|
||||||
@@ -475,17 +472,16 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
verifyCallingPackage(callingUser, callingUid, packageName);
|
verifyCallingPackage(callingUser, callingUid, packageName);
|
||||||
AppSearchBatchResult.Builder<String, Void> resultBuilder =
|
AppSearchBatchResult.Builder<String, Void> resultBuilder =
|
||||||
new AppSearchBatchResult.Builder<>();
|
new AppSearchBatchResult.Builder<>();
|
||||||
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
|
instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
|
||||||
logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
|
|
||||||
for (int i = 0; i < documentBundles.size(); i++) {
|
for (int i = 0; i < documentBundles.size(); i++) {
|
||||||
GenericDocument document = new GenericDocument(documentBundles.get(i));
|
GenericDocument document = new GenericDocument(documentBundles.get(i));
|
||||||
try {
|
try {
|
||||||
impl.putDocument(packageName, databaseName, document, logger);
|
instance.getAppSearchImpl().putDocument(
|
||||||
resultBuilder.setSuccess(document.getId(), /*result=*/ null);
|
packageName, databaseName, document, instance.getLogger());
|
||||||
|
resultBuilder.setSuccess(document.getId(), /*value=*/ null);
|
||||||
++operationSuccessCount;
|
++operationSuccessCount;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
resultBuilder.setResult(document.getId(),
|
resultBuilder.setResult(document.getId(), throwableToFailedResult(t));
|
||||||
throwableToFailedResult(t));
|
|
||||||
AppSearchResult<Void> result = throwableToFailedResult(t);
|
AppSearchResult<Void> result = throwableToFailedResult(t);
|
||||||
resultBuilder.setResult(document.getId(), result);
|
resultBuilder.setResult(document.getId(), result);
|
||||||
// Since we can only include one status code in the atom,
|
// Since we can only include one status code in the atom,
|
||||||
@@ -495,19 +491,19 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Now that the batch has been written. Persist the newly written data.
|
// Now that the batch has been written. Persist the newly written data.
|
||||||
impl.persistToDisk(PersistType.Code.LITE);
|
instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
|
||||||
invokeCallbackOnResult(callback, resultBuilder.build());
|
invokeCallbackOnResult(callback, resultBuilder.build());
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
++operationFailureCount;
|
++operationFailureCount;
|
||||||
statusCode = throwableToFailedResult(t).getResultCode();
|
statusCode = throwableToFailedResult(t).getResultCode();
|
||||||
invokeCallbackOnError(callback, t);
|
invokeCallbackOnError(callback, t);
|
||||||
} finally {
|
} finally {
|
||||||
if (logger != null) {
|
if (instance != null) {
|
||||||
int estimatedBinderLatencyMillis =
|
int estimatedBinderLatencyMillis =
|
||||||
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
|
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
|
||||||
int totalLatencyMillis =
|
int totalLatencyMillis =
|
||||||
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
|
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
|
||||||
logger.logStats(new CallStats.Builder()
|
instance.getLogger().logStats(new CallStats.Builder()
|
||||||
.setPackageName(packageName)
|
.setPackageName(packageName)
|
||||||
.setDatabase(databaseName)
|
.setDatabase(databaseName)
|
||||||
.setStatusCode(statusCode)
|
.setStatusCode(statusCode)
|
||||||
@@ -548,7 +544,7 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
|
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
|
||||||
EXECUTOR.execute(() -> {
|
EXECUTOR.execute(() -> {
|
||||||
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
|
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
|
||||||
PlatformLogger logger = null;
|
AppSearchUserInstance instance = null;
|
||||||
int operationSuccessCount = 0;
|
int operationSuccessCount = 0;
|
||||||
int operationFailureCount = 0;
|
int operationFailureCount = 0;
|
||||||
try {
|
try {
|
||||||
@@ -556,13 +552,11 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
verifyCallingPackage(callingUser, callingUid, packageName);
|
verifyCallingPackage(callingUser, callingUid, packageName);
|
||||||
AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
|
AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
|
||||||
new AppSearchBatchResult.Builder<>();
|
new AppSearchBatchResult.Builder<>();
|
||||||
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
|
instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
|
||||||
logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
|
|
||||||
for (int i = 0; i < ids.size(); i++) {
|
for (int i = 0; i < ids.size(); i++) {
|
||||||
String id = ids.get(i);
|
String id = ids.get(i);
|
||||||
try {
|
try {
|
||||||
GenericDocument document =
|
GenericDocument document = instance.getAppSearchImpl().getDocument(
|
||||||
impl.getDocument(
|
|
||||||
packageName,
|
packageName,
|
||||||
databaseName,
|
databaseName,
|
||||||
namespace,
|
namespace,
|
||||||
@@ -585,12 +579,12 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
statusCode = throwableToFailedResult(t).getResultCode();
|
statusCode = throwableToFailedResult(t).getResultCode();
|
||||||
invokeCallbackOnError(callback, t);
|
invokeCallbackOnError(callback, t);
|
||||||
} finally {
|
} finally {
|
||||||
if (logger != null) {
|
if (instance != null) {
|
||||||
int estimatedBinderLatencyMillis =
|
int estimatedBinderLatencyMillis =
|
||||||
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
|
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
|
||||||
int totalLatencyMillis =
|
int totalLatencyMillis =
|
||||||
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
|
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
|
||||||
logger.logStats(new CallStats.Builder()
|
instance.getLogger().logStats(new CallStats.Builder()
|
||||||
.setPackageName(packageName)
|
.setPackageName(packageName)
|
||||||
.setDatabase(databaseName)
|
.setDatabase(databaseName)
|
||||||
.setStatusCode(statusCode)
|
.setStatusCode(statusCode)
|
||||||
@@ -629,21 +623,19 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
|
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
|
||||||
EXECUTOR.execute(() -> {
|
EXECUTOR.execute(() -> {
|
||||||
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
|
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
|
||||||
PlatformLogger logger = null;
|
AppSearchUserInstance instance = null;
|
||||||
int operationSuccessCount = 0;
|
int operationSuccessCount = 0;
|
||||||
int operationFailureCount = 0;
|
int operationFailureCount = 0;
|
||||||
try {
|
try {
|
||||||
verifyUserUnlocked(callingUser);
|
verifyUserUnlocked(callingUser);
|
||||||
verifyCallingPackage(callingUser, callingUid, packageName);
|
verifyCallingPackage(callingUser, callingUid, packageName);
|
||||||
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
|
instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
|
||||||
logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
|
SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
|
||||||
SearchResultPage searchResultPage =
|
|
||||||
impl.query(
|
|
||||||
packageName,
|
packageName,
|
||||||
databaseName,
|
databaseName,
|
||||||
queryExpression,
|
queryExpression,
|
||||||
new SearchSpec(searchSpecBundle),
|
new SearchSpec(searchSpecBundle),
|
||||||
logger);
|
instance.getLogger());
|
||||||
++operationSuccessCount;
|
++operationSuccessCount;
|
||||||
invokeCallbackOnResult(
|
invokeCallbackOnResult(
|
||||||
callback,
|
callback,
|
||||||
@@ -653,12 +645,12 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
statusCode = throwableToFailedResult(t).getResultCode();
|
statusCode = throwableToFailedResult(t).getResultCode();
|
||||||
invokeCallbackOnError(callback, t);
|
invokeCallbackOnError(callback, t);
|
||||||
} finally {
|
} finally {
|
||||||
if (logger != null) {
|
if (instance != null) {
|
||||||
int estimatedBinderLatencyMillis =
|
int estimatedBinderLatencyMillis =
|
||||||
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
|
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
|
||||||
int totalLatencyMillis =
|
int totalLatencyMillis =
|
||||||
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
|
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
|
||||||
logger.logStats(new CallStats.Builder()
|
instance.getLogger().logStats(new CallStats.Builder()
|
||||||
.setPackageName(packageName)
|
.setPackageName(packageName)
|
||||||
.setDatabase(databaseName)
|
.setDatabase(databaseName)
|
||||||
.setStatusCode(statusCode)
|
.setStatusCode(statusCode)
|
||||||
@@ -695,21 +687,24 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
|
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
|
||||||
EXECUTOR.execute(() -> {
|
EXECUTOR.execute(() -> {
|
||||||
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
|
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
|
||||||
PlatformLogger logger = null;
|
AppSearchUserInstance instance = null;
|
||||||
int operationSuccessCount = 0;
|
int operationSuccessCount = 0;
|
||||||
int operationFailureCount = 0;
|
int operationFailureCount = 0;
|
||||||
try {
|
try {
|
||||||
verifyUserUnlocked(callingUser);
|
verifyUserUnlocked(callingUser);
|
||||||
verifyCallingPackage(callingUser, callingUid, packageName);
|
verifyCallingPackage(callingUser, callingUid, packageName);
|
||||||
logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
|
instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
|
||||||
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
|
|
||||||
SearchResultPage searchResultPage =
|
boolean callerHasSystemAccess =
|
||||||
impl.globalQuery(
|
instance.getVisibilityStore().doesCallerHaveSystemAccess(packageName);
|
||||||
|
SearchResultPage searchResultPage = instance.getAppSearchImpl().globalQuery(
|
||||||
queryExpression,
|
queryExpression,
|
||||||
new SearchSpec(searchSpecBundle),
|
new SearchSpec(searchSpecBundle),
|
||||||
packageName,
|
packageName,
|
||||||
|
instance.getVisibilityStore(),
|
||||||
callingUid,
|
callingUid,
|
||||||
logger);
|
callerHasSystemAccess,
|
||||||
|
instance.getLogger());
|
||||||
++operationSuccessCount;
|
++operationSuccessCount;
|
||||||
invokeCallbackOnResult(
|
invokeCallbackOnResult(
|
||||||
callback,
|
callback,
|
||||||
@@ -719,12 +714,12 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
statusCode = throwableToFailedResult(t).getResultCode();
|
statusCode = throwableToFailedResult(t).getResultCode();
|
||||||
invokeCallbackOnError(callback, t);
|
invokeCallbackOnError(callback, t);
|
||||||
} finally {
|
} finally {
|
||||||
if (logger != null) {
|
if (instance != null) {
|
||||||
int estimatedBinderLatencyMillis =
|
int estimatedBinderLatencyMillis =
|
||||||
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
|
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
|
||||||
int totalLatencyMillis =
|
int totalLatencyMillis =
|
||||||
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
|
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
|
||||||
logger.logStats(new CallStats.Builder()
|
instance.getLogger().logStats(new CallStats.Builder()
|
||||||
.setPackageName(packageName)
|
.setPackageName(packageName)
|
||||||
.setStatusCode(statusCode)
|
.setStatusCode(statusCode)
|
||||||
.setTotalLatencyMillis(totalLatencyMillis)
|
.setTotalLatencyMillis(totalLatencyMillis)
|
||||||
@@ -756,8 +751,10 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
EXECUTOR.execute(() -> {
|
EXECUTOR.execute(() -> {
|
||||||
try {
|
try {
|
||||||
verifyUserUnlocked(callingUser);
|
verifyUserUnlocked(callingUser);
|
||||||
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
|
AppSearchUserInstance instance =
|
||||||
SearchResultPage searchResultPage = impl.getNextPage(nextPageToken);
|
mAppSearchUserInstanceManager.getUserInstance(callingUser);
|
||||||
|
SearchResultPage searchResultPage =
|
||||||
|
instance.getAppSearchImpl().getNextPage(nextPageToken);
|
||||||
invokeCallbackOnResult(
|
invokeCallbackOnResult(
|
||||||
callback,
|
callback,
|
||||||
AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
|
AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
|
||||||
@@ -776,8 +773,9 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
EXECUTOR.execute(() -> {
|
EXECUTOR.execute(() -> {
|
||||||
try {
|
try {
|
||||||
verifyUserUnlocked(callingUser);
|
verifyUserUnlocked(callingUser);
|
||||||
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
|
AppSearchUserInstance instance =
|
||||||
impl.invalidateNextPageToken(nextPageToken);
|
mAppSearchUserInstanceManager.getUserInstance(callingUser);
|
||||||
|
instance.getAppSearchImpl().invalidateNextPageToken(nextPageToken);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
Log.e(TAG, "Unable to invalidate the query page token", t);
|
Log.e(TAG, "Unable to invalidate the query page token", t);
|
||||||
}
|
}
|
||||||
@@ -806,11 +804,12 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
EXECUTOR.execute(() -> {
|
EXECUTOR.execute(() -> {
|
||||||
try {
|
try {
|
||||||
verifyCallingPackage(callingUser, callingUid, packageName);
|
verifyCallingPackage(callingUser, callingUid, packageName);
|
||||||
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
|
AppSearchUserInstance instance =
|
||||||
|
mAppSearchUserInstanceManager.getUserInstance(callingUser);
|
||||||
// we don't need to append the file. The file is always brand new.
|
// we don't need to append the file. The file is always brand new.
|
||||||
try (DataOutputStream outputStream = new DataOutputStream(
|
try (DataOutputStream outputStream = new DataOutputStream(
|
||||||
new FileOutputStream(fileDescriptor.getFileDescriptor()))) {
|
new FileOutputStream(fileDescriptor.getFileDescriptor()))) {
|
||||||
SearchResultPage searchResultPage = impl.query(
|
SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
|
||||||
packageName,
|
packageName,
|
||||||
databaseName,
|
databaseName,
|
||||||
queryExpression,
|
queryExpression,
|
||||||
@@ -822,7 +821,7 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
outputStream, searchResultPage.getResults().get(i)
|
outputStream, searchResultPage.getResults().get(i)
|
||||||
.getGenericDocument().getBundle());
|
.getGenericDocument().getBundle());
|
||||||
}
|
}
|
||||||
searchResultPage = impl.getNextPage(
|
searchResultPage = instance.getAppSearchImpl().getNextPage(
|
||||||
searchResultPage.getNextPageToken());
|
searchResultPage.getNextPageToken());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -851,7 +850,8 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
EXECUTOR.execute(() -> {
|
EXECUTOR.execute(() -> {
|
||||||
try {
|
try {
|
||||||
verifyCallingPackage(callingUser, callingUid, packageName);
|
verifyCallingPackage(callingUser, callingUid, packageName);
|
||||||
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
|
AppSearchUserInstance instance =
|
||||||
|
mAppSearchUserInstanceManager.getUserInstance(callingUser);
|
||||||
|
|
||||||
GenericDocument document;
|
GenericDocument document;
|
||||||
ArrayList<Bundle> migrationFailureBundles = new ArrayList<>();
|
ArrayList<Bundle> migrationFailureBundles = new ArrayList<>();
|
||||||
@@ -866,8 +866,8 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
impl.putDocument(packageName, databaseName, document,
|
instance.getAppSearchImpl().putDocument(
|
||||||
/*logger=*/ null);
|
packageName, databaseName, document, /*logger=*/ null);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
migrationFailureBundles.add(new SetSchemaResponse.MigrationFailure(
|
migrationFailureBundles.add(new SetSchemaResponse.MigrationFailure(
|
||||||
document.getNamespace(),
|
document.getNamespace(),
|
||||||
@@ -878,7 +878,7 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl.persistToDisk(PersistType.Code.FULL);
|
instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
|
||||||
invokeCallbackOnResult(callback,
|
invokeCallbackOnResult(callback,
|
||||||
AppSearchResult.newSuccessfulResult(migrationFailureBundles));
|
AppSearchResult.newSuccessfulResult(migrationFailureBundles));
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
@@ -909,17 +909,23 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
EXECUTOR.execute(() -> {
|
EXECUTOR.execute(() -> {
|
||||||
try {
|
try {
|
||||||
verifyUserUnlocked(callingUser);
|
verifyUserUnlocked(callingUser);
|
||||||
|
verifyCallingPackage(callingUser, callingUid, packageName);
|
||||||
|
AppSearchUserInstance instance =
|
||||||
|
mAppSearchUserInstanceManager.getUserInstance(callingUser);
|
||||||
|
|
||||||
if (systemUsage) {
|
if (systemUsage
|
||||||
// TODO(b/183031844): Validate that the call comes from the system
|
&& !instance.getVisibilityStore()
|
||||||
|
.doesCallerHaveSystemAccess(packageName)) {
|
||||||
|
throw new AppSearchException(
|
||||||
|
AppSearchResult.RESULT_SECURITY_ERROR,
|
||||||
|
packageName + " does not have access to report system usage");
|
||||||
}
|
}
|
||||||
|
|
||||||
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
|
instance.getAppSearchImpl().reportUsage(
|
||||||
impl.reportUsage(
|
|
||||||
packageName, databaseName, namespace, documentId,
|
packageName, databaseName, namespace, documentId,
|
||||||
usageTimeMillis, systemUsage);
|
usageTimeMillis, systemUsage);
|
||||||
invokeCallbackOnResult(
|
invokeCallbackOnResult(
|
||||||
callback, AppSearchResult.newSuccessfulResult(/*result=*/ null));
|
callback, AppSearchResult.newSuccessfulResult(/*value=*/ null));
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
invokeCallbackOnError(callback, t);
|
invokeCallbackOnError(callback, t);
|
||||||
}
|
}
|
||||||
@@ -947,7 +953,7 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
|
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
|
||||||
EXECUTOR.execute(() -> {
|
EXECUTOR.execute(() -> {
|
||||||
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
|
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
|
||||||
PlatformLogger logger = null;
|
AppSearchUserInstance instance = null;
|
||||||
int operationSuccessCount = 0;
|
int operationSuccessCount = 0;
|
||||||
int operationFailureCount = 0;
|
int operationFailureCount = 0;
|
||||||
try {
|
try {
|
||||||
@@ -955,12 +961,11 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
verifyCallingPackage(callingUser, callingUid, packageName);
|
verifyCallingPackage(callingUser, callingUid, packageName);
|
||||||
AppSearchBatchResult.Builder<String, Void> resultBuilder =
|
AppSearchBatchResult.Builder<String, Void> resultBuilder =
|
||||||
new AppSearchBatchResult.Builder<>();
|
new AppSearchBatchResult.Builder<>();
|
||||||
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
|
instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
|
||||||
logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
|
|
||||||
for (int i = 0; i < ids.size(); i++) {
|
for (int i = 0; i < ids.size(); i++) {
|
||||||
String id = ids.get(i);
|
String id = ids.get(i);
|
||||||
try {
|
try {
|
||||||
impl.remove(
|
instance.getAppSearchImpl().remove(
|
||||||
packageName,
|
packageName,
|
||||||
databaseName,
|
databaseName,
|
||||||
namespace,
|
namespace,
|
||||||
@@ -978,19 +983,19 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Now that the batch has been written. Persist the newly written data.
|
// Now that the batch has been written. Persist the newly written data.
|
||||||
impl.persistToDisk(PersistType.Code.LITE);
|
instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
|
||||||
invokeCallbackOnResult(callback, resultBuilder.build());
|
invokeCallbackOnResult(callback, resultBuilder.build());
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
++operationFailureCount;
|
++operationFailureCount;
|
||||||
statusCode = throwableToFailedResult(t).getResultCode();
|
statusCode = throwableToFailedResult(t).getResultCode();
|
||||||
invokeCallbackOnError(callback, t);
|
invokeCallbackOnError(callback, t);
|
||||||
} finally {
|
} finally {
|
||||||
if (logger != null) {
|
if (instance != null) {
|
||||||
int estimatedBinderLatencyMillis =
|
int estimatedBinderLatencyMillis =
|
||||||
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
|
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
|
||||||
int totalLatencyMillis =
|
int totalLatencyMillis =
|
||||||
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
|
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
|
||||||
logger.logStats(new CallStats.Builder()
|
instance.getLogger().logStats(new CallStats.Builder()
|
||||||
.setPackageName(packageName)
|
.setPackageName(packageName)
|
||||||
.setDatabase(databaseName)
|
.setDatabase(databaseName)
|
||||||
.setStatusCode(statusCode)
|
.setStatusCode(statusCode)
|
||||||
@@ -1030,22 +1035,21 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
|
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
|
||||||
EXECUTOR.execute(() -> {
|
EXECUTOR.execute(() -> {
|
||||||
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
|
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
|
||||||
PlatformLogger logger = null;
|
AppSearchUserInstance instance = null;
|
||||||
int operationSuccessCount = 0;
|
int operationSuccessCount = 0;
|
||||||
int operationFailureCount = 0;
|
int operationFailureCount = 0;
|
||||||
try {
|
try {
|
||||||
verifyUserUnlocked(callingUser);
|
verifyUserUnlocked(callingUser);
|
||||||
verifyCallingPackage(callingUser, callingUid, packageName);
|
verifyCallingPackage(callingUser, callingUid, packageName);
|
||||||
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
|
instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
|
||||||
logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
|
instance.getAppSearchImpl().removeByQuery(
|
||||||
impl.removeByQuery(
|
|
||||||
packageName,
|
packageName,
|
||||||
databaseName,
|
databaseName,
|
||||||
queryExpression,
|
queryExpression,
|
||||||
new SearchSpec(searchSpecBundle),
|
new SearchSpec(searchSpecBundle),
|
||||||
/*removeStatsBuilder=*/ null);
|
/*removeStatsBuilder=*/ null);
|
||||||
// Now that the batch has been written. Persist the newly written data.
|
// Now that the batch has been written. Persist the newly written data.
|
||||||
impl.persistToDisk(PersistType.Code.LITE);
|
instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
|
||||||
++operationSuccessCount;
|
++operationSuccessCount;
|
||||||
invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
|
invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
@@ -1053,12 +1057,12 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
statusCode = throwableToFailedResult(t).getResultCode();
|
statusCode = throwableToFailedResult(t).getResultCode();
|
||||||
invokeCallbackOnError(callback, t);
|
invokeCallbackOnError(callback, t);
|
||||||
} finally {
|
} finally {
|
||||||
if (logger != null) {
|
if (instance != null) {
|
||||||
int estimatedBinderLatencyMillis =
|
int estimatedBinderLatencyMillis =
|
||||||
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
|
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
|
||||||
int totalLatencyMillis =
|
int totalLatencyMillis =
|
||||||
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
|
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
|
||||||
logger.logStats(new CallStats.Builder()
|
instance.getLogger().logStats(new CallStats.Builder()
|
||||||
.setPackageName(packageName)
|
.setPackageName(packageName)
|
||||||
.setDatabase(databaseName)
|
.setDatabase(databaseName)
|
||||||
.setStatusCode(statusCode)
|
.setStatusCode(statusCode)
|
||||||
@@ -1093,9 +1097,10 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
try {
|
try {
|
||||||
verifyUserUnlocked(callingUser);
|
verifyUserUnlocked(callingUser);
|
||||||
verifyCallingPackage(callingUser, callingUid, packageName);
|
verifyCallingPackage(callingUser, callingUid, packageName);
|
||||||
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
|
AppSearchUserInstance instance =
|
||||||
StorageInfo storageInfo = impl.getStorageInfoForDatabase(packageName,
|
mAppSearchUserInstanceManager.getUserInstance(callingUser);
|
||||||
databaseName);
|
StorageInfo storageInfo = instance.getAppSearchImpl()
|
||||||
|
.getStorageInfoForDatabase(packageName, databaseName);
|
||||||
Bundle storageInfoBundle = storageInfo.getBundle();
|
Bundle storageInfoBundle = storageInfo.getBundle();
|
||||||
invokeCallbackOnResult(
|
invokeCallbackOnResult(
|
||||||
callback, AppSearchResult.newSuccessfulResult(storageInfoBundle));
|
callback, AppSearchResult.newSuccessfulResult(storageInfoBundle));
|
||||||
@@ -1116,26 +1121,25 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
|
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
|
||||||
EXECUTOR.execute(() -> {
|
EXECUTOR.execute(() -> {
|
||||||
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
|
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
|
||||||
PlatformLogger logger = null;
|
AppSearchUserInstance instance = null;
|
||||||
int operationSuccessCount = 0;
|
int operationSuccessCount = 0;
|
||||||
int operationFailureCount = 0;
|
int operationFailureCount = 0;
|
||||||
try {
|
try {
|
||||||
verifyUserUnlocked(callingUser);
|
verifyUserUnlocked(callingUser);
|
||||||
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
|
instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
|
||||||
logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
|
instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
|
||||||
impl.persistToDisk(PersistType.Code.FULL);
|
|
||||||
++operationSuccessCount;
|
++operationSuccessCount;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
++operationFailureCount;
|
++operationFailureCount;
|
||||||
statusCode = throwableToFailedResult(t).getResultCode();
|
statusCode = throwableToFailedResult(t).getResultCode();
|
||||||
Log.e(TAG, "Unable to persist the data to disk", t);
|
Log.e(TAG, "Unable to persist the data to disk", t);
|
||||||
} finally {
|
} finally {
|
||||||
if (logger != null) {
|
if (instance != null) {
|
||||||
int estimatedBinderLatencyMillis =
|
int estimatedBinderLatencyMillis =
|
||||||
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
|
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
|
||||||
int totalLatencyMillis =
|
int totalLatencyMillis =
|
||||||
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
|
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
|
||||||
logger.logStats(new CallStats.Builder()
|
instance.getLogger().logStats(new CallStats.Builder()
|
||||||
.setStatusCode(statusCode)
|
.setStatusCode(statusCode)
|
||||||
.setTotalLatencyMillis(totalLatencyMillis)
|
.setTotalLatencyMillis(totalLatencyMillis)
|
||||||
.setCallType(CallStats.CALL_TYPE_FLUSH)
|
.setCallType(CallStats.CALL_TYPE_FLUSH)
|
||||||
@@ -1164,15 +1168,13 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
|
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
|
||||||
EXECUTOR.execute(() -> {
|
EXECUTOR.execute(() -> {
|
||||||
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
|
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
|
||||||
PlatformLogger logger = null;
|
AppSearchUserInstance instance = null;
|
||||||
int operationSuccessCount = 0;
|
int operationSuccessCount = 0;
|
||||||
int operationFailureCount = 0;
|
int operationFailureCount = 0;
|
||||||
try {
|
try {
|
||||||
verifyUserUnlocked(callingUser);
|
verifyUserUnlocked(callingUser);
|
||||||
logger = mLoggerInstanceManager.getOrCreatePlatformLogger(
|
instance = mAppSearchUserInstanceManager.getOrCreateUserInstance(
|
||||||
mContext, callingUser,
|
mContext, callingUser, AppSearchConfig.getInstance(EXECUTOR));
|
||||||
AppSearchConfig.getInstance(EXECUTOR));
|
|
||||||
mImplInstanceManager.getOrCreateAppSearchImpl(mContext, callingUser, logger);
|
|
||||||
++operationSuccessCount;
|
++operationSuccessCount;
|
||||||
invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
|
invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
@@ -1180,12 +1182,12 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
statusCode = throwableToFailedResult(t).getResultCode();
|
statusCode = throwableToFailedResult(t).getResultCode();
|
||||||
invokeCallbackOnError(callback, t);
|
invokeCallbackOnError(callback, t);
|
||||||
} finally {
|
} finally {
|
||||||
if (logger != null) {
|
if (instance != null) {
|
||||||
int estimatedBinderLatencyMillis =
|
int estimatedBinderLatencyMillis =
|
||||||
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
|
2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
|
||||||
int totalLatencyMillis =
|
int totalLatencyMillis =
|
||||||
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
|
(int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
|
||||||
logger.logStats(new CallStats.Builder()
|
instance.getLogger().logStats(new CallStats.Builder()
|
||||||
.setStatusCode(statusCode)
|
.setStatusCode(statusCode)
|
||||||
.setTotalLatencyMillis(totalLatencyMillis)
|
.setTotalLatencyMillis(totalLatencyMillis)
|
||||||
.setCallType(CallStats.CALL_TYPE_INITIALIZE)
|
.setCallType(CallStats.CALL_TYPE_INITIALIZE)
|
||||||
@@ -1329,12 +1331,11 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
verifyUserUnlocked(userHandle);
|
verifyUserUnlocked(userHandle);
|
||||||
PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(
|
AppSearchUserInstance instance =
|
||||||
mContext, userHandle,
|
mAppSearchUserInstanceManager.getOrCreateUserInstance(
|
||||||
AppSearchConfig.getInstance(EXECUTOR));
|
mContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
|
||||||
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(
|
stats.dataSize += instance.getAppSearchImpl()
|
||||||
mContext, userHandle, logger);
|
.getStorageInfoForPackage(packageName).getSizeBytes();
|
||||||
stats.dataSize += impl.getStorageInfoForPackage(packageName).getSizeBytes();
|
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
Log.e(
|
Log.e(
|
||||||
TAG,
|
TAG,
|
||||||
@@ -1358,14 +1359,12 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
if (packagesForUid == null) {
|
if (packagesForUid == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(
|
AppSearchUserInstance instance =
|
||||||
mContext, userHandle,
|
mAppSearchUserInstanceManager.getOrCreateUserInstance(
|
||||||
AppSearchConfig.getInstance(EXECUTOR));
|
mContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
|
||||||
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(
|
|
||||||
mContext, userHandle, logger);
|
|
||||||
for (int i = 0; i < packagesForUid.length; i++) {
|
for (int i = 0; i < packagesForUid.length; i++) {
|
||||||
stats.dataSize +=
|
stats.dataSize += instance.getAppSearchImpl()
|
||||||
impl.getStorageInfoForPackage(packagesForUid[i]).getSizeBytes();
|
.getStorageInfoForPackage(packagesForUid[i]).getSizeBytes();
|
||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
Log.e(TAG, "Unable to augment storage stats for uid " + uid, t);
|
Log.e(TAG, "Unable to augment storage stats for uid " + uid, t);
|
||||||
@@ -1388,14 +1387,13 @@ public class AppSearchManagerService extends SystemService {
|
|||||||
if (packagesForUser == null) {
|
if (packagesForUser == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(
|
AppSearchUserInstance instance =
|
||||||
mContext, userHandle,
|
mAppSearchUserInstanceManager.getOrCreateUserInstance(
|
||||||
AppSearchConfig.getInstance(EXECUTOR));
|
mContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
|
||||||
AppSearchImpl impl =
|
|
||||||
mImplInstanceManager.getOrCreateAppSearchImpl(mContext, userHandle, 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 += instance.getAppSearchImpl()
|
||||||
|
.getStorageInfoForPackage(packageName).getSizeBytes();
|
||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
Log.e(TAG, "Unable to augment storage stats for " + userHandle, t);
|
Log.e(TAG, "Unable to augment storage stats for " + userHandle, t);
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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.appsearch;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.android.server.appsearch.external.localstorage.AppSearchImpl;
|
||||||
|
import com.android.server.appsearch.stats.PlatformLogger;
|
||||||
|
import com.android.server.appsearch.visibilitystore.VisibilityStore;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Container for AppSearch classes that should only be initialized once per device-user and make up
|
||||||
|
* the core of the AppSearch system.
|
||||||
|
*/
|
||||||
|
public final class AppSearchUserInstance {
|
||||||
|
private final PlatformLogger mLogger;
|
||||||
|
private final AppSearchImpl mAppSearchImpl;
|
||||||
|
private final VisibilityStore mVisibilityStore;
|
||||||
|
|
||||||
|
AppSearchUserInstance(
|
||||||
|
@NonNull PlatformLogger logger,
|
||||||
|
@NonNull AppSearchImpl appSearchImpl,
|
||||||
|
@NonNull VisibilityStore visibilityStore) {
|
||||||
|
mLogger = Objects.requireNonNull(logger);
|
||||||
|
mAppSearchImpl = Objects.requireNonNull(appSearchImpl);
|
||||||
|
mVisibilityStore = Objects.requireNonNull(visibilityStore);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public PlatformLogger getLogger() {
|
||||||
|
return mLogger;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public AppSearchImpl getAppSearchImpl() {
|
||||||
|
return mAppSearchImpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public VisibilityStore getVisibilityStore() {
|
||||||
|
return mVisibilityStore;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,195 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 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.appsearch;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.app.appsearch.exceptions.AppSearchException;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.os.SystemClock;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
import android.util.ArrayMap;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.GuardedBy;
|
||||||
|
import com.android.server.appsearch.external.localstorage.AppSearchImpl;
|
||||||
|
import com.android.server.appsearch.external.localstorage.FrameworkOptimizeStrategy;
|
||||||
|
import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
|
||||||
|
import com.android.server.appsearch.stats.PlatformLogger;
|
||||||
|
import com.android.server.appsearch.visibilitystore.VisibilityStore;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages the lifecycle of AppSearch classes that should only be initialized once per device-user
|
||||||
|
* and make up the core of the AppSearch system.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public final class AppSearchUserInstanceManager {
|
||||||
|
private static final String TAG = "AppSearchUserInstanceMa";
|
||||||
|
|
||||||
|
private static volatile AppSearchUserInstanceManager sAppSearchUserInstanceManager;
|
||||||
|
|
||||||
|
@GuardedBy("mInstancesLocked")
|
||||||
|
private final Map<UserHandle, AppSearchUserInstance> mInstancesLocked = new ArrayMap<>();
|
||||||
|
|
||||||
|
private AppSearchUserInstanceManager() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an instance of AppSearchUserInstanceManager to be used.
|
||||||
|
*
|
||||||
|
* <p>If no instance has been initialized yet, a new one will be created. Otherwise, the
|
||||||
|
* existing instance will be returned.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public static AppSearchUserInstanceManager getInstance() {
|
||||||
|
if (sAppSearchUserInstanceManager == null) {
|
||||||
|
synchronized (AppSearchUserInstanceManager.class) {
|
||||||
|
if (sAppSearchUserInstanceManager == null) {
|
||||||
|
sAppSearchUserInstanceManager = new AppSearchUserInstanceManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sAppSearchUserInstanceManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns AppSearch directory in the credential encrypted system directory for the given user.
|
||||||
|
*
|
||||||
|
* <p>This folder should only be accessed after unlock.
|
||||||
|
*/
|
||||||
|
public static File getAppSearchDir(@NonNull UserHandle userHandle) {
|
||||||
|
// Duplicates the implementation of Environment#getDataSystemCeDirectory
|
||||||
|
// TODO(b/191059409): Unhide Environment#getDataSystemCeDirectory and switch to it.
|
||||||
|
File systemCeDir = new File(Environment.getDataDirectory(), "system_ce");
|
||||||
|
File systemCeUserDir = new File(systemCeDir, String.valueOf(userHandle.getIdentifier()));
|
||||||
|
return new File(systemCeUserDir, "appsearch");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an instance of AppSearchUserInstance for the given user, or creates one if none exists.
|
||||||
|
*
|
||||||
|
* <p>If no AppSearchUserInstance exists for the unlocked user, Icing will be initialized and
|
||||||
|
* one will be created.
|
||||||
|
*
|
||||||
|
* @param context The context
|
||||||
|
* @param userHandle The multi-user handle of the device user calling AppSearch
|
||||||
|
* @param config Flag manager for AppSearch
|
||||||
|
* @return An initialized {@link AppSearchUserInstance} for this user
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public AppSearchUserInstance getOrCreateUserInstance(
|
||||||
|
@NonNull Context context,
|
||||||
|
@NonNull UserHandle userHandle,
|
||||||
|
@NonNull AppSearchConfig config)
|
||||||
|
throws AppSearchException {
|
||||||
|
Objects.requireNonNull(context);
|
||||||
|
Objects.requireNonNull(userHandle);
|
||||||
|
Objects.requireNonNull(config);
|
||||||
|
|
||||||
|
synchronized (mInstancesLocked) {
|
||||||
|
AppSearchUserInstance instance = mInstancesLocked.get(userHandle);
|
||||||
|
if (instance == null) {
|
||||||
|
Context userContext = context.createContextAsUser(userHandle, /*flags=*/ 0);
|
||||||
|
instance = createUserInstance(userContext, userHandle, config);
|
||||||
|
mInstancesLocked.put(userHandle, instance);
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes and removes an {@link AppSearchUserInstance} for the given user.
|
||||||
|
*
|
||||||
|
* <p>All mutations applied to the underlying {@link AppSearchImpl} will be persisted to disk.
|
||||||
|
*
|
||||||
|
* @param userHandle The multi-user user handle of the user that need to be removed.
|
||||||
|
*/
|
||||||
|
public void closeAndRemoveUserInstance(@NonNull UserHandle userHandle) {
|
||||||
|
Objects.requireNonNull(userHandle);
|
||||||
|
synchronized (mInstancesLocked) {
|
||||||
|
AppSearchUserInstance instance = mInstancesLocked.remove(userHandle);
|
||||||
|
if (instance != null) {
|
||||||
|
instance.getAppSearchImpl().close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an {@link AppSearchUserInstance} for the given user.
|
||||||
|
*
|
||||||
|
* <p>This method should only be called by an initialized SearchSession, which has already
|
||||||
|
* called {@link #getOrCreateUserInstance} before.
|
||||||
|
*
|
||||||
|
* @param userHandle The multi-user handle of the device user calling AppSearch
|
||||||
|
* @return An initialized {@link AppSearchUserInstance} for this user
|
||||||
|
* @throws IllegalStateException if {@link AppSearchUserInstance} haven't created for the given
|
||||||
|
* user.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public AppSearchUserInstance getUserInstance(@NonNull UserHandle userHandle) {
|
||||||
|
Objects.requireNonNull(userHandle);
|
||||||
|
synchronized (mInstancesLocked) {
|
||||||
|
AppSearchUserInstance instance = mInstancesLocked.get(userHandle);
|
||||||
|
if (instance == null) {
|
||||||
|
// Impossible scenario, user cannot call an uninitialized SearchSession,
|
||||||
|
// getInstance should always find the instance for the given user and never try to
|
||||||
|
// create an instance for this user again.
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"AppSearchUserInstance has never been created for: " + userHandle);
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private AppSearchUserInstance createUserInstance(
|
||||||
|
@NonNull Context userContext,
|
||||||
|
@NonNull UserHandle userHandle,
|
||||||
|
@NonNull AppSearchConfig config)
|
||||||
|
throws AppSearchException {
|
||||||
|
long totalLatencyStartMillis = SystemClock.elapsedRealtime();
|
||||||
|
InitializeStats.Builder initStatsBuilder = new InitializeStats.Builder();
|
||||||
|
|
||||||
|
// Initialize the classes that make up AppSearchUserInstance
|
||||||
|
PlatformLogger logger = new PlatformLogger(userContext, userHandle, config);
|
||||||
|
|
||||||
|
File appSearchDir = getAppSearchDir(userHandle);
|
||||||
|
File icingDir = new File(appSearchDir, "icing");
|
||||||
|
Log.i(TAG, "Creating new AppSearch instance at: " + icingDir);
|
||||||
|
AppSearchImpl appSearchImpl =
|
||||||
|
AppSearchImpl.create(icingDir, initStatsBuilder, new FrameworkOptimizeStrategy());
|
||||||
|
|
||||||
|
long prepareVisibilityStoreLatencyStartMillis = SystemClock.elapsedRealtime();
|
||||||
|
VisibilityStore visibilityStore = VisibilityStore.create(appSearchImpl, userContext);
|
||||||
|
long prepareVisibilityStoreLatencyEndMillis = SystemClock.elapsedRealtime();
|
||||||
|
|
||||||
|
initStatsBuilder
|
||||||
|
.setTotalLatencyMillis(
|
||||||
|
(int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
|
||||||
|
.setPrepareVisibilityStoreLatencyMillis(
|
||||||
|
(int)
|
||||||
|
(prepareVisibilityStoreLatencyEndMillis
|
||||||
|
- prepareVisibilityStoreLatencyStartMillis));
|
||||||
|
logger.logStats(initStatsBuilder.build());
|
||||||
|
|
||||||
|
return new AppSearchUserInstance(logger, appSearchImpl, visibilityStore);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,170 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2019 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.appsearch;
|
|
||||||
|
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
|
||||||
import android.annotation.Nullable;
|
|
||||||
import android.app.appsearch.exceptions.AppSearchException;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Environment;
|
|
||||||
import android.os.UserHandle;
|
|
||||||
import android.util.ArrayMap;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import com.android.internal.annotations.GuardedBy;
|
|
||||||
import com.android.server.appsearch.external.localstorage.AppSearchImpl;
|
|
||||||
import com.android.server.appsearch.external.localstorage.AppSearchLogger;
|
|
||||||
import com.android.server.appsearch.external.localstorage.FrameworkOptimizeStrategy;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manages the lifecycle of instances of {@link AppSearchImpl}.
|
|
||||||
*
|
|
||||||
* <p>These instances are managed per unique device-user.
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public final class ImplInstanceManager {
|
|
||||||
private static final String TAG = "AppSearchImplInstanceMa";
|
|
||||||
|
|
||||||
private static ImplInstanceManager sImplInstanceManager;
|
|
||||||
|
|
||||||
@GuardedBy("mInstancesLocked")
|
|
||||||
private final Map<UserHandle, AppSearchImpl> mInstancesLocked = new ArrayMap<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets an instance of ImplInstanceManager to be used.
|
|
||||||
*
|
|
||||||
* <p>If no instance has been initialized yet, a new one will be created. Otherwise, the
|
|
||||||
* existing instance will be returned.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
public static ImplInstanceManager getInstance(@NonNull Context context) {
|
|
||||||
if (sImplInstanceManager == null) {
|
|
||||||
synchronized (ImplInstanceManager.class) {
|
|
||||||
if (sImplInstanceManager == null) {
|
|
||||||
sImplInstanceManager = new ImplInstanceManager();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sImplInstanceManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns AppSearch directory in the credential encrypted system directory for the given user.
|
|
||||||
*
|
|
||||||
* <p>This folder should only be accessed after unlock.
|
|
||||||
*/
|
|
||||||
public static File getAppSearchDir(@NonNull UserHandle userHandle) {
|
|
||||||
// Duplicates the implementation of Environment#getDataSystemCeDirectory
|
|
||||||
// TODO(b/191059409): Unhide Environment#getDataSystemCeDirectory and switch to it.
|
|
||||||
File systemCeDir = new File(Environment.getDataDirectory(), "system_ce");
|
|
||||||
File systemCeUserDir = new File(systemCeDir, String.valueOf(userHandle.getIdentifier()));
|
|
||||||
return new File(systemCeUserDir, "appSearch");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets an instance of AppSearchImpl for the given user, or creates one if none exists.
|
|
||||||
*
|
|
||||||
* <p>If no AppSearchImpl instance exists for the unlocked user, Icing will be initialized and
|
|
||||||
* one will be created.
|
|
||||||
*
|
|
||||||
* @param context The system context
|
|
||||||
* @param userHandle The multi-user handle of the device user calling AppSearch
|
|
||||||
* @return An initialized {@link AppSearchImpl} for this user
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
public AppSearchImpl getOrCreateAppSearchImpl(
|
|
||||||
@NonNull Context context,
|
|
||||||
@NonNull UserHandle userHandle,
|
|
||||||
@Nullable AppSearchLogger logger) throws AppSearchException {
|
|
||||||
Objects.requireNonNull(context);
|
|
||||||
Objects.requireNonNull(userHandle);
|
|
||||||
|
|
||||||
synchronized (mInstancesLocked) {
|
|
||||||
AppSearchImpl instance = mInstancesLocked.get(userHandle);
|
|
||||||
if (instance == null) {
|
|
||||||
Context userContext = context.createContextAsUser(userHandle, /*flags=*/ 0);
|
|
||||||
instance = createImpl(userContext, userHandle, logger);
|
|
||||||
mInstancesLocked.put(userHandle, instance);
|
|
||||||
}
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close and remove an instance of {@link AppSearchImpl} for the given user.
|
|
||||||
*
|
|
||||||
* <p>All mutation apply to this {@link AppSearchImpl} will be persisted to disk.
|
|
||||||
*
|
|
||||||
* @param userHandle The multi-user user handle of the user that need to be removed.
|
|
||||||
*/
|
|
||||||
public void closeAndRemoveAppSearchImplForUser(@NonNull UserHandle userHandle) {
|
|
||||||
Objects.requireNonNull(userHandle);
|
|
||||||
synchronized (mInstancesLocked) {
|
|
||||||
AppSearchImpl appSearchImpl = mInstancesLocked.get(userHandle);
|
|
||||||
if (appSearchImpl != null) {
|
|
||||||
appSearchImpl.close();
|
|
||||||
mInstancesLocked.remove(userHandle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets an instance of AppSearchImpl for the given user.
|
|
||||||
*
|
|
||||||
* <p>This method should only be called by an initialized SearchSession, which has been already
|
|
||||||
* created the AppSearchImpl instance for the given user.
|
|
||||||
*
|
|
||||||
* @param userHandle The multi-user handle of the device user calling AppSearch
|
|
||||||
* @return An initialized {@link AppSearchImpl} for this user
|
|
||||||
* @throws IllegalStateException if {@link AppSearchImpl} haven't created for the given user.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
public AppSearchImpl getAppSearchImpl(@NonNull UserHandle userHandle) {
|
|
||||||
Objects.requireNonNull(userHandle);
|
|
||||||
synchronized (mInstancesLocked) {
|
|
||||||
AppSearchImpl instance = mInstancesLocked.get(userHandle);
|
|
||||||
if (instance == null) {
|
|
||||||
// Impossible scenario, user cannot call an uninitialized SearchSession,
|
|
||||||
// getInstance should always find the instance for the given user and never try to
|
|
||||||
// create an instance for this user again.
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"AppSearchImpl has never been created for: " + userHandle);
|
|
||||||
}
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private AppSearchImpl createImpl(
|
|
||||||
@NonNull Context userContext,
|
|
||||||
@NonNull UserHandle userHandle,
|
|
||||||
@Nullable AppSearchLogger logger)
|
|
||||||
throws AppSearchException {
|
|
||||||
File appSearchDir = getAppSearchDir(userHandle);
|
|
||||||
File icingDir = new File(appSearchDir, "icing");
|
|
||||||
Log.i(TAG, "Creating new AppSearch instance at: " + icingDir);
|
|
||||||
return AppSearchImpl.create(
|
|
||||||
icingDir,
|
|
||||||
userContext,
|
|
||||||
/*logger=*/ null,
|
|
||||||
new FrameworkOptimizeStrategy());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -39,7 +39,6 @@ import android.app.appsearch.SetSchemaResponse;
|
|||||||
import android.app.appsearch.StorageInfo;
|
import android.app.appsearch.StorageInfo;
|
||||||
import android.app.appsearch.exceptions.AppSearchException;
|
import android.app.appsearch.exceptions.AppSearchException;
|
||||||
import android.app.appsearch.util.LogUtil;
|
import android.app.appsearch.util.LogUtil;
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
@@ -157,9 +156,6 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
final IcingSearchEngine mIcingSearchEngineLocked;
|
final IcingSearchEngine mIcingSearchEngineLocked;
|
||||||
|
|
||||||
@GuardedBy("mReadWriteLock")
|
|
||||||
private final VisibilityStore mVisibilityStoreLocked;
|
|
||||||
|
|
||||||
// This map contains schema types and SchemaTypeConfigProtos for all package-database
|
// This map contains schema types and SchemaTypeConfigProtos for all package-database
|
||||||
// prefixes. It maps each package-database prefix to an inner-map. The inner-map maps each
|
// prefixes. It maps each package-database prefix to an inner-map. The inner-map maps each
|
||||||
// prefixed schema type to its respective SchemaTypeConfigProto.
|
// prefixed schema type to its respective SchemaTypeConfigProto.
|
||||||
@@ -195,56 +191,27 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
* <p>Instead, logger instance needs to be passed to each individual method, like create, query
|
* <p>Instead, logger instance needs to be passed to each individual method, like create, query
|
||||||
* and putDocument.
|
* and putDocument.
|
||||||
*
|
*
|
||||||
* @param logger collects stats for initialization if provided.
|
* @param initStatsBuilder collects stats for initialization if provided.
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public static AppSearchImpl create(
|
public static AppSearchImpl create(
|
||||||
@NonNull File icingDir,
|
@NonNull File icingDir,
|
||||||
@NonNull Context userContext,
|
@Nullable InitializeStats.Builder initStatsBuilder,
|
||||||
@Nullable AppSearchLogger logger,
|
|
||||||
@NonNull OptimizeStrategy optimizeStrategy)
|
@NonNull OptimizeStrategy optimizeStrategy)
|
||||||
throws AppSearchException {
|
throws AppSearchException {
|
||||||
Objects.requireNonNull(icingDir);
|
return new AppSearchImpl(icingDir, initStatsBuilder, optimizeStrategy);
|
||||||
Objects.requireNonNull(userContext);
|
|
||||||
Objects.requireNonNull(optimizeStrategy);
|
|
||||||
|
|
||||||
long totalLatencyStartMillis = SystemClock.elapsedRealtime();
|
|
||||||
InitializeStats.Builder initStatsBuilder = null;
|
|
||||||
if (logger != null) {
|
|
||||||
initStatsBuilder = new InitializeStats.Builder();
|
|
||||||
}
|
|
||||||
|
|
||||||
AppSearchImpl appSearchImpl =
|
|
||||||
new AppSearchImpl(
|
|
||||||
icingDir, userContext, initStatsBuilder, optimizeStrategy);
|
|
||||||
|
|
||||||
long prepareVisibilityStoreLatencyStartMillis = SystemClock.elapsedRealtime();
|
|
||||||
appSearchImpl.initializeVisibilityStore();
|
|
||||||
long prepareVisibilityStoreLatencyEndMillis = SystemClock.elapsedRealtime();
|
|
||||||
|
|
||||||
if (logger != null) {
|
|
||||||
initStatsBuilder
|
|
||||||
.setTotalLatencyMillis(
|
|
||||||
(int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
|
|
||||||
.setPrepareVisibilityStoreLatencyMillis(
|
|
||||||
(int)
|
|
||||||
(prepareVisibilityStoreLatencyEndMillis
|
|
||||||
- prepareVisibilityStoreLatencyStartMillis));
|
|
||||||
logger.logStats(initStatsBuilder.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
return appSearchImpl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param initStatsBuilder collects stats for initialization if provided. */
|
/** @param initStatsBuilder collects stats for initialization if provided. */
|
||||||
private AppSearchImpl(
|
private AppSearchImpl(
|
||||||
@NonNull File icingDir,
|
@NonNull File icingDir,
|
||||||
@NonNull Context userContext,
|
|
||||||
@Nullable InitializeStats.Builder initStatsBuilder,
|
@Nullable InitializeStats.Builder initStatsBuilder,
|
||||||
@NonNull OptimizeStrategy optimizeStrategy)
|
@NonNull OptimizeStrategy optimizeStrategy)
|
||||||
throws AppSearchException {
|
throws AppSearchException {
|
||||||
mReadWriteLock.writeLock().lock();
|
Objects.requireNonNull(icingDir);
|
||||||
|
mOptimizeStrategy = Objects.requireNonNull(optimizeStrategy);
|
||||||
|
|
||||||
|
mReadWriteLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
// We synchronize here because we don't want to call IcingSearchEngine.initialize() more
|
// We synchronize here because we don't want to call IcingSearchEngine.initialize() more
|
||||||
// than once. It's unnecessary and can be a costly operation.
|
// than once. It's unnecessary and can be a costly operation.
|
||||||
@@ -258,9 +225,6 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
"Constructing IcingSearchEngine, response",
|
"Constructing IcingSearchEngine, response",
|
||||||
Objects.hashCode(mIcingSearchEngineLocked));
|
Objects.hashCode(mIcingSearchEngineLocked));
|
||||||
|
|
||||||
mVisibilityStoreLocked = new VisibilityStore(this, userContext);
|
|
||||||
mOptimizeStrategy = optimizeStrategy;
|
|
||||||
|
|
||||||
// The core initialization procedure. If any part of this fails, we bail into
|
// The core initialization procedure. If any part of this fails, we bail into
|
||||||
// resetLocked(), deleting all data (but hopefully allowing AppSearchImpl to come up).
|
// resetLocked(), deleting all data (but hopefully allowing AppSearchImpl to come up).
|
||||||
try {
|
try {
|
||||||
@@ -342,23 +306,6 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the visibility store in AppSearchImpl.
|
|
||||||
*
|
|
||||||
* @throws AppSearchException on IcingSearchEngine error.
|
|
||||||
*/
|
|
||||||
void initializeVisibilityStore() throws AppSearchException {
|
|
||||||
mReadWriteLock.writeLock().lock();
|
|
||||||
try {
|
|
||||||
throwIfClosedLocked();
|
|
||||||
mLogUtil.piiTrace("Initializing VisibilityStore, request");
|
|
||||||
mVisibilityStoreLocked.initialize();
|
|
||||||
mLogUtil.piiTrace("Initializing VisibilityStore, response");
|
|
||||||
} finally {
|
|
||||||
mReadWriteLock.writeLock().unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@GuardedBy("mReadWriteLock")
|
@GuardedBy("mReadWriteLock")
|
||||||
private void throwIfClosedLocked() {
|
private void throwIfClosedLocked() {
|
||||||
if (mClosedLocked) {
|
if (mClosedLocked) {
|
||||||
@@ -399,6 +346,8 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
* @param packageName The package name that owns the schemas.
|
* @param packageName The package name that owns the schemas.
|
||||||
* @param databaseName The name of the database where this schema lives.
|
* @param databaseName The name of the database where this schema lives.
|
||||||
* @param schemas Schemas to set for this app.
|
* @param schemas Schemas to set for this app.
|
||||||
|
* @param visibilityStore If set, {@code schemasNotPlatformSurfaceable} and {@code
|
||||||
|
* schemasPackageAccessible} will be saved here if the schema is successfully applied.
|
||||||
* @param schemasNotPlatformSurfaceable Schema types that should not be surfaced on platform
|
* @param schemasNotPlatformSurfaceable Schema types that should not be surfaced on platform
|
||||||
* surfaces.
|
* surfaces.
|
||||||
* @param schemasPackageAccessible Schema types that are visible to the specified packages.
|
* @param schemasPackageAccessible Schema types that are visible to the specified packages.
|
||||||
@@ -416,6 +365,7 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
@NonNull String packageName,
|
@NonNull String packageName,
|
||||||
@NonNull String databaseName,
|
@NonNull String databaseName,
|
||||||
@NonNull List<AppSearchSchema> schemas,
|
@NonNull List<AppSearchSchema> schemas,
|
||||||
|
@Nullable VisibilityStore visibilityStore,
|
||||||
@NonNull List<String> schemasNotPlatformSurfaceable,
|
@NonNull List<String> schemasNotPlatformSurfaceable,
|
||||||
@NonNull Map<String, List<PackageIdentifier>> schemasPackageAccessible,
|
@NonNull Map<String, List<PackageIdentifier>> schemasPackageAccessible,
|
||||||
boolean forceOverride,
|
boolean forceOverride,
|
||||||
@@ -479,6 +429,7 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
removeFromMap(mSchemaMapLocked, prefix, schemaType);
|
removeFromMap(mSchemaMapLocked, prefix, schemaType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (visibilityStore != null) {
|
||||||
Set<String> prefixedSchemasNotPlatformSurfaceable =
|
Set<String> prefixedSchemasNotPlatformSurfaceable =
|
||||||
new ArraySet<>(schemasNotPlatformSurfaceable.size());
|
new ArraySet<>(schemasNotPlatformSurfaceable.size());
|
||||||
for (int i = 0; i < schemasNotPlatformSurfaceable.size(); i++) {
|
for (int i = 0; i < schemasNotPlatformSurfaceable.size(); i++) {
|
||||||
@@ -493,11 +444,12 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
prefixedSchemasPackageAccessible.put(prefix + entry.getKey(), entry.getValue());
|
prefixedSchemasPackageAccessible.put(prefix + entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
mVisibilityStoreLocked.setVisibility(
|
visibilityStore.setVisibility(
|
||||||
packageName,
|
packageName,
|
||||||
databaseName,
|
databaseName,
|
||||||
prefixedSchemasNotPlatformSurfaceable,
|
prefixedSchemasNotPlatformSurfaceable,
|
||||||
prefixedSchemasPackageAccessible);
|
prefixedSchemasPackageAccessible);
|
||||||
|
}
|
||||||
|
|
||||||
return SetSchemaResponseToProtoConverter.toSetSchemaResponse(
|
return SetSchemaResponseToProtoConverter.toSetSchemaResponse(
|
||||||
setSchemaResultProto, prefix);
|
setSchemaResultProto, prefix);
|
||||||
@@ -817,7 +769,11 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
* @param searchSpec Spec for setting filters, raw query etc.
|
* @param searchSpec Spec for setting filters, raw query etc.
|
||||||
* @param callerPackageName Package name of the caller, should belong to the {@code
|
* @param callerPackageName Package name of the caller, should belong to the {@code
|
||||||
* userContext}.
|
* userContext}.
|
||||||
|
* @param visibilityStore Optional visibility store to obtain system and package visibility
|
||||||
|
* settings from
|
||||||
* @param callerUid UID of the client making the globalQuery call.
|
* @param callerUid UID of the client making the globalQuery call.
|
||||||
|
* @param callerHasSystemAccess Whether the caller has been positively identified as having
|
||||||
|
* access to schemas marked system surfaceable.
|
||||||
* @param logger logger to collect globalQuery stats
|
* @param logger logger to collect globalQuery stats
|
||||||
* @return The results of performing this search. It may contain an empty list of results if no
|
* @return The results of performing this search. It may contain an empty list of results if no
|
||||||
* documents matched the query.
|
* documents matched the query.
|
||||||
@@ -828,7 +784,9 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
@NonNull String queryExpression,
|
@NonNull String queryExpression,
|
||||||
@NonNull SearchSpec searchSpec,
|
@NonNull SearchSpec searchSpec,
|
||||||
@NonNull String callerPackageName,
|
@NonNull String callerPackageName,
|
||||||
|
@Nullable VisibilityStore visibilityStore,
|
||||||
int callerUid,
|
int callerUid,
|
||||||
|
boolean callerHasSystemAccess,
|
||||||
@Nullable AppSearchLogger logger)
|
@Nullable AppSearchLogger logger)
|
||||||
throws AppSearchException {
|
throws AppSearchException {
|
||||||
long totalLatencyStartMillis = SystemClock.elapsedRealtime();
|
long totalLatencyStartMillis = SystemClock.elapsedRealtime();
|
||||||
@@ -885,15 +843,18 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
if (packageName.equals(callerPackageName)) {
|
if (packageName.equals(callerPackageName)) {
|
||||||
// Callers can always retrieve their own data
|
// Callers can always retrieve their own data
|
||||||
allow = true;
|
allow = true;
|
||||||
|
} else if (visibilityStore == null) {
|
||||||
|
// If there's no visibility store, there's no extra access
|
||||||
|
allow = false;
|
||||||
} else {
|
} else {
|
||||||
String databaseName = getDatabaseName(prefixedSchema);
|
String databaseName = getDatabaseName(prefixedSchema);
|
||||||
allow =
|
allow =
|
||||||
mVisibilityStoreLocked.isSchemaSearchableByCaller(
|
visibilityStore.isSchemaSearchableByCaller(
|
||||||
packageName,
|
packageName,
|
||||||
databaseName,
|
databaseName,
|
||||||
prefixedSchema,
|
prefixedSchema,
|
||||||
callerPackageName,
|
callerUid,
|
||||||
callerUid);
|
callerHasSystemAccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!allow) {
|
if (!allow) {
|
||||||
@@ -1488,9 +1449,6 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
/**
|
/**
|
||||||
* Clears documents and schema across all packages and databaseNames.
|
* Clears documents and schema across all packages and databaseNames.
|
||||||
*
|
*
|
||||||
* <p>This method also clear all data in {@link VisibilityStore}, an {@link
|
|
||||||
* #initializeVisibilityStore()} must be called after this.
|
|
||||||
*
|
|
||||||
* <p>This method belongs to mutate group.
|
* <p>This method belongs to mutate group.
|
||||||
*
|
*
|
||||||
* @throws AppSearchException on IcingSearchEngine error.
|
* @throws AppSearchException on IcingSearchEngine error.
|
||||||
@@ -1514,9 +1472,6 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
.setResetStatusCode(statusProtoToResultCode(resetResultProto.getStatus()));
|
.setResetStatusCode(statusProtoToResultCode(resetResultProto.getStatus()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must be called after everything else since VisibilityStore may repopulate
|
|
||||||
// IcingSearchEngine with an initial schema.
|
|
||||||
mVisibilityStoreLocked.handleReset();
|
|
||||||
checkSuccess(resetResultProto.getStatus());
|
checkSuccess(resetResultProto.getStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2075,13 +2030,6 @@ public final class AppSearchImpl implements Closeable {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GuardedBy("mReadWriteLock")
|
|
||||||
@NonNull
|
|
||||||
@VisibleForTesting
|
|
||||||
VisibilityStore getVisibilityStoreLocked() {
|
|
||||||
return mVisibilityStoreLocked;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts an erroneous status code from the Icing status enums to the AppSearchResult enums.
|
* Converts an erroneous status code from the Icing status enums to the AppSearchResult enums.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,126 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2021 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.appsearch.stats;
|
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.UserHandle;
|
|
||||||
import android.util.ArrayMap;
|
|
||||||
|
|
||||||
import com.android.internal.annotations.GuardedBy;
|
|
||||||
import com.android.server.appsearch.AppSearchConfig;
|
|
||||||
import com.android.server.appsearch.AppSearchManagerService;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manages the lifecycle of instances of {@link PlatformLogger}.
|
|
||||||
*
|
|
||||||
* <p>These instances are managed per unique device-user.
|
|
||||||
*/
|
|
||||||
public final class LoggerInstanceManager {
|
|
||||||
private static volatile LoggerInstanceManager sLoggerInstanceManager;
|
|
||||||
|
|
||||||
@GuardedBy("mInstancesLocked")
|
|
||||||
private final Map<UserHandle, PlatformLogger> mInstancesLocked = new ArrayMap<>();
|
|
||||||
|
|
||||||
private LoggerInstanceManager() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets an instance of {@link LoggerInstanceManager} to be used.
|
|
||||||
*
|
|
||||||
* <p>If no instance has been initialized yet, a new one will be created. Otherwise, the
|
|
||||||
* existing instance will be returned.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
public static LoggerInstanceManager getInstance() {
|
|
||||||
if (sLoggerInstanceManager == null) {
|
|
||||||
synchronized (LoggerInstanceManager.class) {
|
|
||||||
if (sLoggerInstanceManager == null) {
|
|
||||||
sLoggerInstanceManager =
|
|
||||||
new LoggerInstanceManager();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sLoggerInstanceManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets an instance of PlatformLogger for the given user, or creates one if none exists.
|
|
||||||
*
|
|
||||||
* @param context The context
|
|
||||||
* @param userHandle The multi-user handle of the device user calling AppSearch
|
|
||||||
* @return An initialized {@link PlatformLogger} for this user
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
public PlatformLogger getOrCreatePlatformLogger(
|
|
||||||
@NonNull Context context, @NonNull UserHandle userHandle,
|
|
||||||
@NonNull AppSearchConfig config) {
|
|
||||||
Objects.requireNonNull(userHandle);
|
|
||||||
synchronized (mInstancesLocked) {
|
|
||||||
PlatformLogger instance = mInstancesLocked.get(userHandle);
|
|
||||||
if (instance == null) {
|
|
||||||
instance = new PlatformLogger(context, userHandle, config);
|
|
||||||
mInstancesLocked.put(userHandle, instance);
|
|
||||||
}
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets an instance of PlatformLogger for the given user.
|
|
||||||
*
|
|
||||||
* <p>This method should only be called by an initialized SearchSession, which has been already
|
|
||||||
* created the PlatformLogger instance for the given user.
|
|
||||||
*
|
|
||||||
* @param userHandle The multi-user handle of the device user calling AppSearch
|
|
||||||
* @return An initialized {@link PlatformLogger} for this user
|
|
||||||
* @throws IllegalStateException if {@link PlatformLogger} haven't created for the given user.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
public PlatformLogger getPlatformLogger(@NonNull UserHandle userHandle) {
|
|
||||||
Objects.requireNonNull(userHandle);
|
|
||||||
synchronized (mInstancesLocked) {
|
|
||||||
PlatformLogger instance = mInstancesLocked.get(userHandle);
|
|
||||||
if (instance == null) {
|
|
||||||
// Impossible scenario, user cannot call an uninitialized SearchSession,
|
|
||||||
// getInstance should always find the instance for the given user and never try to
|
|
||||||
// create an instance for this user again.
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"PlatformLogger has never been created for: " + userHandle);
|
|
||||||
}
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove an instance of {@link PlatformLogger} for the given user.
|
|
||||||
*
|
|
||||||
* <p>This method should only be called if {@link AppSearchManagerService} receives an
|
|
||||||
* ACTION_USER_REMOVED, which the logger instance of given user should be removed.
|
|
||||||
*
|
|
||||||
* @param userHandle The multi-user handle of the user that need to be removed.
|
|
||||||
*/
|
|
||||||
public void removePlatformLoggerForUser(@NonNull UserHandle userHandle) {
|
|
||||||
Objects.requireNonNull(userHandle);
|
|
||||||
synchronized (mInstancesLocked) {
|
|
||||||
mInstancesLocked.remove(userHandle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -73,9 +73,4 @@ class NotPlatformSurfaceableMap {
|
|||||||
// isn't one of those opt-outs, it's surfaceable.
|
// isn't one of those opt-outs, it's surfaceable.
|
||||||
return !schemaTypes.contains(prefixedSchema);
|
return !schemaTypes.contains(prefixedSchema);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Discards all data in the map. */
|
|
||||||
public void clear() {
|
|
||||||
mMap.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,9 +82,4 @@ class PackageAccessibleMap {
|
|||||||
}
|
}
|
||||||
return accessiblePackages;
|
return accessiblePackages;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Discards all data in the map. */
|
|
||||||
public void clear() {
|
|
||||||
mMap.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,28 +99,23 @@ public class VisibilityStore {
|
|||||||
private final PackageAccessibleMap mPackageAccessibleMap = new PackageAccessibleMap();
|
private final PackageAccessibleMap mPackageAccessibleMap = new PackageAccessibleMap();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an uninitialized VisibilityStore object. Callers must also call {@link #initialize()}
|
* Creates and initializes VisibilityStore.
|
||||||
* before using the object.
|
|
||||||
*
|
*
|
||||||
* @param appSearchImpl AppSearchImpl instance
|
* @param appSearchImpl AppSearchImpl instance
|
||||||
* @param userContext Context of the user that the call is being made as
|
* @param userContext Context of the user that the call is being made as
|
||||||
*/
|
*/
|
||||||
public VisibilityStore(@NonNull AppSearchImpl appSearchImpl, @NonNull Context userContext) {
|
@NonNull
|
||||||
mAppSearchImpl = Objects.requireNonNull(appSearchImpl);
|
public static VisibilityStore create(
|
||||||
mUserContext = Objects.requireNonNull(userContext);
|
@NonNull AppSearchImpl appSearchImpl, @NonNull Context userContext)
|
||||||
|
throws AppSearchException {
|
||||||
|
return new VisibilityStore(appSearchImpl, userContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private VisibilityStore(@NonNull AppSearchImpl appSearchImpl, @NonNull Context userContext)
|
||||||
* Initializes schemas and member variables to track visibility settings.
|
throws AppSearchException {
|
||||||
*
|
mAppSearchImpl = Objects.requireNonNull(appSearchImpl);
|
||||||
* <p>This is kept separate from the constructor because this will call methods on
|
mUserContext = Objects.requireNonNull(userContext);
|
||||||
* AppSearchImpl. Some may even then recursively call back into VisibilityStore (for example,
|
|
||||||
* {@link AppSearchImpl#setSchema} will call {@link #setVisibility}. We need to have both
|
|
||||||
* AppSearchImpl and VisibilityStore fully initialized for this call flow to work.
|
|
||||||
*
|
|
||||||
* @throws AppSearchException AppSearchException on AppSearchImpl error.
|
|
||||||
*/
|
|
||||||
public void initialize() throws AppSearchException {
|
|
||||||
GetSchemaResponse getSchemaResponse = mAppSearchImpl.getSchema(PACKAGE_NAME, DATABASE_NAME);
|
GetSchemaResponse getSchemaResponse = mAppSearchImpl.getSchema(PACKAGE_NAME, DATABASE_NAME);
|
||||||
boolean hasVisibilityType = false;
|
boolean hasVisibilityType = false;
|
||||||
boolean hasPackageAccessibleType = false;
|
boolean hasPackageAccessibleType = false;
|
||||||
@@ -142,6 +137,7 @@ public class VisibilityStore {
|
|||||||
PACKAGE_NAME,
|
PACKAGE_NAME,
|
||||||
DATABASE_NAME,
|
DATABASE_NAME,
|
||||||
Arrays.asList(VisibilityDocument.SCHEMA, PackageAccessibleDocument.SCHEMA),
|
Arrays.asList(VisibilityDocument.SCHEMA, PackageAccessibleDocument.SCHEMA),
|
||||||
|
/*visibilityStore=*/ null, // Avoid recursive calls
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -149,7 +145,6 @@ public class VisibilityStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Populate visibility settings set
|
// Populate visibility settings set
|
||||||
mNotPlatformSurfaceableMap.clear();
|
|
||||||
for (Map.Entry<String, Set<String>> entry :
|
for (Map.Entry<String, Set<String>> entry :
|
||||||
mAppSearchImpl.getPackageToDatabases().entrySet()) {
|
mAppSearchImpl.getPackageToDatabases().entrySet()) {
|
||||||
String packageName = entry.getKey();
|
String packageName = entry.getKey();
|
||||||
@@ -280,39 +275,46 @@ public class VisibilityStore {
|
|||||||
packageName, databaseName, schemaToPackageIdentifierMap);
|
packageName, databaseName, schemaToPackageIdentifierMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given package has access to system-surfaceable schemas.
|
||||||
|
*
|
||||||
|
* @param callerPackageName Package name of the caller.
|
||||||
|
*/
|
||||||
|
public boolean doesCallerHaveSystemAccess(@NonNull String callerPackageName) {
|
||||||
|
Objects.requireNonNull(callerPackageName);
|
||||||
|
return mUserContext.getPackageManager()
|
||||||
|
.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, callerPackageName)
|
||||||
|
== PackageManager.PERMISSION_GRANTED;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether {@code prefixedSchema} can be searched over by the {@code callerUid}.
|
* Checks whether {@code prefixedSchema} can be searched over by the {@code callerUid}.
|
||||||
*
|
*
|
||||||
* @param packageName Package that owns the schema.
|
* @param packageName Package that owns the schema.
|
||||||
* @param databaseName Database within the package that owns the schema.
|
* @param databaseName Database within the package that owns the schema.
|
||||||
* @param prefixedSchema Prefixed schema type the caller is trying to access.
|
* @param prefixedSchema Prefixed schema type the caller is trying to access.
|
||||||
* @param callerPackageName Package name of the caller.
|
* @param callerUid UID of the client making the globalQuery call.
|
||||||
* @param callerUid Uid of the caller.
|
* @param callerHasSystemAccess Whether the caller has been identified as having
|
||||||
|
* access to schemas marked system surfaceable by {@link
|
||||||
|
* #doesCallerHaveSystemAccess}.
|
||||||
*/
|
*/
|
||||||
public boolean isSchemaSearchableByCaller(
|
public boolean isSchemaSearchableByCaller(
|
||||||
@NonNull String packageName,
|
@NonNull String packageName,
|
||||||
@NonNull String databaseName,
|
@NonNull String databaseName,
|
||||||
@NonNull String prefixedSchema,
|
@NonNull String prefixedSchema,
|
||||||
@NonNull String callerPackageName,
|
int callerUid,
|
||||||
int callerUid) {
|
boolean callerHasSystemAccess) {
|
||||||
Objects.requireNonNull(packageName);
|
Objects.requireNonNull(packageName);
|
||||||
Objects.requireNonNull(databaseName);
|
Objects.requireNonNull(databaseName);
|
||||||
Objects.requireNonNull(prefixedSchema);
|
Objects.requireNonNull(prefixedSchema);
|
||||||
Objects.requireNonNull(callerPackageName);
|
|
||||||
|
|
||||||
if (packageName.equals(PACKAGE_NAME)) {
|
if (packageName.equals(PACKAGE_NAME)) {
|
||||||
return false; // VisibilityStore schemas are for internal bookkeeping.
|
return false; // VisibilityStore schemas are for internal bookkeeping.
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(b/180058203): If we can cache or pass in that a caller has the
|
if (callerHasSystemAccess
|
||||||
// READ_GLOBAL_SEARCH_DATA permission, then we can save this package manager lookup for
|
&& mNotPlatformSurfaceableMap.isSchemaPlatformSurfaceable(
|
||||||
// each schema we may check in the loop.
|
packageName, databaseName, prefixedSchema)) {
|
||||||
if (mNotPlatformSurfaceableMap.isSchemaPlatformSurfaceable(
|
|
||||||
packageName, databaseName, prefixedSchema)
|
|
||||||
&& mUserContext
|
|
||||||
.getPackageManager()
|
|
||||||
.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, callerPackageName)
|
|
||||||
== PackageManager.PERMISSION_GRANTED) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,16 +374,6 @@ public class VisibilityStore {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles an {@code AppSearchImpl#reset()} by clearing any cached state.
|
|
||||||
*
|
|
||||||
* <p>{@link #initialize()} must be called after this.
|
|
||||||
*/
|
|
||||||
public void handleReset() {
|
|
||||||
mNotPlatformSurfaceableMap.clear();
|
|
||||||
mPackageAccessibleMap.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a prefix to create a visibility store document's id.
|
* Adds a prefix to create a visibility store document's id.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import androidx.test.core.app.ApplicationProvider;
|
|||||||
|
|
||||||
import com.android.compatibility.common.util.SystemUtil;
|
import com.android.compatibility.common.util.SystemUtil;
|
||||||
import com.android.server.appsearch.external.localstorage.util.PrefixUtil;
|
import com.android.server.appsearch.external.localstorage.util.PrefixUtil;
|
||||||
|
import com.android.server.appsearch.visibilitystore.VisibilityStore;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
@@ -66,6 +67,7 @@ public class AppSearchImplPlatformTest {
|
|||||||
private final Map<UserHandle, PackageManager> mMockPackageManagers = new ArrayMap<>();
|
private final Map<UserHandle, PackageManager> mMockPackageManagers = new ArrayMap<>();
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private AppSearchImpl mAppSearchImpl;
|
private AppSearchImpl mAppSearchImpl;
|
||||||
|
private VisibilityStore mVisibilityStore;
|
||||||
private int mGlobalQuerierUid;
|
private int mGlobalQuerierUid;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@@ -89,13 +91,9 @@ public class AppSearchImplPlatformTest {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Give ourselves global query permissions
|
// Give ourselves global query permissions
|
||||||
mAppSearchImpl =
|
mAppSearchImpl = AppSearchImpl.create(
|
||||||
AppSearchImpl.create(
|
mTemporaryFolder.newFolder(), /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
|
||||||
mTemporaryFolder.newFolder(),
|
mVisibilityStore = VisibilityStore.create(mAppSearchImpl, mContext);
|
||||||
mContext,
|
|
||||||
/*logger=*/ null,
|
|
||||||
ALWAYS_OPTIMIZE);
|
|
||||||
|
|
||||||
mGlobalQuerierUid =
|
mGlobalQuerierUid =
|
||||||
mContext.getPackageManager().getPackageUid(mContext.getPackageName(), /*flags=*/ 0);
|
mContext.getPackageManager().getPackageUid(mContext.getPackageName(), /*flags=*/ 0);
|
||||||
}
|
}
|
||||||
@@ -128,6 +126,7 @@ public class AppSearchImplPlatformTest {
|
|||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
|
Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
|
||||||
|
mVisibilityStore,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
|
/*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
|
||||||
/*schemasPackageAccessible=*/ ImmutableMap.of(
|
/*schemasPackageAccessible=*/ ImmutableMap.of(
|
||||||
"schema1",
|
"schema1",
|
||||||
@@ -136,26 +135,20 @@ public class AppSearchImplPlatformTest {
|
|||||||
/*schemaVersion=*/ 0);
|
/*schemaVersion=*/ 0);
|
||||||
|
|
||||||
// "schema1" is platform hidden now and package visible to package1
|
// "schema1" is platform hidden now and package visible to package1
|
||||||
assertThat(
|
assertThat(mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
mAppSearchImpl
|
|
||||||
.getVisibilityStoreLocked()
|
|
||||||
.isSchemaSearchableByCaller(
|
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
prefix + "schema1",
|
prefix + "schema1",
|
||||||
mContext.getPackageName(),
|
mGlobalQuerierUid,
|
||||||
mGlobalQuerierUid))
|
/*callerHasSystemAccess=*/ true))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
|
|
||||||
assertThat(
|
assertThat(mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
mAppSearchImpl
|
|
||||||
.getVisibilityStoreLocked()
|
|
||||||
.isSchemaSearchableByCaller(
|
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
prefix + "schema1",
|
prefix + "schema1",
|
||||||
packageNameFoo,
|
uidFoo,
|
||||||
uidFoo))
|
/*callerHasSystemAccess=*/ false))
|
||||||
.isTrue();
|
.isTrue();
|
||||||
|
|
||||||
// Add a new schema, and include the already-existing "schema1"
|
// Add a new schema, and include the already-existing "schema1"
|
||||||
@@ -165,6 +158,7 @@ public class AppSearchImplPlatformTest {
|
|||||||
ImmutableList.of(
|
ImmutableList.of(
|
||||||
new AppSearchSchema.Builder("schema1").build(),
|
new AppSearchSchema.Builder("schema1").build(),
|
||||||
new AppSearchSchema.Builder("schema2").build()),
|
new AppSearchSchema.Builder("schema2").build()),
|
||||||
|
mVisibilityStore,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
|
/*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
|
||||||
/*schemasPackageAccessible=*/ ImmutableMap.of(
|
/*schemasPackageAccessible=*/ ImmutableMap.of(
|
||||||
"schema1",
|
"schema1",
|
||||||
@@ -174,50 +168,40 @@ public class AppSearchImplPlatformTest {
|
|||||||
|
|
||||||
// Check that "schema1" still has the same visibility settings
|
// Check that "schema1" still has the same visibility settings
|
||||||
SystemUtil.runWithShellPermissionIdentity(() -> assertThat(
|
SystemUtil.runWithShellPermissionIdentity(() -> assertThat(
|
||||||
mAppSearchImpl
|
mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
.getVisibilityStoreLocked()
|
|
||||||
.isSchemaSearchableByCaller(
|
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
prefix + "schema1",
|
prefix + "schema1",
|
||||||
mContext.getPackageName(),
|
mGlobalQuerierUid,
|
||||||
mGlobalQuerierUid))
|
/*callerHasSystemAccess=*/ true))
|
||||||
.isFalse(),
|
.isFalse(),
|
||||||
READ_GLOBAL_APP_SEARCH_DATA);
|
READ_GLOBAL_APP_SEARCH_DATA);
|
||||||
|
|
||||||
assertThat(
|
assertThat(mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
mAppSearchImpl
|
|
||||||
.getVisibilityStoreLocked()
|
|
||||||
.isSchemaSearchableByCaller(
|
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
prefix + "schema1",
|
prefix + "schema1",
|
||||||
packageNameFoo,
|
uidFoo,
|
||||||
uidFoo))
|
/*callerHasSystemAccess=*/ false))
|
||||||
.isTrue();
|
.isTrue();
|
||||||
|
|
||||||
// "schema2" has default visibility settings
|
// "schema2" has default visibility settings
|
||||||
SystemUtil.runWithShellPermissionIdentity(() -> assertThat(
|
SystemUtil.runWithShellPermissionIdentity(() -> assertThat(
|
||||||
mAppSearchImpl
|
mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
.getVisibilityStoreLocked()
|
|
||||||
.isSchemaSearchableByCaller(
|
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
prefix + "schema2",
|
prefix + "schema2",
|
||||||
mContext.getPackageName(),
|
mGlobalQuerierUid,
|
||||||
mGlobalQuerierUid))
|
/*callerHasSystemAccess=*/ true))
|
||||||
.isTrue(),
|
.isTrue(),
|
||||||
READ_GLOBAL_APP_SEARCH_DATA);
|
READ_GLOBAL_APP_SEARCH_DATA);
|
||||||
|
|
||||||
assertThat(
|
assertThat(mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
mAppSearchImpl
|
|
||||||
.getVisibilityStoreLocked()
|
|
||||||
.isSchemaSearchableByCaller(
|
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
prefix + "schema2",
|
prefix + "schema2",
|
||||||
packageNameFoo,
|
uidFoo,
|
||||||
uidFoo))
|
/*callerHasSystemAccess=*/ false))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,6 +232,7 @@ public class AppSearchImplPlatformTest {
|
|||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
|
Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
|
||||||
|
mVisibilityStore,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
|
/*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
|
||||||
/*schemasPackageAccessible=*/ ImmutableMap.of(
|
/*schemasPackageAccessible=*/ ImmutableMap.of(
|
||||||
"schema1",
|
"schema1",
|
||||||
@@ -256,26 +241,20 @@ public class AppSearchImplPlatformTest {
|
|||||||
/*schemaVersion=*/ 0);
|
/*schemaVersion=*/ 0);
|
||||||
|
|
||||||
// "schema1" is platform hidden now and package accessible
|
// "schema1" is platform hidden now and package accessible
|
||||||
assertThat(
|
assertThat(mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
mAppSearchImpl
|
|
||||||
.getVisibilityStoreLocked()
|
|
||||||
.isSchemaSearchableByCaller(
|
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
prefix + "schema1",
|
prefix + "schema1",
|
||||||
mContext.getPackageName(),
|
mGlobalQuerierUid,
|
||||||
mGlobalQuerierUid))
|
/*callerHasSystemAccess=*/ true))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
|
|
||||||
assertThat(
|
assertThat(mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
mAppSearchImpl
|
|
||||||
.getVisibilityStoreLocked()
|
|
||||||
.isSchemaSearchableByCaller(
|
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
prefix + "schema1",
|
prefix + "schema1",
|
||||||
packageNameFoo,
|
uidFoo,
|
||||||
uidFoo))
|
/*callerHasSystemAccess=*/ false))
|
||||||
.isTrue();
|
.isTrue();
|
||||||
|
|
||||||
// Remove "schema1" by force overriding
|
// Remove "schema1" by force overriding
|
||||||
@@ -283,32 +262,27 @@ public class AppSearchImplPlatformTest {
|
|||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
/*schemas=*/ Collections.emptyList(),
|
/*schemas=*/ Collections.emptyList(),
|
||||||
|
mVisibilityStore,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ true,
|
/*forceOverride=*/ true,
|
||||||
/*schemaVersion=*/ 0);
|
/*schemaVersion=*/ 0);
|
||||||
|
|
||||||
// Check that "schema1" is no longer considered platform hidden or package accessible
|
// Check that "schema1" is no longer considered platform hidden or package accessible
|
||||||
assertThat(
|
assertThat(mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
mAppSearchImpl
|
|
||||||
.getVisibilityStoreLocked()
|
|
||||||
.isSchemaSearchableByCaller(
|
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
prefix + "schema1",
|
prefix + "schema1",
|
||||||
mContext.getPackageName(),
|
mGlobalQuerierUid,
|
||||||
mGlobalQuerierUid))
|
/*callerHasSystemAccess=*/ true))
|
||||||
.isTrue();
|
.isTrue();
|
||||||
|
|
||||||
assertThat(
|
assertThat(mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
mAppSearchImpl
|
|
||||||
.getVisibilityStoreLocked()
|
|
||||||
.isSchemaSearchableByCaller(
|
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
prefix + "schema1",
|
prefix + "schema1",
|
||||||
packageNameFoo,
|
uidFoo,
|
||||||
uidFoo))
|
/*callerHasSystemAccess=*/ false))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
|
|
||||||
// Add "schema1" back, it gets default visibility settings which means it's not platform
|
// Add "schema1" back, it gets default visibility settings which means it's not platform
|
||||||
@@ -317,30 +291,25 @@ public class AppSearchImplPlatformTest {
|
|||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
|
Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
|
||||||
|
mVisibilityStore,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
/*schemaVersion=*/ 0);
|
/*schemaVersion=*/ 0);
|
||||||
|
|
||||||
assertThat(
|
assertThat(mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
mAppSearchImpl
|
|
||||||
.getVisibilityStoreLocked()
|
|
||||||
.isSchemaSearchableByCaller(
|
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
prefix + "schema1",
|
prefix + "schema1",
|
||||||
mContext.getPackageName(),
|
mGlobalQuerierUid,
|
||||||
mGlobalQuerierUid))
|
/*callerHasSystemAccess=*/ true))
|
||||||
.isTrue();
|
.isTrue();
|
||||||
assertThat(
|
assertThat(mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
mAppSearchImpl
|
|
||||||
.getVisibilityStoreLocked()
|
|
||||||
.isSchemaSearchableByCaller(
|
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
prefix + "schema1",
|
prefix + "schema1",
|
||||||
packageNameFoo,
|
uidFoo,
|
||||||
uidFoo))
|
/*callerHasSystemAccess=*/ false))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,20 +326,18 @@ public class AppSearchImplPlatformTest {
|
|||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
|
Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
|
||||||
|
mVisibilityStore,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
/*schemaVersion=*/ 0);
|
/*schemaVersion=*/ 0);
|
||||||
|
|
||||||
assertThat(
|
assertThat(mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
mAppSearchImpl
|
|
||||||
.getVisibilityStoreLocked()
|
|
||||||
.isSchemaSearchableByCaller(
|
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
prefix + "Schema",
|
prefix + "Schema",
|
||||||
mContext.getPackageName(),
|
mGlobalQuerierUid,
|
||||||
mGlobalQuerierUid))
|
/*callerHasSystemAccess=*/ true))
|
||||||
.isTrue();
|
.isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,20 +354,18 @@ public class AppSearchImplPlatformTest {
|
|||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
|
Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
|
||||||
|
mVisibilityStore,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.singletonList("Schema"),
|
/*schemasNotPlatformSurfaceable=*/ Collections.singletonList("Schema"),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
/*schemaVersion=*/ 0);
|
/*schemaVersion=*/ 0);
|
||||||
|
|
||||||
assertThat(
|
assertThat(mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
mAppSearchImpl
|
|
||||||
.getVisibilityStoreLocked()
|
|
||||||
.isSchemaSearchableByCaller(
|
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
prefix + "Schema",
|
prefix + "Schema",
|
||||||
mContext.getPackageName(),
|
mGlobalQuerierUid,
|
||||||
mGlobalQuerierUid))
|
/*callerHasSystemAccess=*/ true))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -418,19 +383,18 @@ public class AppSearchImplPlatformTest {
|
|||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
|
Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
|
||||||
|
mVisibilityStore,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
/*schemaVersion=*/ 0);
|
/*schemaVersion=*/ 0);
|
||||||
assertThat(
|
assertThat(mVisibilityStore
|
||||||
mAppSearchImpl
|
|
||||||
.getVisibilityStoreLocked()
|
|
||||||
.isSchemaSearchableByCaller(
|
.isSchemaSearchableByCaller(
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
prefix + "Schema",
|
prefix + "Schema",
|
||||||
packageName,
|
/*callerUid=*/ 42,
|
||||||
/*callerUid=*/ 42))
|
/*callerHasSystemAccess=*/ false))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,21 +422,20 @@ public class AppSearchImplPlatformTest {
|
|||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
|
Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
|
||||||
|
mVisibilityStore,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ ImmutableMap.of(
|
/*schemasPackageAccessible=*/ ImmutableMap.of(
|
||||||
"Schema",
|
"Schema",
|
||||||
ImmutableList.of(new PackageIdentifier(packageNameFoo, sha256CertFoo))),
|
ImmutableList.of(new PackageIdentifier(packageNameFoo, sha256CertFoo))),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
/*schemaVersion=*/ 0);
|
/*schemaVersion=*/ 0);
|
||||||
assertThat(
|
assertThat(mVisibilityStore
|
||||||
mAppSearchImpl
|
|
||||||
.getVisibilityStoreLocked()
|
|
||||||
.isSchemaSearchableByCaller(
|
.isSchemaSearchableByCaller(
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
prefix + "Schema",
|
prefix + "Schema",
|
||||||
packageNameFoo,
|
uidFoo,
|
||||||
uidFoo))
|
/*callerHasSystemAccess=*/ false))
|
||||||
.isTrue();
|
.isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,15 +88,10 @@ public class VisibilityStoreTest {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Give ourselves global query permissions
|
// Give ourselves global query permissions
|
||||||
AppSearchImpl appSearchImpl =
|
AppSearchImpl appSearchImpl = AppSearchImpl.create(
|
||||||
AppSearchImpl.create(
|
mTemporaryFolder.newFolder(), /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
|
||||||
mTemporaryFolder.newFolder(),
|
mVisibilityStore = VisibilityStore.create(appSearchImpl, mContext);
|
||||||
mContext,
|
|
||||||
/*logger=*/ null,
|
|
||||||
ALWAYS_OPTIMIZE);
|
|
||||||
|
|
||||||
mUid = mContext.getPackageManager().getPackageUid(mContext.getPackageName(), /*flags=*/ 0);
|
mUid = mContext.getPackageManager().getPackageUid(mContext.getPackageName(), /*flags=*/ 0);
|
||||||
mVisibilityStore = appSearchImpl.getVisibilityStoreLocked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -121,6 +116,21 @@ public class VisibilityStoreTest {
|
|||||||
.doesNotContain(String.valueOf(PrefixUtil.DATABASE_DELIMITER));
|
.doesNotContain(String.valueOf(PrefixUtil.DATABASE_DELIMITER));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoesCallerHaveSystemAccess() {
|
||||||
|
PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
|
||||||
|
when(mockPackageManager
|
||||||
|
.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
|
||||||
|
.thenReturn(PERMISSION_GRANTED);
|
||||||
|
assertThat(mVisibilityStore.doesCallerHaveSystemAccess(mContext.getPackageName())).isTrue();
|
||||||
|
|
||||||
|
when(mockPackageManager
|
||||||
|
.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
|
||||||
|
.thenReturn(PERMISSION_DENIED);
|
||||||
|
assertThat(mVisibilityStore.doesCallerHaveSystemAccess(mContext.getPackageName()))
|
||||||
|
.isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetVisibility_platformSurfaceable() throws Exception {
|
public void testSetVisibility_platformSurfaceable() throws Exception {
|
||||||
// Make sure we have global query privileges
|
// Make sure we have global query privileges
|
||||||
@@ -128,6 +138,7 @@ public class VisibilityStoreTest {
|
|||||||
when(mockPackageManager
|
when(mockPackageManager
|
||||||
.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
|
.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
|
||||||
.thenReturn(PERMISSION_GRANTED);
|
.thenReturn(PERMISSION_GRANTED);
|
||||||
|
assertThat(mVisibilityStore.doesCallerHaveSystemAccess(mContext.getPackageName())).isTrue();
|
||||||
|
|
||||||
mVisibilityStore.setVisibility(
|
mVisibilityStore.setVisibility(
|
||||||
"package",
|
"package",
|
||||||
@@ -140,16 +151,16 @@ public class VisibilityStoreTest {
|
|||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
"prefix/schema1",
|
"prefix/schema1",
|
||||||
mContext.getPackageName(),
|
mUid,
|
||||||
mUid))
|
/*callerHasSystemAccess=*/ true))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
assertThat(
|
assertThat(
|
||||||
mVisibilityStore.isSchemaSearchableByCaller(
|
mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
"prefix/schema2",
|
"prefix/schema2",
|
||||||
mContext.getPackageName(),
|
mUid,
|
||||||
mUid))
|
/*callerHasSystemAccess=*/ true))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
|
|
||||||
// New .setVisibility() call completely overrides previous visibility settings.
|
// New .setVisibility() call completely overrides previous visibility settings.
|
||||||
@@ -165,24 +176,24 @@ public class VisibilityStoreTest {
|
|||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
"prefix/schema1",
|
"prefix/schema1",
|
||||||
mContext.getPackageName(),
|
mUid,
|
||||||
mUid))
|
/*callerHasSystemAccess=*/ true))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
assertThat(
|
assertThat(
|
||||||
mVisibilityStore.isSchemaSearchableByCaller(
|
mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
"prefix/schema2",
|
"prefix/schema2",
|
||||||
mContext.getPackageName(),
|
mUid,
|
||||||
mUid))
|
/*callerHasSystemAccess=*/ true))
|
||||||
.isTrue();
|
.isTrue();
|
||||||
assertThat(
|
assertThat(
|
||||||
mVisibilityStore.isSchemaSearchableByCaller(
|
mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
"prefix/schema3",
|
"prefix/schema3",
|
||||||
mContext.getPackageName(),
|
mUid,
|
||||||
mUid))
|
/*callerHasSystemAccess=*/ true))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
|
|
||||||
// Everything defaults to visible again.
|
// Everything defaults to visible again.
|
||||||
@@ -196,24 +207,24 @@ public class VisibilityStoreTest {
|
|||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
"prefix/schema1",
|
"prefix/schema1",
|
||||||
mContext.getPackageName(),
|
mUid,
|
||||||
mUid))
|
/*callerHasSystemAccess=*/ true))
|
||||||
.isTrue();
|
.isTrue();
|
||||||
assertThat(
|
assertThat(
|
||||||
mVisibilityStore.isSchemaSearchableByCaller(
|
mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
"prefix/schema2",
|
"prefix/schema2",
|
||||||
mContext.getPackageName(),
|
mUid,
|
||||||
mUid))
|
/*callerHasSystemAccess=*/ true))
|
||||||
.isTrue();
|
.isTrue();
|
||||||
assertThat(
|
assertThat(
|
||||||
mVisibilityStore.isSchemaSearchableByCaller(
|
mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
"prefix/schema3",
|
"prefix/schema3",
|
||||||
mContext.getPackageName(),
|
mUid,
|
||||||
mUid))
|
/*callerHasSystemAccess=*/ true))
|
||||||
.isTrue();
|
.isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,13 +253,19 @@ public class VisibilityStoreTest {
|
|||||||
.thenReturn(PERMISSION_DENIED);
|
.thenReturn(PERMISSION_DENIED);
|
||||||
|
|
||||||
// By default, a schema isn't package accessible.
|
// By default, a schema isn't package accessible.
|
||||||
assertThat(
|
assertThat(mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
mVisibilityStore.isSchemaSearchableByCaller(
|
"package",
|
||||||
"package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
|
"database",
|
||||||
|
"prefix/schemaFoo",
|
||||||
|
uidFoo,
|
||||||
|
/*callerHasSystemAccess=*/ false))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
assertThat(
|
assertThat(mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
mVisibilityStore.isSchemaSearchableByCaller(
|
"package",
|
||||||
"package", "database", "prefix/schemaBar", packageNameBar, uidBar))
|
"database",
|
||||||
|
"prefix/schemaBar",
|
||||||
|
uidBar,
|
||||||
|
/*callerHasSystemAccess=*/ false))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
|
|
||||||
// Grant package access
|
// Grant package access
|
||||||
@@ -268,9 +285,12 @@ public class VisibilityStoreTest {
|
|||||||
when(mockPackageManager.hasSigningCertificate(
|
when(mockPackageManager.hasSigningCertificate(
|
||||||
packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
|
packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
|
||||||
.thenReturn(false);
|
.thenReturn(false);
|
||||||
assertThat(
|
assertThat(mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
mVisibilityStore.isSchemaSearchableByCaller(
|
"package",
|
||||||
"package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
|
"database",
|
||||||
|
"prefix/schemaFoo",
|
||||||
|
uidFoo,
|
||||||
|
/*callerHasSystemAccess=*/ false))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
|
|
||||||
// Should fail if PackageManager doesn't think the package belongs to the uid
|
// Should fail if PackageManager doesn't think the package belongs to the uid
|
||||||
@@ -279,9 +299,12 @@ public class VisibilityStoreTest {
|
|||||||
when(mockPackageManager.hasSigningCertificate(
|
when(mockPackageManager.hasSigningCertificate(
|
||||||
packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
|
packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
|
||||||
.thenReturn(true);
|
.thenReturn(true);
|
||||||
assertThat(
|
assertThat(mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
mVisibilityStore.isSchemaSearchableByCaller(
|
"package",
|
||||||
"package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
|
"database",
|
||||||
|
"prefix/schemaFoo",
|
||||||
|
uidFoo,
|
||||||
|
/*callerHasSystemAccess=*/ false))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
|
|
||||||
// But if uid and certificate match, then we should have access
|
// But if uid and certificate match, then we should have access
|
||||||
@@ -290,9 +313,12 @@ public class VisibilityStoreTest {
|
|||||||
when(mockPackageManager.hasSigningCertificate(
|
when(mockPackageManager.hasSigningCertificate(
|
||||||
packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
|
packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
|
||||||
.thenReturn(true);
|
.thenReturn(true);
|
||||||
assertThat(
|
assertThat(mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
mVisibilityStore.isSchemaSearchableByCaller(
|
"package",
|
||||||
"package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
|
"database",
|
||||||
|
"prefix/schemaFoo",
|
||||||
|
uidFoo,
|
||||||
|
/*callerHasSystemAccess=*/ false))
|
||||||
.isTrue();
|
.isTrue();
|
||||||
|
|
||||||
when(mockPackageManager.getPackageUid(eq(packageNameBar), /*flags=*/ anyInt()))
|
when(mockPackageManager.getPackageUid(eq(packageNameBar), /*flags=*/ anyInt()))
|
||||||
@@ -300,9 +326,12 @@ public class VisibilityStoreTest {
|
|||||||
when(mockPackageManager.hasSigningCertificate(
|
when(mockPackageManager.hasSigningCertificate(
|
||||||
packageNameBar, sha256CertBar, PackageManager.CERT_INPUT_SHA256))
|
packageNameBar, sha256CertBar, PackageManager.CERT_INPUT_SHA256))
|
||||||
.thenReturn(true);
|
.thenReturn(true);
|
||||||
assertThat(
|
assertThat(mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
mVisibilityStore.isSchemaSearchableByCaller(
|
"package",
|
||||||
"package", "database", "prefix/schemaBar", packageNameBar, uidBar))
|
"database",
|
||||||
|
"prefix/schemaBar",
|
||||||
|
uidBar,
|
||||||
|
/*callerHasSystemAccess=*/ false))
|
||||||
.isTrue();
|
.isTrue();
|
||||||
|
|
||||||
// New .setVisibility() call completely overrides previous visibility settings. So
|
// New .setVisibility() call completely overrides previous visibility settings. So
|
||||||
@@ -320,9 +349,12 @@ public class VisibilityStoreTest {
|
|||||||
when(mockPackageManager.hasSigningCertificate(
|
when(mockPackageManager.hasSigningCertificate(
|
||||||
packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
|
packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
|
||||||
.thenReturn(true);
|
.thenReturn(true);
|
||||||
assertThat(
|
assertThat(mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
mVisibilityStore.isSchemaSearchableByCaller(
|
"package",
|
||||||
"package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
|
"database",
|
||||||
|
"prefix/schemaFoo",
|
||||||
|
uidFoo,
|
||||||
|
/*callerHasSystemAccess=*/ false))
|
||||||
.isTrue();
|
.isTrue();
|
||||||
|
|
||||||
when(mockPackageManager.getPackageUid(eq(packageNameBar), /*flags=*/ anyInt()))
|
when(mockPackageManager.getPackageUid(eq(packageNameBar), /*flags=*/ anyInt()))
|
||||||
@@ -330,9 +362,12 @@ public class VisibilityStoreTest {
|
|||||||
when(mockPackageManager.hasSigningCertificate(
|
when(mockPackageManager.hasSigningCertificate(
|
||||||
packageNameBar, sha256CertBar, PackageManager.CERT_INPUT_SHA256))
|
packageNameBar, sha256CertBar, PackageManager.CERT_INPUT_SHA256))
|
||||||
.thenReturn(true);
|
.thenReturn(true);
|
||||||
assertThat(
|
assertThat(mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
mVisibilityStore.isSchemaSearchableByCaller(
|
"package",
|
||||||
"package", "database", "prefix/schemaBar", packageNameBar, uidBar))
|
"database",
|
||||||
|
"prefix/schemaBar",
|
||||||
|
uidBar,
|
||||||
|
/*callerHasSystemAccess=*/ false))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,9 +398,12 @@ public class VisibilityStoreTest {
|
|||||||
ImmutableList.of(new PackageIdentifier(packageNameFoo, sha256CertFoo))));
|
ImmutableList.of(new PackageIdentifier(packageNameFoo, sha256CertFoo))));
|
||||||
|
|
||||||
// If we can't verify the Foo package that has access, assume it doesn't have access.
|
// If we can't verify the Foo package that has access, assume it doesn't have access.
|
||||||
assertThat(
|
assertThat(mVisibilityStore.isSchemaSearchableByCaller(
|
||||||
mVisibilityStore.isSchemaSearchableByCaller(
|
"package",
|
||||||
"package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
|
"database",
|
||||||
|
"prefix/schemaFoo",
|
||||||
|
uidFoo,
|
||||||
|
/*callerHasSystemAccess=*/ false))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,8 +435,8 @@ public class VisibilityStoreTest {
|
|||||||
/*packageName=*/ "",
|
/*packageName=*/ "",
|
||||||
/*databaseName=*/ "",
|
/*databaseName=*/ "",
|
||||||
"schema",
|
"schema",
|
||||||
mContext.getPackageName(),
|
mUid,
|
||||||
mUid))
|
/*callerHasSystemAccess=*/ true))
|
||||||
.isTrue();
|
.isTrue();
|
||||||
|
|
||||||
when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
|
when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
|
||||||
@@ -411,8 +449,8 @@ public class VisibilityStoreTest {
|
|||||||
/*packageName=*/ "",
|
/*packageName=*/ "",
|
||||||
/*databaseName=*/ "",
|
/*databaseName=*/ "",
|
||||||
"schema",
|
"schema",
|
||||||
packageNameFoo,
|
uidFoo,
|
||||||
uidFoo))
|
/*callerHasSystemAccess=*/ false))
|
||||||
.isTrue();
|
.isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -83,15 +83,9 @@ public class AppSearchImplTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
Context context = ApplicationProvider.getApplicationContext();
|
|
||||||
|
|
||||||
// Give ourselves global query permissions.
|
|
||||||
mAppSearchImpl =
|
mAppSearchImpl =
|
||||||
AppSearchImpl.create(
|
AppSearchImpl.create(
|
||||||
mTemporaryFolder.newFolder(),
|
mTemporaryFolder.newFolder(), /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
|
||||||
context,
|
|
||||||
/*logger=*/ null,
|
|
||||||
ALWAYS_OPTIMIZE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -149,7 +143,7 @@ public class AppSearchImplTest {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
|
AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
|
||||||
mAppSearchImpl.rewriteSchema(
|
AppSearchImpl.rewriteSchema(
|
||||||
createPrefix("package", "newDatabase"), existingSchemaBuilder, newSchema);
|
createPrefix("package", "newDatabase"), existingSchemaBuilder, newSchema);
|
||||||
|
|
||||||
// We rewrote all the new types that were added. And nothing was removed.
|
// We rewrote all the new types that were added. And nothing was removed.
|
||||||
@@ -249,7 +243,7 @@ public class AppSearchImplTest {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
|
AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
|
||||||
mAppSearchImpl.rewriteSchema(
|
AppSearchImpl.rewriteSchema(
|
||||||
createPrefix("package", "existingDatabase"),
|
createPrefix("package", "existingDatabase"),
|
||||||
existingSchemaBuilder,
|
existingSchemaBuilder,
|
||||||
newSchema);
|
newSchema);
|
||||||
@@ -284,7 +278,7 @@ public class AppSearchImplTest {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
|
AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
|
||||||
mAppSearchImpl.rewriteSchema(
|
AppSearchImpl.rewriteSchema(
|
||||||
createPrefix("package", "existingDatabase"),
|
createPrefix("package", "existingDatabase"),
|
||||||
existingSchemaBuilder,
|
existingSchemaBuilder,
|
||||||
newSchema);
|
newSchema);
|
||||||
@@ -386,7 +380,7 @@ public class AppSearchImplTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveDatabasesFromDocumentThrowsException() throws Exception {
|
public void testRemoveDatabasesFromDocumentThrowsException() {
|
||||||
// Set two different database names in the document, which should never happen
|
// Set two different database names in the document, which should never happen
|
||||||
DocumentProto documentProto =
|
DocumentProto documentProto =
|
||||||
DocumentProto.newBuilder()
|
DocumentProto.newBuilder()
|
||||||
@@ -403,7 +397,7 @@ public class AppSearchImplTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNestedRemoveDatabasesFromDocumentThrowsException() throws Exception {
|
public void testNestedRemoveDatabasesFromDocumentThrowsException() {
|
||||||
// Set two different database names in the outer and inner document, which should never
|
// Set two different database names in the outer and inner document, which should never
|
||||||
// happen.
|
// happen.
|
||||||
DocumentProto insideDocument =
|
DocumentProto insideDocument =
|
||||||
@@ -436,6 +430,7 @@ public class AppSearchImplTest {
|
|||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -473,11 +468,7 @@ public class AppSearchImplTest {
|
|||||||
Context context = ApplicationProvider.getApplicationContext();
|
Context context = ApplicationProvider.getApplicationContext();
|
||||||
File appsearchDir = mTemporaryFolder.newFolder();
|
File appsearchDir = mTemporaryFolder.newFolder();
|
||||||
AppSearchImpl appSearchImpl =
|
AppSearchImpl appSearchImpl =
|
||||||
AppSearchImpl.create(
|
AppSearchImpl.create(appsearchDir, /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
|
||||||
appsearchDir,
|
|
||||||
context,
|
|
||||||
/*logger=*/ null,
|
|
||||||
ALWAYS_OPTIMIZE);
|
|
||||||
|
|
||||||
// Insert schema
|
// Insert schema
|
||||||
List<AppSearchSchema> schemas =
|
List<AppSearchSchema> schemas =
|
||||||
@@ -488,6 +479,7 @@ public class AppSearchImplTest {
|
|||||||
context.getPackageName(),
|
context.getPackageName(),
|
||||||
"database1",
|
"database1",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -506,7 +498,9 @@ public class AppSearchImplTest {
|
|||||||
/*queryExpression=*/ "",
|
/*queryExpression=*/ "",
|
||||||
new SearchSpec.Builder().addFilterSchemas("Type1").build(),
|
new SearchSpec.Builder().addFilterSchemas("Type1").build(),
|
||||||
context.getPackageName(),
|
context.getPackageName(),
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
VisibilityStore.NO_OP_UID,
|
VisibilityStore.NO_OP_UID,
|
||||||
|
/*callerHasSystemAccess=*/ false,
|
||||||
/*logger=*/ null);
|
/*logger=*/ null);
|
||||||
assertThat(results.getResults()).hasSize(1);
|
assertThat(results.getResults()).hasSize(1);
|
||||||
assertThat(results.getResults().get(0).getGenericDocument()).isEqualTo(validDoc);
|
assertThat(results.getResults().get(0).getGenericDocument()).isEqualTo(validDoc);
|
||||||
@@ -532,18 +526,13 @@ public class AppSearchImplTest {
|
|||||||
PutResultProto putResultProto = appSearchImpl.mIcingSearchEngineLocked.put(invalidDoc);
|
PutResultProto putResultProto = appSearchImpl.mIcingSearchEngineLocked.put(invalidDoc);
|
||||||
assertThat(putResultProto.getStatus().getCode()).isEqualTo(StatusProto.Code.OK);
|
assertThat(putResultProto.getStatus().getCode()).isEqualTo(StatusProto.Code.OK);
|
||||||
|
|
||||||
// Create a logger for capturing initialization to make sure we are logging the recovery
|
|
||||||
// process correctly.
|
|
||||||
AppSearchLoggerTest.TestLogger testLogger = new AppSearchLoggerTest.TestLogger();
|
|
||||||
|
|
||||||
// Initialize AppSearchImpl. This should cause a reset.
|
// Initialize AppSearchImpl. This should cause a reset.
|
||||||
|
InitializeStats.Builder initStatsBuilder = new InitializeStats.Builder();
|
||||||
appSearchImpl.close();
|
appSearchImpl.close();
|
||||||
appSearchImpl =
|
appSearchImpl = AppSearchImpl.create(appsearchDir, initStatsBuilder, ALWAYS_OPTIMIZE);
|
||||||
AppSearchImpl.create(
|
|
||||||
appsearchDir, context, testLogger, ALWAYS_OPTIMIZE);
|
|
||||||
|
|
||||||
// Check recovery state
|
// Check recovery state
|
||||||
InitializeStats initStats = testLogger.mInitializeStats;
|
InitializeStats initStats = initStatsBuilder.build();
|
||||||
assertThat(initStats).isNotNull();
|
assertThat(initStats).isNotNull();
|
||||||
assertThat(initStats.getStatusCode()).isEqualTo(AppSearchResult.RESULT_INTERNAL_ERROR);
|
assertThat(initStats.getStatusCode()).isEqualTo(AppSearchResult.RESULT_INTERNAL_ERROR);
|
||||||
assertThat(initStats.hasDeSync()).isFalse();
|
assertThat(initStats.hasDeSync()).isFalse();
|
||||||
@@ -568,7 +557,9 @@ public class AppSearchImplTest {
|
|||||||
/*queryExpression=*/ "",
|
/*queryExpression=*/ "",
|
||||||
new SearchSpec.Builder().addFilterSchemas("Type1").build(),
|
new SearchSpec.Builder().addFilterSchemas("Type1").build(),
|
||||||
context.getPackageName(),
|
context.getPackageName(),
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
VisibilityStore.NO_OP_UID,
|
VisibilityStore.NO_OP_UID,
|
||||||
|
/*callerHasSystemAccess=*/ false,
|
||||||
/*logger=*/ null);
|
/*logger=*/ null);
|
||||||
assertThat(results.getResults()).isEmpty();
|
assertThat(results.getResults()).isEmpty();
|
||||||
|
|
||||||
@@ -577,6 +568,7 @@ public class AppSearchImplTest {
|
|||||||
context.getPackageName(),
|
context.getPackageName(),
|
||||||
"database1",
|
"database1",
|
||||||
Collections.singletonList(new AppSearchSchema.Builder("Type1").build()),
|
Collections.singletonList(new AppSearchSchema.Builder("Type1").build()),
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -592,7 +584,9 @@ public class AppSearchImplTest {
|
|||||||
/*queryExpression=*/ "",
|
/*queryExpression=*/ "",
|
||||||
new SearchSpec.Builder().addFilterSchemas("Type1").build(),
|
new SearchSpec.Builder().addFilterSchemas("Type1").build(),
|
||||||
context.getPackageName(),
|
context.getPackageName(),
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
VisibilityStore.NO_OP_UID,
|
VisibilityStore.NO_OP_UID,
|
||||||
|
/*callerHasSystemAccess=*/ false,
|
||||||
/*logger=*/ null);
|
/*logger=*/ null);
|
||||||
assertThat(results.getResults()).hasSize(1);
|
assertThat(results.getResults()).hasSize(1);
|
||||||
assertThat(results.getResults().get(0).getGenericDocument()).isEqualTo(validDoc);
|
assertThat(results.getResults().get(0).getGenericDocument()).isEqualTo(validDoc);
|
||||||
@@ -609,6 +603,7 @@ public class AppSearchImplTest {
|
|||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -642,6 +637,7 @@ public class AppSearchImplTest {
|
|||||||
"package",
|
"package",
|
||||||
"database1",
|
"database1",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -650,6 +646,7 @@ public class AppSearchImplTest {
|
|||||||
"package",
|
"package",
|
||||||
"database2",
|
"database2",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -694,6 +691,7 @@ public class AppSearchImplTest {
|
|||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -735,6 +733,7 @@ public class AppSearchImplTest {
|
|||||||
"package1",
|
"package1",
|
||||||
"database1",
|
"database1",
|
||||||
schema1,
|
schema1,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -747,6 +746,7 @@ public class AppSearchImplTest {
|
|||||||
"package2",
|
"package2",
|
||||||
"database2",
|
"database2",
|
||||||
schema2,
|
schema2,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -789,6 +789,7 @@ public class AppSearchImplTest {
|
|||||||
"package1",
|
"package1",
|
||||||
"database1",
|
"database1",
|
||||||
schema1,
|
schema1,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -801,6 +802,7 @@ public class AppSearchImplTest {
|
|||||||
"package2",
|
"package2",
|
||||||
"database2",
|
"database2",
|
||||||
schema2,
|
schema2,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -848,7 +850,9 @@ public class AppSearchImplTest {
|
|||||||
"",
|
"",
|
||||||
searchSpec,
|
searchSpec,
|
||||||
/*callerPackageName=*/ "",
|
/*callerPackageName=*/ "",
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
VisibilityStore.NO_OP_UID,
|
VisibilityStore.NO_OP_UID,
|
||||||
|
/*callerHasSystemAccess=*/ false,
|
||||||
/*logger=*/ null);
|
/*logger=*/ null);
|
||||||
assertThat(searchResultPage.getResults()).isEmpty();
|
assertThat(searchResultPage.getResults()).isEmpty();
|
||||||
}
|
}
|
||||||
@@ -888,6 +892,7 @@ public class AppSearchImplTest {
|
|||||||
"package",
|
"package",
|
||||||
"database1",
|
"database1",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -911,9 +916,6 @@ public class AppSearchImplTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetSchema_incompatible() throws Exception {
|
public void testSetSchema_incompatible() throws Exception {
|
||||||
List<SchemaTypeConfigProto> existingSchemas =
|
|
||||||
mAppSearchImpl.getSchemaProtoLocked().getTypesList();
|
|
||||||
|
|
||||||
List<AppSearchSchema> oldSchemas = new ArrayList<>();
|
List<AppSearchSchema> oldSchemas = new ArrayList<>();
|
||||||
oldSchemas.add(
|
oldSchemas.add(
|
||||||
new AppSearchSchema.Builder("Email")
|
new AppSearchSchema.Builder("Email")
|
||||||
@@ -935,6 +937,7 @@ public class AppSearchImplTest {
|
|||||||
"package",
|
"package",
|
||||||
"database1",
|
"database1",
|
||||||
oldSchemas,
|
oldSchemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -950,6 +953,7 @@ public class AppSearchImplTest {
|
|||||||
"package",
|
"package",
|
||||||
"database1",
|
"database1",
|
||||||
newSchemas,
|
newSchemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ true,
|
/*forceOverride=*/ true,
|
||||||
@@ -972,6 +976,7 @@ public class AppSearchImplTest {
|
|||||||
"package",
|
"package",
|
||||||
"database1",
|
"database1",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -1004,6 +1009,7 @@ public class AppSearchImplTest {
|
|||||||
"package",
|
"package",
|
||||||
"database1",
|
"database1",
|
||||||
finalSchemas,
|
finalSchemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -1017,6 +1023,7 @@ public class AppSearchImplTest {
|
|||||||
"package",
|
"package",
|
||||||
"database1",
|
"database1",
|
||||||
finalSchemas,
|
finalSchemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ true,
|
/*forceOverride=*/ true,
|
||||||
@@ -1054,6 +1061,7 @@ public class AppSearchImplTest {
|
|||||||
"package",
|
"package",
|
||||||
"database1",
|
"database1",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -1062,6 +1070,7 @@ public class AppSearchImplTest {
|
|||||||
"package",
|
"package",
|
||||||
"database2",
|
"database2",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -1101,6 +1110,7 @@ public class AppSearchImplTest {
|
|||||||
"package",
|
"package",
|
||||||
"database1",
|
"database1",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ true,
|
/*forceOverride=*/ true,
|
||||||
@@ -1145,6 +1155,7 @@ public class AppSearchImplTest {
|
|||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
schema,
|
schema,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -1206,6 +1217,7 @@ public class AppSearchImplTest {
|
|||||||
"packageA",
|
"packageA",
|
||||||
"database",
|
"database",
|
||||||
schema,
|
schema,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -1214,6 +1226,7 @@ public class AppSearchImplTest {
|
|||||||
"packageB",
|
"packageB",
|
||||||
"database",
|
"database",
|
||||||
schema,
|
schema,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -1259,6 +1272,7 @@ public class AppSearchImplTest {
|
|||||||
"package1",
|
"package1",
|
||||||
"database1",
|
"database1",
|
||||||
Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
|
Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -1272,6 +1286,7 @@ public class AppSearchImplTest {
|
|||||||
"package1",
|
"package1",
|
||||||
"database2",
|
"database2",
|
||||||
Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
|
Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -1285,6 +1300,7 @@ public class AppSearchImplTest {
|
|||||||
"package2",
|
"package2",
|
||||||
"database1",
|
"database1",
|
||||||
Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
|
Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -1343,6 +1359,7 @@ public class AppSearchImplTest {
|
|||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -1493,6 +1510,7 @@ public class AppSearchImplTest {
|
|||||||
"package1",
|
"package1",
|
||||||
"database",
|
"database",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -1515,6 +1533,7 @@ public class AppSearchImplTest {
|
|||||||
"package1",
|
"package1",
|
||||||
"database",
|
"database",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -1530,6 +1549,7 @@ public class AppSearchImplTest {
|
|||||||
"package2",
|
"package2",
|
||||||
"database",
|
"database",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -1578,6 +1598,7 @@ public class AppSearchImplTest {
|
|||||||
"package1",
|
"package1",
|
||||||
"database",
|
"database",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -1600,6 +1621,7 @@ public class AppSearchImplTest {
|
|||||||
"package1",
|
"package1",
|
||||||
"database1",
|
"database1",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -1621,6 +1643,7 @@ public class AppSearchImplTest {
|
|||||||
"package1",
|
"package1",
|
||||||
"database1",
|
"database1",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -1629,6 +1652,7 @@ public class AppSearchImplTest {
|
|||||||
"package1",
|
"package1",
|
||||||
"database2",
|
"database2",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -1664,13 +1688,9 @@ public class AppSearchImplTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testThrowsExceptionIfClosed() throws Exception {
|
public void testThrowsExceptionIfClosed() throws Exception {
|
||||||
Context context = ApplicationProvider.getApplicationContext();
|
|
||||||
AppSearchImpl appSearchImpl =
|
AppSearchImpl appSearchImpl =
|
||||||
AppSearchImpl.create(
|
AppSearchImpl.create(
|
||||||
mTemporaryFolder.newFolder(),
|
mTemporaryFolder.newFolder(), /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
|
||||||
context,
|
|
||||||
/*logger=*/ null,
|
|
||||||
ALWAYS_OPTIMIZE);
|
|
||||||
|
|
||||||
// Initial check that we could do something at first.
|
// Initial check that we could do something at first.
|
||||||
List<AppSearchSchema> schemas =
|
List<AppSearchSchema> schemas =
|
||||||
@@ -1679,6 +1699,7 @@ public class AppSearchImplTest {
|
|||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -1689,140 +1710,115 @@ public class AppSearchImplTest {
|
|||||||
// Check all our public APIs
|
// Check all our public APIs
|
||||||
expectThrows(
|
expectThrows(
|
||||||
IllegalStateException.class,
|
IllegalStateException.class,
|
||||||
() -> {
|
() ->
|
||||||
appSearchImpl.setSchema(
|
appSearchImpl.setSchema(
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
/*version=*/ 0);
|
/*version=*/ 0));
|
||||||
});
|
|
||||||
|
expectThrows(
|
||||||
|
IllegalStateException.class, () -> appSearchImpl.getSchema("package", "database"));
|
||||||
|
|
||||||
expectThrows(
|
expectThrows(
|
||||||
IllegalStateException.class,
|
IllegalStateException.class,
|
||||||
() -> {
|
() ->
|
||||||
appSearchImpl.getSchema("package", "database");
|
|
||||||
});
|
|
||||||
|
|
||||||
expectThrows(
|
|
||||||
IllegalStateException.class,
|
|
||||||
() -> {
|
|
||||||
appSearchImpl.putDocument(
|
appSearchImpl.putDocument(
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
new GenericDocument.Builder<>("namespace", "id", "type").build(),
|
new GenericDocument.Builder<>("namespace", "id", "type").build(),
|
||||||
/*logger=*/ null);
|
/*logger=*/ null));
|
||||||
});
|
|
||||||
|
|
||||||
expectThrows(
|
expectThrows(
|
||||||
IllegalStateException.class,
|
IllegalStateException.class,
|
||||||
() -> {
|
() ->
|
||||||
appSearchImpl.getDocument(
|
appSearchImpl.getDocument(
|
||||||
"package", "database", "namespace", "id", Collections.emptyMap());
|
"package", "database", "namespace", "id", Collections.emptyMap()));
|
||||||
});
|
|
||||||
|
|
||||||
expectThrows(
|
expectThrows(
|
||||||
IllegalStateException.class,
|
IllegalStateException.class,
|
||||||
() -> {
|
() ->
|
||||||
appSearchImpl.query(
|
appSearchImpl.query(
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
"query",
|
"query",
|
||||||
new SearchSpec.Builder()
|
new SearchSpec.Builder().build(),
|
||||||
.setTermMatch(TermMatchType.Code.PREFIX_VALUE)
|
/*logger=*/ null));
|
||||||
.build(),
|
|
||||||
/*logger=*/ null);
|
|
||||||
});
|
|
||||||
|
|
||||||
expectThrows(
|
expectThrows(
|
||||||
IllegalStateException.class,
|
IllegalStateException.class,
|
||||||
() -> {
|
() ->
|
||||||
appSearchImpl.globalQuery(
|
appSearchImpl.globalQuery(
|
||||||
"query",
|
"query",
|
||||||
new SearchSpec.Builder()
|
new SearchSpec.Builder().build(),
|
||||||
.setTermMatch(TermMatchType.Code.PREFIX_VALUE)
|
|
||||||
.build(),
|
|
||||||
"package",
|
"package",
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
VisibilityStore.NO_OP_UID,
|
VisibilityStore.NO_OP_UID,
|
||||||
/*logger=*/ null);
|
/*callerHasSystemAccess=*/ false,
|
||||||
});
|
/*logger=*/ null));
|
||||||
|
|
||||||
expectThrows(
|
expectThrows(
|
||||||
IllegalStateException.class,
|
IllegalStateException.class,
|
||||||
() -> {
|
() -> appSearchImpl.getNextPage(/*nextPageToken=*/ 1L));
|
||||||
appSearchImpl.getNextPage(/*nextPageToken=*/ 1L);
|
|
||||||
});
|
|
||||||
|
|
||||||
expectThrows(
|
expectThrows(
|
||||||
IllegalStateException.class,
|
IllegalStateException.class,
|
||||||
() -> {
|
() -> appSearchImpl.invalidateNextPageToken(/*nextPageToken=*/ 1L));
|
||||||
appSearchImpl.invalidateNextPageToken(/*nextPageToken=*/ 1L);
|
|
||||||
});
|
|
||||||
|
|
||||||
expectThrows(
|
expectThrows(
|
||||||
IllegalStateException.class,
|
IllegalStateException.class,
|
||||||
() -> {
|
() ->
|
||||||
appSearchImpl.reportUsage(
|
appSearchImpl.reportUsage(
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
"namespace",
|
"namespace",
|
||||||
"id",
|
"id",
|
||||||
/*usageTimestampMillis=*/ 1000L,
|
/*usageTimestampMillis=*/ 1000L,
|
||||||
/*systemUsage=*/ false);
|
/*systemUsage=*/ false));
|
||||||
});
|
|
||||||
|
|
||||||
expectThrows(
|
expectThrows(
|
||||||
IllegalStateException.class,
|
IllegalStateException.class,
|
||||||
() -> {
|
() ->
|
||||||
appSearchImpl.remove(
|
appSearchImpl.remove(
|
||||||
"package", "database", "namespace", "id", /*statsBuilder=*/ null);
|
"package",
|
||||||
});
|
"database",
|
||||||
|
"namespace",
|
||||||
|
"id",
|
||||||
|
/*removeStatsBuilder=*/ null));
|
||||||
|
|
||||||
expectThrows(
|
expectThrows(
|
||||||
IllegalStateException.class,
|
IllegalStateException.class,
|
||||||
() -> {
|
() ->
|
||||||
appSearchImpl.removeByQuery(
|
appSearchImpl.removeByQuery(
|
||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
"query",
|
"query",
|
||||||
new SearchSpec.Builder()
|
new SearchSpec.Builder().build(),
|
||||||
.setTermMatch(TermMatchType.Code.PREFIX_VALUE)
|
/*removeStatsBuilder=*/ null));
|
||||||
.build(),
|
|
||||||
/*statsBuilder=*/ null);
|
|
||||||
});
|
|
||||||
|
|
||||||
expectThrows(
|
expectThrows(
|
||||||
IllegalStateException.class,
|
IllegalStateException.class,
|
||||||
() -> {
|
() -> appSearchImpl.getStorageInfoForPackage("package"));
|
||||||
appSearchImpl.getStorageInfoForPackage("package");
|
|
||||||
});
|
|
||||||
|
|
||||||
expectThrows(
|
expectThrows(
|
||||||
IllegalStateException.class,
|
IllegalStateException.class,
|
||||||
() -> {
|
() -> appSearchImpl.getStorageInfoForDatabase("package", "database"));
|
||||||
appSearchImpl.getStorageInfoForDatabase("package", "database");
|
|
||||||
});
|
|
||||||
|
|
||||||
expectThrows(
|
expectThrows(
|
||||||
IllegalStateException.class,
|
IllegalStateException.class,
|
||||||
() -> {
|
() -> appSearchImpl.persistToDisk(PersistType.Code.FULL));
|
||||||
appSearchImpl.persistToDisk(PersistType.Code.FULL);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPutPersistsWithLiteFlush() throws Exception {
|
public void testPutPersistsWithLiteFlush() throws Exception {
|
||||||
// Setup the index
|
// Setup the index
|
||||||
Context context = ApplicationProvider.getApplicationContext();
|
|
||||||
File appsearchDir = mTemporaryFolder.newFolder();
|
File appsearchDir = mTemporaryFolder.newFolder();
|
||||||
AppSearchImpl appSearchImpl =
|
AppSearchImpl appSearchImpl =
|
||||||
AppSearchImpl.create(
|
AppSearchImpl.create(appsearchDir, /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
|
||||||
appsearchDir,
|
|
||||||
context,
|
|
||||||
/*logger=*/ null,
|
|
||||||
ALWAYS_OPTIMIZE);
|
|
||||||
|
|
||||||
List<AppSearchSchema> schemas =
|
List<AppSearchSchema> schemas =
|
||||||
Collections.singletonList(new AppSearchSchema.Builder("type").build());
|
Collections.singletonList(new AppSearchSchema.Builder("type").build());
|
||||||
@@ -1830,6 +1826,7 @@ public class AppSearchImplTest {
|
|||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -1848,11 +1845,7 @@ public class AppSearchImplTest {
|
|||||||
|
|
||||||
// That document should be visible even from another instance.
|
// That document should be visible even from another instance.
|
||||||
AppSearchImpl appSearchImpl2 =
|
AppSearchImpl appSearchImpl2 =
|
||||||
AppSearchImpl.create(
|
AppSearchImpl.create(appsearchDir, /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
|
||||||
appsearchDir,
|
|
||||||
context,
|
|
||||||
/*logger=*/ null,
|
|
||||||
ALWAYS_OPTIMIZE);
|
|
||||||
getResult =
|
getResult =
|
||||||
appSearchImpl2.getDocument(
|
appSearchImpl2.getDocument(
|
||||||
"package", "database", "namespace1", "id1", Collections.emptyMap());
|
"package", "database", "namespace1", "id1", Collections.emptyMap());
|
||||||
@@ -1862,14 +1855,9 @@ public class AppSearchImplTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testDeletePersistsWithLiteFlush() throws Exception {
|
public void testDeletePersistsWithLiteFlush() throws Exception {
|
||||||
// Setup the index
|
// Setup the index
|
||||||
Context context = ApplicationProvider.getApplicationContext();
|
|
||||||
File appsearchDir = mTemporaryFolder.newFolder();
|
File appsearchDir = mTemporaryFolder.newFolder();
|
||||||
AppSearchImpl appSearchImpl =
|
AppSearchImpl appSearchImpl =
|
||||||
AppSearchImpl.create(
|
AppSearchImpl.create(appsearchDir, /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
|
||||||
appsearchDir,
|
|
||||||
context,
|
|
||||||
/*logger=*/ null,
|
|
||||||
ALWAYS_OPTIMIZE);
|
|
||||||
|
|
||||||
List<AppSearchSchema> schemas =
|
List<AppSearchSchema> schemas =
|
||||||
Collections.singletonList(new AppSearchSchema.Builder("type").build());
|
Collections.singletonList(new AppSearchSchema.Builder("type").build());
|
||||||
@@ -1877,6 +1865,7 @@ public class AppSearchImplTest {
|
|||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -1919,11 +1908,7 @@ public class AppSearchImplTest {
|
|||||||
|
|
||||||
// Only the second document should be retrievable from another instance.
|
// Only the second document should be retrievable from another instance.
|
||||||
AppSearchImpl appSearchImpl2 =
|
AppSearchImpl appSearchImpl2 =
|
||||||
AppSearchImpl.create(
|
AppSearchImpl.create(appsearchDir, /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
|
||||||
appsearchDir,
|
|
||||||
context,
|
|
||||||
/*logger=*/ null,
|
|
||||||
ALWAYS_OPTIMIZE);
|
|
||||||
expectThrows(
|
expectThrows(
|
||||||
AppSearchException.class,
|
AppSearchException.class,
|
||||||
() ->
|
() ->
|
||||||
@@ -1942,14 +1927,9 @@ public class AppSearchImplTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testDeleteByQueryPersistsWithLiteFlush() throws Exception {
|
public void testDeleteByQueryPersistsWithLiteFlush() throws Exception {
|
||||||
// Setup the index
|
// Setup the index
|
||||||
Context context = ApplicationProvider.getApplicationContext();
|
|
||||||
File appsearchDir = mTemporaryFolder.newFolder();
|
File appsearchDir = mTemporaryFolder.newFolder();
|
||||||
AppSearchImpl appSearchImpl =
|
AppSearchImpl appSearchImpl =
|
||||||
AppSearchImpl.create(
|
AppSearchImpl.create(appsearchDir, /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
|
||||||
appsearchDir,
|
|
||||||
context,
|
|
||||||
/*logger=*/ null,
|
|
||||||
ALWAYS_OPTIMIZE);
|
|
||||||
|
|
||||||
List<AppSearchSchema> schemas =
|
List<AppSearchSchema> schemas =
|
||||||
Collections.singletonList(new AppSearchSchema.Builder("type").build());
|
Collections.singletonList(new AppSearchSchema.Builder("type").build());
|
||||||
@@ -1957,6 +1937,7 @@ public class AppSearchImplTest {
|
|||||||
"package",
|
"package",
|
||||||
"database",
|
"database",
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -2007,11 +1988,7 @@ public class AppSearchImplTest {
|
|||||||
|
|
||||||
// Only the second document should be retrievable from another instance.
|
// Only the second document should be retrievable from another instance.
|
||||||
AppSearchImpl appSearchImpl2 =
|
AppSearchImpl appSearchImpl2 =
|
||||||
AppSearchImpl.create(
|
AppSearchImpl.create(appsearchDir, /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
|
||||||
appsearchDir,
|
|
||||||
context,
|
|
||||||
/*logger=*/ null,
|
|
||||||
ALWAYS_OPTIMIZE);
|
|
||||||
expectThrows(
|
expectThrows(
|
||||||
AppSearchException.class,
|
AppSearchException.class,
|
||||||
() ->
|
() ->
|
||||||
|
|||||||
@@ -25,9 +25,6 @@ import android.app.appsearch.AppSearchSchema;
|
|||||||
import android.app.appsearch.GenericDocument;
|
import android.app.appsearch.GenericDocument;
|
||||||
import android.app.appsearch.SearchResultPage;
|
import android.app.appsearch.SearchResultPage;
|
||||||
import android.app.appsearch.SearchSpec;
|
import android.app.appsearch.SearchSpec;
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
|
||||||
|
|
||||||
import com.android.server.appsearch.external.localstorage.stats.CallStats;
|
import com.android.server.appsearch.external.localstorage.stats.CallStats;
|
||||||
import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
|
import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
|
||||||
@@ -60,15 +57,9 @@ public class AppSearchLoggerTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
Context context = ApplicationProvider.getApplicationContext();
|
|
||||||
|
|
||||||
// Give ourselves global query permissions
|
|
||||||
mAppSearchImpl =
|
mAppSearchImpl =
|
||||||
AppSearchImpl.create(
|
AppSearchImpl.create(
|
||||||
mTemporaryFolder.newFolder(),
|
mTemporaryFolder.newFolder(), /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
|
||||||
context,
|
|
||||||
/*logger=*/ null,
|
|
||||||
ALWAYS_OPTIMIZE);
|
|
||||||
mLogger = new TestLogger();
|
mLogger = new TestLogger();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,20 +280,15 @@ public class AppSearchLoggerTest {
|
|||||||
//
|
//
|
||||||
@Test
|
@Test
|
||||||
public void testLoggingStats_initialize() throws Exception {
|
public void testLoggingStats_initialize() throws Exception {
|
||||||
Context context = ApplicationProvider.getApplicationContext();
|
|
||||||
|
|
||||||
// Create an unused AppSearchImpl to generated an InitializeStats.
|
// Create an unused AppSearchImpl to generated an InitializeStats.
|
||||||
AppSearchImpl appSearchImpl =
|
InitializeStats.Builder initStatsBuilder = new InitializeStats.Builder();
|
||||||
AppSearchImpl.create(
|
AppSearchImpl.create(mTemporaryFolder.newFolder(), initStatsBuilder, ALWAYS_OPTIMIZE);
|
||||||
mTemporaryFolder.newFolder(),
|
InitializeStats iStats = initStatsBuilder.build();
|
||||||
context,
|
|
||||||
mLogger,
|
|
||||||
ALWAYS_OPTIMIZE);
|
|
||||||
|
|
||||||
InitializeStats iStats = mLogger.mInitializeStats;
|
|
||||||
assertThat(iStats).isNotNull();
|
assertThat(iStats).isNotNull();
|
||||||
assertThat(iStats.getStatusCode()).isEqualTo(AppSearchResult.RESULT_OK);
|
assertThat(iStats.getStatusCode()).isEqualTo(AppSearchResult.RESULT_OK);
|
||||||
assertThat(iStats.getTotalLatencyMillis()).isGreaterThan(0);
|
// Total latency captured in LocalStorage
|
||||||
|
assertThat(iStats.getTotalLatencyMillis()).isEqualTo(0);
|
||||||
assertThat(iStats.hasDeSync()).isFalse();
|
assertThat(iStats.hasDeSync()).isFalse();
|
||||||
assertThat(iStats.getNativeLatencyMillis()).isGreaterThan(0);
|
assertThat(iStats.getNativeLatencyMillis()).isGreaterThan(0);
|
||||||
assertThat(iStats.getDocumentStoreDataStatus())
|
assertThat(iStats.getDocumentStoreDataStatus())
|
||||||
@@ -322,6 +308,7 @@ public class AppSearchLoggerTest {
|
|||||||
testPackageName,
|
testPackageName,
|
||||||
testDatabase,
|
testDatabase,
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -350,10 +337,12 @@ public class AppSearchLoggerTest {
|
|||||||
testPackageName,
|
testPackageName,
|
||||||
testDatabase,
|
testDatabase,
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
/*version=*/ 0);
|
/*version=*/ 0);
|
||||||
|
|
||||||
GenericDocument document = new GenericDocument.Builder<>("namespace", "id", "type").build();
|
GenericDocument document = new GenericDocument.Builder<>("namespace", "id", "type").build();
|
||||||
mAppSearchImpl.putDocument(testPackageName, testDatabase, document, mLogger);
|
mAppSearchImpl.putDocument(testPackageName, testDatabase, document, mLogger);
|
||||||
|
|
||||||
@@ -401,6 +390,7 @@ public class AppSearchLoggerTest {
|
|||||||
testPackageName,
|
testPackageName,
|
||||||
testDatabase,
|
testDatabase,
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
@@ -432,6 +422,7 @@ public class AppSearchLoggerTest {
|
|||||||
testPackageName,
|
testPackageName,
|
||||||
testDatabase,
|
testDatabase,
|
||||||
schemas,
|
schemas,
|
||||||
|
/*visibilityStore=*/ null,
|
||||||
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
|
||||||
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
/*schemasPackageAccessible=*/ Collections.emptyMap(),
|
||||||
/*forceOverride=*/ false,
|
/*forceOverride=*/ false,
|
||||||
|
|||||||
Reference in New Issue
Block a user