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:
committed by
Android (Google) Code Review
commit
ed23887b8e
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user