Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e94ff369 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Making some ActivityManager API calls synchronous"

parents 29f5ff87 eae1c34e
Loading
Loading
Loading
Loading
+19 −104
Original line number Diff line number Diff line
@@ -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,9 +148,6 @@ 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());
@@ -169,51 +155,6 @@ public class ActivityManagerWrapper {
            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();
        }
        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;
    }

    /**
     * Starts the recents activity. The caller should manage the thread on which this is called.
@@ -342,61 +283,35 @@ 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() {
    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);
        }
    }
        });
    }

    /**
     * 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);
        } catch (RemoteException e) {
            Log.w(TAG, "Failed to cancel window transition for task=" + taskId, e);
        }
    }

    /**
     * @return whether screen pinning is active.
+0 −61
Original line number Diff line number Diff line
/*
 * 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);
    }
}
+0 −109
Original line number Diff line number Diff line
/*
 * 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);
        }
    }
}
+1 −12
Original line number Diff line number Diff line
@@ -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();
+0 −9
Original line number Diff line number Diff line
@@ -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