Merge "Making some ActivityManager API calls synchronous"
This commit is contained in:
committed by
Android (Google) Code Review
commit
e94ff36994
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user