Merge changes I2a817d71,I86f800c4 into sc-dev

* changes:
  Avoid waiting for the async notifyAnrDelayStarted
  Implement ANR delay with app IO blocked reason
This commit is contained in:
Zimuzo Ezeozue
2021-03-04 10:37:03 +00:00
committed by Android (Google) Code Review
5 changed files with 98 additions and 23 deletions

View File

@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.IVold;
import java.util.List;
import java.util.Set;
/**
@@ -112,4 +113,10 @@ public abstract class StorageManagerInternal {
* @param bytes number of bytes which need to be freed
*/
public abstract void freeCache(@Nullable String volumeUuid, long bytes);
/**
* Returns the {@link VolumeInfo#getId()} values for the volumes matching
* {@link VolumeInfo#isPrimary()}
*/
public abstract List<String> getPrimaryVolumeIds();
}

View File

@@ -239,14 +239,13 @@ public abstract class ExternalStorageService extends Service {
}
@Override
public void notifyAnrDelayStarted(String packageName, int uid, int tid, int reason,
RemoteCallback callback) throws RemoteException {
public void notifyAnrDelayStarted(String packageName, int uid, int tid, int reason)
throws RemoteException {
mHandler.post(() -> {
try {
onAnrDelayStarted(packageName, uid, tid, reason);
sendResult(packageName, null /* throwable */, callback);
} catch (Throwable t) {
sendResult(packageName, t, callback);
// Ignored
}
});
}

View File

@@ -32,6 +32,5 @@ oneway interface IExternalStorageService
in RemoteCallback callback);
void freeCache(@utf8InCpp String sessionId, in String volumeUuid, long bytes,
in RemoteCallback callback);
void notifyAnrDelayStarted(String packageName, int uid, int tid, int reason,
in RemoteCallback callback);
void notifyAnrDelayStarted(String packageName, int uid, int tid, int reason);
}

View File

@@ -578,6 +578,12 @@ class StorageManagerService extends IStorageManager.Stub
*/
private static final int PBKDF2_HASH_ROUNDS = 1024;
private static final String ANR_DELAY_MILLIS_DEVICE_CONFIG_KEY =
"anr_delay_millis";
private static final String ANR_DELAY_NOTIFY_EXTERNAL_STORAGE_SERVICE_DEVICE_CONFIG_KEY =
"anr_delay_notify_external_storage_service";
/**
* Mounted OBB tracking information. Used to track the current state of all
* OBBs.
@@ -948,25 +954,51 @@ class StorageManagerService extends IStorageManager.Stub
}
}
// TODO(b/170486601): Check transcoding status based on events pushed from the MediaProvider
private class ExternalStorageServiceAnrController implements AnrController {
@Override
public long getAnrDelayMillis(String packageName, int uid) {
int delay = SystemProperties.getInt("sys.fuse.transcode_anr_delay", 0);
Log.d(TAG, "getAnrDelayMillis: " + packageName + ". Delaying for " + delay + "ms");
if (!isAppIoBlocked(uid)) {
return 0;
}
int delay = DeviceConfig.getInt(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
ANR_DELAY_MILLIS_DEVICE_CONFIG_KEY, 0);
Slog.v(TAG, "getAnrDelayMillis for " + packageName + ". " + delay + "ms");
return delay;
}
@Override
public void onAnrDelayStarted(String packageName, int uid) {
Log.d(TAG, "onAnrDelayStarted: " + packageName);
if (!isAppIoBlocked(uid)) {
return;
}
boolean notifyExternalStorageService = DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
ANR_DELAY_NOTIFY_EXTERNAL_STORAGE_SERVICE_DEVICE_CONFIG_KEY, true);
if (notifyExternalStorageService) {
Slog.d(TAG, "onAnrDelayStarted for " + packageName
+ ". Notifying external storage service");
try {
mStorageSessionController.notifyAnrDelayStarted(packageName, uid, 0 /* tid */,
StorageManager.APP_IO_BLOCKED_REASON_TRANSCODING);
} catch (ExternalStorageServiceException e) {
Slog.e(TAG, "Failed to notify ANR delay started for " + packageName, e);
}
} else {
// TODO(b/170973510): Implement framework spinning dialog for ANR delay
}
}
@Override
public boolean onAnrDelayCompleted(String packageName, int uid) {
boolean show = SystemProperties.getBoolean("sys.fuse.transcode_anr_dialog_show", true);
Log.d(TAG, "onAnrDelayCompleted: " + packageName + ". Show: " + show);
return show;
if (isAppIoBlocked(uid)) {
Slog.d(TAG, "onAnrDelayCompleted for " + packageName + ". Showing ANR dialog...");
return true;
} else {
Slog.d(TAG, "onAnrDelayCompleted for " + packageName + ". Skipping ANR dialog...");
return false;
}
}
}
@@ -4690,5 +4722,19 @@ class StorageManagerService extends IStorageManager.Stub
Binder.restoreCallingIdentity(token);
}
}
@Override
public List<String> getPrimaryVolumeIds() {
final List<String> primaryVolumeIds = new ArrayList<>();
synchronized (mLock) {
for (int i = 0; i < mVolumes.size(); i++) {
final VolumeInfo vol = mVolumes.valueAt(i);
if (vol.isPrimary()) {
primaryVolumeIds.add(vol.getId());
}
}
}
return primaryVolumeIds;
}
}
}

