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

Commit b43a529e authored by Winson Chung's avatar Winson Chung Committed by Android (Google) Code Review
Browse files

Merge changes Icb5ea78e,I1cf97299

* changes:
  Move more calls to the lib.
  Migrating some animation spec logic to shared lib
parents bb6468ba aa357456
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -232,7 +232,7 @@ interface IActivityManager {
            boolean requireFull, in String name, in String callerPackage);
    void addPackageDependency(in String packageName);
    void killApplication(in String pkg, int appId, int userId, in String reason);
    void closeSystemDialogs(in String reason);
    oneway void closeSystemDialogs(in String reason);
    Debug.MemoryInfo[] getProcessMemoryInfo(in int[] pids);
    void killApplicationProcess(in String processName, int uid);
    int startActivityIntentSender(in IApplicationThread caller,
@@ -450,9 +450,8 @@ interface IActivityManager {
    int checkPermissionWithToken(in String permission, int pid, int uid,
            in IBinder callerToken);
    void registerTaskStackListener(in ITaskStackListener listener);
    void unregisterTaskStackListener(in ITaskStackListener listener);


    // Start of M transactions
    void notifyCleartextNetwork(int uid, in byte[] firstPacket);
    int createStackOnDisplay(int displayId);
    void setTaskResizeable(int taskId, int resizeableMode);
@@ -618,7 +617,6 @@ interface IActivityManager {
     * @return Returns true if the configuration was updated.
     */
    boolean updateDisplayOverrideConfiguration(in Configuration values, int displayId);
    void unregisterTaskStackListener(ITaskStackListener listener);
    void moveStackToDisplay(int stackId, int displayId);
    boolean requestAutofillData(in IAssistDataReceiver receiver, in Bundle receiverExtras,
                                in IBinder activityToken, int flags);
+84 −0
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.recents.view;

import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.view.AppTransitionAnimationSpec;
import android.view.IAppTransitionAnimationSpecsFuture;

import java.util.List;
import java.util.concurrent.FutureTask;

/**
 * To be implemented by a particular animation to asynchronously provide the animation specs for a
 * particular transition.
 */
public abstract class AppTransitionAnimationSpecsFuture {

    private final Handler mHandler;
    private FutureTask<List<AppTransitionAnimationSpec>> mComposeTask = new FutureTask<>(() -> {
        synchronized (AppTransitionAnimationSpecsFuture.this) {
            return composeSpecs();
        }
    });

    private final IAppTransitionAnimationSpecsFuture mFuture =
            new IAppTransitionAnimationSpecsFuture.Stub() {
        @Override
        public AppTransitionAnimationSpec[] get() throws RemoteException {
            try {
                if (!mComposeTask.isDone()) {
                    mHandler.post(mComposeTask);
                }
                List<AppTransitionAnimationSpec> specs = mComposeTask.get();
                if (specs == null) {
                    return null;
                }

                AppTransitionAnimationSpec[] arr = new AppTransitionAnimationSpec[specs.size()];
                specs.toArray(arr);
                return arr;
            } catch (Exception e) {
                return null;
            }
        }
    };

    public AppTransitionAnimationSpecsFuture(Handler handler) {
        mHandler = handler;
    }

    /**
     * Returns the future to handle the call from window manager.
     */
    public final IAppTransitionAnimationSpecsFuture getFuture() {
        return mFuture;
    }

    /**
     * Called ahead of the future callback to compose the specs to be returned in the future.
     */
    public final void composeSpecsSynchronous() {
        if (Looper.myLooper() != mHandler.getLooper()) {
            throw new RuntimeException("composeSpecsSynchronous() called from wrong looper");
        }
        mComposeTask.run();
    }

    public abstract List<AppTransitionAnimationSpec> composeSpecs();
}
+117 −0
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.recents.view;

import android.app.ActivityOptions;
import android.app.ActivityOptions.OnAnimationStartedListener;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.GraphicBuffer;
import android.os.Bundle;
import android.os.Handler;
import android.os.IRemoteCallback;
import android.os.RemoteException;
import android.view.DisplayListCanvas;
import android.view.RenderNode;
import android.view.ThreadedRenderer;
import android.view.View;

import java.util.function.Consumer;

/**
 * A helper class to create transitions to/from an App to Recents.
 */
public class RecentsTransition {

    /**
     * Creates a new transition aspect scaled transition activity options.
     */
    public static ActivityOptions createAspectScaleAnimation(Context context, Handler handler,
            boolean scaleUp, AppTransitionAnimationSpecsFuture animationSpecsFuture,
            OnAnimationStartedListener animationStartCallback) {
        final OnAnimationStartedListener animStartedListener = new OnAnimationStartedListener() {
            private boolean mHandled;

            @Override
            public void onAnimationStarted() {
                // OnAnimationStartedListener can be called numerous times, so debounce here to
                // prevent multiple callbacks
                if (mHandled) {
                    return;
                }
                mHandled = true;

                if (animationStartCallback != null) {
                    animationStartCallback.onAnimationStarted();
                }
            }
        };
        final ActivityOptions opts = ActivityOptions.makeMultiThumbFutureAspectScaleAnimation(
                context, handler,
                animationSpecsFuture != null ? animationSpecsFuture.getFuture() : null,
                animStartedListener, scaleUp);
        return opts;
    }

    /**
     * Wraps a animation-start callback in a binder that can be called from window manager.
     */
    public static IRemoteCallback wrapStartedListener(Handler handler,
            OnAnimationStartedListener listener) {
        if (listener == null) {
            return null;
        }
        return new IRemoteCallback.Stub() {
            @Override
            public void sendResult(Bundle data) throws RemoteException {
                handler.post(listener::onAnimationStarted);
            }
        };
    }

    /**
     * @return a {@link GraphicBuffer} with the {@param view} drawn into it. Result can be null if
     *         we were unable to allocate a hardware bitmap.
     */
    public static GraphicBuffer drawViewIntoGraphicBuffer(int width, int height, View view,
            float scale, int eraseColor) {
        final Bitmap hwBitmap = createHardwareBitmap(width, height, (c) -> {
            c.scale(scale, scale);
            if (eraseColor != 0) {
                c.drawColor(eraseColor);
            }
            if (view != null) {
                view.draw(c);
            }
        });
        return hwBitmap != null ? hwBitmap.createGraphicBufferHandle() : null;
    }

    /**
     * @return a hardware {@link Bitmap} after being drawn with the {@param consumer}. Result can be
     *         null if we were unable to allocate a hardware bitmap.
     */
    public static Bitmap createHardwareBitmap(int width, int height, Consumer<Canvas> consumer) {
        RenderNode node = RenderNode.create("RecentsTransition", null);
        node.setLeftTopRightBottom(0, 0, width, height);
        node.setClipToBounds(false);
        DisplayListCanvas c = node.start(width, height);
        consumer.accept(c);
        node.end(c);
        return ThreadedRenderer.createHardwareBitmap(node, width, height);
    }
}
+50 −0
Original line number Diff line number Diff line
@@ -50,11 +50,13 @@ public class ActivityManagerWrapper {

    private final PackageManager mPackageManager;
    private final IconDrawableFactory mDrawableFactory;
    private final BackgroundExecutor mBackgroundExecutor;

    private ActivityManagerWrapper() {
        final Context context = AppGlobals.getInitialApplication();
        mPackageManager = context.getPackageManager();
        mDrawableFactory = IconDrawableFactory.newInstance(context);
        mBackgroundExecutor = BackgroundExecutor.get();
    }

    public static ActivityManagerWrapper getInstance() {
@@ -198,4 +200,52 @@ public class ActivityManagerWrapper {
        }
        return label;
    }

    /**
     * Requests that the system close any open system windows (including other SystemUI).
     */
    public void closeSystemWindows(String reason) {
        mBackgroundExecutor.submit(() -> {
            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(int taskId) {
        mBackgroundExecutor.submit(() -> {
            try {
                ActivityManager.getService().removeTask(taskId);
            } catch (RemoteException e) {
                Log.w(TAG, "Failed to remove task=" + taskId, e);
            }
        });
    }

    /**
     * Cancels the current window transtion to/from Recents for the given task id.
     */
    public void cancelWindowTransition(int taskId) {
        try {
            ActivityManager.getService().cancelTaskWindowTransition(taskId);
        } catch (RemoteException e) {
            Log.w(TAG, "Failed to cancel window transition for task=" + taskId, e);
        }
    }

    /**
     * Cancels the current thumbnail transtion to/from Recents for the given task id.
     */
    public void cancelThumbnailTransition(int taskId) {
        try {
            ActivityManager.getService().cancelTaskThumbnailTransition(taskId);
        } catch (RemoteException e) {
            Log.w(TAG, "Failed to cancel window transition for task=" + taskId, e);
        }
    }
}
+45 −0
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.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 runnable} on one of the background executor threads.
     */
    public Future<?> submit(Runnable runnable) {
        return mExecutorService.submit(runnable);
    }
}
Loading