Merge "Making some ActivityManager API calls synchronous"

This commit is contained in:
TreeHugger Robot
2020-11-05 23:12:36 +00:00
committed by Android (Google) Code Review
5 changed files with 20 additions and 295 deletions

View File

@@ -34,8 +34,6 @@ import android.app.WindowConfiguration;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.graphics.Rect;
@@ -45,7 +43,6 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
import android.view.IRecentsAnimationController;
@@ -58,7 +55,6 @@ import com.android.systemui.shared.recents.model.ThumbnailData;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;
import java.util.function.Consumer;
public class ActivityManagerWrapper {
@@ -74,14 +70,7 @@ public class ActivityManagerWrapper {
// Should match the value in AssistManager
private static final String INVOCATION_TIME_MS_KEY = "invocation_time_ms";
private final PackageManager mPackageManager;
private final BackgroundExecutor mBackgroundExecutor;
private ActivityManagerWrapper() {
final Context context = AppGlobals.getInitialApplication();
mPackageManager = context.getPackageManager();
mBackgroundExecutor = BackgroundExecutor.get();
}
private ActivityManagerWrapper() { }
public static ActivityManagerWrapper getInstance() {
return sInstance;
@@ -159,60 +148,12 @@ public class ActivityManagerWrapper {
* Removes the outdated snapshot of home task.
*/
public void invalidateHomeTaskSnapshot(final Activity homeActivity) {
mBackgroundExecutor.submit(new Runnable() {
@Override
public void run() {
try {
ActivityTaskManager.getService().invalidateHomeTaskSnapshot(
homeActivity.getActivityToken());
} catch (RemoteException e) {
Log.w(TAG, "Failed to invalidate home snapshot", e);
}
}
});
}
/**
* @return the activity label, badging if necessary.
*/
public String getBadgedActivityLabel(ActivityInfo info, int userId) {
return getBadgedLabel(info.loadLabel(mPackageManager).toString(), userId);
}
/**
* @return the application label, badging if necessary.
*/
public String getBadgedApplicationLabel(ApplicationInfo appInfo, int userId) {
return getBadgedLabel(appInfo.loadLabel(mPackageManager).toString(), userId);
}
/**
* @return the content description for a given task, badging it if necessary. The content
* description joins the app and activity labels.
*/
public String getBadgedContentDescription(ActivityInfo info, int userId,
ActivityManager.TaskDescription td) {
String activityLabel;
if (td != null && td.getLabel() != null) {
activityLabel = td.getLabel();
} else {
activityLabel = info.loadLabel(mPackageManager).toString();
try {
ActivityTaskManager.getService().invalidateHomeTaskSnapshot(
homeActivity.getActivityToken());
} catch (RemoteException e) {
Log.w(TAG, "Failed to invalidate home snapshot", e);
}
String applicationLabel = info.applicationInfo.loadLabel(mPackageManager).toString();
String badgedApplicationLabel = getBadgedLabel(applicationLabel, userId);
return applicationLabel.equals(activityLabel)
? badgedApplicationLabel
: badgedApplicationLabel + " " + activityLabel;
}
/**
* @return the given label for a user, badging if necessary.
*/
private String getBadgedLabel(String label, int userId) {
if (userId != UserHandle.myUserId()) {
label = mPackageManager.getUserBadgedLabel(label, new UserHandle(userId)).toString();
}
return label;
}
/**
@@ -342,59 +283,33 @@ public class ActivityManagerWrapper {
/**
* Requests that the system close any open system windows (including other SystemUI).
*/
public Future<?> closeSystemWindows(final String reason) {
return mBackgroundExecutor.submit(new Runnable() {
@Override
public void run() {
try {
ActivityManager.getService().closeSystemDialogs(reason);
} catch (RemoteException e) {
Log.w(TAG, "Failed to close system windows", e);
}
}
});
public void closeSystemWindows(final String reason) {
try {
ActivityManager.getService().closeSystemDialogs(reason);
} catch (RemoteException e) {
Log.w(TAG, "Failed to close system windows", e);
}
}
/**
* Removes a task by id.
*/
public void removeTask(final int taskId) {
mBackgroundExecutor.submit(new Runnable() {
@Override
public void run() {
try {
ActivityTaskManager.getService().removeTask(taskId);
} catch (RemoteException e) {
Log.w(TAG, "Failed to remove task=" + taskId, e);
}
}
});
try {
ActivityTaskManager.getService().removeTask(taskId);
} catch (RemoteException e) {
Log.w(TAG, "Failed to remove task=" + taskId, e);
}
}
/**
* Removes all the recent tasks.
*/
public void removeAllRecentTasks() {
mBackgroundExecutor.submit(new Runnable() {
@Override
public void run() {
try {
ActivityTaskManager.getService().removeAllVisibleRecentTasks();
} catch (RemoteException e) {
Log.w(TAG, "Failed to remove all tasks", e);
}
}
});
}
/**
* Cancels the current window transtion to/from Recents for the given task id.
*/
public void cancelWindowTransition(int taskId) {
try {
ActivityTaskManager.getService().cancelTaskWindowTransition(taskId);
ActivityTaskManager.getService().removeAllVisibleRecentTasks();
} catch (RemoteException e) {
Log.w(TAG, "Failed to cancel window transition for task=" + taskId, e);
Log.w(TAG, "Failed to remove all tasks", e);
}
}

View File

@@ -1,61 +0,0 @@
/*
* Copyright (C) 2017 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.systemui.shared.system;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* Offloads work from other threads by running it in a background thread.
*/
public class BackgroundExecutor {
private static final BackgroundExecutor sInstance = new BackgroundExecutor();
private final ExecutorService mExecutorService = Executors.newFixedThreadPool(2);
/**
* @return the static instance of the background executor.
*/
public static BackgroundExecutor get() {
return sInstance;
}
/**
* Runs the given {@param callable} on one of the background executor threads.
*/
public <T> Future<T> submit(Callable<T> callable) {
return mExecutorService.submit(callable);
}
/**
* Runs the given {@param runnable} on one of the background executor threads.
*/
public Future<?> submit(Runnable runnable) {
return mExecutorService.submit(runnable);
}
/**
* Runs the given {@param runnable} on one of the background executor threads. Return
* {@param result} when the future is resolved.
*/
public <T> Future<T> submit(Runnable runnable, T result) {
return mExecutorService.submit(runnable, result);
}
}

View File

@@ -1,109 +0,0 @@
/*
* Copyright (C) 2018 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.systemui.shared.system;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.RecordingCanvas;
import android.view.View;
import android.view.ViewRootImpl;
import android.view.WindowCallbacks;
public class WindowCallbacksCompat {
private final WindowCallbacks mWindowCallbacks = new WindowCallbacks() {
@Override
public void onWindowSizeIsChanging(Rect newBounds, boolean fullscreen, Rect systemInsets,
Rect stableInsets) {
WindowCallbacksCompat.this.onWindowSizeIsChanging(newBounds, fullscreen, systemInsets,
stableInsets);
}
@Override
public void onWindowDragResizeStart(Rect initialBounds, boolean fullscreen,
Rect systemInsets, Rect stableInsets, int resizeMode) {
WindowCallbacksCompat.this.onWindowDragResizeStart(initialBounds, fullscreen,
systemInsets, stableInsets, resizeMode);
}
@Override
public void onWindowDragResizeEnd() {
WindowCallbacksCompat.this.onWindowDragResizeEnd();
}
@Override
public boolean onContentDrawn(int offsetX, int offsetY, int sizeX, int sizeY) {
return WindowCallbacksCompat.this.onContentDrawn(offsetX, offsetY, sizeX, sizeY);
}
@Override
public void onRequestDraw(boolean reportNextDraw) {
WindowCallbacksCompat.this.onRequestDraw(reportNextDraw);
}
@Override
public void onPostDraw(RecordingCanvas canvas) {
WindowCallbacksCompat.this.onPostDraw(canvas);
}
};
private final View mView;
public WindowCallbacksCompat(View view) {
mView = view;
}
public void onWindowSizeIsChanging(Rect newBounds, boolean fullscreen, Rect systemInsets,
Rect stableInsets) { }
public void onWindowDragResizeStart(Rect initialBounds, boolean fullscreen, Rect systemInsets,
Rect stableInsets, int resizeMode) { }
public void onWindowDragResizeEnd() { }
public boolean onContentDrawn(int offsetX, int offsetY, int sizeX, int sizeY) {
return false;
}
public void onRequestDraw(boolean reportNextDraw) {
if (reportNextDraw) {
reportDrawFinish();
}
}
public void onPostDraw(Canvas canvas) { }
public void reportDrawFinish() {
mView.getViewRootImpl().reportDrawFinish();
}
public boolean attach() {
ViewRootImpl root = mView.getViewRootImpl();
if (root != null) {
root.addWindowCallbacks(mWindowCallbacks);
root.requestInvalidateRootRenderNode();
return true;
}
return false;
}
public void detach() {
ViewRootImpl root = mView.getViewRootImpl();
if (root != null) {
root.removeWindowCallbacks(mWindowCallbacks);
}
}
}

View File

@@ -35,9 +35,6 @@ import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.statusbar.phone.StatusBar;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.inject.Inject;
@@ -48,7 +45,6 @@ import javax.inject.Inject;
public class ActionProxyReceiver extends BroadcastReceiver {
private static final String TAG = "ActionProxyReceiver";
private static final int CLOSE_WINDOWS_TIMEOUT_MILLIS = 3000;
private final StatusBar mStatusBar;
private final ActivityManagerWrapper mActivityManagerWrapper;
private final ScreenshotSmartActions mScreenshotSmartActions;
@@ -65,14 +61,7 @@ public class ActionProxyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, final Intent intent) {
Runnable startActivityRunnable = () -> {
try {
mActivityManagerWrapper.closeSystemWindows(
SYSTEM_DIALOG_REASON_SCREENSHOT).get(
CLOSE_WINDOWS_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
} catch (TimeoutException | InterruptedException | ExecutionException e) {
Log.e(TAG, "Unable to share screenshot", e);
return;
}
mActivityManagerWrapper.closeSystemWindows(SYSTEM_DIALOG_REASON_SCREENSHOT);
PendingIntent actionIntent = intent.getParcelableExtra(EXTRA_ACTION_INTENT);
ActivityOptions opts = ActivityOptions.makeBasic();

View File

@@ -24,14 +24,12 @@ import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASO
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.PendingIntent;
import android.content.Context;
@@ -54,8 +52,6 @@ import org.mockito.stubbing.Answer;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@RunWith(AndroidTestingRunner.class)
@@ -67,8 +63,6 @@ public class ActionProxyReceiverTest extends SysuiTestCase {
@Mock
private ActivityManagerWrapper mMockActivityManagerWrapper;
@Mock
private Future mMockFuture;
@Mock
private ScreenshotSmartActions mMockScreenshotSmartActions;
@Mock
private PendingIntent mMockPendingIntent;
@@ -80,9 +74,6 @@ public class ActionProxyReceiverTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
mIntent = new Intent(mContext, ActionProxyReceiver.class)
.putExtra(ScreenshotController.EXTRA_ACTION_INTENT, mMockPendingIntent);
when(mMockActivityManagerWrapper.closeSystemWindows(anyString())).thenReturn(mMockFuture);
when(mMockFuture.get(anyLong(), any(TimeUnit.class))).thenReturn(null);
}
@Test