Merge "Refactor SystemServicesProxy to manage ITaskStackListener locally" into nyc-dev

This commit is contained in:
Jaewan Kim
2016-03-24 01:31:40 +00:00
committed by Android (Google) Code Review
5 changed files with 200 additions and 179 deletions

View File

@@ -180,7 +180,7 @@ public class Recents extends SystemUI
@Override
public void start() {
sDebugFlags = new RecentsDebugFlags(mContext);
sSystemServicesProxy = new SystemServicesProxy(mContext);
sSystemServicesProxy = SystemServicesProxy.getInstance(mContext);
sTaskLoader = new RecentsTaskLoader(mContext);
sConfiguration = new RecentsConfiguration(mContext);
mHandler = new Handler();

View File

@@ -20,7 +20,6 @@ import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.ITaskStackListener;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ActivityNotFoundException;
import android.content.Context;
@@ -59,6 +58,7 @@ import com.android.systemui.recents.events.ui.DraggingInRecentsEvent;
import com.android.systemui.recents.misc.DozeTrigger;
import com.android.systemui.recents.misc.ForegroundThread;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
import com.android.systemui.recents.model.RecentsTaskLoadPlan;
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.model.Task;
@@ -95,37 +95,13 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
public final static String RECENTS_ACTIVITY = "com.android.systemui.recents.RecentsActivity";
/**
* An implementation of ITaskStackListener, that allows us to listen for changes to the system
* An implementation of TaskStackListener, that allows us to listen for changes to the system
* task stacks and update recents accordingly.
*/
class TaskStackListenerImpl extends ITaskStackListener.Stub implements Runnable {
Handler mHandler;
public TaskStackListenerImpl(Handler handler) {
mHandler = handler;
}
class TaskStackListenerImpl extends TaskStackListener {
@Override
public void onTaskStackChanged() {
// Debounce any task stack changes
mHandler.removeCallbacks(this);
mHandler.post(this);
}
@Override
public void onActivityPinned() {
}
@Override
public void onPinnedActivityRestartAttempt() {
}
@Override
public void onPinnedStackAnimationEnded() {
}
/** Preloads the next task */
public void run() {
// Preloads the next task
RecentsConfiguration config = Recents.getConfiguration();
if (config.svelteLevel == RecentsConfiguration.SVELTE_NONE) {
RecentsTaskLoader loader = Recents.getTaskLoader();
@@ -201,7 +177,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
ForegroundThread.get();
// Register the task stack listener
mTaskStackListener = new TaskStackListenerImpl(mHandler);
mTaskStackListener = new TaskStackListenerImpl();
SystemServicesProxy ssp = Recents.getSystemServices();
ssp.registerTaskStackListener(mTaskStackListener);

View File

@@ -48,6 +48,9 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.SystemProperties;
@@ -106,6 +109,8 @@ public class SystemServicesProxy {
sRecentsBlacklist.add("com.android.systemui.tv.pip.PipMenuActivity");
}
private static SystemServicesProxy sSystemServicesProxy;
AccessibilityManager mAccm;
ActivityManager mAm;
IActivityManager mIam;
@@ -128,8 +133,58 @@ public class SystemServicesProxy {
Paint mBgProtectionPaint;
Canvas mBgProtectionCanvas;
private final Handler mHandler = new H();
/**
* An abstract class to track task stack changes.
* Classes should implement this instead of {@link android.app.ITaskStackListener}
* to reduce IPC calls from system services. These callbacks will be called on the main thread.
*/
public abstract static class TaskStackListener {
public void onTaskStackChanged() { }
public void onActivityPinned() { }
public void onPinnedActivityRestartAttempt() { }
public void onPinnedStackAnimationEnded() { }
}
/**
* Implementation of {@link android.app.ITaskStackListener} to listen task stack changes from
* ActivityManagerNative.
* This simply passes callbacks to listeners through {@link H}.
* */
private ITaskStackListener.Stub mTaskStackListener = new ITaskStackListener.Stub() {
@Override
public void onTaskStackChanged() throws RemoteException {
mHandler.removeMessages(H.ON_TASK_STACK_CHANGED);
mHandler.sendEmptyMessage(H.ON_TASK_STACK_CHANGED);
}
@Override
public void onActivityPinned() throws RemoteException {
mHandler.removeMessages(H.ON_ACTIVITY_PINNED);
mHandler.sendEmptyMessage(H.ON_ACTIVITY_PINNED);
}
@Override
public void onPinnedActivityRestartAttempt() throws RemoteException{
mHandler.removeMessages(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT);
mHandler.sendEmptyMessage(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT);
}
@Override
public void onPinnedStackAnimationEnded() throws RemoteException {
mHandler.removeMessages(H.ON_PINNED_STACK_ANIMATION_ENDED);
mHandler.sendEmptyMessage(H.ON_PINNED_STACK_ANIMATION_ENDED);
}
};
/**
* List of {@link TaskStackListener} registered from {@link registerTaskStackListener}.
*/
private List<TaskStackListener> mTaskStackListeners = new ArrayList<>();
/** Private constructor */
public SystemServicesProxy(Context context) {
private SystemServicesProxy(Context context) {
mAccm = AccessibilityManager.getInstance(context);
mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
mIam = ActivityManagerNative.getDefault();
@@ -170,6 +225,20 @@ public class SystemServicesProxy {
}
}
/**
* Returns the single instance of the {@link SystemServicesProxy}.
* This should only be called on the main thread.
*/
public static SystemServicesProxy getInstance(Context context) {
if (!Looper.getMainLooper().isCurrentThread()) {
throw new RuntimeException("Must be called on the UI thread");
}
if (sSystemServicesProxy == null) {
sSystemServicesProxy = new SystemServicesProxy(context);
}
return sSystemServicesProxy;
}
/** Returns a list of the recents tasks */
public List<ActivityManager.RecentTaskInfo> getRecentTasks(int numLatestTasks, int userId,
boolean isTopTaskHome, ArraySet<Integer> quietProfileIds) {
@@ -982,14 +1051,21 @@ public class SystemServicesProxy {
}
}
/** Registers a task stack listener with the system. */
public void registerTaskStackListener(ITaskStackListener listener) {
/**
* Registers a task stack listener with the system.
* This should be called on the main thread.
*/
public void registerTaskStackListener(TaskStackListener listener) {
if (mIam == null) return;
try {
mIam.registerTaskStackListener(listener);
} catch (Exception e) {
e.printStackTrace();
mTaskStackListeners.add(listener);
if (mTaskStackListeners.size() == 1) {
// Register mTaskStackListener to IActivityManager only once if needed.
try {
mIam.registerTaskStackListener(mTaskStackListener);
} catch (Exception e) {
Log.w(TAG, "Failed to call registerTaskStackListener", e);
}
}
}
@@ -1039,4 +1115,41 @@ public class SystemServicesProxy {
e.printStackTrace();
}
}
private final class H extends Handler {
private static final int ON_TASK_STACK_CHANGED = 1;
private static final int ON_ACTIVITY_PINNED = 2;
private static final int ON_PINNED_ACTIVITY_RESTART_ATTEMPT = 3;
private static final int ON_PINNED_STACK_ANIMATION_ENDED = 4;
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case ON_TASK_STACK_CHANGED: {
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
mTaskStackListeners.get(i).onTaskStackChanged();
}
break;
}
case ON_ACTIVITY_PINNED: {
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
mTaskStackListeners.get(i).onActivityPinned();
}
break;
}
case ON_PINNED_ACTIVITY_RESTART_ATTEMPT: {
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
mTaskStackListeners.get(i).onPinnedActivityRestartAttempt();
}
break;
}
case ON_PINNED_STACK_ANIMATION_ENDED: {
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
mTaskStackListeners.get(i).onPinnedStackAnimationEnded();
}
break;
}
}
}
}
}

View File

@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.car;
import android.app.ActivityManager;
import android.app.ITaskStackListener;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -33,6 +32,7 @@ import android.view.WindowManager;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
@@ -40,9 +40,7 @@ import com.android.systemui.statusbar.phone.PhoneStatusBar;
* A status bar (and navigation bar) tailored for the automotive use case.
*/
public class CarStatusBar extends PhoneStatusBar {
private SystemServicesProxy mSystemServicesProxy;
private TaskStackListenerImpl mTaskStackListener;
private Handler mHandler;
private CarNavigationBarView mCarNavigationBar;
private CarNavigationBarController mController;
@@ -51,10 +49,8 @@ public class CarStatusBar extends PhoneStatusBar {
@Override
public void start() {
super.start();
mHandler = new Handler();
mTaskStackListener = new TaskStackListenerImpl(mHandler);
mSystemServicesProxy = new SystemServicesProxy(mContext);
mSystemServicesProxy.registerTaskStackListener(mTaskStackListener);
mTaskStackListener = new TaskStackListenerImpl();
SystemServicesProxy.getInstance(mContext).registerTaskStackListener(mTaskStackListener);
registerPackageChangeReceivers();
}
@@ -114,47 +110,16 @@ public class CarStatusBar extends PhoneStatusBar {
}
/**
* An implementation of ITaskStackListener, that listens for changes in the system task
* An implementation of TaskStackListener, that listens for changes in the system task
* stack and notifies the navigation bar.
*/
private class TaskStackListenerImpl extends ITaskStackListener.Stub implements Runnable {
private Handler mHandler;
public TaskStackListenerImpl(Handler handler) {
this.mHandler = handler;
}
@Override
public void onActivityPinned() {
}
@Override
public void onPinnedActivityRestartAttempt() {
}
@Override
public void onPinnedStackAnimationEnded() {
}
private class TaskStackListenerImpl extends TaskStackListener {
@Override
public void onTaskStackChanged() {
mHandler.removeCallbacks(this);
mHandler.post(this);
}
@Override
public void run() {
ensureMainThread();
SystemServicesProxy ssp = Recents.getSystemServices();
ActivityManager.RunningTaskInfo runningTaskInfo = ssp.getTopMostTask();
mController.taskChanged(runningTaskInfo.baseActivity.getPackageName());
}
private void ensureMainThread() {
if (!Looper.getMainLooper().isCurrentThread()) {
throw new RuntimeException("Must be called on the UI thread");
}
}
}
@Override

View File

@@ -21,7 +21,6 @@ import android.app.ActivityManager.StackInfo;
import android.app.ActivityManagerNative;
import android.app.ActivityOptions;
import android.app.IActivityManager;
import android.app.ITaskStackListener;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -38,6 +37,8 @@ import android.os.SystemProperties;
import android.util.Log;
import com.android.systemui.Prefs;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
import java.util.ArrayList;
import java.util.List;
@@ -95,89 +96,6 @@ public class PipManager {
private boolean mIsRecentsShown;
private boolean mIsPipFocusedInRecent;
private final Runnable mOnActivityPinnedRunnable = new Runnable() {
@Override
public void run() {
StackInfo stackInfo = null;
try {
stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
if (stackInfo == null) {
Log.w(TAG, "Cannot find pinned stack");
return;
}
} catch (RemoteException e) {
Log.e(TAG, "getStackInfo failed", e);
return;
}
if (DEBUG) Log.d(TAG, "PINNED_STACK:" + stackInfo);
mPipTaskId = stackInfo.taskIds[stackInfo.taskIds.length - 1];
mPipComponentName = ComponentName.unflattenFromString(
stackInfo.taskNames[stackInfo.taskNames.length - 1]);
// Set state to overlay so we show it when the pinned stack animation ends.
mState = STATE_PIP_OVERLAY;
mCurrentPipBounds = mPipBounds;
launchPipOnboardingActivityIfNeeded();
mMediaSessionManager.addOnActiveSessionsChangedListener(
mActiveMediaSessionListener, null);
updateMediaController(mMediaSessionManager.getActiveSessions(null));
if (mIsRecentsShown) {
// If an activity becomes PIPed again after the fullscreen, the Recents is shown
// behind so we need to resize the pinned stack and show the correct overlay.
resizePinnedStack(STATE_PIP_OVERLAY);
}
for (int i = mListeners.size() - 1; i >= 0; i--) {
mListeners.get(i).onPipEntered();
}
}
};
private final Runnable mOnTaskStackChanged = new Runnable() {
@Override
public void run() {
if (mState != STATE_NO_PIP) {
StackInfo stackInfo = null;
try {
stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
if (stackInfo == null) {
Log.w(TAG, "There is no pinned stack");
closePipInternal(false);
return;
}
} catch (RemoteException e) {
Log.e(TAG, "getStackInfo failed", e);
return;
}
for (int i = stackInfo.taskIds.length - 1; i >= 0; --i) {
if (stackInfo.taskIds[i] == mPipTaskId) {
// PIP task is still alive.
return;
}
}
// PIP task doesn't exist anymore in PINNED_STACK.
closePipInternal(true);
}
}
};
private final Runnable mOnPinnedActivityRestartAttempt = new Runnable() {
@Override
public void run() {
// If PIPed activity is launched again by Launcher or intent, make it fullscreen.
movePipToFullscreen();
}
};
private final Runnable mOnPinnedStackAnimationEnded = new Runnable() {
@Override
public void run() {
switch (mState) {
case STATE_PIP_OVERLAY:
showPipOverlay();
break;
case STATE_PIP_MENU:
showPipMenu();
break;
}
}
};
private final Runnable mResizePinnedStackRunnable = new Runnable() {
@Override
public void run() {
@@ -241,13 +159,7 @@ public class PipManager {
(int) (mRecentsPipBounds.bottom + scaleBy * mRecentsPipBounds.height()));
mActivityManager = ActivityManagerNative.getDefault();
TaskStackListener taskStackListener = new TaskStackListener();
IActivityManager iam = ActivityManagerNative.getDefault();
try {
iam.registerTaskStackListener(taskStackListener);
} catch (RemoteException e) {
Log.e(TAG, "registerTaskStackListener failed", e);
}
SystemServicesProxy.getInstance(context).registerTaskStackListener(mTaskStackListener);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_MEDIA_RESOURCE_GRANTED);
mContext.registerReceiver(mBroadcastReceiver, intentFilter);
@@ -566,33 +478,88 @@ public class PipManager {
return mPipMediaController;
}
private class TaskStackListener extends ITaskStackListener.Stub {
TaskStackListener mTaskStackListener = new TaskStackListener() {
@Override
public void onTaskStackChanged() throws RemoteException {
// Post the message back to the UI thread.
mHandler.post(mOnTaskStackChanged);
public void onTaskStackChanged() {
if (mState != STATE_NO_PIP) {
StackInfo stackInfo = null;
try {
stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
if (stackInfo == null) {
Log.w(TAG, "There is no pinned stack");
closePipInternal(false);
return;
}
} catch (RemoteException e) {
Log.e(TAG, "getStackInfo failed", e);
return;
}
for (int i = stackInfo.taskIds.length - 1; i >= 0; --i) {
if (stackInfo.taskIds[i] == mPipTaskId) {
// PIP task is still alive.
return;
}
}
// PIP task doesn't exist anymore in PINNED_STACK.
closePipInternal(true);
}
}
@Override
public void onActivityPinned() throws RemoteException {
// Post the message back to the UI thread.
public void onActivityPinned() {
if (DEBUG) Log.d(TAG, "onActivityPinned()");
mHandler.post(mOnActivityPinnedRunnable);
StackInfo stackInfo = null;
try {
stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
if (stackInfo == null) {
Log.w(TAG, "Cannot find pinned stack");
return;
}
} catch (RemoteException e) {
Log.e(TAG, "getStackInfo failed", e);
return;
}
if (DEBUG) Log.d(TAG, "PINNED_STACK:" + stackInfo);
mPipTaskId = stackInfo.taskIds[stackInfo.taskIds.length - 1];
mPipComponentName = ComponentName.unflattenFromString(
stackInfo.taskNames[stackInfo.taskNames.length - 1]);
// Set state to overlay so we show it when the pinned stack animation ends.
mState = STATE_PIP_OVERLAY;
mCurrentPipBounds = mPipBounds;
launchPipOnboardingActivityIfNeeded();
mMediaSessionManager.addOnActiveSessionsChangedListener(
mActiveMediaSessionListener, null);
updateMediaController(mMediaSessionManager.getActiveSessions(null));
if (mIsRecentsShown) {
// If an activity becomes PIPed again after the fullscreen, the Recents is shown
// behind so we need to resize the pinned stack and show the correct overlay.
resizePinnedStack(STATE_PIP_OVERLAY);
}
for (int i = mListeners.size() - 1; i >= 0; i--) {
mListeners.get(i).onPipEntered();
}
}
@Override
public void onPinnedActivityRestartAttempt() {
// Post the message back to the UI thread.
if (DEBUG) Log.d(TAG, "onPinnedActivityRestartAttempt()");
mHandler.post(mOnPinnedActivityRestartAttempt);
// If PIPed activity is launched again by Launcher or intent, make it fullscreen.
movePipToFullscreen();
}
@Override
public void onPinnedStackAnimationEnded() {
if (DEBUG) Log.d(TAG, "onPinnedStackAnimationEnded()");
mHandler.post(mOnPinnedStackAnimationEnded);
switch (mState) {
case STATE_PIP_OVERLAY:
showPipOverlay();
break;
case STATE_PIP_MENU:
showPipMenu();
break;
}
}
}
};
/**
* A listener interface to receive notification on changes in PIP.