View File

@@ -53,11 +53,13 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
/**
* Controls the lifecycle of the {@link ActiveConnection} to an {@link ExternalStorageService}
@@ -72,6 +74,7 @@ public final class StorageUserConnection {
private final Context mContext;
private final int mUserId;
private final StorageSessionController mSessionController;
private final StorageManagerInternal mSmInternal;
private final ActiveConnection mActiveConnection = new ActiveConnection();
@GuardedBy("mLock") private final Map<String, Session> mSessions = new HashMap<>();
@GuardedBy("mLock") private final Set<Integer> mUidsBlockedOnIo = new ArraySet<>();
@@ -81,6 +84,7 @@ public final class StorageUserConnection {
mContext = Objects.requireNonNull(context);
mUserId = Preconditions.checkArgumentNonnegative(userId);
mSessionController = controller;
mSmInternal = LocalServices.getService(StorageManagerInternal.class);
mHandlerThread = new HandlerThread("StorageUserConnectionThread-" + mUserId);
mHandlerThread.start();
}
@@ -152,9 +156,13 @@ public final class StorageUserConnection {
*/
public void notifyAnrDelayStarted(String packageName, int uid, int tid, int reason)
throws ExternalStorageServiceException {
List<String> primarySessionIds = mSmInternal.getPrimaryVolumeIds();
synchronized (mSessionsLock) {
for (String sessionId : mSessions.keySet()) {
mActiveConnection.notifyAnrDelayStarted(packageName, uid, tid, reason);
if (primarySessionIds.contains(sessionId)) {
mActiveConnection.notifyAnrDelayStarted(packageName, uid, tid, reason);
return;
}
}
}
}
@@ -201,8 +209,7 @@ public final class StorageUserConnection {
return;
}
}
StorageManagerInternal sm = LocalServices.getService(StorageManagerInternal.class);
sm.resetUser(mUserId);
mSmInternal.resetUser(mUserId);
}
/**
@@ -317,6 +324,23 @@ public final class StorageUserConnection {
}
}
private void asyncBestEffort(Consumer<IExternalStorageService> consumer) {
synchronized (mLock) {
if (mRemoteFuture == null) {
Slog.w(TAG, "Dropping async request service is not bound");
return;
}
IExternalStorageService service = mRemoteFuture.getNow(null);
if (service == null) {
Slog.w(TAG, "Dropping async request service is not connected");
return;
}
consumer.accept(service);
}
}
private void waitForAsyncVoid(AsyncStorageServiceCall asyncCall) throws Exception {
CompletableFuture<Void> opFuture = new CompletableFuture<>();
RemoteCallback callback = new RemoteCallback(result -> setResult(result, opFuture));
@@ -401,13 +425,13 @@ public final class StorageUserConnection {
public void notifyAnrDelayStarted(String packgeName, int uid, int tid, int reason)
throws ExternalStorageServiceException {
try {
waitForAsyncVoid((service, callback) ->
service.notifyAnrDelayStarted(packgeName, uid, tid, reason, callback));
} catch (Exception e) {
throw new ExternalStorageServiceException("Failed to notify ANR delay started: "
+ packgeName, e);
}
asyncBestEffort(service -> {
try {
service.notifyAnrDelayStarted(packgeName, uid, tid, reason);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to notify ANR delay started", e);
}
});
}
private void setResult(Bundle result, CompletableFuture<Void> future) {