Skip to content

Instantly share code, notes, and snippets.

@PatoFlamejanteTV
Created November 27, 2024 17:00
Show Gist options
  • Save PatoFlamejanteTV/654e95c4be9e76856868a1e9d17d4035 to your computer and use it in GitHub Desktop.
Save PatoFlamejanteTV/654e95c4be9e76856868a1e9d17d4035 to your computer and use it in GitHub Desktop.
Leaked Samsung code.
/*
* Copyright (C) 2013 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.server.am;
import static android.Manifest.permission.START_ANY_ACTIVITY;
import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static com.android.server.am.ActivityManagerDebugConfig.*;
//start SEC_PRODUCT_FEATURE_COMMON_SUPPORT_SE_FOR_ANDROID
import static android.content.pm.PackageManager.PERMISSION_DENIED;
//end SEC_PRODUCT_FEATURE_COMMON_SUPPORT_SE_FOR_ANDROID
import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
import static com.android.server.am.ActivityStack.ActivityState.*;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
import android.Manifest;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.StackInfo;
import android.app.ActivityOptions;
import android.app.AlertDialog;
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.IActivityContainer;
import android.app.IActivityContainerCallback;
import android.app.IActivityManager;
import android.app.IApplicationThread;
import android.app.PendingIntent;
import android.app.ProfilerInfo;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.IActivityManager.WaitResult;
import android.app.ResultInfo;
import android.app.StatusBarManager;
import android.app.admin.IDevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.content.ActivityNotFoundException;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
import android.hardware.display.DisplayManagerGlobal;
import android.hardware.display.VirtualDisplay;
import android.hardware.input.InputManager;
import android.hardware.input.InputManagerInternal;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.TransactionTooLargeException;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.WorkSource;
import android.provider.MediaStore;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.service.voice.IVoiceInteractionSession;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.EventLog;
import android.util.Slog;
import android.util.SparseArray;
import android.util.BoostFramework;
import android.util.SparseIntArray;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.InputEvent;
import android.view.Surface;
import android.view.WindowManagerImpl;
/* { SRC-TJ AppLock */
import com.android.internal.app.AppLockPolicy;
/* SRC-TJ AppLock } */
import com.android.internal.app.HeavyWeightSwitcherActivity;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.content.ReferrerIntent;
import com.android.internal.os.TransferPipe;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.ArrayUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.LocalServices;
import com.android.server.am.ActivityStack.ActivityState;
import com.android.server.wm.WindowManagerService;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
/* { BikeMode Implementation */
import com.sec.android.app.CscFeature;
import com.sec.android.app.CscFeatureTagVoiceCall;
/* BikeMode Implementation } */
// SecProductFeature_KNOX.SEC_PRODUCT_FEATURE_KNOX_SUPPORT_MDM {
import android.app.ActivityManagerNative;
import android.app.enterprise.ContextInfo;
import android.app.enterprise.IApplicationPolicy;
import android.app.enterprise.IRestrictionPolicy;
import android.app.enterprise.IPasswordPolicy;
import android.app.enterprise.kioskmode.KioskMode;
import android.app.enterprise.kioskmode.IKioskMode;
import android.app.enterprise.PasswordPolicy;
import android.app.enterprise.RestrictionPolicy;
import android.os.StrictMode;
import android.preference.PreferenceActivity;
import android.sec.enterprise.ApplicationPolicy;
import android.sec.enterprise.auditlog.AuditEvents;
import android.sec.enterprise.auditlog.AuditLog;
import android.sec.enterprise.EnterpriseDeviceManager;
import android.app.enterprise.ISecurityPolicy;
import com.sec.android.app.SecProductFeature_KNOX;
import static android.sec.enterprise.RestrictionPolicy.SVOICE_PACKAGE1;
import static android.sec.enterprise.RestrictionPolicy.SVOICE_PACKAGE2;
// } SecProductFeature_KNOX.SEC_PRODUCT_FEATURE_KNOX_SUPPORT_MDM
import com.sec.android.app.SecProductFeature_COMMON;
/* { Multi-Window */
import static com.samsung.android.multiwindow.MultiWindowFeatures.DESKTOPMODE_ENABLED;
import java.util.Collection;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.view.ContextThemeWrapper;
import android.view.WindowManager;
import android.widget.Toast;
import com.android.server.wm.AppTransition;
import com.android.server.wm.MultiWindowTransition;
import com.samsung.android.multiwindow.MultiWindowApplicationInfos;
import com.samsung.android.multiwindow.MultiWindowStyle;
import com.samsung.android.multiwindow.MultiWindowTab;
import com.samsung.android.multiwindow.MultiWindowFeatures;
import android.view.WindowManagerPolicy;
/* Multi-Window } */
/* { Dual-Screen */
import static android.view.Display.DUAL_SCREEN_TYPE_MAX;
import static com.android.server.am.ActivityManagerService.DEBUG_DUALSCREEN;
import static com.android.server.am.ActivityRecord.SAMSUNG_HOME_ACTIVITY_TYPE;
import static com.android.server.am.ActivityStackSupervisor.SUPPORT_EXPANDED_MODE;
import static com.samsung.android.multidisplay.dualscreen.DualScreenFeatures.DESKTOP_MODE_ENABLED;
import static com.samsung.android.multidisplay.dualscreen.DualScreenFeatures.DUALSCREEN_ENABLED;
import com.samsung.android.dualscreen.DualScreen;
import com.samsung.android.dualscreen.DualScreenLaunchParams;
import com.samsung.android.dualscreen.DualScreenManager;
import com.samsung.android.multidisplay.common.UnRestrictedArrayList;
import com.samsung.android.multidisplay.dualscreen.DualScreenFeatures;
import com.samsung.android.multidisplay.dualscreen.DualScreenSettings;
import com.samsung.android.multidisplay.dualscreen.DualScreenUtils;
import java.util.HashMap;
/* Dual-Screen } */
/* { Edge-Screen */
import com.samsung.android.cocktailbar.CocktailBarFeatures;
/* Edge-Screen } */
/* { KNOX_BBC */
import android.os.PersonaManager;
import android.os.IPersonaManager;
import android.os.PersonaManager.KnoxContainerVersion;
import com.android.server.pm.PersonaManagerService;
/* KNOX_BBC } */
/* { SRUK DSS */
import android.os.DssHelper;
import static android.os.DssHelper.DSS_ENABLED;
/* SRUK DSS } */
/* { CuVasChecker */
import com.sec.android.app.CscFeature;
import android.os.SystemProperties;
import android.telephony.TelephonyManager;
import com.sec.android.app.CscFeatureTagFramework;
import com.sec.android.app.SecProductFeature_RIL;
import com.sec.android.app.SecProductFeature_COMMON;
import com.samsung.android.telephony.MultiSimManager;
import android.telephony.SubscriptionManager;
import com.android.internal.telephony.TelephonyProperties;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
/* CuVasChecker } */
import com.sec.android.app.CscFeature;
import com.sec.android.app.CscFeatureTagCommon;
import com.sec.android.app.SecProductFeature_FRAMEWORK;
// [Sprint ItsOn START
import com.itsoninc.android.ItsOnOemApi;
// Sprint ItsON END]
/* { Virtual-Screen */
import android.util.DisplayMetrics;
import com.samsung.android.multidisplay.virtualscreen.VirtualScreenLaunchParams;
import static com.samsung.android.multidisplay.virtualscreen.VirtualScreenFeatures.TAG_VIRTUALSCREEN;
import static com.samsung.android.multidisplay.virtualscreen.VirtualScreenFeatures.VIRTUALSCREEN_ENABLED;
/* Virtual-Screen } */
/* { Multi-Display */
import static com.samsung.android.multidisplay.common.MultiDisplayFeatures.MULTIDISPLAY_ENABLED;
/* Multi-Display } */
/* { Multi-Density */
import com.samsung.android.multidensity.MultiDensityGlobal;
import static com.samsung.android.multidensity.MultiDensityGlobal.MULTI_DENSITY_ENABLED;
/* Multi-Density } */
public final class ActivityStackSupervisor implements DisplayListener {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStackSupervisor" : TAG_AM;
private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
private static final String TAG_CONTAINERS = TAG + POSTFIX_CONTAINERS;
private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
private static final String TAG_IDLE = TAG + POSTFIX_IDLE;
private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE;
private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE;
private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
private static final String TAG_STACK = TAG + POSTFIX_STACK;
private static final String TAG_STATES = TAG + POSTFIX_STATES;
private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
private static final String TAG_VISIBLE_BEHIND = TAG + POSTFIX_VISIBLE_BEHIND;
private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
public static final int HOME_STACK_ID = 0;
/* { Multi-Window */
static final boolean SAFE_DEBUG = Debug.isProductShip() == 1 ? false : true;
public static final int HOME_STACK_TYPE = 1;
public static final int NORMAL_APP_STACK_TYPE = 2;
public static final int FLOATING_APP_STACK_TYPE = 3;
/* { Dual-Screen */
public static final int SAMSUNG_HOME_STACK_TYPE = 4;
public static final int EXPANDED_HOME_STACK_TYPE = 6;
/* Dual-Screen } */
/* Multi-Window } */
/* { Dual-Screen */
public static final int SAMSUNG_HOME_STACK_ID = 1;
public static final int EXPANDED_HOME_STACK_ID = 2;
public static final boolean SUPPORT_EXPANDED_MODE = DualScreenFeatures.SUPPORT_EXPANDED_MODE && DUALSCREEN_ENABLED;
public static final int DUAL_SCREEN_ZONE_UNKNOWN = 0;
public static final int DUAL_SCREEN_ZONE_MAIN = 0x01;
public static final int DUAL_SCREEN_ZONE_SUB = 0x02;
public static final int DUAL_SCREEN_ZONE_FULL = DUAL_SCREEN_ZONE_MAIN|DUAL_SCREEN_ZONE_SUB;
/* Dual-Screen } */
/** How long we wait until giving up on the last activity telling us it is idle. */
static final int IDLE_TIMEOUT = 10 * 1000;
/** How long we can hold the sleep wake lock before giving up. */
static final int SLEEP_TIMEOUT = 5 * 1000;
// How long we can hold the launch wake lock before giving up.
static final int LAUNCH_TIMEOUT = 10 * 1000;
static final int IDLE_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG;
static final int IDLE_NOW_MSG = FIRST_SUPERVISOR_STACK_MSG + 1;
static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_STACK_MSG + 2;
static final int SLEEP_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 3;
static final int LAUNCH_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 4;
public BoostFramework mPerf_iop = null;
public BoostFramework mPerfBoost = null;
public BoostFramework mPerfPack = null;
public boolean mIsPerfBoostEnabled = false;
public boolean mIsperfDisablepackingEnable = false;
public int lBoostTimeOut = 0;
public int lDisPackTimeOut = 0;
public int lBoostCpuParamVal[];
public int lBoostPackParamVal[];
static final int HANDLE_DISPLAY_ADDED = FIRST_SUPERVISOR_STACK_MSG + 5;
static final int HANDLE_DISPLAY_CHANGED = FIRST_SUPERVISOR_STACK_MSG + 6;
static final int HANDLE_DISPLAY_REMOVED = FIRST_SUPERVISOR_STACK_MSG + 7;
static final int CONTAINER_CALLBACK_VISIBILITY = FIRST_SUPERVISOR_STACK_MSG + 8;
static final int LOCK_TASK_START_MSG = FIRST_SUPERVISOR_STACK_MSG + 9;
static final int LOCK_TASK_END_MSG = FIRST_SUPERVISOR_STACK_MSG + 10;
static final int CONTAINER_CALLBACK_TASK_LIST_EMPTY = FIRST_SUPERVISOR_STACK_MSG + 11;
static final int LAUNCH_TASK_BEHIND_COMPLETE = FIRST_SUPERVISOR_STACK_MSG + 12;
static final int SHOW_LOCK_TASK_ESCAPE_MESSAGE_MSG = FIRST_SUPERVISOR_STACK_MSG + 13;
/* { Multi-Window */
static final int SHOW_TOAST_UNABLE_PENWINDOW_MSG = FIRST_SUPERVISOR_STACK_MSG + 100;
static final int SHOW_TOAST_NOT_SUPPORT_CURRENT_SCREEN_MSG = FIRST_SUPERVISOR_STACK_MSG + 101;
/* Multi-Window } */
/* { Dual-Screen */
static final int FIXED_SCREEN_MODE_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 200;
static final int RELEASE_FIXED_SCREEN_MODE_DIALG_MSG = FIRST_SUPERVISOR_STACK_MSG + 201;
/* Dual-Screen } */
private final static String VIRTUAL_DISPLAY_BASE_NAME = "ActivityViewVirtualDisplay";
private static final String LOCK_TASK_TAG = "Lock-to-App";
/* { CustomStartingWindow */
public static final boolean CUSTOM_STARTING_WINDOW = SecProductFeature_FRAMEWORK.SEC_PRODUCT_FEATURE_FRAMEWORK_SUPPORT_CUSTOM_STARTING_WINDOW;
/* CustomStartingWindow } */
// Activity actions an app cannot start if it uses a permission which is not granted.
private static final ArrayMap<String, String> ACTION_TO_RUNTIME_PERMISSION =
new ArrayMap<>();
static {
ACTION_TO_RUNTIME_PERMISSION.put(MediaStore.ACTION_IMAGE_CAPTURE,
Manifest.permission.CAMERA);
ACTION_TO_RUNTIME_PERMISSION.put(MediaStore.ACTION_VIDEO_CAPTURE,
Manifest.permission.CAMERA);
ACTION_TO_RUNTIME_PERMISSION.put(Intent.ACTION_CALL,
Manifest.permission.CALL_PHONE);
}
/** Action restriction: launching the activity is not restricted. */
private static final int ACTIVITY_RESTRICTION_NONE = 0;
/** Action restriction: launching the activity is restricted by a permission. */
private static final int ACTIVITY_RESTRICTION_PERMISSION = 1;
/** Action restriction: launching the activity is restricted by an app op. */
private static final int ACTIVITY_RESTRICTION_APPOP = 2;
//KNOX_CONTAINER2.3_START
private final static String FORWARD_INTENT_TO_MANAGED_PROFILE = "com.android.internal.app.ForwardIntentToManagedProfile";
/* { KNOX_BBC */
private static final String BBC_METADATA = "com.samsung.android.knoxenabled";
/* KNOX_BBC } */
/* { KNOX Mode */
private static boolean isLaunchKnoxApps = false;
/* KNOX Mode }*/
private PersonaManagerService mPersonaManager = null;
//KNOX_CONTAINER2.3_END
/** Status Bar Service **/
private IBinder mToken = new Binder();
private IStatusBarService mStatusBarService;
private IDevicePolicyManager mDevicePolicyManager;
// For debugging to make sure the caller when acquiring/releasing our
// wake lock is the system process.
static final boolean VALIDATE_WAKE_LOCK_CALLER = false;
final ActivityManagerService mService;
private final RecentTasks mRecentTasks;
final ActivityStackSupervisorHandler mHandler;
/** Short cut */
WindowManagerService mWindowManager;
DisplayManager mDisplayManager;
/** Identifier counter for all ActivityStacks */
private int mLastStackId = HOME_STACK_ID;
/** Task identifier that activities are currently being started in. Incremented each time a
* new task is created. */
private int mCurTaskId = 0;
/** The current user */
private int mCurrentUser;
/** The stack containing the launcher app. Assumed to always be attached to
* Display.DEFAULT_DISPLAY. */
private ActivityStack mHomeStack;
/** The stack currently receiving input or launching the next activity. */
private ActivityStack mFocusedStack;
/** If this is the same as mFocusedStack then the activity on the top of the focused stack has
* been resumed. If stacks are changing position this will hold the old stack until the new
* stack becomes resumed after which it will be set to mFocusedStack. */
private ActivityStack mLastFocusedStack;
/* { Multi-Window */
private ActivityStack mNonFloatingFocusedStack;
private ActivityStack mSpecificFloatingStack;
/* Multi-Window } */
/* { AppCore */
boolean mChangedFocusedStackWhileSleeping = false;
/* AppCore } */
/* { Dual-Screen */
/** If non-empty then the tasks specified remains in front and no other tasks may be started
* until the tasks exit or #stopLockTaskMode() is called.
* These tasks are coupled by each other and non-empty only if coupled-task screen pinned. */
ArrayList<TaskRecord> mUniversalTaskHistory = new ArrayList<TaskRecord>();
private ActivityStack mSamsungHomeStack;
private ActivityStack mExpandedHomeStack;
private ActivityStack[] mHomeStacks = new ActivityStack[Display.DUAL_SCREEN_TYPE_MAX];
private ActivityStack[] mFrontStacks = new ActivityStack[Display.DUAL_SCREEN_TYPE_MAX];
private ActivityStack[] mLastFocusedStacks = new ActivityStack[Display.DUAL_SCREEN_TYPE_MAX];
private ActivityStack[] mNonFloatingFocusedStacks = new ActivityStack[Display.DUAL_SCREEN_TYPE_MAX];
HashMap<ActivityRecord, DualScreen> mPendingActivitiesToMove = new HashMap<ActivityRecord, DualScreen>();
TaskRecord mSamsungHomeTask = null;
TaskRecord mExpandedHomeTask = null;
boolean mNeedToMovePrevSamsungHomeTasks = false;
TaskRecord mFixedTask;
boolean[] mChangedFrontStackWhileSleeping = new boolean[Display.DUAL_SCREEN_TYPE_MAX];
/* Dual-Screen } */
/** List of activities that are waiting for a new activity to become visible before completing
* whatever operation they are supposed to do. */
final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<>();
/** List of processes waiting to find out about the next visible activity. */
final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible = new ArrayList<>();
/** List of processes waiting to find out about the next launched activity. */
final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched = new ArrayList<>();
/** List of activities that are ready to be stopped, but waiting for the next activity to
* settle down before doing so. */
final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<>();
/** List of activities that are ready to be finished, but waiting for the previous activity to
* settle down before doing so. It contains ActivityRecord objects. */
final ArrayList<ActivityRecord> mFinishingActivities = new ArrayList<>();
/** List of activities that are in the process of going to sleep. */
final ArrayList<ActivityRecord> mGoingToSleepActivities = new ArrayList<>();
/** Used on user changes */
final ArrayList<UserState> mStartingUsers = new ArrayList<>();
/** Used to queue up any background users being started */
final ArrayList<UserState> mStartingBackgroundUsers = new ArrayList<>();
/** Set to indicate whether to issue an onUserLeaving callback when a newly launched activity
* is being brought in front of us. */
boolean mUserLeaving = false;
/** Set when we have taken too long waiting to go to sleep. */
boolean mSleepTimeout = false;
/** Indicates if we are running on a Leanback-only (TV) device. Only initialized after
* setWindowManager is called. **/
private boolean mLeanbackOnlyDevice;
/**
* We don't want to allow the device to go to sleep while in the process
* of launching an activity. This is primarily to allow alarm intent
* receivers to launch an activity and get that to run before the device
* goes back to sleep.
*/
PowerManager.WakeLock mLaunchingActivity;
/**
* Set when the system is going to sleep, until we have
* successfully paused the current activity and released our wake lock.
* At that point the system is allowed to actually sleep.
*/
PowerManager.WakeLock mGoingToSleep;
/** Stack id of the front stack when user switched, indexed by userId. */
SparseIntArray mUserStackInFront = new SparseIntArray(2);
/* { Multi-Window */
static final boolean DEBUG_MULTIWINDOW = false;
/* Multi-Window } */
// TODO: Add listener for removal of references.
/** Mapping from (ActivityStack/TaskStack).mStackId to their current state */
private SparseArray<ActivityContainer> mActivityContainers = new SparseArray<>();
/** Mapping from displayId to display current state */
private final SparseArray<ActivityDisplay> mActivityDisplays = new SparseArray<>();
InputManagerInternal mInputManagerInternal;
/** The chain of tasks in lockTask mode. The current frontmost task is at the top, and tasks
* may be finished until there is only one entry left. If this is empty the system is not
* in lockTask mode. */
ArrayList<TaskRecord> mLockTaskModeTasks = new ArrayList<>();
/** Store the current lock task mode. Possible values:
* {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
* {@link ActivityManager#LOCK_TASK_MODE_PINNED}
*/
private int mLockTaskModeState;
/**
* Notifies the user when entering/exiting lock-task.
*/
private LockTaskNotify mLockTaskNotify;
final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
/** Used to keep resumeTopActivityLocked() from being entered recursively */
boolean inResumeTopActivity;
/** Anti-Phishing */
private static final String DEST_PACKAGE = "dest_package";
private static final String DEST_CLASS = "dest_class";
private static final String SCAN_URL = "scan_url";
private static final String APH_PACKAGE_NAME = "com.example.aogata.antiphishingdemo";
private static final String APH_SERVICE_NAME = "com.example.aogata.antiphishingdemo.AntiPhishingService";
private static final String RESOLVER_NAME = "com.android.internal.app.ResolverActivity";
/** End Anti-Phishing */
/**
* Description of a request to start a new activity, which has been held
* due to app switches being disabled.
*/
static class PendingActivityLaunch {
final ActivityRecord r;
final ActivityRecord sourceRecord;
final int startFlags;
final ActivityStack stack;
PendingActivityLaunch(ActivityRecord _r, ActivityRecord _sourceRecord,
int _startFlags, ActivityStack _stack) {
r = _r;
sourceRecord = _sourceRecord;
startFlags = _startFlags;
stack = _stack;
}
}
public ActivityStackSupervisor(ActivityManagerService service, RecentTasks recentTasks) {
mService = service;
mRecentTasks = recentTasks;
mHandler = new ActivityStackSupervisorHandler(mService.mHandler.getLooper());
/* Is perf lock for cpu-boost enabled during App 1st launch */
mIsPerfBoostEnabled = mService.mContext.getResources().getBoolean(
com.android.internal.R.bool.config_enableCpuBoostForAppLaunch);
mIsperfDisablepackingEnable = mService.mContext.getResources().getBoolean(
com.android.internal.R.bool.config_disablePacking);
if(mIsPerfBoostEnabled) {
lBoostTimeOut = mService.mContext.getResources().getInteger(
com.android.internal.R.integer.launchboost_timeout_param);
lBoostCpuParamVal = mService.mContext.getResources().getIntArray(
com.android.internal.R.array.launchboost_param_value);
}
if(mIsperfDisablepackingEnable) {
lDisPackTimeOut = mService.mContext.getResources().getInteger(
com.android.internal.R.integer.disablepacking_timeout_param);
lBoostPackParamVal = mService.mContext.getResources().getIntArray(
com.android.internal.R.array.launchboost_packing_param_value);
}
}
/**
* At the time when the constructor runs, the power manager has not yet been
* initialized. So we initialize our wakelocks afterwards.
*/
void initPowerManagement() {
PowerManager pm = (PowerManager)mService.mContext.getSystemService(Context.POWER_SERVICE);
mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*launch*");
mLaunchingActivity.setReferenceCounted(false);
}
// This function returns a IStatusBarService. The value is from ServiceManager.
// getService and is cached.
private IStatusBarService getStatusBarService() {
synchronized (mService) {
if (mStatusBarService == null) {
mStatusBarService = IStatusBarService.Stub.asInterface(
ServiceManager.checkService(Context.STATUS_BAR_SERVICE));
if (mStatusBarService == null) {
Slog.w("StatusBarManager", "warning: no STATUS_BAR_SERVICE");
}
}
return mStatusBarService;
}
}
private IDevicePolicyManager getDevicePolicyManager() {
synchronized (mService) {
if (mDevicePolicyManager == null) {
mDevicePolicyManager = IDevicePolicyManager.Stub.asInterface(
ServiceManager.checkService(Context.DEVICE_POLICY_SERVICE));
if (mDevicePolicyManager == null) {
Slog.w(TAG, "warning: no DEVICE_POLICY_SERVICE");
}
}
return mDevicePolicyManager;
}
}
void setWindowManager(WindowManagerService wm) {
synchronized (mService) {
mWindowManager = wm;
mDisplayManager =
(DisplayManager)mService.mContext.getSystemService(Context.DISPLAY_SERVICE);
mDisplayManager.registerDisplayListener(this, null);
Display[] displays = mDisplayManager.getDisplays();
for (int displayNdx = displays.length - 1; displayNdx >= 0; --displayNdx) {
final int displayId = displays[displayNdx].getDisplayId();
ActivityDisplay activityDisplay = new ActivityDisplay(displayId);
if (activityDisplay.mDisplay == null) {
throw new IllegalStateException("Default Display does not exist");
}
mActivityDisplays.put(displayId, activityDisplay);
/* { Dual-Screen */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
mService.mMultiWindowPolicy.initCenterBarPosition(displayId);
}
/* Dual-Screen } */
}
createStackOnDisplay(HOME_STACK_ID, Display.DEFAULT_DISPLAY);
mHomeStack = mFocusedStack = mLastFocusedStack = getStack(HOME_STACK_ID);
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
mHomeStacks[Display.DEFAULT_DISPLAY] = mFrontStacks[Display.DEFAULT_DISPLAY] = mLastFocusedStacks[Display.DEFAULT_DISPLAY] = mHomeStack;
mChangedFrontStackWhileSleeping[Display.DEFAULT_DISPLAY] = false;
// create SAMSUNG HOME STACK
createStackOnDisplay(SAMSUNG_HOME_STACK_ID, Display.DUAL_SCREEN_SUB_DISPLAY);
mSamsungHomeStack = getStack(SAMSUNG_HOME_STACK_ID);
mHomeStacks[Display.DUAL_SCREEN_SUB_DISPLAY] = mFrontStacks[Display.DUAL_SCREEN_SUB_DISPLAY] = mLastFocusedStacks[Display.DUAL_SCREEN_SUB_DISPLAY] = mSamsungHomeStack;
mChangedFrontStackWhileSleeping[Display.DUAL_SCREEN_SUB_DISPLAY] = false;
if (SUPPORT_EXPANDED_MODE) {
// create expanded stack
createStackOnDisplay(EXPANDED_HOME_STACK_ID, Display.DUAL_SCREEN_EXPANDED_DISPLAY);
mExpandedHomeStack = getStack(EXPANDED_HOME_STACK_ID);
mHomeStacks[Display.DUAL_SCREEN_EXPANDED_DISPLAY] = mFrontStacks[Display.DUAL_SCREEN_EXPANDED_DISPLAY] = mLastFocusedStacks[Display.DUAL_SCREEN_EXPANDED_DISPLAY] = mExpandedHomeStack;
mChangedFrontStackWhileSleeping[Display.DUAL_SCREEN_EXPANDED_DISPLAY] = false;
}
}
/* Dual-Screen } */
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
// Initialize this here, now that we can get a valid reference to PackageManager.
mLeanbackOnlyDevice = isLeanbackOnlyDevice();
}
}
void notifyActivityDrawnForKeyguard() {
if (DEBUG_LOCKSCREEN) mService.logLockScreen("");
mWindowManager.notifyActivityDrawnForKeyguard();
/* { AppCore */
mService.mTargetDismiss = null;
mService.mIsKeyguardWaitingForActivityDrawnRequested = false;
/* AppCore } */
}
ActivityStack getFocusedStack() {
return mFocusedStack;
}
/* { Dual-Screen */
ActivityStack getFocusedStack(int displayId) {
if (DUALSCREEN_ENABLED) {
return mFrontStacks[displayId];
}
return mFocusedStack;
}
/* Dual-Screen } */
ActivityStack getLastStack() {
return mLastFocusedStack;
}
/* { Dual-Screen */
ActivityStack getLastStack(int displayId) {
if (DUALSCREEN_ENABLED) {
return mLastFocusedStacks[displayId];
}
return mLastFocusedStack;
}
/* Dual-Screen } */
/* { Multi-Window */
boolean isIsolated(int displayId) {
boolean bPopup = false;
boolean bHasVisible = false;
for (ActivityStack as : getStacks()) {
ActivityRecord topActivity = as.topActivity();
if (topActivity != null && as.mDisplayId == displayId) {
if (isFrontStack(as)) {
if (topActivity.multiWindowStyle.isSplit()
&& topActivity.multiWindowStyle.isEnabled(MultiWindowStyle.OPTION_ISOLATED_SPLIT)) {
return true;
}
if (topActivity.multiWindowStyle.isNormal() && topActivity.fullscreen == false) {
bPopup = true;
}
} else if (topActivity.visible
&& topActivity.multiWindowStyle.isSplit()
&& topActivity.multiWindowStyle.isEnabled(MultiWindowStyle.OPTION_ISOLATED_SPLIT)) {
bHasVisible = true;
}
}
}
return bHasVisible && bPopup;
}
boolean checkFullScreenOnlyExist(ArrayList<TaskRecord> taskOrder, ActivityStack curStack) {
int N = taskOrder.size();
for (int i = 0 ; i < N ; i++) {
final ActivityStack stack = taskOrder.get(i).stack;
if (stack == null || curStack.equals(stack))
continue;
ArrayList<TaskRecord> tasks = stack.getAllTasks();
for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
TaskRecord task = tasks.get(taskNdx);
if (task.userId == mCurrentUser) {
ArrayList<ActivityRecord> activities = task.mActivities;
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
ActivityRecord activityRecord = activities.get(activityNdx);
if (activityRecord.finishing || activityRecord.multiWindowStyle.isCascade()) {
continue;
}
if (activityRecord.multiWindowStyle.isSplit()
&& activityRecord.multiWindowStyle.isEnabled(MultiWindowStyle.OPTION_FULLSCREEN_ONLY)) {
if (activityRecord.fullscreen) {
return true;
}
} else {
return false;
}
}
}
}
}
return false;
}
/* Multi-Window } */
boolean isFrontStack(ActivityStack stack) {
return isFrontStack(stack, false);
}
/** Top of all visible stacks is/should always be equal to the focused stack.
* Use {@link ActivityStack#isStackVisibleLocked} to determine if a specific
* stack is visible or not. */
boolean isFrontStack(ActivityStack stack, /* { Multi-Window */ boolean ignoreMinimize /* Multi-Window } */) {
/* { Multi-Window */
if (stack == null) {
return false;
}
/* { Virtual-Screen */
if (VIRTUALSCREEN_ENABLED) {
if (VirtualScreenManagerService.self().isVirtualScreen(stack.getDisplayId())) {
if (VirtualScreenManagerService.self().isFrontVirtualScreen(stack)) {
return true;
}
return false;
}
}
/* Virtual-Screen } */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
if (!stack.mActivityContainer.isAttachedLocked())
return false;
ActivityRecord top = stack.topRunningActivityLocked(null, true);
if (top != null && top.state != ActivityStack.ActivityState.INITIALIZING
&& ((top.multiWindowStyle.isEnabled(MultiWindowStyle.OPTION_MINIMIZED) && !ignoreMinimize)
|| top.multiWindowStyle.isEnabled(MultiWindowStyle.OPTION_HIDDEN)
|| (top.multiWindowStyle.isEnabled(MultiWindowStyle.OPTION_TAB_MODE)
&& stack.getStackId() != mService.mMultiWindowPolicy.getTabFrontStack()))) {
return false;
}
synchronized (mService) {
if (stack.mActivityContainer.mActivityDisplay == null) {
return false;
}
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
if (stack.isFloatingStack() && stack.isAllHidden()) {
return false;
}
}
/* Multi-Window } */
ArrayList<TaskRecord> taskOrder = /* { Dual-Screen */SUPPORT_EXPANDED_MODE ? mUniversalTaskHistory : /* Dual-Screen } */
getGlobalTaskHistoryLocked(stack.mDisplayId);
int obscuredZone = MultiWindowStyle.ZONE_UNKNOWN;
int N = taskOrder.size();
/* { Dual-Screen */
if (SUPPORT_EXPANDED_MODE) {
if (stack.isHomeStack() && stack.topRunningActivityLocked(null) == null) {
boolean homeIsFront = true;
int homeScreenZone = convertDisplayIdToScreenZone(stack.getDisplayId());
int obscuredScreenZone = DUAL_SCREEN_ZONE_UNKNOWN;
for (int i = N-1; i >= 0; i--) {
obscuredScreenZone |= taskOrder.get(i).getScreenZone();
if ((obscuredScreenZone & homeScreenZone) != 0) {
homeIsFront = false;
break;
}
}
if (homeIsFront) {
return homeIsFront;
}
}
} else {
/* Dual-Screen } */
int M = taskOrder.size();
for (int i = M - 1; i >= 0; i--) {
TaskRecord task = taskOrder.get(i);
if (task.userId != mCurrentUser) {
M--; // Checking If Current GlobalTask Size,if ZERO should start
// resumeHomeStackTask for CurrentUser.
}
}
if ((N == 0 || M == 0) && stack.isHomeStack()) {
return true;
}
if (stack.isHomeStack() && (stack.numActivitiesCurrentUser() == 0 || stack.numActivities() == 0)) {
boolean homeIsFront = true;
for (int i = 0; i < N; i++) {
if (taskOrder.get(i).topRunningActivityLocked(null) != null) {
homeIsFront = false;
break;
}
}
if (homeIsFront) {
return homeIsFront;
}
}
}
/* SEC_PRODUCT_FEATURE_COMMON_SUPPORT_WEARABLE_HMT {*/
if(VRApplicationPolicy.FEATURE_HMT) {
if (top != null && top.launchedBehindVRApp) {
if(mService.mVRApplicationPolicy.isHMTconnected()) {
return true;
} else {
top.launchedBehindVRApp = false;
}
}
}
/*} SEC_PRODUCT_FEATURE_COMMON_SUPPORT_WEARABLE_HMT */
if (stack.isSplitStack() && !stack.isHomeStack()
&& checkFullScreenOnlyExist(taskOrder, stack)) {
return false;
}
int obscuredScreenZone = DUAL_SCREEN_ZONE_UNKNOWN;
int obscuredZones[] = new int[] { MultiWindowStyle.ZONE_UNKNOWN, MultiWindowStyle.ZONE_UNKNOWN, MultiWindowStyle.ZONE_UNKNOWN};
for (int i = N - 1; i >= 0; i--) {
TaskRecord task = taskOrder.get(i);
ActivityStack currStack = task.stack;
if (currStack == null) {
Slog.w(TAG, "isFrontStack: stack is not exist. id=" + taskOrder.get(i));
continue;
}
/* { Dual-Screen */
if (SUPPORT_EXPANDED_MODE) {
int displayId = currStack.getDisplayId();
if ((convertDisplayIdToScreenZone(displayId) & obscuredScreenZone) != 0) {
if (displayId == Display.DUAL_SCREEN_EXPANDED_DISPLAY) {
return false;
}
}
SparseArray<Integer> taskDisplayObscuredZones = task.getDisplayObscuredZones(true);
int taskObscuredZone = taskDisplayObscuredZones.get(displayId, MultiWindowStyle.ZONE_UNKNOWN);
if (currStack == stack) {
if (taskObscuredZone == MultiWindowStyle.ZONE_FULL) {
return (obscuredZones[displayId] & MultiWindowStyle.ZONE_FULL) == 0;
} else if (taskObscuredZone == MultiWindowStyle.ZONE_UNKNOWN
&& task.topRunningActivityLocked(null) == null) {
continue;
} else {
return (obscuredZones[displayId] & taskObscuredZone) == 0;
}
}
int NZ = taskDisplayObscuredZones.size();
for (int zoneNdx = 0; zoneNdx < NZ; zoneNdx++) {
int zoneDisplayId = taskDisplayObscuredZones.keyAt(zoneNdx);
obscuredZones[zoneDisplayId] |= taskDisplayObscuredZones.valueAt(zoneNdx);
}
if (task.topRunningActivityLocked(null) != null) {
obscuredScreenZone |= task.getScreenZone();
}
if (obscuredScreenZone == DUAL_SCREEN_ZONE_FULL) {
return false;
}
} else {
/* Dual-Screen } */
int taskObscuredZone = task.getVisibleObscuredZone(true);
if (currStack == stack) {
if (taskObscuredZone == MultiWindowStyle.ZONE_FULL) {
return obscuredZone != MultiWindowStyle.ZONE_FULL;
} else if (taskObscuredZone == MultiWindowStyle.ZONE_UNKNOWN
&& task.topRunningActivityLocked(null) == null) {
continue;
} else {
return obscuredZone != MultiWindowStyle.ZONE_FULL;
}
}
obscuredZone |= taskObscuredZone;
if (obscuredZone == MultiWindowStyle.ZONE_FULL)
return false;
}
}
return false;
}
} else {
/* Multi-Window } */
final ActivityRecord parent = stack.mActivityContainer.mParentActivity;
if (parent != null) {
stack = parent.task.stack;
}
return stack == mFocusedStack;
}
}
void moveHomeStack(boolean toFront, String reason) {
/* { Dual-Screen */
moveHomeStack(toFront, reason, null, Display.DEFAULT_DISPLAY);
}
void moveHomeStack(boolean toFront, String reason, ActivityStack lastFocusedStack, int displayId) {
/* Dual-Screen } */
/* { Dual-Screen */
ActivityStack homeStack;
if (DUALSCREEN_ENABLED) {
if (displayId < Display.DUAL_SCREEN_TYPE_MAX) {
homeStack = mHomeStacks[displayId];
} else {
Slog.d(TAG, "Unable to moveHomeStack because displayId is invalid.");
return;
}
} else {
homeStack = mHomeStack;
}
ArrayList<ActivityStack> stacks = homeStack.mStacks;
/* Dual-Screen } */
final int topNdx = stacks.size() - 1;
if (topNdx <= 0) {
/* { Dual-Screen */
if (SUPPORT_EXPANDED_MODE && DualScreenSettings.isExpandHomeModeEnabled()
&& homeStack.getStackId() == EXPANDED_HOME_STACK_ID && getStacks().size() > 1) {
// If any ActivityStack which is not ExpandedHomeStack existed, allow ExpandedHomeStack to be moved.
} else {
/* Dual-Screen } */
return;
}
return;
}
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
/* { Dual-Screen */
//moveStack(mHomeStack, toFront);
moveStack(homeStack, toFront);
/* Dual-Screen } */
} else {
/* Multi-Window } */
/* { Virtual-Screen */
if (VIRTUALSCREEN_ENABLED) {
// TODO: need policy which task has to move.
if (toFront) {
TaskRecord topTask = homeStack.topTask();
if (!reason.startsWith("moveTaskToBack") && !reason.equals("startingNewTask")
&& topTask != null && topTask.isHomeTask()) {
VirtualScreenManagerService.self().moveTaskBackToDisplayIfNeeded(mFocusedStack.topTask(), true, false);
}
}
}
/* Virtual-Screen } */
// The home stack should either be at the top or bottom of the stack list.
if ((toFront && (stacks.get(topNdx) != mHomeStack))
|| (!toFront && (stacks.get(0) != mHomeStack))) {
if (DEBUG_STACK) Slog.d(TAG_STACK, "moveHomeTask: topStack old="
+ ((lastFocusedStack != null) ? lastFocusedStack : stacks.get(topNdx))
+ " new=" + mFocusedStack);
stacks.remove(mHomeStack);
stacks.add(toFront ? topNdx : 0, mHomeStack);
}
if (lastFocusedStack != null) {
mLastFocusedStack = lastFocusedStack;
}
mFocusedStack = stacks.get(topNdx);
}
EventLog.writeEvent(EventLogTags.AM_HOME_STACK_MOVED,
mCurrentUser, toFront ? 1 : 0, stacks.get(topNdx).getStackId(),
mFocusedStack == null ? -1 : mFocusedStack.getStackId(), reason);
if (mService.mBooting || !mService.mBooted) {
final ActivityRecord r = topRunningActivityLocked();
if (r != null && r.idle) {
checkFinishBootingLocked();
}
}
}
/* { Multi-Window */
void moveStack(ActivityStack stack, boolean toFront) {
ArrayList<ActivityStack> stacks = stack.mStacks;
int topNdx = stacks.size() - 1;
stacks.remove(stack);
stacks.add(toFront ? topNdx : 0, stack);
ActivityStack focusedStack = stacks.get(topNdx);
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
if (!toFront) {
if (mFrontStacks[stack.getDisplayId()] != stack) {
// If target stack is not frontStack, it is not necessary to update focusedStack.
return;
}
ArrayList<Integer> stackOrder = getStackOrder(false, null, false);
if (!stackOrder.isEmpty()) {
focusedStack = getStack(stackOrder.get(0));
}
}
}
/* Dual-Screen } */
if (focusedStack != mFocusedStack) {
mLastFocusedStack = mFocusedStack;
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
mLastFocusedStacks[mFocusedStack.getDisplayId()] = mFocusedStack;
}
/* Dual-Screen } */
updateFocusedStack(focusedStack, "movestack to "+ toFront);
}
if (DEBUG_STACK) Slog.d(TAG, "moveTask: stack=" + stack + " tgoFront=" + toFront);
}
/* Multi-Window } */
/** Returns true if the focus activity was adjusted to the home stack top activity. */
boolean moveHomeStackTaskToTop(int homeStackTaskType, String reason) {
/* { Dual-Screen */
return moveHomeStackTaskToTop(homeStackTaskType, reason, Display.DEFAULT_DISPLAY);
}
boolean moveHomeStackTaskToTop(int homeStackTaskType, String reason, int displayId) {
return moveHomeStackTaskToTop(homeStackTaskType, reason, displayId, false);
}
boolean moveHomeStackTaskToTop(int homeStackTaskType, String reason, int displayId, boolean preArrangeHomeTask) {
boolean result = false;
if (SUPPORT_EXPANDED_MODE && !DualScreenSettings.isExpandHomeModeEnabled()
&& displayId == Display.DUAL_SCREEN_EXPANDED_DISPLAY) {
/* TODO : MW/DUAL */
// Need to check result for dual display
result = moveHomeStackTaskToTopInner(homeStackTaskType, reason, Display.DUAL_SCREEN_MAIN_DISPLAY, preArrangeHomeTask);
result &= moveHomeStackTaskToTopInner(homeStackTaskType, reason, Display.DUAL_SCREEN_SUB_DISPLAY, preArrangeHomeTask);
} else {
result = moveHomeStackTaskToTopInner(homeStackTaskType, reason, displayId, preArrangeHomeTask);
}
return result;
}
boolean moveHomeStackTaskToTopInner(int homeStackTaskType, String reason, int displayId, boolean preArrangeHomeTask) {
/* Dual-Screen } */
if (homeStackTaskType == RECENTS_ACTIVITY_TYPE) {
mWindowManager.showRecentApps();
return false;
}
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
displayId = mService.mDualScreenPolicy.moveExpandHomeStackTaskToTopInner(homeStackTaskType, reason, displayId, preArrangeHomeTask);
if (displayId == Display.DUAL_SCREEN_SUB_DISPLAY) {
if (homeStackTaskType == ActivityRecord.SAMSUNG_PINNED_HOME_ACTIVITY_TYPE) {
if (mService.startSamsungPinnedHomeIfNeeded(reason)) {
// TODO : DualScreen need to check return value
return false;
}
} else if (homeStackTaskType == ActivityRecord.HOME_ACTIVITY_TYPE) {
homeStackTaskType = ActivityRecord.SAMSUNG_HOME_ACTIVITY_TYPE;
}
}
}
if (DUALSCREEN_ENABLED) {
if (displayId < Display.DUAL_SCREEN_TYPE_MAX) {
mHomeStacks[displayId].moveHomeStackTaskToTop(homeStackTaskType);
}
} else {
mHomeStack.moveHomeStackTaskToTop(homeStackTaskType);
}
/* Dual-Screen } */
final ActivityRecord top = getHomeActivity(/* { Dual-Screen */displayId/* Dual-Screen } */);
if (top == null) {
return false;
}
mService.setFocusedActivityLocked(top, reason);
return true;
}
boolean resumeHomeStackTask(int homeStackTaskType, ActivityRecord prev, String reason) {
/* { Dual-Screen */
return resumeHomeStackTask(homeStackTaskType, prev, reason, Display.DEFAULT_DISPLAY);
}
boolean resumeHomeStackTask(int homeStackTaskType, ActivityRecord prev, String reason, int displayId) {
/* Dual-Screen } */
if (!mService.mBooting && !mService.mBooted) {
// Not ready yet!
return false;
}
if (homeStackTaskType == RECENTS_ACTIVITY_TYPE) {
mWindowManager.showRecentApps();
return false;
}
if (prev != null) {
prev.task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
}
/* { Dual-Screen */
ActivityStack mHomeStack = this.mHomeStack;
if (DUALSCREEN_ENABLED && displayId < Display.DUAL_SCREEN_TYPE_MAX) {
if (SUPPORT_EXPANDED_MODE && DualScreenSettings.isExpandHomeModeEnabled()) {
displayId = mService.mDualScreenPolicy.moveExpandHomeStackTaskToTopInner(homeStackTaskType, reason, displayId, false);
}
mHomeStack = mHomeStacks[displayId];
}
/* Dual-Screen } */
mHomeStack.moveHomeStackTaskToTop(homeStackTaskType);
/* { Dual-Screen */
ActivityRecord r;
if (DUALSCREEN_ENABLED && displayId < Display.DUAL_SCREEN_TYPE_MAX) {
r = getHomeActivity(displayId);
} else {
r = getHomeActivity();
}
/* Dual-Screen } */
if (r != null && !r.finishing) { // Do not resume finishing home activity again here.
mService.setFocusedActivityLocked(r, reason);
return resumeTopActivitiesLocked(mHomeStack, prev, null);
}
/* { Dual-Screen */
if (DUALSCREEN_ENABLED && homeStackTaskType == ActivityRecord.SAMSUNG_PINNED_HOME_ACTIVITY_TYPE) {
return mService.startSamsungPinnedHomeActivityLocked(mCurrentUser, reason, displayId);
}
/* Dual-Screen } */
return mService.startHomeActivityLocked(mCurrentUser, reason /* { Dual-Screen */, displayId /* Dual-Screen } */);
}
TaskRecord anyTaskForIdLocked(int id) {
return anyTaskForIdLocked(id, true);
}
/**
* Returns a {@link TaskRecord} for the input id if available. Null otherwise.
* @param id Id of the task we would like returned.
* @param restoreFromRecents If the id was not in the active list, but was found in recents,
* restore the task from recents to the active list.
*/
TaskRecord anyTaskForIdLocked(int id, boolean restoreFromRecents) {
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
ActivityStack stack = stacks.get(stackNdx);
TaskRecord task = stack.taskForIdLocked(id);
if (task != null) {
return task;
}
}
}
// Don't give up! Look in recents.
if (DEBUG_RECENTS) Slog.v(TAG_RECENTS, "Looking for task id=" + id + " in recents");
TaskRecord task = mRecentTasks.taskForIdLocked(id);
if (task == null) {
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "\tDidn't find task id=" + id + " in recents");
return null;
}
if (!restoreFromRecents) {
return task;
}
if (!restoreRecentTaskLocked(task)) {
if (DEBUG_RECENTS) Slog.w(TAG_RECENTS,
"Couldn't restore task id=" + id + " found in recents");
return null;
}
if (DEBUG_RECENTS) Slog.w(TAG_RECENTS, "Restored task id=" + id + " from in recents");
return task;
}
ActivityRecord isInAnyStackLocked(IBinder token) {
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityRecord r = stacks.get(stackNdx).isInStackLocked(token);
if (r != null) {
return r;
}
}
}
return null;
}
void setNextTaskId(int taskId) {
if (taskId > mCurTaskId) {
mCurTaskId = taskId;
}
}
int getNextTaskId() {
do {
mCurTaskId++;
if (mCurTaskId <= 0) {
mCurTaskId = 1;
}
} while (anyTaskForIdLocked(mCurTaskId, false) != null);
return mCurTaskId;
}
ActivityRecord resumedAppLocked() {
ActivityStack stack = mFocusedStack;
if (stack == null) {
return null;
}
ActivityRecord resumedActivity = stack.mResumedActivity;
if (resumedActivity == null || resumedActivity.app == null) {
resumedActivity = stack.mPausingActivity;
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED && ActivityStack.SUPPORT_MULTIPLE_PAUSING_ACTIVITIES) {
final int N = stack.mPausingActivities.size();
if (N > 0) {
// We overwrite resumedActivity local variable here
resumedActivity = stack.mPausingActivities.get(N - 1);
}
}
/* Multi-Window } */
if (resumedActivity == null || resumedActivity.app == null) {
resumedActivity = stack.topRunningActivityLocked(null);
}
}
return resumedActivity;
}
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
final String processName = app.processName;
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (!isFrontStack(stack, true)) {
continue;
}
ActivityRecord hr = stack.topRunningActivityLocked(null, true);
if (hr != null) {
if (hr.app == null && app.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
try {
/* { Multi-Window */
boolean minimize = false;
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
minimize = hr.multiWindowStyle.isEnabled(MultiWindowStyle.OPTION_MINIMIZED);
}
/* { AppCore */
if ((hr.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(hr.info.packageName)) {
app.addPackage(hr.info.packageName, hr.info.applicationInfo.versionCode,mService.mProcessStats);
}
/* AppCore } */
if (realStartActivityLocked(hr, app, !minimize, true)) {
/* Multi-Window } */
didSomething = true;
}
// <-- AppCore
// Call ensureActivitiesVisibleLocked() only Activity launching failed.
else {
ensureActivitiesVisibleLocked(null, 0);
}
// AppCore -->
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting activity "
+ hr.intent.getComponent().flattenToShortString(), e);
throw e;
}
}
}
}
}
// <-- AppCore
// Call ensureActivitiesVisibleLocked() only Activity launching failed.
// ensureActivitiesVisibleLocked() called whenever a process bound which is not related to launched Activity.
// It causes realStartActivityLocked() with andResume==false, so that launched activity will be paused as soon as resumed.
/*
if (!didSomething) {
ensureActivitiesVisibleLocked(null, 0);
}
*/
// AppCore -->
return didSomething;
}
boolean allResumedActivitiesIdle() {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (!isFrontStack(stack) || stack.numActivities() == 0) {
continue;
}
final ActivityRecord resumedActivity = stack.mResumedActivity;
if (resumedActivity == null || !resumedActivity.idle) {
if (DEBUG_STATES) Slog.d(TAG_STATES, "allResumedActivitiesIdle: stack="
+ stack.mStackId + " " + resumedActivity + " not idle");
return false;
}
}
}
return true;
}
boolean allResumedActivitiesComplete() {
/* { Multi-Window */
return allResumedActivitiesComplete(false);
}
boolean allResumedActivitiesComplete(boolean resumedActivityMustBeNotNull) {
/* Multi-Window } */
/* { Dual-Screen */
return allResumedActivitiesComplete(resumedActivityMustBeNotNull, Display.DISPLAY_NONE);
}
boolean allResumedActivitiesComplete(int displayId) {
return allResumedActivitiesComplete(false, displayId);
}
boolean allResumedActivitiesComplete(boolean resumedActivityMustBeNotNull, int displayId) {
/* Dual-Screen } */
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
/* { Multi-Display */
if (MULTIDISPLAY_ENABLED) {
if (displayId > Display.DISPLAY_NONE && mActivityDisplays.valueAt(displayNdx).mDisplayId != displayId) {
continue;
}
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
if (stacks.size() > 0 && !mService.isScreenOn(mActivityDisplays.valueAt(displayNdx).mDisplayId)) {
continue;
}
}
/* Dual-Screen } */
}
/* Multi-Display } */
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (isFrontStack(stack)) {
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
final ActivityRecord r = resumedActivityMustBeNotNull &&
stack.mResumedActivity == null && (mService.mLockScreenShown != ActivityManagerService.LOCK_SCREEN_SHOWN) ?
stack.topRunningActivityLocked(null) : stack.mResumedActivity;
if (r != null && r.state != RESUMED) {
return false;
}
} else {
/* Multi-Window } */
final ActivityRecord r = stack.mResumedActivity;
if (r != null && r.state != RESUMED) {
return false;
}
}
}
}
}
// TODO: Not sure if this should check if all Paused are complete too.
if (DEBUG_STACK) Slog.d(TAG_STACK,
"allResumedActivitiesComplete: mLastFocusedStack changing from=" +
mLastFocusedStack + " to=" + mFocusedStack);
mLastFocusedStack = mFocusedStack;
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
mLastFocusedStacks[mFocusedStack.getDisplayId()] = mFocusedStack;
}
/* Dual-Screen } */
return true;
}
boolean allResumedActivitiesVisible() {
/* { Dual-Screen */
return allResumedActivitiesVisible(Display.DISPLAY_NONE);
}
boolean allResumedActivitiesVisible(int displayId) {
/* Dual-Screen } */
boolean foundResumed = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
if (displayId > Display.DISPLAY_NONE && mActivityDisplays.valueAt(displayNdx).mDisplayId != displayId) {
continue;
}
}
/* Dual-Screen } */
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
final ActivityRecord r = stack.mResumedActivity;
if (r != null) {
if (!r.nowVisible || mWaitingVisibleActivities.contains(r)) {
return false;
}
foundResumed = true;
}
}
}
return foundResumed;
}
/**
* Pause all activities in either all of the stacks or just the back stacks.
* @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
* @return true if any activity was paused as a result of this call.
*/
boolean pauseBackStacks(boolean userLeaving, boolean resuming, boolean dontWait) {
/* { Dual-Screen */
return pauseBackStacks(userLeaving, resuming, dontWait, false);
}
boolean pauseBackStacks(boolean userLeaving, boolean resuming, boolean dontWait, boolean needToIdle) {
/* Dual-Screen } */
boolean someActivityPaused = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (!isFrontStack(stack) && stack.mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
" mResumedActivity=" + stack.mResumedActivity);
/* { Dual-Screen */
if (SUPPORT_EXPANDED_MODE && needToIdle) {
stack.mResumedIdleActivity = stack.mResumedActivity;
}
/* Dual-Screen } */
someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
dontWait);
}
}
}
return someActivityPaused;
}
boolean allPausedActivitiesComplete() {
/* { Dual-Screen */
return allPausedActivitiesComplete(Display.DISPLAY_NONE);
}
boolean allPausedActivitiesComplete(int displayId) {
/* Dual-Screen } */
boolean pausing = true;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
/* { Multi-Display */
if (MULTIDISPLAY_ENABLED) {
if (displayId > Display.DISPLAY_NONE && displayId != mActivityDisplays.valueAt(displayNdx).mDisplayId) {
continue;
}
}
/* Multi-Display } */
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED && ActivityStack.SUPPORT_MULTIPLE_PAUSING_ACTIVITIES) {
for (ActivityRecord record : stack.mPausingActivities) {
if (record.state != PAUSED
&& record.state != STOPPED
&& record.state != STOPPING) {
if (DEBUG_STATES) {
Slog.d(TAG_STATES,
"allPausedActivitiesComplete: r=" + record + " state=" + record.state);
pausing = false;
} else {
return false;
}
}
}
} else {
/* Multi-Window } */
final ActivityRecord r = stack.mPausingActivity;
if (r != null && r.state != PAUSED && r.state != STOPPED && r.state != STOPPING) {
if (DEBUG_STATES) {
Slog.d(TAG_STATES,
"allPausedActivitiesComplete: r=" + r + " state=" + r.state);
pausing = false;
} else {
return false;
}
}
}
}
}
return pausing;
}
void pauseChildStacks(ActivityRecord parent, boolean userLeaving, boolean uiSleeping,
boolean resuming, boolean dontWait) {
// TODO: Put all stacks in supervisor and iterate through them instead.
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (stack.mResumedActivity != null &&
stack.mActivityContainer.mParentActivity == parent) {
stack.startPausingLocked(userLeaving, uiSleeping, resuming, dontWait);
}
}
}
}
void reportActivityVisibleLocked(ActivityRecord r) {
sendWaitingVisibleReportLocked(r);
/* { Framework-Core */
if (mService.isTargetDismissIntent(r)) {
notifyActivityDrawnForKeyguard();
}
/* Framework-Core } */
}
void sendWaitingVisibleReportLocked(ActivityRecord r) {
boolean changed = false;
for (int i = mWaitingActivityVisible.size()-1; i >= 0; i--) {
WaitResult w = mWaitingActivityVisible.get(i);
if (w.who == null) {
changed = true;
w.timeout = false;
if (r != null) {
w.who = new ComponentName(r.info.packageName, r.info.name);
}
w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
w.thisTime = w.totalTime;
}
}
if (changed) {
mService.notifyAll();
}
}
void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
long thisTime, long totalTime) {
boolean changed = false;
for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
WaitResult w = mWaitingActivityLaunched.remove(i);
if (w.who == null) {
changed = true;
w.timeout = timeout;
if (r != null) {
w.who = new ComponentName(r.info.packageName, r.info.name);
}
w.thisTime = thisTime;
w.totalTime = totalTime;
}
}
if (changed) {
mService.notifyAll();
}
}
ActivityRecord topRunningActivityLocked() {
/* { Multi-Window */
return topRunningActivityLocked(null/* { Dual-Screen */, Display.DISPLAY_NONE/* Dual-Screen } */);
}
ActivityRecord topRunningActivityLocked(ActivityRecord notTop /* { Dual-Screen */, int displayId/* Dual-Screen } */) {
/* Multi-Window } */
/* { Dual-Screen */
return topRunningActivityLocked(null, displayId, false);
}
ActivityRecord topRunningActivityLocked(ActivityRecord notTop, int displayId, boolean checkObscuredScreen) {
if (DUALSCREEN_ENABLED && SUPPORT_EXPANDED_MODE) {
if (displayId == Display.DISPLAY_NONE || checkObscuredScreen) {
for (int i = mUniversalTaskHistory.size() - 1; i >= 0; i--) {
TaskRecord top = mUniversalTaskHistory.get(i);
ActivityRecord topRunningActivity = top.topRunningActivityLocked(null);
if (checkObscuredScreen && displayId != Display.DISPLAY_NONE && (topRunningActivity == null
|| (convertDisplayIdToScreenZone(topRunningActivity.getDisplayId()) & convertDisplayIdToScreenZone(displayId)) == 0)) {
continue;
}
if (topRunningActivity != null && !topRunningActivity.multiWindowStyle.isEnabled(MultiWindowStyle.OPTION_MINIMIZED)) {
return topRunningActivity;
}
}
}
}
if (displayId < 0) {
displayId = Display.DEFAULT_DISPLAY;
}
/* Dual-Screen } */
final ActivityStack focusedStack;
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
focusedStack = getFocusedStack(displayId);
} else {
/* Dual-Screen } */
focusedStack = mFocusedStack;
}
ActivityRecord r = null;
if (isFrontStack(focusedStack)/* { Galaxy-Desktop */ && !mService.isKnoxDesktopModeLocked()/* Galaxy-Desktop } */) {
r = focusedStack.topRunningActivityLocked(null);
if (r != null && notTop != r) {
return r;
}
}
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
for (int i = focusedStack.getGlobalTaskHistoryLocked().size() - 1; i >= 0; i--) {
TaskRecord top = focusedStack.getGlobalTaskHistoryLocked().get(i);
if (top.stack != null && top.stack.isFloatingStack() && top.bHidden) {
continue;
}
ActivityRecord topRunningActivity = top.topRunningActivityLocked(null);
if (topRunningActivity != null && !topRunningActivity.multiWindowStyle.isEnabled(MultiWindowStyle.OPTION_MINIMIZED)) {
return topRunningActivity;
}
}
}
// Return to the home stack.
/* { Dual-Screen */
// final ArrayList<ActivityStack> stacks = mHomeStack.mStacks;
ArrayList<ActivityStack> stacks;
if (DUALSCREEN_ENABLED) {
stacks = getHomeStack(displayId).mStacks;
} else {
stacks = mHomeStack.mStacks;
}
/* Dual-Screen } */
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (stack != focusedStack && isFrontStack(stack)) {
r = stack.topRunningActivityLocked(null);
if (r != null) {
return r;
}
}
}
return null;
}
/* { Virtual-Screen */
int createVirtualScreen(int width, int height) {
DisplayMetrics metrics = new DisplayMetrics();
WindowManager wm = (WindowManager) mService.mContext.getSystemService(Context.WINDOW_SERVICE);
wm.getDefaultDisplay().getMetrics(metrics);
VirtualActivityDisplay virtualActivityDisplay = new VirtualActivityDisplay(width, height, metrics.densityDpi, true);
if (virtualActivityDisplay.mDisplayId != Display.DISPLAY_NONE) {
mActivityDisplays.put(virtualActivityDisplay.mDisplayId, virtualActivityDisplay);
EventLog.writeEvent(EventLogTags.VS_CREATE_DISPLAY, virtualActivityDisplay.mDisplayId);
}
return virtualActivityDisplay.mDisplayId;
}
void removeVirtualScreen(int displayId) {
EventLog.writeEvent(EventLogTags.VS_REMOVE_DISPLAY, displayId);
onDisplayRemoved(displayId);
}
ArrayList<ActivityStack> getStacks(int displayId) {
ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
if (activityDisplay != null) {
return activityDisplay.mStacks;
}
return null;
}
/* Virtual-Screen } */
void getTasksLocked(int maxNum, List<RunningTaskInfo> list, int callingUid, boolean allowed/* { Multi-Window */, int flags/* Multi-Window } */) {
/* { Dual-Screen */
getTasksLocked(maxNum, list, callingUid, allowed, flags, Display.DISPLAY_NONE);
}
void getTasksLocked(int maxNum, List<RunningTaskInfo> list, int callingUid, boolean allowed
/* { Multi-Window */, int flags/* Multi-Window } */, int displayId) {
/* Dual-Screen } */
// Gather all of the running tasks for each stack into runningTaskLists.
ArrayList<ArrayList<RunningTaskInfo>> runningTaskLists =
new ArrayList<ArrayList<RunningTaskInfo>>();
/* { Dual-Screen */
if (DUALSCREEN_ENABLED && displayId != Display.DISPLAY_NONE) {
ArrayList<ActivityStack> stacks = mActivityDisplays.get(displayId).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
ArrayList<RunningTaskInfo> stackTaskList = new ArrayList<RunningTaskInfo>();
runningTaskLists.add(stackTaskList);
stack.getTasksLocked(stackTaskList, callingUid, allowed/* { Multi-Window */, flags/* Multi-Window } */);
}
} else {
/* Dual-Screen } */
final int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
/* { Virtual-Screen */
if (VIRTUALSCREEN_ENABLED) {
if (VirtualScreenManagerService.self().isVirtualScreen(mActivityDisplays.valueAt(displayNdx).mDisplayId)) {
continue;
}
}
/* Virtual-Screen } */
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
ArrayList<RunningTaskInfo> stackTaskList = new ArrayList<RunningTaskInfo>();
runningTaskLists.add(stackTaskList);
stack.getTasksLocked(stackTaskList, callingUid, allowed/* { Multi-Window */, flags/* Multi-Window } */);
}
}
}
// The lists are already sorted from most recent to oldest. Just pull the most recent off
// each list and add it to list. Stop when all lists are empty or maxNum reached.
while (maxNum > 0) {
long mostRecentActiveTime = Long.MIN_VALUE;
ArrayList<RunningTaskInfo> selectedStackList = null;
// { AppCore : prevent wrong task order return
boolean taskIsInitState = false;
// AppCore }
final int numTaskLists = runningTaskLists.size();
for (int stackNdx = 0; stackNdx < numTaskLists; ++stackNdx) {
ArrayList<RunningTaskInfo> stackTaskList = runningTaskLists.get(stackNdx);
if (!stackTaskList.isEmpty()) {
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED
&& mService.mFocusedActivity != null
&& !mService.mFocusedActivity.multiWindowStyle.isNormal()
&& stackTaskList.get(0).id == mService.mFocusedActivity.task.taskId) {
selectedStackList = stackTaskList;
break;
}
/* Multi-Window } */
final long lastActiveTime = stackTaskList.get(0).lastActiveTime;
final long lastActiveElapsedTime = stackTaskList.get(0).lastActiveElapsedTime;
// { AppCore : prevent wrong task order return
// stackTaskList.get(0) task is actually not running task yet.
if (lastActiveTime == 0) {
stackTaskList.remove(0);
taskIsInitState = true;
break;
}
// AppCore }
if (lastActiveElapsedTime > mostRecentActiveTime) {
mostRecentActiveTime = lastActiveElapsedTime;
selectedStackList = stackTaskList;
}
}
}
if (selectedStackList != null) {
list.add(selectedStackList.remove(0));
--maxNum;
// { AppCore : prevent wrong task order return
// Google origin
// } else {
} else if (!taskIsInitState) {
// AppCore }
break;
}
}
Collections.sort(list, mRunningTaskComparator);
}
final Comparator<RunningTaskInfo> mRunningTaskComparator = new Comparator<RunningTaskInfo>() {
@Override
public int compare(RunningTaskInfo lhs, RunningTaskInfo rhs) {
long time1_elapsed = lhs.lastActiveElapsedTime;
long time2_elapsed = rhs.lastActiveElapsedTime;
if (time1_elapsed - time2_elapsed > 0) {
return -1;
}
if (time1_elapsed - time2_elapsed < 0) {
return 1;
}
long time1 = lhs.lastActiveTime;
long time2 = rhs.lastActiveTime;
if (time1 - time2 > 0) {
return -1;
}
if (time1 - time2 < 0) {
return 1;
}
return 0;
}
};
ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
ProfilerInfo profilerInfo, int userId) {
/* { Dual-Screen */
return resolveActivity(null, intent, resolvedType, startFlags, profilerInfo, userId);
}
ActivityInfo resolveActivity(IApplicationThread caller, Intent intent, String resolvedType, int startFlags,
ProfilerInfo profilerInfo, int userId) {
boolean displayChooserSelected = false;
ProcessRecord callerApp = null;
ActivityRecord callerActivityRecord = null;
int callerActivitiesSize = 0;
if (DUALSCREEN_ENABLED) {
if (caller != null) {
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
callerActivitiesSize = callerApp.activities.size();
if (callerActivitiesSize > 0) {
callerActivityRecord = (ActivityRecord) callerApp.activities.get(callerActivitiesSize - 1);
}
}
}
}
/* Dual-Screen } */
// Collect information about the target of the Intent.
ActivityInfo aInfo;
ResolveInfo rInfo = null;
try {
/* { Dual-Screen */
Intent queryIntent = null;
if (DUALSCREEN_ENABLED
&& intent != null && intent.hasCategory(Intent.CATEGORY_SAMSUNG_HOME)
&& mService.mSamsungHomeComponentName != null) {
if (intent.getCategories().size() > 1 ) {
queryIntent = new Intent(intent);
queryIntent.removeCategory(Intent.CATEGORY_SAMSUNG_HOME);
} else if (intent.getComponent() == null) {
queryIntent = new Intent(intent);
queryIntent.setComponent(mService.mSamsungHomeComponentName);
} else if (!mService.mSamsungHomeComponentName.equals(intent.getComponent())) {
queryIntent = new Intent(intent);
queryIntent.removeCategory(Intent.CATEGORY_SAMSUNG_HOME);
}
}
/* Dual-Screen } */
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED
|| VRApplicationPolicy.FEATURE_HMT
/* { CustomStartingWindow */
|| CUSTOM_STARTING_WINDOW
/* CustomStartingWindow } */
/* { KNOX_BBC */
|| (SecProductFeature_KNOX.SEC_PRODUCT_FEATURE_KNOX_SUPPORT_BBC && PersonaManager.getKnoxContainerVersion() != KnoxContainerVersion.KNOX_CONTAINER_VERSION_NONE)
/* KNOX_BBC } */
) {
rInfo = AppGlobals.getPackageManager().resolveIntent(
/* { Dual-Screen */(DUALSCREEN_ENABLED && queryIntent != null)? queryIntent :/* Dual-Screen } */
intent, resolvedType,
PackageManager.MATCH_DEFAULT_ONLY
| ActivityManagerService.STOCK_PM_FLAGS
| PackageManager.GET_META_DATA, userId);
aInfo = rInfo != null ? rInfo.activityInfo : null;
} else {
/* Multi-Window } */
rInfo = AppGlobals.getPackageManager().resolveIntent(
intent, resolvedType,
PackageManager.MATCH_DEFAULT_ONLY
| ActivityManagerService.STOCK_PM_FLAGS, userId);
aInfo = rInfo != null ? rInfo.activityInfo : null;
/* { Multi-Window */
}
/* Multi-Window } */
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
final long origId = Binder.clearCallingIdentity();
Display[] displays = mDisplayManager.getDisplays(null);
if (DEBUG_DUALSCREEN) {
Slog.d(TAG, "resolveActivity() : caller=" + caller);
Slog.d(TAG, "resolveActivity() : displays : " + displays.length);
Slog.d(TAG, "resolveActivity() : callerActivityRecord : " + callerActivityRecord);
Slog.d(TAG, "resolveActivity() : callerActivitiesSize : " + callerActivitiesSize);
Slog.d(TAG, "resolveActivity() : FocusedStack : " + getFocusedStack());
if (displays.length > 0) {
for (int i = 0; i < displays.length; ++i) {
Display display = displays[i];
DisplayInfo di = new DisplayInfo();
display.getDisplayInfo(di);
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
Slog.d(TAG, "resolveActivity() : display[" + i + "] : "
+ "(" + width + "x" + height + ") type="
+ display.getType() + " flags=" + display.getFlags());
Slog.d(TAG, "resolveActivity() : => " + display);
}
}
}
if (callerActivityRecord != null) {
if (mService.mDualScreenPolicy.resolveDisplayChooser(intent, callerActivityRecord, rInfo)) {
// show display chooser activity
rInfo = AppGlobals.getPackageManager().getDisplayChooserResolveInfo();
displayChooserSelected = true;
if (DEBUG_DUALSCREEN) {
Slog.d(TAG, "resolveActivity() : show display chooser!");
}
}
}
}
/* Dual-Screen } */
} catch (RemoteException e) {
aInfo = null;
}
/* { KNOX_BBC */
if (SecProductFeature_KNOX.SEC_PRODUCT_FEATURE_KNOX_SUPPORT_BBC){
if (userId == UserHandle.USER_OWNER) {
aInfo = PersonaManagerService.changeInfoIfBBC(mService.mContext, rInfo, intent);
}
}
/* KNOX_BBC } */
if (aInfo != null) {
// Store the found target back into the intent, because now that
// we have it we never want to do this again. For example, if the
// user navigates back to this point in the history, we should
// always restart the exact same activity.
/* { Dual-Screen */
if (DUALSCREEN_ENABLED && displayChooserSelected) {
ComponentName origin = intent.getComponent();
intent.putExtra(Intent.EXTRA_DUAL_SCREEN_ORIGINAL_TARGET_ACTIVITY, origin);
if (callerActivityRecord == null) {
intent.putExtra(Intent.EXTRA_DUAL_SCREEN_CALLER_ACTIVITY_DISPLAY_ID,
Display.DEFAULT_DISPLAY);
} else {
intent.putExtra(Intent.EXTRA_DUAL_SCREEN_CALLER_ACTIVITY_DISPLAY_ID,
callerActivityRecord.getDisplayId());
}
}
/* Dual-Screen } */
intent.setComponent(new ComponentName(
aInfo.applicationInfo.packageName, aInfo.name));
//KNOX_CONTAINER2.3_START
if((aInfo.name).equals(FORWARD_INTENT_TO_MANAGED_PROFILE) && rInfo!=null
&& rInfo.targetUserId >= PersonaManager.MIN_PERSONA_ID) {
intent.putExtra("crossProfileTargetUserId", rInfo.targetUserId);
}
//KNOX_CONTAINER2.3_END
// Don't debug things in the system process
if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
if (!aInfo.processName.equals("system")) {
mService.setDebugApp(aInfo.processName, true, false);
}
}
if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
if (!aInfo.processName.equals("system")) {
mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
}
}
if (profilerInfo != null) {
if (!aInfo.processName.equals("system")) {
mService.setProfileApp(aInfo.applicationInfo, aInfo.processName, profilerInfo);
}
}
}
return aInfo;
}
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason) {
/* { Dual-Screen */
startHomeActivity(intent, aInfo, reason, Display.DEFAULT_DISPLAY);
}
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason, int displayId) {
/* Dual-Screen } */
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
if (SUPPORT_EXPANDED_MODE && DualScreenSettings.isExpandHomeModeEnabled()) {
moveHomeStackTaskToTop(ActivityRecord.SAMSUNG_EXPAND_HOME_ACTIVITY_TYPE, reason, displayId);
} else {
if (displayId == Display.DEFAULT_DISPLAY) {
moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
} else {
moveHomeStackTaskToTop(SAMSUNG_HOME_ACTIVITY_TYPE, reason, displayId);
}
}
} else {
/* Dual-Screen } */
moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
}
startActivityLocked(null /* caller */, intent, null /* resolvedType */, aInfo,
null /* voiceSession */, null /* voiceInteractor */, null /* resultTo */,
null /* resultWho */, 0 /* requestCode */, 0 /* callingPid */, 0 /* callingUid */,
null /* callingPackage */, 0 /* realCallingPid */, 0 /* realCallingUid */,
0 /* startFlags */, null /* options */, false /* ignoreTargetSecurity */,
false /* componentSpecified */,
null /* outActivity */, null /* container */, null /* inTask */);
if (inResumeTopActivity) {
// If we are in resume section already, home activity will be initialized, but not
// resumed (to avoid recursive resume) and will stay that way until something pokes it
// again. We need to schedule another resume.
scheduleResumeTopActivities();
}
}
final int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, Intent intent, String resolvedType,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
Bundle options, boolean ignoreTargetSecurity, int userId,
IActivityContainer iContainer, TaskRecord inTask) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
ActivityRecord sr = resultTo != null ? isInAnyStackLocked(resultTo) : null;
boolean isNotFromResolverActivity = sr != null && sr.isNotResolverActivity();
boolean componentSpecified = intent.getComponent() != null && isNotFromResolverActivity;
// Don't modify the client's object!
intent = new Intent(intent);
// Collect information about the target of the Intent.
ActivityInfo aInfo =
resolveActivity(/* { Dual-Screen */caller, /* Dual-Screen } */intent, resolvedType, startFlags, profilerInfo, userId);
ActivityContainer container = (ActivityContainer)iContainer;
synchronized (mService) {
if (container != null && container.mParentActivity != null &&
container.mParentActivity.state != RESUMED) {
// Cannot start a child activity if the parent is not resumed.
return ActivityManager.START_CANCELED;
}
final int realCallingPid = Binder.getCallingPid();
final int realCallingUid = Binder.getCallingUid();
int callingPid;
if (callingUid >= 0) {
callingPid = -1;
} else if (caller == null) {
callingPid = realCallingPid;
callingUid = realCallingUid;
} else {
callingPid = callingUid = -1;
}
ActivityStack stack;
if (container == null || container.mStack.isOnHomeDisplay()) {
stack = mFocusedStack;
} else {
stack = container.mStack;
}
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
stack.mConfigWillChange = config != null
&& mService.mConfigurations.get(stack.getDisplayId()).diff(config) != 0;
} else {
/* Dual-Screen } */
stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
}
if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Starting activity when config will change = " + stack.mConfigWillChange);
final long origId = Binder.clearCallingIdentity();
if (aInfo != null &&
(aInfo.applicationInfo.privateFlags
&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
// This may be a heavy-weight process! Check to see if we already
// have another, different heavy-weight process running.
if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
if (mService.mHeavyWeightProcess != null &&
(mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
!mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
int appCallingUid = callingUid;
if (caller != null) {
ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
appCallingUid = callerApp.info.uid;
} else {
Slog.w(TAG, "Unable to find app for caller " + caller
+ " (pid=" + callingPid + ") when starting: "
+ intent.toString());
ActivityOptions.abort(options);
return ActivityManager.START_PERMISSION_DENIED;
}
}
IIntentSender target = mService.getIntentSenderLocked(
ActivityManager.INTENT_SENDER_ACTIVITY, "android",
appCallingUid, userId, null, null, 0, new Intent[] { intent },
new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
| PendingIntent.FLAG_ONE_SHOT, null);
Intent newIntent = new Intent();
if (requestCode >= 0) {
// Caller is requesting a result.
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
}
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
new IntentSender(target));
if (mService.mHeavyWeightProcess.activities.size() > 0) {
ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
hist.packageName);
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
hist.task.taskId);
}
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
aInfo.packageName);
newIntent.setFlags(intent.getFlags());
newIntent.setClassName("android",
HeavyWeightSwitcherActivity.class.getName());
intent = newIntent;
resolvedType = null;
caller = null;
callingUid = Binder.getCallingUid();
callingPid = Binder.getCallingPid();
componentSpecified = true;
try {
ResolveInfo rInfo =
AppGlobals.getPackageManager().resolveIntent(
intent, null,
PackageManager.MATCH_DEFAULT_ONLY /* { Multi-Window */| PackageManager.GET_META_DATA /* Multi-Window } */
| ActivityManagerService.STOCK_PM_FLAGS, userId);
aInfo = rInfo != null ? rInfo.activityInfo : null;
aInfo = mService.getActivityInfoForUser(aInfo, userId);
} catch (RemoteException e) {
aInfo = null;
}
}
}
}
int res = startActivityLocked(caller, intent, resolvedType, aInfo,
voiceSession, voiceInteractor, resultTo, resultWho,
requestCode, callingPid, callingUid, callingPackage,
realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
componentSpecified, null, container, inTask);
Binder.restoreCallingIdentity(origId);
if (stack.mConfigWillChange) {
// If the caller also wants to switch to a new configuration,
// do so now. This allows a clean switch, as we are waiting
// for the current activity to pause (so we will not destroy
// it), and have not yet started the next activity.
mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
"updateConfiguration()");
stack.mConfigWillChange = false;
if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Updating to new configuration after starting activity.");
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
UnRestrictedArrayList<Configuration> configs = new UnRestrictedArrayList<Configuration>();
configs.set(config.displayId, config);
mService.updateConfigurationLocked(configs, null, false, false);
} else {
/* Dual-Screen } */
mService.updateConfigurationLocked(config, null, false, false);
}
}
/* joosung.jin we need to update stack here caused by KK separation acitivy stack */
if (container == null || (container.mStack != null && container.mStack.isOnHomeDisplay())) {
stack = getFocusedStack();
} else {
stack = container.mStack;
}
if (outResult != null) {
outResult.result = res;
if (res == ActivityManager.START_SUCCESS) {
mWaitingActivityLaunched.add(outResult);
do {
try {
mService.wait();
} catch (InterruptedException e) {
}
} while (!outResult.timeout && outResult.who == null);
} else if (res == ActivityManager.START_TASK_TO_FRONT) {
ActivityRecord r = stack.topRunningActivityLocked(null);
if (r != null && r.nowVisible && r.state == RESUMED) {
outResult.timeout = false;
outResult.who = new ComponentName(r.info.packageName, r.info.name);
outResult.totalTime = 0;
outResult.thisTime = 0;
} else {
outResult.thisTime = SystemClock.uptimeMillis();
mWaitingActivityVisible.add(outResult);
do {
try {
mService.wait();
} catch (InterruptedException e) {
}
} while (!outResult.timeout && outResult.who == null);
}
}
}
return res;
}
}
final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
Intent[] intents, String[] resolvedTypes, IBinder resultTo,
Bundle options, int userId) {
if (intents == null) {
throw new NullPointerException("intents is null");
}
if (resolvedTypes == null) {
throw new NullPointerException("resolvedTypes is null");
}
if (intents.length != resolvedTypes.length) {
throw new IllegalArgumentException("intents are length different than resolvedTypes");
}
int callingPid;
if (callingUid >= 0) {
callingPid = -1;
} else if (caller == null) {
callingPid = Binder.getCallingPid();
callingUid = Binder.getCallingUid();
} else {
callingPid = callingUid = -1;
}
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mService) {
ActivityRecord[] outActivity = new ActivityRecord[1];
for (int i=0; i<intents.length; i++) {
Intent intent = intents[i];
if (intent == null) {
continue;
}
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
ActivityRecord sr = resultTo != null ? isInAnyStackLocked(resultTo) : null;
boolean isNotFromResolverActivity = sr != null && sr.isNotResolverActivity();
boolean componentSpecified = intent.getComponent() != null && isNotFromResolverActivity;
// Don't modify the client's object!
intent = new Intent(intent);
// Collect information about the target of the Intent.
ActivityInfo aInfo = resolveActivity(/* { Dual-Screen */caller, /* Dual-Screen } */intent, resolvedTypes[i], 0, null, userId);
// TODO: New, check if this is correct
aInfo = mService.getActivityInfoForUser(aInfo, userId);
if (aInfo != null &&
(aInfo.applicationInfo.privateFlags
& ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
throw new IllegalArgumentException(
"FLAG_CANT_SAVE_STATE not supported here");
}
Bundle theseOptions;
if (options != null && i == intents.length-1) {
theseOptions = options;
} else {
theseOptions = null;
}
int res = startActivityLocked(caller, intent, resolvedTypes[i],
aInfo, null, null, resultTo, null, -1, callingPid, callingUid,
callingPackage, callingPid, callingUid,
0, theseOptions, false, componentSpecified, outActivity, null, null);
if (res < 0) {
return res;
}
resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
}
}
} finally {
Binder.restoreCallingIdentity(origId);
}
return ActivityManager.START_SUCCESS;
}
final boolean realStartActivityLocked(ActivityRecord r,
ProcessRecord app, boolean andResume, boolean checkConfig)
throws RemoteException {
if (andResume) {
r.startFreezingScreenLocked(app, 0);
/* SEC_PRODUCT_FEATURE_COMMON_SUPPORT_WEARABLE_HMT {*/
if(VRApplicationPolicy.FEATURE_HMT) {
if(!r.isVRActivity() && mService.mVRApplicationPolicy.inVRMode()) {
r.launchedBehindVRApp = true;
}
}
/*} SEC_PRODUCT_FEATURE_COMMON_SUPPORT_WEARABLE_HMT */
/* { Edge-Screen */
if (CocktailBarFeatures.COCKTAIL_ENABLED) {
mService.updateSubWindowState(r, app);
}
/* Edge-Screen } */
mWindowManager.setAppVisibility(r.appToken, true/* { Dual-Screen */, r.getDisplayId()/* Dual-Screen } */);
// schedule launch ticks to collect information about slow apps.
r.startLaunchTickingLocked();
}
// Have the window manager re-evaluate the orientation of
// the screen based on the new activity order. Note that
// as a result of this, it can call back into the activity
// manager with a new orientation. We don't care about that,
// because the activity is not currently running so we are
// just restarting it anyway.
if (checkConfig) {
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
app.displayId = r.getDisplayId();
Configuration config = mWindowManager.updateOrientationFromAppTokens(
mService.mConfigurations.get(app.displayId),
r.mayFreezeScreenLocked(app) ? r.appToken : null);
UnRestrictedArrayList<Configuration> configs = new UnRestrictedArrayList<Configuration>();
configs.set(app.displayId, config);
int oppositeDisplayId = -1;
if (app.displayId == Display.DUAL_SCREEN_MAIN_DISPLAY) {
oppositeDisplayId = Display.DUAL_SCREEN_SUB_DISPLAY;
} else if (app.displayId == Display.DUAL_SCREEN_SUB_DISPLAY) {
oppositeDisplayId = Display.DUAL_SCREEN_MAIN_DISPLAY;
}
if (oppositeDisplayId != -1) {
Configuration oppositeConfig = mWindowManager.updateOrientationFromAppTokens(
mService.mConfigurations.get(oppositeDisplayId), null); //TODO : findmayFreezeScreenLocked(), is this needed?
configs.set(oppositeDisplayId, oppositeConfig);
}
mService.updateConfigurationLocked(configs, r, false, false);
} else {
/* Dual-Screen } */
Configuration config = mWindowManager.updateOrientationFromAppTokens(
mService.mConfiguration,
r.mayFreezeScreenLocked(app) ? r.appToken : null);
mService.updateConfigurationLocked(config, r, false, false);
}
}
r.app = app;
app.waitingToKill = null;
r.launchCount++;
r.lastLaunchTime = SystemClock.uptimeMillis();
if (DEBUG_ALL) Slog.v(TAG, "Launching: " + r);
int idx = app.activities.indexOf(r);
if (idx < 0) {
app.activities.add(r);
}
mService.updateLruProcessLocked(app, true, null);
mService.updateOomAdjLocked();
final TaskRecord task = r.task;
if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE ||
task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV) {
setLockTaskModeLocked(task, LOCK_TASK_MODE_LOCKED, "mLockTaskAuth==LAUNCHABLE", false);
}
final ActivityStack stack = task.stack;
try {
if (app.thread == null) {
throw new RemoteException();
}
List<ResultInfo> results = null;
List<ReferrerIntent> newIntents = null;
if (andResume) {
results = r.results;
newIntents = r.newIntents;
/* { Multi-Window */
r.task.bHidden = false;
/* Multi-Window } */
}
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
"Launching: " + r + " icicle=" + r.icicle + " with results=" + results
+ " newIntents=" + newIntents + " andResume=" + andResume);
if (andResume) {
EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
r.userId, System.identityHashCode(r),
task.taskId, r.shortComponentName, r.multiWindowStyle.getType());
}
if (r.isHomeActivity() && r.isNotResolverActivity()) {
// Home process is the root process of the task.
mService.mHomeProcess = task.mActivities.get(0).app;
}
/* { AppCore */
else if (r.isRecentsActivity()) {
mService.mRecentsProcess = r.app;
}
/* AppCore } */
mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
r.sleeping = false;
r.forceNewConfig = false;
mService.showAskCompatModeDialogLocked(r);
r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
ProfilerInfo profilerInfo = null;
if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
if (mService.mProfileProc == null || mService.mProfileProc == app) {
mService.mProfileProc = app;
final String profileFile = mService.mProfileFile;
if (profileFile != null) {
ParcelFileDescriptor profileFd = mService.mProfileFd;
if (profileFd != null) {
try {
profileFd = profileFd.dup();
} catch (IOException e) {
if (profileFd != null) {
try {
profileFd.close();
} catch (IOException o) {
}
profileFd = null;
}
}
}
profilerInfo = new ProfilerInfo(profileFile, profileFd,
mService.mSamplingInterval, mService.mAutoStopProfiler);
}
}
}
if (andResume) {
app.hasShownUi = true;
app.pendingUiClean = true;
}
app.forceProcessStateUpTo(mService.mTopProcessState);
Configuration config;
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
config = new Configuration(mService.mConfigurations.get(r.getDisplayId()));
} else {
/* Dual-Screen } */
config = new Configuration(mService.mConfiguration);
}
/* { Multi-Density */
if (MULTI_DENSITY_ENABLED
&& MultiDensityGlobal.getInstance().hasApplication(r.processName)) {
final int customDensity = MultiDensityGlobal.getInstance().getDensity(r.processName);
config = MultiDensityGlobal.getDensityConfiguration(config, customDensity, "realStart");
}
/* Multi-Density } */
/* { SRUK DSS */
if (DSS_ENABLED && mService.mScaledAppNames.containsKey(app.processName)) {
float dssScale = mService.mDssHelper.getScalingFactorAdss(r.processName);
ActivityManagerService.applyDssToConfiguration(config, dssScale);
}
/* SRUK DSS } */
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
r.multiWindowStyle.setAppRequestOrientation(r.info.screenOrientation);
}
/* Multi-Window } */
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
app.thread.scheduleApplicationDisplayIdChanged(r.getDisplayId());
mService.mDualScreenPolicy.setFullViewHomeStatusLocked(r);
}
/* Dual-Screen } */
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, /* { Multi-Window */config/* Multi-Window } */,
new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
newIntents, !andResume, mService.isNextTransitionForward(/* { Dual-Screen */r.getDisplayId()/* Dual-Screen } */), profilerInfo
/* { Multi-Window */, r.multiWindowStyle/* Multi-Window } */
/* { Dual-Screen */, r.getDisplayId()/* Dual-Screen } */);
if ((app.info.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
// This may be a heavy-weight process! Note that the package
// manager will ensure that only activity can run in the main
// process of the .apk, which is the only thing that will be
// considered heavy-weight.
if (app.processName != null && app.processName.equals(app.info.packageName)) {
if (mService.mHeavyWeightProcess != null
&& mService.mHeavyWeightProcess != app) {
Slog.w(TAG, "Starting new heavy weight process " + app
+ " when already running "
+ mService.mHeavyWeightProcess);
}
mService.mHeavyWeightProcess = app;
Message msg = mService.mHandler.obtainMessage(
ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
msg.obj = r;
mService.mHandler.sendMessage(msg);
}
}
} catch (RemoteException e) {
if (r.launchFailed) {
// This is the second time we failed -- finish activity
// and give up.
Slog.e(TAG, "Second failure launching "
+ r.intent.getComponent().flattenToShortString()
+ ", giving up", e);
mService.appDiedLocked(app);
stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
"2nd-crash", false);
return false;
}
// This is the first time we failed -- restart process and
// retry.
app.activities.remove(r);
throw e;
}
r.launchFailed = false;
if (stack.updateLRUListLocked(r)) {
Slog.w(TAG, "Activity " + r
+ " being launched, but already in LRU list");
}
if (andResume) {
// As part of the process of launching, ActivityThread also performs
// a resume.
stack.minimalResumeActivityLocked(r);
/* { Dual-Screen */
// After Force-Stop, there's no focusedActivity.
// So that update focusedActivity at here.
if (DUALSCREEN_ENABLED) {
if (mService.mFocusedActivity == null) {
mService.setFocusedActivityLocked(r, "realStartActivity");
}
}
/* Dual-Screen } */
} else {
// This activity is not starting in the resumed state... which
// should look like we asked it to pause+stop (but remain visible),
// and it has done so and reported back the current icicle and
// other state.
if (DEBUG_STATES) Slog.v(TAG_STATES,
"Moving to STOPPED: " + r + " (starting in stopped state)");
r.state = STOPPED;
r.stopped = true;
}
// Launch the new version setup screen if needed. We do this -after-
// launching the initial activity (that is, home), so that it can have
// a chance to initialize itself while in the background, making the
// switch back to it faster and look better.
if (isFrontStack(stack)) {
mService.startSetupActivityLocked();
}
// Update any services we are bound to that might care about whether
// their client may have activities.
mService.mServices.updateServiceConnectionActivitiesLocked(r.app);
return true;
}
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
// if the activity is not be resume, skip setLaunchTime
if (andResume) {
r.task.stack.setLaunchTime(r);
}
if (app != null && app.thread != null) {
/* { System SW, SA_SAMP */
if (SmartAdjustManager.SAMP_HOTNESS_ENABLE) {
if (mService != null && mService.mSmartAdjustManager != null)
mService.mSmartAdjustManager.updateHotnessAdj(app, SmartAdjustManager.HOTNESS_ACTIVITY);
}/* System SW, SA_SAMP }, { System SW, SAnP_DHA : hotness */
else if(DynamicHiddenApp.DHA_HOTNESS_ENABLE){
if (mService != null && mService.mDynamicHiddenApp != null)
mService.mDynamicHiddenApp.updateHotnessAdj(app, DynamicHiddenApp.HOTNESS_ACTIVITY);
}
/* System SW, SAnP_DHA : hotness} */
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(r.info.packageName)) {
// Don't add this if it is a platform component that is marked
// to run in multiple processes, because this is actually
// part of the framework so doesn't make sense to track as a
// separate apk in the process.
app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
mService.mProcessStats);
}
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
//r.task.stack.setLaunchTime(r, true);
/* { System SW, SA_SAMP */
ProcessRecord startedApp =
/* System SW, SA_SAMP } */
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true
/* { Dual-Screen */, r.getDisplayId()/* Dual-Screen } */);
/* { System SW, SA_SAMP */
if (SmartAdjustManager.SAMP_HOTNESS_ENABLE) {
if (mService != null && mService.mSmartAdjustManager != null)
mService.mSmartAdjustManager.updateHotnessAdj(startedApp, SmartAdjustManager.HOTNESS_ACTIVITY);
}/* System SW, SA_SAMP }, { System SW, SAnP_DHA : hotness */
else if(DynamicHiddenApp.DHA_HOTNESS_ENABLE){
if (mService != null && mService.mDynamicHiddenApp != null)
mService.mDynamicHiddenApp.updateHotnessAdj(startedApp, DynamicHiddenApp.HOTNESS_ACTIVITY);
}
/* System SW, SAnP_DHA : hotness} */
// DEVICEREPORTING_TMO_INTEGRATION_START
if (CscFeature.getInstance().getEnableStatus("CscFeature_Common_SupportDeviceReporting")) {
// Sending information of the application started, application has package name
// as "r.packageName"
if (app != null) {
AppStateBroadcaster.sendApplicationStart(mService.mContext, r.packageName, app.pid);
}
}
// DEVICEREPORTING_TMO_INTEGRATION_END
}
final int startActivityLocked(IApplicationThread caller,
Intent intent, String resolvedType, ActivityInfo aInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode,
int callingPid, int callingUid, String callingPackage,
int realCallingPid, int realCallingUid, int startFlags, Bundle options,
boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
ActivityContainer container, TaskRecord inTask) {
int err = ActivityManager.START_SUCCESS;
ProcessRecord callerApp = null;
if (caller != null) {
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
} else {
Slog.w(TAG, "Unable to find app for caller " + caller
+ " (pid=" + callingPid + ") when starting: "
+ intent.toString());
err = ActivityManager.START_PERMISSION_DENIED;
}
}
ComponentName cmp = null;
String className = "";
if (SecProductFeature_KNOX.SEC_PRODUCT_FEATURE_KNOX_SUPPORT_MDM) {
try {
// P130328-4214. Do not modify original intent.
Intent mEdmIntent = new Intent(intent);
cmp = mEdmIntent.getComponent();
className = mEdmIntent.getStringExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT);
if (className == null && cmp != null) {
className = cmp.getClassName();
}
} catch (Exception e) {
className = "unknown";
}
if (checkStartActivityAllowedByEDM(intent, aInfo, realCallingUid,
options, cmp, className) == ActivityManager.START_SUCCESS) {
return ActivityManager.START_SUCCESS;
}
}
final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
if (err == ActivityManager.START_SUCCESS) {
Slog.secI(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
+ "} from uid " + callingUid + " pid " + realCallingPid
+ " on display " + (container == null ? (mFocusedStack == null ?
Display.DEFAULT_DISPLAY : mFocusedStack.mDisplayId) :
(container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
container.mActivityDisplay.mDisplayId)));
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED && SAFE_DEBUG) {
Slog.d(TAG, "START " + intent.getMultiWindowStyle());
}
/* Multi-Window } */
}
// KNOX_DLP_START
if (SecProductFeature_KNOX.SEC_PRODUCT_FEATURE_KNOX_SUPPORT_DLP && PersonaManager.isKnoxId(userId)) {
com.android.server.enterprise.dlp.DLPManagerPolicyService.checkLaunchIntentForAccessDLP(intent, aInfo, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid);
}
// KNOX_DLP_END
// [Sprint ItsOn START
if (CscFeature.getInstance().getEnableStatus("CscFeature_Common_EnableItsOn")) {
String intentData = intent.getDataString();
String intentType = intent.getType();
String intentAction = intent.getAction();
if ((intentAction != null && intentAction.equals(Intent.ACTION_VIEW)) &&
(intentType != null && (intentType.startsWith("video") || intentType.startsWith("audio"))) &&
(intentData != null && intentData.startsWith("http"))) {
ItsOnOemApi.getInstance().registerActivityMapping(intentData, callingUid);
}
}
// Sprint ItsON END]
ActivityRecord sourceRecord = null;
ActivityRecord resultRecord = null;
if (resultTo != null) {
sourceRecord = isInAnyStackLocked(resultTo);
if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
"Will send result to " + resultTo + " " + sourceRecord);
if (sourceRecord != null) {
if (requestCode >= 0 && !sourceRecord.finishing) {
resultRecord = sourceRecord;
}
}
}
final int launchFlags = intent.getFlags();
if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
// Transfer the result target from the source activity to the new
// one being started, including any failures.
if (requestCode >= 0) {
ActivityOptions.abort(options);
return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
}
resultRecord = sourceRecord.resultTo;
if (resultRecord != null && !resultRecord.isInStackLocked()) {
resultRecord = null;
}
resultWho = sourceRecord.resultWho;
requestCode = sourceRecord.requestCode;
sourceRecord.resultTo = null;
if (resultRecord != null) {
resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
}
if (sourceRecord.launchedFromUid == callingUid) {
// The new activity is being launched from the same uid as the previous
// activity in the flow, and asking to forward its result back to the
// previous. In this case the activity is serving as a trampoline between
// the two, so we also want to update its launchedFromPackage to be the
// same as the previous activity. Note that this is safe, since we know
// these two packages come from the same uid; the caller could just as
// well have supplied that same package name itself. This specifially
// deals with the case of an intent picker/chooser being launched in the app
// flow to redirect to an activity picked by the user, where we want the final
// activity to consider it to have been launched by the previous app activity.
callingPackage = sourceRecord.launchedFromPackage;
}
}
if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
// We couldn't find a class that can handle the given Intent.
// That's the end of that!
err = ActivityManager.START_INTENT_NOT_RESOLVED;
}
if (err == ActivityManager.START_SUCCESS && aInfo == null) {
// We couldn't find the specific class specified in the Intent.
// Also the end of the line.
err = ActivityManager.START_CLASS_NOT_FOUND;
}
if (err == ActivityManager.START_SUCCESS
&& !isCurrentProfileLocked(userId)
&& (aInfo.flags & FLAG_SHOW_FOR_ALL_USERS) == 0) {
// Trying to launch a background activity that doesn't show for all users.
err = ActivityManager.START_NOT_CURRENT_USER_ACTIVITY;
}
if (err == ActivityManager.START_SUCCESS && sourceRecord != null
&& sourceRecord.task.voiceSession != null) {
// If this activity is being launched as part of a voice session, we need
// to ensure that it is safe to do so. If the upcoming activity will also
// be part of the voice session, we can only launch it if it has explicitly
// said it supports the VOICE category, or it is a part of the calling app.
if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0
&& sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
try {
intent.addCategory(Intent.CATEGORY_VOICE);
if (!AppGlobals.getPackageManager().activitySupportsIntent(
intent.getComponent(), intent, resolvedType)) {
Slog.w(TAG,
"Activity being started in current voice task does not support voice: "
+ intent);
err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
}
} catch (RemoteException e) {
Slog.w(TAG, "Failure checking voice capabilities", e);
err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
}
}
}
if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
// If the caller is starting a new voice session, just make sure the target
// is actually allowing it to run this way.
try {
if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
intent, resolvedType)) {
Slog.w(TAG,
"Activity being started in new voice task does not support: "
+ intent);
err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
}
} catch (RemoteException e) {
Slog.w(TAG, "Failure checking voice capabilities", e);
err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
}
}
final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
if (err != ActivityManager.START_SUCCESS) {
if (resultStack != null && resultRecord != null) {
resultStack.sendActivityResultLocked(-1,
resultRecord, resultWho, requestCode,
Activity.RESULT_CANCELED, null);
}
ActivityOptions.abort(options);
if (SecProductFeature_KNOX.SEC_PRODUCT_FEATURE_KNOX_SUPPORT_MDM) {
AuditLog.logAsUser(AuditLog.NOTICE, AuditLog.AUDIT_LOG_GROUP_APPLICATION, false,
android.os.Process.myPid(), "ActivityStackSupervisor",
AuditEvents.START_ACTIVITY + className + AuditEvents.FAILED, userId);
}
return err;
}
//start SEC_PRODUCT_FEATURE_COMMON_SUPPORT_SE_FOR_ANDROID
boolean allowLaunchIntent = false;
if (SecProductFeature_COMMON.SEC_PRODUCT_FEATURE_COMMON_SUPPORT_SE_FOR_ANDROID) {
if ( ((Intent.ACTION_MAIN.equals(intent.getAction()) &&
intent.hasCategory(Intent.CATEGORY_HOME) ))!= false) {
allowLaunchIntent = true;
}
}
//end SEC_PRODUCT_FEATURE_COMMON_SUPPORT_SE_FOR_ANDROID
boolean abort = false;
final int startAnyPerm = mService.checkPermission(
START_ANY_ACTIVITY, callingPid, callingUid);
if (SecProductFeature_COMMON.SEC_PRODUCT_FEATURE_COMMON_SUPPORT_SE_FOR_ANDROID) {
if (mService.checkContainerAppPermission(intent, callingPid, callingUid, aInfo.applicationInfo.uid,
aInfo.applicationInfo.packageName, allowLaunchIntent) == PackageManager.PERMISSION_DENIED) {
if (resultRecord != null) {
resultStack.sendActivityResultLocked(-1,
resultRecord, resultWho, requestCode,
Activity.RESULT_CANCELED, null);
}
String msg = "checkContainerAppPermission Denial: starting " + intent.toString()
+ " from " + callerApp + " (pid=" + callingPid
+ ", uid=" + callingUid + ")" + " with revoked permission "
+ ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction());
Slog.w(TAG, msg);
if (SecProductFeature_KNOX.SEC_PRODUCT_FEATURE_KNOX_SUPPORT_MDM) {
AuditLog.logAsUser(AuditLog.NOTICE, AuditLog.AUDIT_LOG_GROUP_APPLICATION, false,
android.os.Process.myPid(), "ActivityStackSupervisor",
AuditEvents.START_ACTIVITY + className + AuditEvents.FAILED, userId);
}
throw new SecurityException(msg);
}
}
if (startAnyPerm != PERMISSION_GRANTED) {
final int componentRestriction = getComponentRestrictionForCallingPackage(
aInfo, callingPackage, callingPid, callingUid, ignoreTargetSecurity);
final int actionRestriction = getActionRestrictionForCallingPackage(
intent.getAction(), callingPackage, callingPid, callingUid);
if (componentRestriction == ACTIVITY_RESTRICTION_PERMISSION
|| actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) {
if (resultRecord != null) {
resultStack.sendActivityResultLocked(-1,
resultRecord, resultWho, requestCode,
Activity.RESULT_CANCELED, null);
}
String msg;
if (actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) {
msg = "Permission Denial: starting " + intent.toString()
+ " from " + callerApp + " (pid=" + callingPid
+ ", uid=" + callingUid + ")" + " with revoked permission "
+ ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction());
} else if (!aInfo.exported) {
msg = "Permission Denial: starting " + intent.toString()
+ " from " + callerApp + " (pid=" + callingPid
+ ", uid=" + callingUid + ")"
+ " not exported from uid " + aInfo.applicationInfo.uid;
} else {
msg = "Permission Denial: starting " + intent.toString()
+ " from " + callerApp + " (pid=" + callingPid
+ ", uid=" + callingUid + ")"
+ " requires " + aInfo.permission;
}
Slog.w(TAG, msg);
if (SecProductFeature_KNOX.SEC_PRODUCT_FEATURE_KNOX_SUPPORT_MDM) {
AuditLog.logAsUser(AuditLog.NOTICE, AuditLog.AUDIT_LOG_GROUP_APPLICATION, false,
android.os.Process.myPid(), "ActivityStackSupervisor",
AuditEvents.START_ACTIVITY + className + AuditEvents.FAILED, userId);
}
throw new SecurityException(msg);
}
if (actionRestriction == ACTIVITY_RESTRICTION_APPOP) {
String message = "Appop Denial: starting " + intent.toString()
+ " from " + callerApp + " (pid=" + callingPid
+ ", uid=" + callingUid + ")"
+ " requires " + AppOpsManager.permissionToOp(
ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction()));
Slog.w(TAG, message);
abort = true;
} else if (componentRestriction == ACTIVITY_RESTRICTION_APPOP) {
String message = "Appop Denial: starting " + intent.toString()
+ " from " + callerApp + " (pid=" + callingPid
+ ", uid=" + callingUid + ")"
+ " requires appop " + AppOpsManager.permissionToOp(aInfo.permission);
Slog.w(TAG, message);
abort = true;
}
}
abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
callingPid, resolvedType, aInfo.applicationInfo);
// For Anti-Phishing
if(!abort) {
abort |= scanIntent(mService.mContext, intent, callingUid);
}
if (mService.mController != null) {
try {
// The Intent we give to the watcher has the extra data
// stripped off, since it can contain private information.
Intent watchIntent = intent.cloneFilter();
abort |= !mService.mController.activityStarting(watchIntent,
aInfo.applicationInfo.packageName);
} catch (RemoteException e) {
mService.mController = null;
}
}
if (abort) {
if (resultStack != null && resultRecord != null) {
resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Activity.RESULT_CANCELED, null);
}
// We pretend to the caller that it was really started, but
// they will just get a cancel result.
ActivityOptions.abort(options);
if (SecProductFeature_KNOX.SEC_PRODUCT_FEATURE_KNOX_SUPPORT_MDM) {
AuditLog.logAsUser(AuditLog.NOTICE, AuditLog.AUDIT_LOG_GROUP_APPLICATION, true,
android.os.Process.myPid(), "ActivityStackSupervisor",
AuditEvents.START_ACTIVITY + className + AuditEvents.SUCCEEDED, userId);
}
return ActivityManager.START_SUCCESS;
}
/* { SRC-TJ AppLock */
if(mService.SUPPORT_APPLOCK) {
boolean isLaunchedFromRecents = (intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0;
boolean hasMultiWindowStyle = (intent.getMultiWindowStyle() != null) ||
(sourceRecord != null && sourceRecord.multiWindowStyle != null && !sourceRecord.multiWindowStyle.isNormal());
Slog.d(TAG, "AppLocked getMultiWindowStyle:" + intent.getMultiWindowStyle());
Slog.d(TAG, "AppLocked isLaunchedFromRecents:" + isLaunchedFromRecents + " hasMultiWindowStyle:" + hasMultiWindowStyle +
" not normal : " + (sourceRecord!=null && sourceRecord.multiWindowStyle!=null && !sourceRecord.multiWindowStyle.isNormal()));
if(aInfo.packageName != null && !aInfo.packageName.equals(callingPackage)
&& (mService.isAppLockedPackage(aInfo.packageName) && !mService.isAppLockedVerifying(aInfo.packageName))
&& !isLaunchedFromRecents && !hasMultiWindowStyle
&& !PersonaManager.isKnoxId(userId)) {
Slog.d(TAG, "AppLocked pkgName:" + aInfo.packageName + " className:" + aInfo.name);
mService.setAppLockedVerifying(aInfo.packageName, true);
String action = mService.getAppLockedCheckAction();
Intent newIntent = new Intent(action);
ActivityInfo appLockActivityInfo = resolveActivity(newIntent, null, startFlags,
null, userId);
if(appLockActivityInfo != null) {
newIntent.putExtra(AppLockPolicy.LOCKED_PACKAGE_INTENT, intent);
newIntent.putExtra(AppLockPolicy.LOCKED_PACKAGE_NAME, aInfo.packageName);
newIntent.setClassName(appLockActivityInfo.packageName, appLockActivityInfo.name);
newIntent.setFlags(intent.getFlags());
newIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
aInfo = appLockActivityInfo;
intent = newIntent;
} else {
Slog.e(TAG, "AppLock can not resolve Activity , should never happen. Check Action " + action);
}
}
}
/* SRC-TJ AppLock } */
/* { KNOX_BBC */
mService.setupKEAOverridePath(aInfo);
/* KNOX_BBC } */
ActivityRecord r;
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfigurations.get(Display.DUAL_SCREEN_MAIN_DISPLAY), resultRecord, resultWho,
requestCode, componentSpecified, voiceSession != null, this, container, options
/* { Multi-Window */, sourceRecord, resultTo /* Multi-Window } */);
} else {
/* Dual-Screen } */
r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
requestCode, componentSpecified, voiceSession != null, this, container, options
/* { Multi-Window */, sourceRecord, resultTo /* Multi-Window } */);
}
if (outActivity != null) {
outActivity[0] = r;
}
if (r.appTimeTracker == null && sourceRecord != null) {
// If the caller didn't specify an explicit time tracker, we want to continue
// tracking under any it has.
r.appTimeTracker = sourceRecord.appTimeTracker;
}
/* MARs Managed App Restrictions*/
if (MARsPolicyManager.MARs_ENABLE && mService.mMARsPolicyManager != null) {
if (mService.mMARsPolicyManager.isRestrictedPackage(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name),
caller, callingPid, callingUid , "activity", null)) {
return ActivityManager.START_PERMISSION_DENIED;
}
}
/* MARs */
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
// Block launching samsung home when display is not attached yet.
if (r.isSamsungHomeActivity() &&
mActivityDisplays.get(r.getDisplayId()) == null) {
Slog.d(TAG, "DisplayId#" + r.getDisplayId()
+ " for dualscreen is not attached. Abort!");
return ActivityManager.START_CANCELED;
}
}
/* Dual-Screen } */
/* { Resume-Booster */
if(r.isHomeActivity()) {
mService.setActivitySwitchBooster(true, true, true, r.packageName);
} else {
mService.setActivitySwitchBooster(true, true, false, r.packageName);
}
/* End of Resume-Booster } */
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
mService.mMultiWindowPolicy.applyMultiWindowLaunchStyle(sourceRecord, r);
if (!r.multiWindowStyle.equals(r.lastRelaunchedMultiWindowStyle)) {
r.lastRelaunchedMultiWindowStyle.setTo(r.multiWindowStyle, true);
}
}
/* Multi-Window } */
final ActivityStack stack = mFocusedStack;
if (voiceSession == null && (stack.mResumedActivity == null
|| stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
realCallingPid, realCallingUid, "Activity start")) {
PendingActivityLaunch pal =
new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
mPendingActivityLaunches.add(pal);
ActivityOptions.abort(options);
if (SecProductFeature_KNOX.SEC_PRODUCT_FEATURE_KNOX_SUPPORT_MDM) {
AuditLog.logAsUser(AuditLog.NOTICE, AuditLog.AUDIT_LOG_GROUP_APPLICATION, false,
android.os.Process.myPid(), "ActivityStackSupervisor",
AuditEvents.START_ACTIVITY + className + AuditEvents.FAILED, userId);
}
return ActivityManager.START_SWITCHES_CANCELED;
}
}
if (mService.mDidAppSwitch) {
// This is the second allowed switch since we stopped switches,
// so now just generally allow switches. Use case: user presses
// home (switches disabled, switch to home, mDidAppSwitch now true);
// user taps a home icon (coming from home so allowed, we hit here
// and now allow anyone to switch again).
mService.mAppSwitchesAllowedTime = 0;
} else {
mService.mDidAppSwitch = true;
}
doPendingActivityLaunchesLocked(false);
/* begin of app fw */
/*
if (mService.mTargetDismiss != null) {
mWindowManager.setDismissKeyguardOnNextActivity(true);
}
*/
/* end of app fw */
/* SEC_PRODUCT_FEATURE_COMMON_SUPPORT_WEARABLE_HMT {*/
if(VRApplicationPolicy.FEATURE_HMT) {
if(r.isVRActivity()) {
if(!mService.mVRApplicationPolicy.readyToStartVRActivityLocked(r, intent)) {
if (resultRecord != null) {
resultStack.sendActivityResultLocked(-1,
resultRecord, resultWho, requestCode,
Activity.RESULT_CANCELED, null);
}
ActivityOptions.abort(options);
return ActivityManager.START_SUCCESS;
}
} else {
if(mService.mVRApplicationPolicy.inVRMode()) {
Slog.d(TAG, "startActivity : The current top is vr activity. Do not interrupt it!!");
r.launchedBehindVRApp = true;
}
}
}
/*} SEC_PRODUCT_FEATURE_COMMON_SUPPORT_WEARABLE_HMT */
err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, true, options, inTask);
if (err < 0) {
// If someone asked to have the keyguard dismissed on the next
// activity start, but we are not actually doing an activity
// switch... just dismiss the keyguard now, because we
// probably want to see whatever is behind it.
/* { AppCore */
if (mService.isTargetDismissIntent(r)) {
/* AppCore } */
notifyActivityDrawnForKeyguard();
}
}
return err;
}
private int getComponentRestrictionForCallingPackage(ActivityInfo activityInfo,
String callingPackage, int callingPid, int callingUid, boolean ignoreTargetSecurity) {
if (!ignoreTargetSecurity && mService.checkComponentPermission(activityInfo.permission,
callingPid, callingUid, activityInfo.applicationInfo.uid, activityInfo.exported)
== PackageManager.PERMISSION_DENIED) {
return ACTIVITY_RESTRICTION_PERMISSION;
}
if (activityInfo.permission == null) {
return ACTIVITY_RESTRICTION_NONE;
}
final int opCode = AppOpsManager.permissionToOpCode(activityInfo.permission);
if (opCode == AppOpsManager.OP_NONE) {
return ACTIVITY_RESTRICTION_NONE;
}
if (mService.mAppOpsService.noteOperation(opCode, callingUid,
callingPackage) != AppOpsManager.MODE_ALLOWED) {
if (!ignoreTargetSecurity) {
return ACTIVITY_RESTRICTION_APPOP;
}
}
return ACTIVITY_RESTRICTION_NONE;
}
private int getActionRestrictionForCallingPackage(String action,
String callingPackage, int callingPid, int callingUid) {
if (action == null) {
return ACTIVITY_RESTRICTION_NONE;
}
String permission = ACTION_TO_RUNTIME_PERMISSION.get(action);
if (permission == null) {
return ACTIVITY_RESTRICTION_NONE;
}
final PackageInfo packageInfo;
try {
packageInfo = mService.mContext.getPackageManager()
.getPackageInfo(callingPackage, PackageManager.GET_PERMISSIONS);
} catch (PackageManager.NameNotFoundException e) {
Slog.i(TAG, "Cannot find package info for " + callingPackage);
return ACTIVITY_RESTRICTION_NONE;
}
if (!ArrayUtils.contains(packageInfo.requestedPermissions, permission)) {
return ACTIVITY_RESTRICTION_NONE;
}
if (mService.checkPermission(permission, callingPid, callingUid) ==
PackageManager.PERMISSION_DENIED) {
return ACTIVITY_RESTRICTION_PERMISSION;
}
final int opCode = AppOpsManager.permissionToOpCode(permission);
if (opCode == AppOpsManager.OP_NONE) {
return ACTIVITY_RESTRICTION_NONE;
}
if (mService.mAppOpsService.noteOperation(opCode, callingUid,
callingPackage) != AppOpsManager.MODE_ALLOWED) {
return ACTIVITY_RESTRICTION_APPOP;
}
return ACTIVITY_RESTRICTION_NONE;
}
ActivityStack computeStackFocus(ActivityRecord r, boolean newTask) {
/* { Multi-Window */
return computeStackFocus(r, newTask, null);
}
ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, ActivityRecord sourceRecord) {
/* { Dual-Screen */
return computeStackFocus(r, newTask, sourceRecord, true);
}
ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, ActivityRecord sourceRecord, boolean updateFocus) {
/* Dual-Screen } */
/* Multi-Window } */
final TaskRecord task = r.task;
/* SEC_PRODUCT_FEATURE_COMMON_SUPPORT_WEARABLE_HMT {*/
if(VRApplicationPolicy.FEATURE_HMT) {
if(r.isVRActivity()) {
return mService.mVRApplicationPolicy.adjustStackFocus(r, task);
}
}
/*} SEC_PRODUCT_FEATURE_COMMON_SUPPORT_WEARABLE_HMT */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
return mService.mMultiWindowPolicy.adjustStackFocus(r, task/* { Multi-Window */,sourceRecord/* Multi-Window } */ /* { Dual-Screen */, updateFocus/* Dual-Screen } */);
} else {
// On leanback only devices we should keep all activities in the same stack.
if (!mLeanbackOnlyDevice &&
(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
ActivityStack stack = null;
/* TODO : MW/DUAL */
// Too many conficlt for dualscreen so make it as GED
if (task != null && task.stack != null
/* { Multi-Display */
&& (!MULTIDISPLAY_ENABLED
|| task.stack.mDisplayId == r.getDisplayId())
/* Multi-Display } */) {
stack = task.stack;
if (stack.isOnHomeDisplay()) {
if (mFocusedStack != stack) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
"computeStackFocus: Setting " + "focused stack to r=" + r
+ " task=" + task);
/* { Dual-Screen */
mFocusedStack = stack;
if (DUALSCREEN_ENABLED) {
mFrontStacks[mFocusedStack.getDisplayId()] = mFocusedStack;
}
/* Dual-Screen } */
} else {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
"computeStackFocus: Focused stack already=" + mFocusedStack);
}
}
return stack;
}
final ActivityContainer container = r.mInitialActivityContainer;
if (container != null) {
// The first time put it on the desired stack, after this put on task stack.
r.mInitialActivityContainer = null;
return container.mStack;
}
if (mFocusedStack != mHomeStack && (!newTask ||
mFocusedStack.mActivityContainer.isEligibleForNewTasks())
/* { Multi-Display */
&& (!MULTIDISPLAY_ENABLED
|| mFocusedStack.mDisplayId == r.getDisplayId())
/* Multi-Display } */) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
"computeStackFocus: Have a focused stack=" + mFocusedStack);
return mFocusedStack;
}
/* { Multi-Display */
// TODO: this should be changed also when make logics for homeStack in other
// display.
if (!MULTIDISPLAY_ENABLED
|| r.getDisplayId() == Display.DEFAULT_DISPLAY) {
/* Multi-Display } */
final ArrayList<ActivityStack> homeDisplayStacks = mHomeStack.mStacks;
for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
stack = homeDisplayStacks.get(stackNdx);
if (!stack.isHomeStack()) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
"computeStackFocus: Setting focused stack=" + stack);
/* { Dual-Screen */
mFocusedStack = stack;
if (DUALSCREEN_ENABLED) {
mFrontStacks[mFocusedStack.getDisplayId()] = mFocusedStack;
}
/* Dual-Screen } */
return stack;
}
}
}
/* { Virtual-Screen */
if (VIRTUALSCREEN_ENABLED) {
if (VirtualScreenManagerService.self().isVirtualScreen(r.getDisplayId())) {
ArrayList<ActivityStack> stacks = getStacks(r.getDisplayId());
// Virtual screen basically has only 1 stack.
if (stacks.size() > 0) {
stack = stacks.get(stacks.size() - 1);
return stack;
}
}
}
/* Virtual-Screen } */
// Need to create an app stack for this user.
/* { Multi-Display */
if (MULTIDISPLAY_ENABLED) {
stack = createStackOnDisplay(getNextStackId(), r.getDisplayId());
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
mFocusedStack = stack;
mFrontStacks[mFocusedStack.getDisplayId()] = mFocusedStack;
}
/* Dual-Screen } */
} else {
/* Multi-Display } */
stack = createStackOnDisplay(getNextStackId(), Display.DEFAULT_DISPLAY);
}
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
+ r + " stackId=" + stack.mStackId);
return stack;
}
return mHomeStack;
}
}
boolean setFocusedStack(ActivityRecord r, String reason) {
if (r == null) {
// Not sure what you are trying to do, but it is not going to work...
return false;
}
final TaskRecord task = r.task;
if (task == null || task.stack == null) {
Slog.w(TAG, "Can't set focus stack for r=" + r + " task=" + task);
return false;
}
task.stack.moveToFront(reason);
// KNOX_CONTAINER_START
if(getPersonaManagerLocked() != null) {
getPersonaManagerLocked().notifyFocusChanged(r.userId);
}
// KNOX_CONTAINER_END
return true;
}
// KNOX_CONTAINER_START
/**
* getter for personamanagerservice instance
* @return
*/
PersonaManagerService getPersonaManagerLocked() {
if(SecProductFeature_KNOX.SEC_PRODUCT_FEATURE_KNOX_SUPPORT_CONTAINER) {
if (mPersonaManager == null) {
IBinder b = ServiceManager.getService(Context.PERSONA_SERVICE);
mPersonaManager = (PersonaManagerService) IPersonaManager.Stub.asInterface(b);
}
}
return mPersonaManager;
}
// KNOX_CONTAINER_END
/* { Dual-Screen */
boolean isValidCoupled(ActivityRecord ar, ActivityRecord parent) {
if (ar == null || parent == null) {
Slog.d(TAG, "isValidCoupled() failed! / Reason = ActivityRecord is null / ar = " + ar
+ " / parent = " + parent);
return false;
}
// 1) Check Intent's Flag
int forbidden = Intent.FLAG_ACTIVITY_NEW_TASK;
if (ar.intent != null && (ar.intent.getFlags() & forbidden) != 0) {
Slog.d(TAG, "isValidCoupled() failed! / Reason = It has FLAG_ACTIVITY_NEW_TASK / ar = "
+ ar + " / parent = " + parent);
return false;
}
// 2) Check whether it has right Screen
DualScreen sourceScreen = parent.dualScreenAttrs.getScreen();
DualScreen targetScreen = ar.dualScreenAttrs.getScreen();
if (sourceScreen == targetScreen) {
Slog.d(TAG,
"isValidCoupled() failed! / Reason = Screen Error! sourceScreen == targetScreen! / ar = "
+ ar + "targetScreen = " + targetScreen
+ " / parent = " + parent + "sourceScreen = " + sourceScreen);
return false;
}
return true;
}
/* Dual-Screen } */
final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
boolean doResume, Bundle options, TaskRecord inTask) {
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
mService.mDualScreenPolicy.showBackWindowIfNeededLocked(r);
}
/* Dual-Screen } */
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
mService.mMultiWindowPolicy.applyMultiInstanceStyle(r, sourceRecord);
if (sourceRecord != null) {
r.sourceActivity = sourceRecord.realActivity;
/* { Dual-Screen */
if (DUALSCREEN_ENABLED
&& r.sourceActivity != null
&& r.sourceActivity.getClassName() != null
&& r.sourceActivity.getClassName().equals(
"com.android.internal.app.ResolverActivity")
&& sourceRecord.sourceActivity != null) {
r.dualScreenAttrs.triggerActivity = sourceRecord.sourceActivity;
}
/* Dual-Screen } */
}
}
/* Multi-Window } */
final Intent intent = r.intent;
final int callingUid = r.launchedFromUid;
/* { Dual-Screen */
boolean createdNewTask = false;
/* Dual-Screen } */
// In some flows in to this function, we retrieve the task record and hold on to it
// without a lock before calling back in to here... so the task at this point may
// not actually be in recents. Check for that, and if it isn't in recents just
// consider it invalid.
if (inTask != null && !inTask.inRecents) {
Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
inTask = null;
}
final boolean launchSingleTop = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP;
final boolean launchSingleInstance = r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE;
final boolean launchSingleTask = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK;
int launchFlags = intent.getFlags();
if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
(launchSingleInstance || launchSingleTask)) {
// We have a conflict between the Intent and the Activity manifest, manifest wins.
Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
"\"singleInstance\" or \"singleTask\"");
launchFlags &=
~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
} else {
switch (r.info.documentLaunchMode) {
case ActivityInfo.DOCUMENT_LAUNCH_NONE:
break;
case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
break;
case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
break;
case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
launchFlags &= ~Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
break;
}
}
final boolean launchTaskBehind = r.mLaunchTaskBehind
&& !launchSingleTask && !launchSingleInstance
&& (launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
if (r.resultTo != null && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0
&& r.resultTo.task.stack != null) {
// For whatever reason this activity is being launched into a new
// task... yet the caller has requested a result back. Well, that
// is pretty messed up, so instead immediately send back a cancel
// and let the new task continue launched as normal without a
// dependency on its originator.
Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
r.resultTo.task.stack.sendActivityResultLocked(-1,
r.resultTo, r.resultWho, r.requestCode,
Activity.RESULT_CANCELED, null);
r.resultTo = null;
}
if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
if (!r.fullscreen && sourceRecord != null
&& "android".equals(r.packageName)) {
if (r.multiWindowStyle.isCascade()
&& !sourceRecord.multiWindowStyle.isCascade()) {
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
}
} else {
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
}
} else {
/* Multi-Window } */
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
}
}
// If we are actually going to launch in to a new task, there are some cases where
// we further want to do multiple task.
if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
if (launchTaskBehind
|| r.info.documentLaunchMode == ActivityInfo.DOCUMENT_LAUNCH_ALWAYS) {
launchFlags |= Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
}
}
// We'll invoke onUserLeaving before onPause only if the launching
// activity did not explicitly state that this is an automated launch.
mUserLeaving = (launchFlags & Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
"startActivity() => mUserLeaving=" + mUserLeaving);
// If the caller has asked not to resume at this point, we make note
// of this in the record so that we can skip it when trying to find
// the top running activity.
if (!doResume) {
r.delayedResume = true;
}
ActivityRecord notTop =
(launchFlags & Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
// If the onlyIfNeeded flag is set, then we can do this if the activity
// being launched is the same as the one making the call... or, as
// a special case, if we do not know the caller then we count the
// current top activity as the caller.
if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
ActivityRecord checkedCaller = sourceRecord;
if (checkedCaller == null) {
checkedCaller = mFocusedStack.topRunningNonDelayedActivityLocked(notTop);
}
if (!checkedCaller.realActivity.equals(r.realActivity)) {
// Caller is not the same as launcher, so always needed.
startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
}
}
boolean addingToTask = false;
TaskRecord reuseTask = null;
// If the caller is not coming from another activity, but has given us an
// explicit task into which they would like us to launch the new activity,
// then let's see about doing that.
if (sourceRecord == null && inTask != null && inTask.stack != null
// start activity from recent task but no task in stack and it make NPE
// there is some google patch but it is work incorrectly
// for now block reuse task just check task history condition
&& inTask.stack.topTask() != null) {
final Intent baseIntent = inTask.getBaseIntent();
final ActivityRecord root = inTask.getRootActivity();
if (baseIntent == null) {
ActivityOptions.abort(options);
throw new IllegalArgumentException("Launching into task without base intent: "
+ inTask);
}
// If this task is empty, then we are adding the first activity -- it
// determines the root, and must be launching as a NEW_TASK.
if (launchSingleInstance || launchSingleTask) {
if (!baseIntent.getComponent().equals(r.intent.getComponent())) {
ActivityOptions.abort(options);
throw new IllegalArgumentException("Trying to launch singleInstance/Task "
+ r + " into different task " + inTask);
}
if (root != null) {
ActivityOptions.abort(options);
throw new IllegalArgumentException("Caller with inTask " + inTask
+ " has root " + root + " but target is singleInstance/Task");
}
}
// If task is empty, then adopt the interesting intent launch flags in to the
// activity being started.
if (root == null) {
final int flagsOfInterest = Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT
| Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
launchFlags = (launchFlags&~flagsOfInterest)
| (baseIntent.getFlags()&flagsOfInterest);
intent.setFlags(launchFlags);
inTask.setIntent(r);
addingToTask = true;
// If the task is not empty and the caller is asking to start it as the root
// of a new task, then we don't actually want to start this on the task. We
// will bring the task to the front, and possibly give it a new intent.
} else if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
addingToTask = false;
} else {
addingToTask = true;
}
reuseTask = inTask;
} else {
inTask = null;
}
if (inTask == null) {
if (sourceRecord == null) {
// This activity is not being started from another... in this
// case we -always- start a new task.
if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0 && inTask == null) {
Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
"Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
}
} else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
// The original activity who is starting us is running as a single
// instance... this new activity it is starting must go on its
// own task.
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
} else if (launchSingleInstance || launchSingleTask) {
// The activity being started is a single instance... it always
// gets launched into its own task.
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
}
}
ActivityInfo newTaskInfo = null;
Intent newTaskIntent = null;
ActivityStack sourceStack;
if (sourceRecord != null) {
if (sourceRecord.finishing) {
// If the source is finishing, we can't further count it as our source. This
// is because the task it is associated with may now be empty and on its way out,
// so we don't want to blindly throw it in to that task. Instead we will take
// the NEW_TASK flow and try to find a task for it. But save the task information
// so it can be used when creating the new task.
if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Slog.w(TAG, "startActivity called from finishing " + sourceRecord
+ "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
newTaskInfo = sourceRecord.info;
newTaskIntent = sourceRecord.task.intent;
}
/* { P141022-02089 */
if (r.resultTo != null && r.resultTo.task.stack != null && r.resultTo == sourceRecord) {
Slog.w(TAG, "Activity is launching from finishing " + sourceRecord + ", so cancelling activity result.");
r.resultTo.task.stack.sendActivityResultLocked(-1,
r.resultTo, r.resultWho, r.requestCode,
Activity.RESULT_CANCELED, null);
r.resultTo = null;
}
/* } */
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED
&& sourceRecord.task != null && sourceRecord.task.stack != null
&& sourceRecord.task.stack.isFloatingStack()) {
sourceStack = sourceRecord.task.stack;
} else {
/* Multi-Window } */
sourceStack = null;
sourceRecord = null;
}
} else {
sourceStack = sourceRecord.task.stack;
}
} else {
sourceStack = null;
}
boolean movedHome = false;
/* { Multi-Window */
ActivityStack targetStack = null;
/* Multi-Window } */
intent.setFlags(launchFlags);
final boolean noAnimation = (launchFlags & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0;
// We may want to try to place the new activity in to an existing task. We always
// do this if the target activity is singleTask or singleInstance; we will also do
// this if NEW_TASK has been requested, and there is not an additional qualifier telling
// us to still place it in a new task: multi task, always doc mode, or being asked to
// launch this as a new task behind the current one.
if (((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
(launchFlags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
|| ((launchSingleInstance || launchSingleTask)
/* { Multi-Window */ && !r.bMultiInstance) /* Multi-Window } */){
// If bring to front is requested, and no result is requested and we have not
// been given an explicit task to launch in to, and
// we can find a task that was started with this same
// component, then instead of launching bring that one to the front.
if (inTask == null && r.resultTo == null) {
// See if there is a task to bring to the front. If this is
// a SINGLE_INSTANCE activity, there can be one and only one
// instance of it in the history, and it is always in its own
// unique task, so we do a special search.
ActivityRecord intentActivity = !launchSingleInstance ?
findTaskLocked(r) : findActivityLocked(intent, r.info);
if (intentActivity != null) {
// When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused
// but still needs to be a lock task mode violation since the task gets
// cleared out and the device would otherwise leave the locked task.
if (isLockTaskModeViolation(intentActivity.task,
(launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
showLockTaskToast();
Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
if (r.task == null) {
r.task = intentActivity.task;
}
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
if (DualScreenSettings.isExpandHomeModeEnabled() && intentActivity.task.isExpandHomeTask()) {
if (mExpandedHomeTask != intentActivity.task) {
mExpandedHomeTask = intentActivity.task;
}
if (intentActivity.getDisplayId() != r.getDisplayId()) {
int targetDisplayId = mService.mDualScreenPolicy.moveExpandHomeStackTaskToTopInner(ActivityRecord.SAMSUNG_EXPAND_HOME_ACTIVITY_TYPE, "startActivity", r.getDisplayId(), false);
if (r.getDisplayId() != targetDisplayId) {
r.setScreen(DualScreen.displayIdToScreen(targetDisplayId));
}
}
} else if (intentActivity.task.isSamsungHomeTask()) {
if (r.getDisplayId() != intentActivity.getDisplayId()) {
if (SUPPORT_EXPANDED_MODE && ((intentActivity.getDisplayId() == Display.DUAL_SCREEN_EXPANDED_DISPLAY && r.getDisplayId() == Display.DUAL_SCREEN_SUB_DISPLAY)
|| (intentActivity.getDisplayId() == Display.DUAL_SCREEN_SUB_DISPLAY && r.getDisplayId() == Display.DUAL_SCREEN_EXPANDED_DISPLAY))) {
moveTaskToScreenLocked(intentActivity.task, r.getDisplayId(), true, true, false);
} else {
ActivityRecord topActivity = r.task !=null? r.task.topRunningActivityLocked(null) : null;
if (topActivity != null && topActivity.state == ActivityState.RESUMED && topActivity.nowVisible) {
// TODO : implement animation
Slog.secD(TAG, "SubHome already resumed. show animation!!!");
}
r.setScreen(DualScreen.displayIdToScreen(intentActivity.getDisplayId()));
}
} else {
// If it starts a SubHome consequentially, movePrevSamsungHomeTasks only prepared and not triggered yet.
// So need to update prevSamsungHomeTasks at this point.
scheduleMovePrevSamsungHomeTasks(intentActivity.task);
}
} else if (intentActivity.task.isHomeTask()) {
if (mExpandedHomeTask != null) {
mExpandedHomeTask = null;
}
} else if (intentActivity.task.isApplicationTask()) {
// If ApplicationTask tried to launch as SamusngHomeTask,
// update activityType and the move task to proper stack, then remove previous SamsungHomeTasks.
if (r.isSamsungHomeActivity()) {
for (ActivityRecord samsungHomeAr : intentActivity.task.mActivities) {
samsungHomeAr.mActivityType = ActivityRecord.SAMSUNG_HOME_ACTIVITY_TYPE;
}
intentActivity.task.taskType = ActivityRecord.SAMSUNG_HOME_ACTIVITY_TYPE;
intentActivity.task.fixed = true;
if (r.getDisplayId() != intentActivity.getDisplayId()) {
moveTaskToScreenLocked(intentActivity.task, r.getDisplayId(), true, true, false);
} else {
// move samsungHomeTask to SamsungHomeStack if the task is in Sub display.
moveTaskToStackLocked(intentActivity.task.taskId, SAMSUNG_HOME_STACK_ID, true, true);
}
scheduleMovePrevSamsungHomeTasks(intentActivity.task);
} else {
// SingleTask and SingleInstance task should be maintained a single task.
// Hence it moves the task to a screen if the task is not in foreground.
if (r.getDisplayId() != intentActivity.getDisplayId()
&& r.getDisplayId() != Display.DUAL_SCREEN_EXPANDED_DISPLAY
&& intentActivity.getDisplayId() != Display.DUAL_SCREEN_EXPANDED_DISPLAY) {
ActivityRecord topActivity = r.task !=null? r.task.topRunningActivityLocked(null) : null;
ActivityRecord topRunningActivity = topRunningActivityLocked(null, intentActivity.getDisplayId());
if (topActivity != null && topRunningActivity != null && topActivity.task == topRunningActivity.task && isFrontStack(topActivity.task.stack)
&& !mService.mDualScreenPolicy.mSingleScreenState) {
// TODO : implement animation
Slog.secD(TAG, "Task already on top. Show animation and do not move task to other screen!!!");
if (topActivity.nowVisible /* { Camera Rotation */&& !r.skipRotationAnimation/* Camera Rotation } */) {
mWindowManager.prepareDualScreenDisplayScaleTransition(intentActivity.appToken, intentActivity.getScreen());
}
r.setScreen(DualScreen.displayIdToScreen(intentActivity.getDisplayId()));
} else {
if (intentActivity.getDisplayId() == Display.DUAL_SCREEN_EXPANDED_DISPLAY
&& r.intent.getLaunchParams().getScreen() == DualScreen.UNKNOWN) {
// FullView app never move to other screen if target display is not specified.
r.setScreen(DualScreen.displayIdToScreen(intentActivity.getDisplayId()));
} else {
moveTaskToScreenLocked(intentActivity.task, r.getDisplayId(), true, true, false);
}
}
}
}
}
}
/* Dual-Screen } */
/* { Virtual-Screen */
if (VIRTUALSCREEN_ENABLED) {
if (intentActivity.isApplicationActivity()
&& r.getDisplayId() != intentActivity.getDisplayId()) {
VirtualScreenManagerService.self().moveTaskToDisplay(intentActivity.task, r.getDisplayId(), true);
}
}
/* Virtual-Screen } */
if (intentActivity.task.intent == null) {
// This task was started because of movement of
// the activity based on affinity... now that we
// are actually launching it, we can assign the
// base intent.
intentActivity.task.setIntent(r);
}
targetStack = intentActivity.task.stack;
targetStack.mLastPausedActivity = null;
// If the target task is not in the front, then we need
// to bring it to the front... except... well, with
// SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
// to have the same behavior as if a new instance was
// being started, which means not bringing it to the front
// if the caller is not itself in the front.
final ActivityStack focusStack = getFocusedStack();
ActivityRecord curTop = (focusStack == null)
? null : focusStack.topRunningNonDelayedActivityLocked(notTop);
boolean movedToFront = false;
if (curTop != null && (curTop.task != intentActivity.task ||
curTop.task != focusStack.topTask()
/* { Multi-Window */
|| (MultiWindowFeatures.MULTIWINDOW_ENABLED
&& (!curTop.multiWindowStyle.equals(r.multiWindowStyle) // from kk
|| (focusStack.isFloatingStack() && !isFrontStack(focusStack))))
/* Multi-Window } */)) {
/* { Multi-Window */
if (!(MultiWindowFeatures.MULTIWINDOW_ENABLED
&& curTop.multiWindowStyle.isEnabled(MultiWindowStyle.OPTION_MINIMIZED))) {
/* Multi-Window } */
if(!isKnoxmode()){
r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
isLaunchKnoxApps = false;
} else {
if (isLaunchKnoxApps) {
r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
isLaunchKnoxApps = false;
} else {
try {
if(intentActivity.task.affinity.compareTo("com.sec.android.app.launcher")!=0)
isLaunchKnoxApps = true;
} catch (NullPointerException npe) {
npe.printStackTrace();
}
}
}
}
if (sourceRecord == null || (sourceStack.topActivity() != null &&
sourceStack.topActivity().task == sourceRecord.task)) {
// We really do want to push this one into the user's face, right now.
if (launchTaskBehind && sourceRecord != null) {
intentActivity.setTaskToAffiliateWith(sourceRecord.task);
}
movedHome = true;
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
targetStack = computeStackFocus(r, false/* { Multi-Window */,sourceRecord/* Multi-Window } */);
if (targetStack != r.task.stack) {
targetStack.setMultiWindowStyleForAllActivitiesInTaskLocked(r.task, r.multiWindowStyle);
targetStack.notifyMultiWindowStyleChangedLocked(r.task.getTopActivity(), MultiWindowStyle.NOTIFY_REASON_STYLE_CHANGED, true);
final ArrayList<TaskRecord> taskList = r.task.stack.getAllTasks();
if (taskList.size() > 1 && targetStack.isNormalAppStack() && r.task.stack.isFloatingStack()) {
// When a cascade stack has the task more than 2 tasks, one of them start activity at launcher or quick panel.
// The other task remains cascade. and then if it have not full screen activity only, this is shown with black surface.
// So it is changed to normal app stack in these specific state.
int notFullScreenTaskNum = 0;
final ArrayList<TaskRecord> checkTaskList = new ArrayList<TaskRecord>();
for (TaskRecord task : taskList) {
if (r.task.taskId != task.taskId) {
checkTaskList.add(task);
ActivityRecord top = task.getTopActivity();
if (task.mActivities.size() == 1
&& top != null && !top.fullscreen) {
notFullScreenTaskNum++;
}
}
}
if (notFullScreenTaskNum == checkTaskList.size()) {
for (TaskRecord task : checkTaskList) {
targetStack.setMultiWindowStyleForAllActivitiesInTaskLocked(task, r.multiWindowStyle);
targetStack.notifyMultiWindowStyleChangedLocked(task.getTopActivity(), MultiWindowStyle.NOTIFY_REASON_STYLE_CHANGED, true);
}
}
}
// Change needResume parameter condition for launching app through service case. (P150316-01541)
// If application is launching through service, style is copied by process check routine.
// But, stack is not inherite and new stack is assigned because no source record.
// Because of that activity is move to new floating stack and blackout is coming in normal stack
// reason by no chance to resume on normal stack.
// (other case, stack is inherit and completePause makes call resumeTopActivitiesLocked)
// (this issue is same as before. but found in this version.)
ActivityRecord topActivity = r.task.topRunningActivityLocked(null);
boolean needToResume = (topActivity != null && topActivity.state == ActivityState.RESUMED
&& (!r.task.stack.isFloatingStack() && targetStack.isFloatingStack()));
targetStack.moveToFront("move task to stack", r.task);
moveTaskToStackLocked(r.task.taskId, targetStack.getStackId(), true, needToResume);
// refresh targetStack as stack of current activity record
// after rearrange multi window style and task move to other stack
// to be set targetStack properly.
targetStack = r.task.stack;
targetStack.prepareTaskToFrontTransition(r.task, r, options, startFlags);
if (r.multiWindowStyle.isNormal() && !resumeTopActivitiesLocked()) {
mRecentTasks.addLocked(r.task);
pauseBackStacks(false, true, true);
}
} else {
boolean isDoResume = true;
isDoResume = (r.intent.getFlags() & Intent.FLAG_ACTIVITY_SEND_NEW_INTENT_BEFORE_RESUME) == 0;
targetStack.moveTaskToFrontLocked(intentActivity.task, noAnimation,
options, r.appTimeTracker, 0, "bringingFoundTaskToFront", isDoResume);
targetStack = r.task.stack;
/* { Galaxy-Desktop */
if (DESKTOPMODE_ENABLED && mService.isKnoxDesktopModeLocked()) {
if (intentActivity.task.stack.isHomeStack() && !(r != null && r.isRecentsActivity())) {
ArrayList<TaskRecord> taskOrder = new ArrayList<TaskRecord>(getGlobalTaskHistoryLocked(r.getDisplayId()));
int N = taskOrder.size();
// home key is pressed
boolean pressedHomeKey = r.intent.getFromHomeKey();
for (int i = 0; i < N; i++) {
TaskRecord tr = taskOrder.get(i);
final ActivityStack stack = tr.stack;
if (stack.isFloatingStack() && !tr.multiWindowStyle.isEnabled(MultiWindowStyle.OPTION_MINIMIZED) && !pressedHomeKey) {
Slog.d(TAG_TASKS, "[DeskTopMode] Extra MoveTaskToFront i = "+i+", tr = " + tr);
stack.moveTaskToFrontLocked(tr, noAnimation,
options, r.appTimeTracker, 0, "bringingFoundTaskToFront", isDoResume);
}
}
}
}
/* Galaxy-Desktop } */
}
} else {
/* Multi-Window } */
// We want to immediately deliver the intent to the activity if
// it is currently the top resumed activity... however, if the
// device is sleeping, then all activities are stopped, so in that
// case we will deliver it if this is the current top activity on its
// stack.
boolean isDoResume = true;
isDoResume = (r != null && ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_SEND_NEW_INTENT_BEFORE_RESUME) == 0));
targetStack.moveTaskToFrontLocked(intentActivity.task, noAnimation,
options, r.appTimeTracker, 0, "bringingFoundTaskToFront", isDoResume);
}
movedToFront = true;
if ((launchFlags &
(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
// Caller wants to appear on home activity.
/* Dual-Screen */
if (SUPPORT_EXPANDED_MODE && DualScreenSettings.isExpandHomeModeEnabled()) {
intentActivity.task.setTaskToReturnTo(ActivityRecord.SAMSUNG_EXPAND_HOME_ACTIVITY_TYPE);
} else {
/* Dual-Screen */
intentActivity.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
}
}
options = null;
}
}
if (!movedToFront) {
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + targetStack
+ " from " + intentActivity);
targetStack.moveToFront("intentActivityFound");
}
// If the caller has requested that the target task be
// reset, then do so.
if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
}
if ((startFlags & ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don't need to start a new activity, and
// the client said not to do anything if that
// is the case, so this is it! And for paranoia, make
// sure we have correctly resumed the top activity.
if (doResume) {
resumeTopActivitiesLocked(targetStack, null, options);
// Make sure to notify Keyguard as well if we are not running an app
// transition later.
if (!movedToFront) {
notifyActivityDrawnForKeyguard();
}
} else {
ActivityOptions.abort(options);
}
return ActivityManager.START_RETURN_INTENT_TO_CALLER;
}
/* { Multi Window */
boolean ignoreIntentActivity = false;
/* Multi Window } */
if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
// The caller has requested to completely replace any
// existing task with its new activity. Well that should
// not be too hard...
reuseTask = intentActivity.task;
reuseTask.performClearTaskLocked();
reuseTask.setIntent(r);
} else if ((launchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| launchSingleInstance || launchSingleTask) {
// In this situation we want to remove all activities
// from the task up to the one being started. In most
// cases this means we are resetting the task to its
// initial state.
ActivityRecord top =
intentActivity.task.performClearTaskLocked(r, launchFlags);
if (top != null) {
if (top.frontOfTask) {
// Activity aliases may mean we use different
// intents for the top activity, so make sure
// the task now has the identity of the new
// intent.
top.task.setIntent(r);
}
ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
r, top.task);
top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage);
/* { Multi Window */
} else if (MultiWindowFeatures.MULTIWINDOW_ENABLED
&& intentActivity.task.stack != null && ((getStack(intentActivity.task.stack.mStackId) == null) ||
(intentActivity.task.stack.taskForIdLocked(intentActivity.task.taskId) == null))) {
// If performClearTaskLocked method removed intentActivity's task or its stack,
// we cannot reuse its stack and task. So we need to act like there was no intentActivity here.
r.task = null;
ignoreIntentActivity = true;
if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
// If we don't need to create new task,
// check if the sourceRecord's type with the one of new activity.
if ((sourceRecord != null) &&
(sourceRecord.task.isHomeTask() ^ r.task.isHomeTask())) {
sourceRecord = null;
}
}
/* Multi Window } */
} else {
// A special case: we need to start the activity because it is not
// currently running, and the caller has asked to clear the current
// task to have this activity at the top.
addingToTask = true;
// Now pretend like this activity is being started by the top of its
// task, so it is put in the right place.
sourceRecord = intentActivity;
TaskRecord task = sourceRecord.task;
if (task != null && task.stack == null) {
// Target stack got cleared when we all activities were removed
// above. Go ahead and reset it.
targetStack = computeStackFocus(sourceRecord, false /* newTask */);
targetStack.addTask(
task, !launchTaskBehind /* toTop */, false /* moving */);
}
}
} else if (r.realActivity.equals(intentActivity.task.realActivity)) {
// In this case the top activity on the task is the
// same as the one being launched, so we take that
// as a request to bring the task to the foreground.
// If the top activity in the task is the root
// activity, deliver this new intent to it if it
// desires.
if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0 || launchSingleTop)
&& intentActivity.realActivity.equals(r.realActivity)) {
ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
intentActivity.task);
if (intentActivity.frontOfTask) {
intentActivity.task.setIntent(r);
}
intentActivity.deliverNewIntentLocked(callingUid, r.intent,
r.launchedFromPackage);
} else if (!r.intent.filterEquals(intentActivity.task.intent)) {
// In this case we are launching the root activity
// of the task, but with a different intent. We
// should start a new instance on top.
addingToTask = true;
sourceRecord = intentActivity;
/* { Dual-Screen */
} else if (DUALSCREEN_ENABLED && r.intent.getStringExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT) != null) {
if (!r.intent.getStringExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT)
.equals(intentActivity.task.intent.getStringExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT))) {
addingToTask = true;
sourceRecord = intentActivity;
}
/* Dual-Screen } */
}
} else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
// In this case an activity is being launched in to an
// existing task, without resetting that task. This
// is typically the situation of launching an activity
// from a notification or shortcut. We want to place
// the new activity on top of the current task.
addingToTask = true;
sourceRecord = intentActivity;
} else if (!intentActivity.task.rootWasReset) {
// In this case we are launching in to an existing task
// that has not yet been started from its front door.
// The current task has been brought to the front.
// Ideally, we'd probably like to place this new task
// at the bottom of its stack, but that's a little hard
// to do with the current organization of the code so
// for now we'll just drop it.
intentActivity.task.setIntent(r);
}
if (!addingToTask && reuseTask == null
/* { Multi Window */
&& !(MultiWindowFeatures.MULTIWINDOW_ENABLED && ignoreIntentActivity)
/* Multi Window } */) {
// We didn't do anything... but it was needed (a.k.a., client
// don't use that intent!) And for paranoia, make
// sure we have correctly resumed the top activity.
if (doResume) {
/* { Multi Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
if (r.isHomeActivity()) {
// home key is pressed
boolean fromHomeKey = r.intent.getFromHomeKey();
r.intent.setFromHomeKey(false);
if (fromHomeKey) {
/* { Galaxy-Desktop */
if (DESKTOPMODE_ENABLED && mService.isKnoxDesktopModeLocked()) {
mService.mMultiWindowPolicy.moveAllTasksToBackInAllFloatingStacks(null);
} else {
/* Galaxy-Desktop } */
mService.mMinimizeAllPenWindowRequested = true;
ActivityRecord homeActivity = getHomeActivity();
if (homeActivity != null && homeActivity.state == ActivityState.RESUMED) {
// If topActivity is not home activity, orientation can be changed while launching home activity.
// Delay minimizing pen window action until we can know next device orienation.
// (check resumeTopActivityInnerLocked in ActivityStack)
handleMinimizeAllPenWindow();
}
}
}
}
if (targetStack != null && isFrontStack(targetStack)) {
targetStack.resumeTopActivityLocked(null, options);
ActivityRecord focusedActivity = targetStack.topRunningActivityLocked(null);
mService.setFocusedActivityLocked(focusedActivity, "startActivityUncheckedNewTask");
}
} else {
/* Multi-Window } */
/* { Virtual-Screen */
if (VIRTUALSCREEN_ENABLED) {
if (targetStack != null && isFrontStack(targetStack)) {
targetStack.resumeTopActivityLocked(null, options);
}
} else {
targetStack.resumeTopActivityLocked(null, options);
}
/* Virtual-Screen } */
}
if (!movedToFront) {
// Make sure to notify Keyguard as well if we are not running an app
// transition later.
/* { AppCore */
if (curTop == null || mService.isTargetDismissIntent(curTop)) {
/* AppCore } */
notifyActivityDrawnForKeyguard();
}
}
} else {
ActivityOptions.abort(options);
}
return ActivityManager.START_TASK_TO_FRONT;
}
}
}
}
//String uri = r.intent.toURI();
//Intent intent2 = new Intent(uri);
//Slog.i(TAG, "Given intent: " + r.intent);
//Slog.i(TAG, "URI is: " + uri);
//Slog.i(TAG, "To intent: " + intent2);
if (r.packageName != null) {
// If the activity being launched is the same as the one currently
// at the top, then we need to check if it should only be launched
// once.
ActivityStack topStack = mFocusedStack;
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
/*
ActivityStack expandedStack = getExpandedStack();
// if this is expanded and new layer main/sub then dim layer should be set
if (DUALSCREEN_ENABLED && isFrontStack(expandedStack)
&& (r.dualScreenAttrs.getDisplayId() == Display.DUAL_SCREEN_MAIN_DISPLAY
|| r.dualScreenAttrs.getDisplayId() == Display.DUAL_SCREEN_SUB_DISPLAY)) {
//expandedStack.setDimFlag(true, false);
}
*/
if (r.getDisplayId() == Display.DUAL_SCREEN_MAIN_DISPLAY) {
topStack = mFrontStacks[r.getDisplayId()];
if (topStack == null)
topStack = mHomeStack;
} else if (r.getDisplayId() == Display.DUAL_SCREEN_SUB_DISPLAY) {
topStack = mFrontStacks[r.getDisplayId()];
if (topStack == null)
topStack = mSamsungHomeStack;
} else if (SUPPORT_EXPANDED_MODE
&& r.getDisplayId() == Display.DUAL_SCREEN_EXPANDED_DISPLAY) {
topStack = mFrontStacks[r.getDisplayId()]; //???
}
}
/* Dual-Screen } */
ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
/* { Multi-Window */
// If reuseTask is set, then the task can be clearing by FLAG_ACTIVITY_CLEAR_TASK.
// because of clearing, top can be below task instead of reuseTask.
// and then, if below task is same package due to multi-instance, it works for below task.
// in this case, this logic should skip. so set top to null.
if (MultiWindowFeatures.MULTIWINDOW_ENABLED && reuseTask != null && top != null && reuseTask != top.task) {
top = null;
}
/* Multi-Window } */
if (top != null && r.resultTo == null) {
if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
if (top.app != null && top.app.thread != null) {
if (((launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
|| launchSingleTop || launchSingleTask)
/* { Multi-Window */&& !r.bMultiInstance/* Multi-Window } */){
ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
top.task);
// For paranoia, make sure we have correctly
// resumed the top activity.
topStack.mLastPausedActivity = null;
if (doResume) {
resumeTopActivitiesLocked();
}
ActivityOptions.abort(options);
if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don't need to start a new activity, and
// the client said not to do anything if that
// is the case, so this is it!
return ActivityManager.START_RETURN_INTENT_TO_CALLER;
}
top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage);
return ActivityManager.START_DELIVERED_TO_TOP;
}
}
}
}
} else {
if (r.resultTo != null && r.resultTo.task.stack != null) {
r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
r.requestCode, Activity.RESULT_CANCELED, null);
}
ActivityOptions.abort(options);
return ActivityManager.START_CLASS_NOT_FOUND;
}
if ("46001".equals(CscFeature.getInstance().getString(CscFeatureTagFramework.TAG_CSCFEATURE_FRAMEWORK_CHECKVALIDAPP4SPECIFICMCCMNC))) {
if (checkCUVas(sourceRecord, intent) && !intent.getBooleanExtra("CU_Flag", false)) {
Intent in = new Intent("android.intent.action.CHECK_CU_VAS");
in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY);
in.putExtra("CU_Vas", intent);
try {
mService.mContext.startActivity(in);
} catch (ActivityNotFoundException e) {
Slog.d(TAG, "Activity Not Found !!! ");
e.printStackTrace();
}
return ActivityManager.START_SWITCHES_CANCELED;
}
} else if ("46000".equals(CscFeature.getInstance().getString(CscFeatureTagFramework.TAG_CSCFEATURE_FRAMEWORK_CHECKVALIDAPP4SPECIFICMCCMNC))) {
if (checkCUVas(sourceRecord, intent)) {
Intent in = new Intent("android.intent.action.CHECK_CMCC_VAS");
in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY);
try {
mService.mContext.startActivity(in);
} catch (ActivityNotFoundException e) {
Slog.d(TAG, "Activity Not Found !!! ");
e.printStackTrace();
}
return ActivityManager.START_SWITCHES_CANCELED;
}
}
boolean newTask = false;
boolean keepCurTransition = false;
/* { Dual-Screen */
boolean coupledTaskMode = false;
if (DUALSCREEN_ENABLED) {
if (sourceRecord != null
&& (r.intent.getLaunchParams().getFlags() & DualScreenLaunchParams.FLAG_COUPLED_TASK) != 0) {
if (isValidCoupled(r, sourceRecord)) {
coupledTaskMode = true;
TaskRecord candidateReuseTask = sourceRecord.task.getCoupledTask();
boolean coupledTaskExist = false;
// verify coupledTask is present
if (candidateReuseTask != null && candidateReuseTask.stack != null) {
for (int i = candidateReuseTask.stack.getGlobalTaskHistoryLocked().size() - 1; i >= 0; i--) {
TaskRecord top = candidateReuseTask.stack.getGlobalTaskHistoryLocked().get(i);
if (candidateReuseTask == top) {
coupledTaskExist = true;
break;
}
}
}
if (candidateReuseTask != null && coupledTaskExist) {
reuseTask = candidateReuseTask;
if (reuseTask != null && reuseTask.stack != null
&& isFrontStack(reuseTask.stack)) {
targetStack = reuseTask.stack;
}
} else {
newTaskInfo = sourceRecord.info;
if (sourceRecord.task.intent != null) {
// Prevent breaking down the Integrity of SourceTask's
// intent.
newTaskIntent = new Intent(sourceRecord.task.intent);
/*if (newTaskIntent != null) {
newTaskIntent
.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
}*/
}
}
}
else {
if (r.intent != null && r.intent.getLaunchParams() != null) {
int flag = r.intent.getLaunchParams().getFlags();
r.intent.getLaunchParams()
.setFlags(flag
& (~(DualScreenLaunchParams.FLAG_COUPLED_TASK)));
}
}
}
}
/* Dual-Screen } */
TaskRecord taskToAffiliate = launchTaskBehind && sourceRecord != null ?
sourceRecord.task : null;
// Should this be considered a new task?
if (r.resultTo == null && inTask == null && !addingToTask
&& (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0
/* { Dual-Screen */|| coupledTaskMode/* Dual-Screen } */) {
/* { AppCore : */
TaskRecord task = reuseTask != null ? reuseTask :
new TaskRecord(mService, getNextTaskId(),
newTaskInfo != null ? newTaskInfo : r.info,
newTaskIntent != null ? newTaskIntent : intent,
voiceSession, voiceInteractor);
if (isLockTaskModeViolation(task)) {
showLockTaskToast();
Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
/* AppCore } */
newTask = true;
/* { Virtual-Screen */
boolean updateFocus = true;
if (VIRTUALSCREEN_ENABLED) {
if (VirtualScreenManagerService.self().isVirtualScreen(r.getDisplayId())) {
updateFocus = false;
}
}
/* Virtual-Screen } */
targetStack = computeStackFocus(r, newTask/* { Multi-Window */,sourceRecord/* Multi-Window } */
/* { Virtual-Screen */, updateFocus/* Virtual-Screen } */);
/* { Multi-Window */
//Globaltasks mismatch between AM and WM
//move moveToFront after adding a new task
if (!MultiWindowFeatures.MULTIWINDOW_ENABLED) {
/* Multi-Window } */
targetStack.moveToFront("startingNewTask");
/* { Multi-Window */
}
/* Multi-Window } */
if (reuseTask == null) {
/* { AppCore */
// already created TaskRecord. before checking LockTaskMode.
targetStack.addTask(task, !launchTaskBehind /* toTop */, false, false, newTaskInfo != null ? newTaskInfo.flags : r.info.flags);
r.setTask(task, taskToAffiliate);
/* AppCore } */
if (DEBUG_TASKS) Slog.v(TAG_TASKS,
"Starting new activity " + r + " in new task " + r.task);
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
if (!launchTaskBehind) {
targetStack.moveToFront("startingNewTask");
}
}
/* Multi-Window } */
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
createdNewTask = true;
if (coupledTaskMode && sourceRecord != null && !sourceRecord.finishing) {
//1. make coupled between sourceTask and targetTask
r.task.setParentCoupledTask(sourceRecord.task);
sourceRecord.task.setChildCoupledTask(r.task);
//2. inherit mFinishWithCoupledTask from sourceTask(parentTask)
r.task.setFinishWithCoupledTask(sourceRecord.task.isFinishWithCoupledTask());
}
}
/* Dual-Screen } */
} else {
r.setTask(reuseTask, taskToAffiliate);
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
if (!launchTaskBehind) {
targetStack.moveToFront("startingNewTask", reuseTask);
}
}
/* Multi-Window } */
}
if (!movedHome) {
if ((launchFlags &
(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
// Caller wants to appear on home activity, so before starting
// their own activity we will bring home to the front.
r.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
}
}
} else if (sourceRecord != null) {
TaskRecord sourceTask = sourceRecord.task;
if (isLockTaskModeViolation(sourceTask)) {
showLockTaskToast();
Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
targetStack = sourceTask.stack;
targetStack.moveToFront("sourceStackToFront");
final TaskRecord topTask = targetStack.topTask();
if (topTask != sourceTask) {
targetStack.moveTaskToFrontLocked(sourceTask, noAnimation, options,
r.appTimeTracker, "sourceTaskToFront");
}
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
moveStack(targetStack, true);
if(targetStack.isFloatingStack() && r.multiWindowStyle.isEnabled(MultiWindowStyle.OPTION_FULLSCREEN_ONLY)) {
targetStack.mActivityContainer.moveGlobalTaskToTop(sourceTask);
}
// LRX16 Patch customized on GlobalTaskHistory
// TBD : add logic moving home tasks at moveStack(), make patch code as same as GED.
if(topTask != sourceTask || !isFrontStack(targetStack)) {
targetStack.moveTaskToFrontLocked(sourceTask, noAnimation, options, r.appTimeTracker, "sourceTaskToFront");
}
if (sourceRecord.multiWindowStyle.isEnabled(MultiWindowStyle.OPTION_MINIMIZED) && sourceTask.stack != null) {
sourceTask.stack.setMultiWindowStyleForAllActivitiesInTaskLocked(sourceTask, r.multiWindowStyle);
sourceTask.stack.notifyMultiWindowStyleChangedLocked(sourceRecord, MultiWindowStyle.NOTIFY_REASON_STYLE_CHANGED, true);
}
} else {
/* Multi-Window } */
targetStack.moveToFront("sourceStackToFront");
if (topTask != sourceTask) {
targetStack.moveTaskToFrontLocked(sourceTask, noAnimation, options,
r.appTimeTracker, "sourceTaskToFront");
}
}
if (!addingToTask && (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
// In this case, we are adding the activity to an existing
// task, but the caller has asked to clear that task if the
// activity is already running.
ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags);
keepCurTransition = true;
if (top != null) {
ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage);
// For paranoia, make sure we have correctly
// resumed the top activity.
targetStack.mLastPausedActivity = null;
if (doResume) {
targetStack.resumeTopActivityLocked(null);
/* { AppCore : need to focus Activity routine */
if (!launchTaskBehind) {
mService.setFocusedActivityLocked(top, "FIXME");
}
/* AppCore } : need to focus Activity routine */
}
ActivityOptions.abort(options);
return ActivityManager.START_DELIVERED_TO_TOP;
}
} else if (!addingToTask &&
(launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
// In this case, we are launching an activity in our own task
// that may already be running somewhere in the history, and
// we want to shuffle it to the front of the stack if so.
final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r);
if (top != null) {
final TaskRecord task = top.task;
// DEVICEREPORTING_TMO_INTEGRATION_START
if (CscFeature.getInstance().getEnableStatus("CscFeature_Common_SupportDeviceReporting"))
// Sending information of the focused application which has package name
// "newTop.packageName"
AppStateBroadcaster.sendApplicationFocusGain(mService.mContext, top.packageName);
// DEVICEREPORTING_TMO_INTEGRATION_END
task.moveActivityToFrontLocked(top);
ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
top.updateOptionsLocked(options);
top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage);
targetStack.mLastPausedActivity = null;
if (doResume) {
targetStack.resumeTopActivityLocked(null);
/* { AppCore : need to focus Activity routine */
if (!launchTaskBehind) {
mService.setFocusedActivityLocked(top, "FIXME");
}
/* AppCore } : need to focus Activity routine */
}
return ActivityManager.START_DELIVERED_TO_TOP;
}
}
// An existing activity is starting this new activity, so we want
// to keep the new one in the same task as the one that is starting
// it.
r.setTask(sourceTask, null);
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + r
+ " in existing task " + r.task + " from source " + sourceRecord);
/* { KDM_Start */
if (DESKTOPMODE_ENABLED && mService.isKnoxDesktopModeLocked()) {
if (r.isApplicationActivity()) { // new app is called in same task. (MyFile ->Gallery)
ComponentName cn = null;
if (sourceTask.getTopActivity() != null) {
cn = sourceTask.getTopActivity().intent.getComponent();
} else {
cn = sourceTask.getBaseIntent().getComponent();
}
//
if (!r.realActivity.getPackageName().equals(cn.getPackageName())) {
notifyAppsStatusToTaskBar(APP_UPDATE, sourceTask, r.realActivity, r.launchedFromPackage);
}
}
}
/* KDM_End } */
} else if (inTask != null) {
// The caller is asking that the new activity be started in an explicit
// task it has provided to us.
if (isLockTaskModeViolation(inTask)) {
showLockTaskToast();
Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
if (r.multiWindowStyle.getType() == MultiWindowStyle.TYPE_CASCADE
&& needMoveOnlySpecificTaskToFront(inTask.taskId)
&& getSpecificFloatingStack() != null) {
targetStack = getSpecificFloatingStack();
} else {
targetStack = computeStackFocus(r, true, sourceRecord);
}
if (targetStack != inTask.stack) {
targetStack.setMultiWindowStyleForAllActivitiesInTaskLocked(inTask, r.multiWindowStyle);
targetStack.notifyMultiWindowStyleChangedLocked(inTask.getTopActivity(), MultiWindowStyle.NOTIFY_REASON_STYLE_CHANGED, true);
final TaskRecord task = anyTaskForIdLocked(inTask.taskId);
if (task == null) {
inTask.stack = targetStack;
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
inTask.displayId = targetStack.mDisplayId;
}
/* Dual-Screen } */
}else{
moveTaskToStackLocked(inTask.taskId, targetStack.getStackId(), true, false);
}
} else {
targetStack = inTask.stack;
targetStack.moveTaskToFrontLocked(inTask, noAnimation, options, r.appTimeTracker, "inTaskToFront");
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
// sync displayId of restored task to displayId of targeted stack for avoiding mismatch case.
inTask.displayId = targetStack.mDisplayId;
}
/* Dual-Screen } */
}
} else {
/* Multi-Window } */
targetStack = inTask.stack;
targetStack.moveTaskToFrontLocked(inTask, noAnimation, options, r.appTimeTracker,
"inTaskToFront");
/* { AppCore */
if (targetStack.topRunningActivityLocked(null) == null) {
targetStack.moveToFront("inTaskToFront");
}
/* AppCore } */
}
// Check whether we should actually launch the new activity in to the task,
// or just reuse the current activity on top.
ActivityRecord top = inTask.getTopActivity();
if (top != null && top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
if ((launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
|| launchSingleTop || launchSingleTask) {
ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don't need to start a new activity, and
// the client said not to do anything if that
// is the case, so this is it!
return ActivityManager.START_RETURN_INTENT_TO_CALLER;
}
top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage);
return ActivityManager.START_DELIVERED_TO_TOP;
}
}
if (!addingToTask) {
// We don't actually want to have this activity added to the task, so just
// stop here but still tell the caller that we consumed the intent.
ActivityOptions.abort(options);
return ActivityManager.START_TASK_TO_FRONT;
}
r.setTask(inTask, null);
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + r
+ " in explicit task " + r.task);
} else {
// This not being started from an existing activity, and not part
// of a new task... just put it in the top task, though these days
// this case should never happen.
targetStack = computeStackFocus(r, newTask/* { Multi-Window */,sourceRecord/* Multi-Window } */);
targetStack.moveToFront("addingToTopTask");
ActivityRecord prev = targetStack.topActivity();
r.setTask(prev != null ? prev.task : targetStack.createTaskRecord(getNextTaskId(),
r.info, intent, null, null, true), null);
mWindowManager.moveTaskToTop(r.task.taskId);
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + r
+ " in new guessed " + r.task);
}
/* { Virtual-Screen */
if (VIRTUALSCREEN_ENABLED) {
if (intent != null && (intent.getVirtualScreenParams().mFlags
& VirtualScreenLaunchParams.FLAG_CLEAR_TASKS) != 0) {
for (TaskRecord task : targetStack.getAllTasks()) {
if (r.task != task) {
task.performClearTaskLocked();
}
}
}
}
/* Virtual-Screen } */
mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
intent, r.getUriPermissionsLocked(), r.userId);
if (sourceRecord != null && sourceRecord.isRecentsActivity()) {
r.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
}
if (newTask) {
EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
}
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
if (r.bMultiInstance && r.task.intent != null) {
r.task.intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
}
if (r.multiWindowStyle != null) {
r.multiWindowStyle.resetSpecificTaskId();
}
}
/* Multi-Window } */
ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
targetStack.mLastPausedActivity = null;
targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options
/* { Dual-Screen */, createdNewTask/* Dual-Screen } */);
if (!launchTaskBehind) {
// Don't set focus on an activity that's going to the back.
mService.setFocusedActivityLocked(r, "startedActivity");
}
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
if (r.task.isSamsungHomeTask()) {
// Move prev SubHomeTasks to AppStack if the task changed.
scheduleMovePrevSamsungHomeTasks(r.task);
} else if (r.task.isExpandHomeTask()) {
mExpandedHomeTask = r.task;
} else if (r.task.isHomeTask()) {
mExpandedHomeTask = null;
}
}
/* Dual-Screen } */
return ActivityManager.START_SUCCESS;
}
final void doPendingActivityLaunchesLocked(boolean doResume) {
while (!mPendingActivityLaunches.isEmpty()) {
PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
try {
startActivityUncheckedLocked(pal.r, pal.sourceRecord, null, null, pal.startFlags,
doResume && mPendingActivityLaunches.isEmpty(), null, null);
} catch (Exception e) {
Slog.w(TAG, "Exception during pending activity launch pal=" + pal, e);
}
}
}
void removePendingActivityLaunchesLocked(ActivityStack stack) {
for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
if (pal.stack == stack) {
mPendingActivityLaunches.remove(palNdx);
}
}
}
void setLaunchSource(int uid) {
mLaunchingActivity.setWorkSource(new WorkSource(uid));
}
void acquireLaunchWakelock() {
if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
throw new IllegalStateException("Calling must be system uid");
}
mLaunchingActivity.acquire();
if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
// To be safe, don't allow the wake lock to be held for too long.
mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
}
}
/**
* Called when the frontmost task is idle.
* @return the state of mService.mBooting before this was called.
*/
private boolean checkFinishBootingLocked() {
final boolean booting = mService.mBooting;
boolean enableScreen = false;
mService.mBooting = false;
if (!mService.mBooted) {
mService.mBooted = true;
enableScreen = true;
}
if (booting || enableScreen) {
mService.postFinishBooting(booting, enableScreen);
}
return booting;
}
// Checked.
final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
Configuration config) {
if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + token);
ArrayList<ActivityRecord> stops = null;
ArrayList<ActivityRecord> finishes = null;
ArrayList<UserState> startingUsers = null;
int NS = 0;
int NF = 0;
boolean booting = false;
boolean activityRemoved = false;
/* { Dual-Screen */
int displayId = Display.DISPLAY_NONE;
/* Dual-Screen } */
ActivityRecord r = ActivityRecord.forTokenLocked(token);
if (r != null) {
if (DEBUG_IDLE) Slog.d(TAG_IDLE, "activityIdleInternalLocked: Callers="
+ Debug.getCallers(4));
mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
displayId = r.getDisplayId();
}
/* Dual-Screen } */
r.finishLaunchTickingLocked();
if (fromTimeout) {
reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
}
// This is a hack to semi-deal with a race condition
// in the client where it can be constructed with a
// newer configuration from when we asked it to launch.
// We'll update with whatever configuration it now says
// it used to launch.
if (config != null) {
r.configuration = config;
}
// We are now idle. If someone is waiting for a thumbnail from
// us, we can now deliver.
r.idle = true;
//Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
if (isFrontStack(r.task.stack) || fromTimeout) {
booting = checkFinishBootingLocked();
} else if (mService.mBooting) {
if (mFocusedStack != null &&
mFocusedStack.mResumedActivity != null) {
Slog.e(TAG, "!@Boot: FocusedStack is " +
mFocusedStack.mResumedActivity.info.toString());
} else {
Slog.e(TAG, "!@Boot: mFocusedStack is not mHomeStack ");
}
}
}
if (allResumedActivitiesIdle()) {
if (r != null) {
mService.scheduleAppGcsLocked();
}
if (mLaunchingActivity.isHeld()) {
mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
if (VALIDATE_WAKE_LOCK_CALLER &&
Binder.getCallingUid() != Process.myUid()) {
throw new IllegalStateException("Calling must be system uid");
}
mLaunchingActivity.release();
}
ensureActivitiesVisibleLocked(null, 0);
}
// Atomically retrieve all of the other things to do.
stops = processStoppingActivitiesLocked(true/* { Dual-Screen */, displayId/* Dual-Screen } */);
NS = stops != null ? stops.size() : 0;
/* { Dual-Screen */
ArrayList<ActivityRecord> mFinishingActivities;
if (DUALSCREEN_ENABLED) {
mFinishingActivities = processFinishingActivitiesLocked(true, displayId);
} else {
mFinishingActivities = this.mFinishingActivities;
}
/* Dual-Screen } */
if ((NF=mFinishingActivities.size()) > 0) {
finishes = new ArrayList<>(mFinishingActivities);
mFinishingActivities.clear();
}
if (mStartingUsers.size() > 0) {
startingUsers = new ArrayList<>(mStartingUsers);
mStartingUsers.clear();
}
// Stop any activities that are scheduled to do so but have been
// waiting for the next one to start.
for (int i = 0; i < NS; i++) {
r = stops.get(i);
final ActivityStack stack = r.task.stack;
if (stack != null) {
if (r.finishing) {
stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
} else {
stack.stopActivityLocked(r);
}
}
}
// Finish any activities that are scheduled to do so but have been
// waiting for the next one to start.
for (int i = 0; i < NF; i++) {
r = finishes.get(i);
final ActivityStack stack = r.task.stack;
if (stack != null) {
activityRemoved |= stack.destroyActivityLocked(r, true, "finish-idle");
}
}
if (!booting) {
// Complete user switch
if (startingUsers != null) {
for (int i = 0; i < startingUsers.size(); i++) {
mService.finishUserSwitch(startingUsers.get(i));
}
}
// Complete starting up of background users
if (mStartingBackgroundUsers.size() > 0) {
startingUsers = new ArrayList<UserState>(mStartingBackgroundUsers);
mStartingBackgroundUsers.clear();
for (int i = 0; i < startingUsers.size(); i++) {
mService.finishUserBoot(startingUsers.get(i));
}
}
}
mService.trimApplications();
//dump();
//mWindowManager.dump();
if (activityRemoved) {
resumeTopActivitiesLocked();
}
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
// remove SamsungHomeTasks after all activities's visible change
// to avoid blank screen for a while.
if (mNeedToMovePrevSamsungHomeTasks && mWaitingVisibleActivities.isEmpty()) {
movePrevSamsungHomeTasksLocked(mSamsungHomeTask);
mNeedToMovePrevSamsungHomeTasks = false;
}
}
/* Dual-Screen } */
return r;
}
boolean handleAppDiedLocked(ProcessRecord app) {
boolean hasVisibleActivities = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = new ArrayList(mActivityDisplays.valueAt(displayNdx).mStacks);
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
hasVisibleActivities |= stacks.get(stackNdx).handleAppDiedLocked(app);
}
}
return hasVisibleActivities;
}
void closeSystemDialogsLocked() {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
stacks.get(stackNdx).closeSystemDialogsLocked();
}
}
}
void removeUserLocked(int userId) {
mUserStackInFront.delete(userId);
}
/**
* @return true if some activity was finished (or would have finished if doit were true).
*/
boolean finishDisabledPackageActivitiesLocked(String packageName, Set<String> filterByClasses,
boolean doit, boolean evenPersistent, int userId) {
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
int numStacks = stacks.size();
for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (stack.finishDisabledPackageActivitiesLocked(
packageName, filterByClasses, doit, evenPersistent, userId)) {
didSomething = true;
if (stacks.size() < numStacks) {
// stack is removed by finishDisabledPackageActivitiesLocked in this case.
numStacks = stacks.size();
stackNdx--;
}
}
}
}
return didSomething;
}
void updatePreviousProcessLocked(ActivityRecord r) {
// Now that this process has stopped, we may want to consider
// it to be the previous app to try to keep around in case
// the user wants to return to it.
// First, found out what is currently the foreground app, so that
// we don't blow away the previous app if this activity is being
// hosted by the process that is actually still the foreground.
ProcessRecord fgApp = null;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (isFrontStack(stack)) {
if (stack.mResumedActivity != null) {
fgApp = stack.mResumedActivity.app;
} else if (stack.mPausingActivity != null) {
fgApp = stack.mPausingActivity.app;
}
break;
}
}
}
// Now set this one as the previous process, only if that really
// makes sense to.
if (r.app != null && fgApp != null && r.app != fgApp
&& r.lastVisibleTime > mService.mPreviousProcessVisibleTime
&& r.app != mService.mHomeProcess
/* { AppCore */
&& r.app != mService.mRecentsProcess
/* AppCore } */) {
mService.mPreviousProcess = r.app;
mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
}
}
boolean resumeTopActivitiesLocked() {
return resumeTopActivitiesLocked(null, null, null);
}
boolean forceResumeTopActivitiesLocked(String packageName) {
ActivityStack targetStack = mFocusedStack;
// Do targetStack first.
boolean result = false;
if (isFrontStack(targetStack)) {
result = targetStack.forceResumeTopActivityLocked(packageName);
}
return result;
}
boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
Bundle targetOptions) {
/* { AppCore */
mService.mHandler.removeCallbacks(mPendingResumeTopActivityRunnable);
/* AppCore } */
if (targetStack == null) {
targetStack = mFocusedStack;
}
// Do targetStack first.
boolean result = false;
/* { Dual-Screen */
if (SUPPORT_EXPANDED_MODE) {
mService.mDualScreenPolicy.arrangeFullViewPolicyOnResumeTopActivitiesLocked(targetStack);
}
/* Dual-Screen } */
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
mService.mMultiWindowPolicy.arrangeMultiWindowStyleOnResumeTopActivities(targetStack);
}
/* Multi-Window } */
if (isFrontStack(targetStack)) {
result = targetStack.resumeTopActivityLocked(target, targetOptions);
}
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (stack == targetStack) {
// Already started above.
continue;
}
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
mService.mMultiWindowPolicy.arrangeMultiWindowStyleOnResumeTopActivities(stack);
}
/* Multi-Window } */
if (isFrontStack(stack) &&
/* { Dual-Screen */
// Do not resume topActivity if its display is not active.
// I intend to block resuming a topActivity on not-target stack only.
(!DUALSCREEN_ENABLED || mService.mDualScreenPolicy.isActiveDisplayLocked(stack.mDisplayId))) {
/* Dual-Screen } */
stack.resumeTopActivityLocked(null);
}
}
}
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
notifyGlobalMultiWindowStatusChangedLocked();
if(isIsolated(Display.DEFAULT_DISPLAY)){
mService.mMultiWindowPolicy.resize2Split(Display.DEFAULT_DISPLAY, true);
}else{
mService.mMultiWindowPolicy.resize2Split(Display.DEFAULT_DISPLAY, false);
}
}
/* Multi-Window } */
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
notifyCoupledTaskStatusChangedLocked();
}
/* Dual-Screen } */
return result;
}
void finishTopRunningActivityLocked(ProcessRecord app, String reason) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
final int numStacks = stacks.size();
for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
stack.finishTopRunningActivityLocked(app, reason);
}
}
}
void finishVoiceTask(IVoiceInteractionSession session) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
final int numStacks = stacks.size();
for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
stack.finishVoiceTask(session);
}
}
}
void findTaskToMoveToFrontLocked(TaskRecord task, int flags, Bundle options, String reason) {
ActivityRecord top_activity;
top_activity = task.stack != null ? task.stack.topRunningActivityLocked(null) : null;
/* App is launching from recent apps and it's a new process */
if(top_activity != null && top_activity.state == ActivityState.DESTROYED) {
acquireAppLaunchPerfLock();
}
if ((flags & ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
mUserLeaving = true;
}
if ((flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
// Caller wants the home activity moved with it. To accomplish this,
// we'll just indicate that this task returns to the home task.
/* { Dual-Screen */
if (SUPPORT_EXPANDED_MODE && DualScreenSettings.isExpandHomeModeEnabled()) {
task.setTaskToReturnTo(ActivityRecord.SAMSUNG_EXPAND_HOME_ACTIVITY_TYPE);
} else {
/* Dual-Screen } */
task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
}
}
if (task.stack == null) {
Slog.e(TAG, "findTaskToMoveToFrontLocked: can't move task="
+ task + " to front. Stack is null");
return;
}
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
task.stack.moveTaskToFrontLocked(task, false /* noAnimation */, options,
task.getTopActivity() == null ? null : task.getTopActivity().appTimeTracker, flags,
reason);
} else {
/* Multi-Window } */
task.stack.moveTaskToFrontLocked(task, false /* noAnimation */, options,
task.getTopActivity() == null ? null : task.getTopActivity().appTimeTracker,
reason);
/* { Multi-Window */
}
/* Multi-Window } */
if (DEBUG_STACK) Slog.d(TAG_STACK,
"findTaskToMoveToFront: moved to front of stack=" + task.stack);
}
ActivityStack getStack(int stackId) {
ActivityContainer activityContainer = mActivityContainers.get(stackId);
if (activityContainer != null) {
return activityContainer.mStack;
}
return null;
}
/* { Multi-Window */
ActivityStack getStack(MultiWindowStyle style, int displayId) {
return getStack(style.getZone(), displayId);
}
ActivityStack getStack(int zone, int displayId) {
ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
if (activityDisplay != null) {
for (int i = 0; i < activityDisplay.mStacks.size(); i++) {
ActivityStack stack = activityDisplay.mStacks.get(i);
if (stack.isHomeStack()) {
continue;
}
if (stack.mStackType == NORMAL_APP_STACK_TYPE && stack.getZone() == zone) {
/* SEC_PRODUCT_FEATURE_COMMON_SUPPORT_WEARABLE_HMT {*/
if(VRApplicationPolicy.FEATURE_HMT) {
//The zone information of VR stack is inapplicable.
if (stack.isVRStack()) {
continue;
}
}
/*} SEC_PRODUCT_FEATURE_COMMON_SUPPORT_WEARABLE_HMT */
return stack;
}
}
}
return null;
}
/* Multi-Window }*/
/* SEC_PRODUCT_FEATURE_COMMON_SUPPORT_WEARABLE_HMT {*/
ActivityStack getVRStack(int displayId) {
ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
if (activityDisplay != null) {
for (int i = 0; i < activityDisplay.mStacks.size(); i++) {
ActivityStack stack = activityDisplay.mStacks.get(i);
if (stack.isHomeStack()) {
continue;
}
if (stack.isVRStack()) {
return stack;
}
}
}
return null;
}
/*} SEC_PRODUCT_FEATURE_COMMON_SUPPORT_WEARABLE_HMT */
ArrayList<ActivityStack> getStacks() {
ArrayList<ActivityStack> allStacks = new ArrayList<ActivityStack>();
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
allStacks.addAll(mActivityDisplays.valueAt(displayNdx).mStacks);
}
return allStacks;
}
IBinder getHomeActivityToken() {
ActivityRecord homeActivity = getHomeActivity(Display.DEFAULT_DISPLAY);
if (homeActivity != null) {
return homeActivity.appToken;
}
return null;
}
ActivityRecord getHomeActivity() {
/* { Dual-Screen */
return getHomeActivityForUser(mCurrentUser, Display.DEFAULT_DISPLAY);
}
ActivityRecord getHomeActivity(int displayId) {
return getHomeActivityForUser(mCurrentUser, displayId);
}
ActivityRecord getHomeActivityForUser(int userId, int displayId) {
ActivityStack mHomeStack = this.mHomeStack;
if (DUALSCREEN_ENABLED) {
if (displayId < Display.DUAL_SCREEN_TYPE_MAX) {
mHomeStack = mHomeStacks[displayId];
}
}
/* Dual-Screen } */
final ArrayList<TaskRecord> tasks = mHomeStack.getAllTasks();
for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = tasks.get(taskNdx);
if (task.isHomeTask()) {
final ArrayList<ActivityRecord> activities = task.mActivities;
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = activities.get(activityNdx);
if (r.isHomeActivity()
&& ((userId == UserHandle.USER_ALL) || (r.userId == userId) || (isProfiledUserLocked(userId, r.userId)))) {
return r;
}
}
}
}
return null;
}
/* { Multi-Window */
TaskRecord getHomeTask() {
final ArrayList<TaskRecord> tasks;
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
tasks = mUniversalTaskHistory;
} else {
/* Dual-Screen } */
tasks = mHomeStack.getAllTasks();
}
for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = tasks.get(taskNdx);
if (task.isHomeTask()) {
return task;
}
}
return null;
}
/* Multi-Window } */
ActivityContainer createVirtualActivityContainer(ActivityRecord parentActivity,
IActivityContainerCallback callback) {
ActivityContainer activityContainer =
new VirtualActivityContainer(parentActivity, callback);
mActivityContainers.put(activityContainer.mStackId, activityContainer);
if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS,
"createActivityContainer: " + activityContainer);
parentActivity.mChildContainers.add(activityContainer);
return activityContainer;
}
void removeChildActivityContainers(ActivityRecord parentActivity) {
final ArrayList<ActivityContainer> childStacks = parentActivity.mChildContainers;
for (int containerNdx = childStacks.size() - 1; containerNdx >= 0; --containerNdx) {
ActivityContainer container = childStacks.remove(containerNdx);
if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS, "removeChildActivityContainers: removing "
+ container);
container.release();
}
}
void deleteActivityContainer(IActivityContainer container) {
ActivityContainer activityContainer = (ActivityContainer)container;
if (activityContainer != null) {
if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS,
"deleteActivityContainer: callers=" + Debug.getCallers(4));
final int stackId = activityContainer.mStackId;
mActivityContainers.remove(stackId);
mWindowManager.removeStack(stackId);
}
}
void resizeStackLocked(int stackId, Rect bounds) {
/* { Multi-Window */
resizeStackLocked(stackId, bounds, false);
}
void resizeStackLocked(int stackId, Rect bounds, boolean forceToResize) {
/* Multi-Window } */
final ActivityStack stack = getStack(stackId);
if (stack == null) {
Slog.w(TAG, "resizeStack: stackId " + stackId + " not found.");
return;
}
final ActivityRecord r = stack.topRunningActivityLocked(null);
if (r != null && !r.task.mResizeable) {
/* { Multi-Window */
if (!MultiWindowFeatures.MULTIWINDOW_ENABLED || !forceToResize) {
/* Multi-Window } */
Slog.w(TAG, "resizeStack: top task " + r.task + " not resizeable.");
return;
}
}
final Configuration overrideConfig = mWindowManager.resizeStack(stackId, bounds);
if (stack.updateOverrideConfiguration(overrideConfig)) {
if (r != null) {
final boolean updated = stack.ensureActivityConfigurationLocked(r, 0);
// And we need to make sure at this point that all other activities
// are made visible with the correct configuration.
ensureActivitiesVisibleLocked(r, 0);
if (!updated) {
resumeTopActivitiesLocked(stack, null, null);
}
}
/* { Multi-Window */
} else if (MultiWindowFeatures.MULTIWINDOW_ENABLED && MultiWindowFeatures.SELECTIVE1ORIENTATION_ENABLED && forceToResize) {
if (r != null && stack.isSplitStack() && !stack.mOverrideConfig.equals(r.stackConfigOverride)) {
// need update configuration of activity r
if (SAFE_DEBUG) {
Slog.i(TAG, "need ensureActivityConfig for split, r=" + r + ", r.stackConfigOverride=" + r.stackConfigOverride);
}
stack.ensureActivityConfigurationLocked(r, 0);
}
}
/* Multi-Window } */
}
/** Makes sure the input task is in a stack with the specified bounds by either resizing the
* current task stack if it only has one entry, moving the task to a stack that matches the
* bounds, or creating a new stack with the required bounds. Also, makes the task resizeable.*/
void resizeTaskLocked(TaskRecord task, Rect bounds) {
task.mResizeable = true;
final ActivityStack currentStack = task.stack;
if (currentStack.isHomeStack()) {
// Can't move task off the home stack. Sorry!
return;
}
final int matchingStackId = mWindowManager.getStackIdWithBounds(bounds);
if (matchingStackId != -1) {
// There is already a stack with the right bounds!
if (currentStack != null && currentStack.mStackId == matchingStackId) {
// Nothing to do here. Already in the right stack...
return;
}
// Move task to stack with matching bounds.
moveTaskToStackLocked(task.taskId, matchingStackId, true);
return;
}
if (currentStack != null && currentStack.numTasks() == 1) {
// Just resize the current stack since this is the task in it.
resizeStackLocked(currentStack.mStackId, bounds);
return;
}
// Create new stack and move the task to it.
final int displayId = (currentStack != null && currentStack.mDisplayId != -1)
? currentStack.mDisplayId : Display.DEFAULT_DISPLAY;
ActivityStack newStack = createStackOnDisplay(getNextStackId(), displayId);
if (newStack == null) {
Slog.e(TAG, "resizeTaskLocked: Can't create stack for task=" + task);
return;
}
moveTaskToStackLocked(task.taskId, newStack.mStackId, true);
resizeStackLocked(newStack.mStackId, bounds);
}
/* { Multi-Window */
ActivityStack createStackOnDisplay(int stackId, int displayId, Rect bounds) {
return createStackOnDisplay(stackId, displayId, bounds, false);
}
ActivityStack createStackOnDisplay(int stackId, int displayId, Rect bounds, boolean isSelectiveState) {
ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
if (activityDisplay == null) {
return null;
}
ActivityContainer activityContainer = new ActivityContainer(stackId, FLOATING_APP_STACK_TYPE, MultiWindowStyle.ZONE_UNKNOWN);
mActivityContainers.put(stackId, activityContainer);
activityContainer.attachToDisplayLocked(activityDisplay, bounds, isSelectiveState);
Rect stackBounds = mWindowManager.getStackBound(stackId);
mService.resizeStack(stackId, stackBounds);
return activityContainer.mStack;
}
/* Multi-Window } */
ActivityStack createStackOnDisplay(int stackId, int displayId) {
/* { Multi-Window */
return createStackOnDisplay(stackId, displayId, MultiWindowStyle.ZONE_UNKNOWN);
}
ActivityStack createStackOnDisplay(int stackId, int displayId, int zone) {
/* Multi-Window } */
ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
if (activityDisplay == null) {
return null;
}
/* { Multi-Window */
// ActivityContainer activityContainer = new ActivityContainer(stackId);
/* { Dual-Screen */
// ActivityContainer activityContainer = new ActivityContainer(stackId,
// (stackId == HOME_STACK_ID) ? HOME_STACK_TYPE : NORMAL_APP_STACK_TYPE, zone);
/* Multi-Window } */
ActivityContainer activityContainer;
if (DUALSCREEN_ENABLED) {
if (stackId == SAMSUNG_HOME_STACK_ID) {
activityContainer = new ActivityContainer(stackId,
SAMSUNG_HOME_STACK_TYPE, zone);
} else if (stackId == EXPANDED_HOME_STACK_ID) {
activityContainer = new ActivityContainer(stackId,
EXPANDED_HOME_STACK_TYPE, zone);
} else {
activityContainer = new ActivityContainer(stackId,
(stackId == HOME_STACK_ID) ? HOME_STACK_TYPE : NORMAL_APP_STACK_TYPE, zone);
}
} else {
activityContainer = new ActivityContainer(stackId,
(stackId == HOME_STACK_ID) ? HOME_STACK_TYPE : NORMAL_APP_STACK_TYPE, zone);
}
/* Dual-Screen } */
mActivityContainers.put(stackId, activityContainer);
activityContainer.attachToDisplayLocked(activityDisplay);
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
if (mService.mSystemReady) {
Rect outRect = new Rect();
mService.mMultiWindowPolicy.getBounds(outRect, zone, displayId);
mService.resizeStack(stackId, outRect);
} else {
Slog.d(TAG, "createStackOnDisplay: System is not ready yet!");
}
}
/* Multi-Window }*/
return activityContainer.mStack;
}
int getNextStackId() {
while (true) {
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
if (SUPPORT_EXPANDED_MODE) {
if (++mLastStackId <= EXPANDED_HOME_STACK_ID) {
mLastStackId = EXPANDED_HOME_STACK_ID + 1;
}
} else if (++mLastStackId <= SAMSUNG_HOME_STACK_ID) {
mLastStackId = SAMSUNG_HOME_STACK_ID + 1;
}
} else {
/* Dual-Screen } */
if (++mLastStackId <= HOME_STACK_ID) {
mLastStackId = HOME_STACK_ID + 1;
}
}
if (getStack(mLastStackId) == null) {
break;
}
}
return mLastStackId;
}
private boolean restoreRecentTaskLocked(TaskRecord task) {
ActivityStack stack = null;
// Determine stack to restore task to.
if (mLeanbackOnlyDevice) {
// There is only one stack for lean back devices.
stack = mHomeStack;
} else {
// Look for the top stack on the home display that isn't the home stack.
/* { Dual-Screen */
// final ArrayList<ActivityStack> homeDisplayStacks = mHomeStack.mStacks;
ArrayList<ActivityStack> homeDisplayStacks = mHomeStack.mStacks;
if (DUALSCREEN_ENABLED) {
if (mHomeStacks[task.displayId] != null) {
homeDisplayStacks = mHomeStacks[task.displayId].mStacks;
}
}
/* Dual-Screen } */
/* { Virtual-Screen */
if (VIRTUALSCREEN_ENABLED) {
ActivityRecord r = task.getTopActivity();
if (r != null && !r.finishing && r.virtualScreenAttrs.getBaseDisplayId() != Display.DEFAULT_DISPLAY) {
Slog.w(TAG, TAG_VIRTUALSCREEN + " task " + task + " is not in home display");
return false;
}
}
/* Virtual-Screen } */
for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack tmpStack = homeDisplayStacks.get(stackNdx);
if (MultiWindowFeatures.MULTIWINDOW_ENABLED ? tmpStack.isNormalAppStack() : !tmpStack.isHomeStack() && tmpStack.mFullscreen) { // Multi-Window
stack = tmpStack;
break;
}
}
}
if (stack == null) {
// We couldn't find a stack to restore the task to. Possible if are restoring recents
// before an application stack is created...Go ahead and create one on the default
// display.
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
stack = createStackOnDisplay(getNextStackId(), task.displayId);
} else {
/* Dual-Screen } */
stack = createStackOnDisplay(getNextStackId(), Display.DEFAULT_DISPLAY);
}
// Restore home stack to top.
moveHomeStack(true, "restoreRecentTask");
if (DEBUG_RECENTS) Slog.v(TAG_RECENTS,
"Created stack=" + stack + " for recents restoration.");
}
if (stack == null) {
// What does this mean??? Not sure how we would get here...
if (DEBUG_RECENTS) Slog.v(TAG_RECENTS,
"Unable to find/create stack to restore recent task=" + task);
return false;
}
stack.addTask(task, false, false/* { Multi-Window */, true/* Multi-Window } */);
if (DEBUG_RECENTS) Slog.v(TAG_RECENTS,
"Added restored task=" + task + " to stack=" + stack);
final ArrayList<ActivityRecord> activities = task.mActivities;
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = activities.get(activityNdx);
mWindowManager.addAppToken(0, r.appToken, task.taskId, stack.mStackId,
r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_FOR_ALL_USERS) != 0,
r.userId, r.info.configChanges, task.voiceSession != null,
r.mLaunchTaskBehind,
/* { Multi-Window */ r.multiWindowStyle/* Multi-Window } */,
/* { Camera Rotation */ r.skipRotationAnimation /* Camera Rotation } */
/* { Dual-Screen */, r.noDisplay, r.policyExpandedDisplayOrientation/* Dual-Screen } */
/* { Multi-Window */, r.isPermissionRequestActivity/* Multi-Window } */);
}
return true;
}
void moveTaskToStackLocked(int taskId, int stackId, boolean toTop) {
/* { Multi-Window */
moveTaskToStackLocked(taskId, stackId, toTop, true);
}
void moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean doResumeTop) {
/* Multi-Window } */
/* { Dual-Screen */
moveTaskToStackLocked(taskId, stackId, toTop, doResumeTop, false);
}
void moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean doResumeTop, boolean swap) {
/* Dual-Screen } */
final TaskRecord task = anyTaskForIdLocked(taskId);
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
if (DEBUG_DUALSCREEN) {
Slog.d(TAG, "moveTaskToStackLocked: taskId=" + taskId + " stackId=" + stackId);
}
if (task == null) {
Slog.w(TAG, "moveTaskToStack: no task for id=" + taskId);
return;
}
final ActivityStack stack = getStack(stackId);
if (stack == null) {
Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
return;
}
final ActivityStack prevStack = task.stack;
boolean updateFocus = prevStack.mStackId != stack.mStackId;
boolean needToMoveHomeStackTaskToTop = false;
int taskToReturnTo = task.getTaskToReturnTo();
int prevDisplayId = prevStack.getDisplayId();
if (toTop && prevDisplayId != stack.getDisplayId()) {
ActivityRecord topActivity = task.topRunningActivityLocked(null);
if (topActivity != null) {
topActivity.startDisplayChanging(topActivity.app);
}
}
mWindowManager.moveTaskToStack(taskId, stackId, toTop
/* { Dual-Screen */, task.getScreenZone()/* Dual-Screen } */);
// move previous display's homeStack task to top
// if task moving is topTask and overHomeStack after move the task.
if (!prevStack.isHomeStack() && isFrontStack(prevStack)
&& prevStack.getDisplayId() != stack.getDisplayId()
&& task == prevStack.topTask()
&& (!swap && task.isOverHomeStack())) {
needToMoveHomeStackTaskToTop = true;
}
if (task.stack != null) {
task.stack.removeTask(task, "moveTaskToStack", false /* notMoving */,
/* { Dual-Screen */swap/* Dual-Screen } */, updateFocus, prevStack.mDisplayId != stack.mDisplayId);
}
/* { Dual-Screen */
// Do not need to update a task's taskToReturnTo if the task is moved to FullView home and pre-arrange HomeTask.
boolean taskToReturnToPreArranged = false;
if (SUPPORT_EXPANDED_MODE) {
// pre-arrange HomeTask before adding a fullView task on Expand Stack.
if (needToMoveHomeStackTaskToTop &&
(prevDisplayId == Display.DUAL_SCREEN_EXPANDED_DISPLAY
|| stack.getDisplayId() == Display.DUAL_SCREEN_EXPANDED_DISPLAY)) {
moveHomeStackTaskToTop(taskToReturnTo, "moveTaskToStack", prevDisplayId, true);
needToMoveHomeStackTaskToTop = false;
taskToReturnToPreArranged = true;
}
}
/* Dual-Screen } */
stack.addTask(task, toTop, true);
stack.mResumedIdleActivity = task.topRunningActivityLocked(null);
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
// move homeStack task to top if needed.
if (needToMoveHomeStackTaskToTop) {
moveHomeStackTaskToTop(taskToReturnTo, "moveTaskToStack", prevDisplayId);
}
if (DualScreenSettings.isExpandHomeModeEnabled() && taskToReturnToPreArranged) {
task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
}
}
/* Multi-Window } */
if (!swap) {
prevStack.postProcessAfterMovingTaskLocked(task, stack, toTop);
}
if (toTop) {
ActivityRecord topActivity = stack.topRunningActivityLocked(null);
mService.mFrontActivities[stack.getDisplayId()] = topActivity;
if (prevDisplayId != stack.getDisplayId()) {
mService.mFrontActivities[prevDisplayId] = topRunningActivityLocked(null, prevDisplayId);
if (topActivity != null) {
stack.ensureActivityConfigurationLocked(topActivity, 0);
topActivity.stopDisplayChanging();
}
}
mWindowManager.moveTaskToTop(taskId);
}
if (doResumeTop) {
resumeTopActivitiesLocked(stack, null, null);
}
return;
}
/* Dual-Screen } */
if (task == null) {
Slog.w(TAG, "moveTaskToStack: no task for id=" + taskId);
return;
}
final ActivityStack stack = getStack(stackId);
if (stack == null) {
Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
return;
}
mWindowManager.moveTaskToStack(taskId, stackId, toTop/* { Dual-Screen */, task.getScreenZone()/* Dual-Screen } */);
/* { Multi-Window */
ActivityRecord ar = task.topRunningActivityLocked(null);
if ( ar != null && !ar.visible){
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
task.bHidden = false;
}
}
/* Multi-Window } */
/* SEC_PRODUCT_FEATURE_COMMON_SUPPORT_WEARABLE_HMT {*/
if(VRApplicationPolicy.FEATURE_HMT) {
if(toTop) {
ActivityRecord taskTop = task.getTopActivity();
if(taskTop != null && taskTop.isVRActivity()) {
if(stack.isVRStack()) {
if(!mService.mVRApplicationPolicy.readyToStartVRActivityLocked(taskTop, task.intent)) {
return;
}
} else {
Slog.e(TAG, "moveTaskToStack : can not move VR task " + taskId + " to non VR stack");
return;
}
} else if(taskTop != null && stack.isNormalAppStack()
&& mService.mVRApplicationPolicy.inVRMode()) {
taskTop.launchedBehindVRApp = true;
}
}
}
/*} SEC_PRODUCT_FEATURE_COMMON_SUPPORT_WEARABLE_HMT */
/* { Multi-Window */
boolean wasInFloatingStack = false;
if (task.stack != null) {
wasInFloatingStack = task.stack.isFloatingStack();
}
boolean isTopActivityNormal = false;
ActivityRecord topActivity = task.topRunningActivityLocked(null);
if (topActivity != null && topActivity.multiWindowStyle.isNormal()){
isTopActivityNormal = true;
}
boolean willBeInFloatingStack = stack.isFloatingStack();
final ActivityStack prevStack = task.stack;
boolean updateFocus = false;
int prevDisplayId = 0;
if (prevStack != null) {
updateFocus = prevStack.mStackId != stack.mStackId;
prevDisplayId = prevStack.getDisplayId();
}
boolean needToMoveHomeStackTaskToTop = false;
int taskToReturnTo = task.getTaskToReturnTo();
if (MultiWindowFeatures.MULTIWINDOW_ENABLED
&& prevStack != null) {
if (taskToReturnTo == HOME_ACTIVITY_TYPE
&& ar != null && ar.state == ActivityState.RESUMED
&& !prevStack.isMultiWindowStack()
&& stack.isFloatingStack() && task == prevStack.topTask()
&& task.getLayer() != MultiWindowStyle.NORMAL_LAYER) {
needToMoveHomeStackTaskToTop = true;
}
prevStack.removeTask(task, "moveTaskToStack", false /* notMoving */, false, updateFocus, false);
} else {
/* Multi-Window } */
if (task.stack != null) {
task.stack.removeTask(task, "moveTaskToStack", false /* notMoving */);
}
}
stack.addTask(task, toTop, true);
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
// move homeStack task to top if needed.
if (needToMoveHomeStackTaskToTop) {
moveHomeStackTaskToTop(taskToReturnTo, "moveTaskToStack", prevDisplayId);
}
mWindowManager.addTask(taskId, stackId, toTop, true);
if (!swap && prevStack != null) {
prevStack.postProcessAfterMovingTaskLocked(task, stack, toTop);
}
boolean isNeedEnsureVisibleCall = false;
if (toTop) {
if (wasInFloatingStack || willBeInFloatingStack) {
mService.setFocusedActivityLocked(stack.topRunningActivityLocked(null), true, "moveTaskToStack");
if (MultiWindowFeatures.SELECTIVE1ORIENTATION_ENABLED && topActivity != null) {
if (SAFE_DEBUG) Slog.i(TAG, "ensureConfig while moveTaskToStack , r=" + topActivity);
mWindowManager.getExpectedOrientation(); // To update overrideConfiguration fastly
stack.ensureActivityConfigurationLocked(topActivity, 0);
}
if (!isTopActivityNormal) {
isNeedEnsureVisibleCall = true;
}
}
mWindowManager.moveTaskToTop(taskId);
}
if (doResumeTop) {
resumeTopActivitiesLocked();
ActivityRecord r = task.mActivities.get(task.mActivities.size()-1);
if (isNeedEnsureVisibleCall && r != null && !r.finishing
&& !(r.multiWindowStyle.isEnabled(MultiWindowStyle.OPTION_RESIZE))) {
ensureActivitiesVisibleLocked(null, 0);
}
if (willBeInFloatingStack) {
ArrayList<IBinder> appTokens = new ArrayList<IBinder>();
ActivityDisplay targetDisplay = mActivityDisplays.get(task.stack.mDisplayId);
final ArrayList<ActivityStack> targetStacks = targetDisplay.mStacks;
for (ActivityStack targetStack : targetStacks) {
if (!targetStack.isFloatingStack() && !targetStack.equals(stack) && isFrontStack(targetStack)) {
if (targetStack.mResumedActivity != null) {
appTokens.add(targetStack.mResumedActivity.appToken);
}
}
}
mWindowManager.addMultiWindowTransitionTargetIfNeeded(appTokens/* { Dual-Screen */, stack.getDisplayId() /* Dual-Screen } */);
}
}
} else {
/* Multi-Window } */
// The task might have already been running and its visibility needs to be synchronized with
// the visibility of the stack / windows.
/* { Virtual-Screen */
if (VIRTUALSCREEN_ENABLED) {
if (prevDisplayId != stack.mDisplayId && (VirtualScreenManagerService.self().isVirtualScreen(prevDisplayId)
|| VirtualScreenManagerService.self().isVirtualScreen(stack.mDisplayId))) {
if (mService.mFocusedActivity != null
&& mService.mFocusedActivity.task.stack != mFocusedStack) {
setFocusedStack(mService.mFocusedActivity, "vs updateFocusedStack");
}
prevStack.postProcessAfterMovingTaskLocked(task, stack, toTop);
}
}
/* Virtual-Screen } */
stack.ensureActivitiesVisibleLocked(null, 0);
resumeTopActivitiesLocked();
}
}
void acquireAppLaunchPerfLock() {
/* Acquire perf lock during new app launch */
/*if (mIsPerfBoostEnabled == true && mPerf == null) {
}
if (mPerfBoost != null) {
mPerfBoost.perfLockAcquire(lBoostTimeOut, lBoostCpuParamVal);
}*/
}
/* { Multi-Window */
// Move task1 to stack of task2, and Move task2 to stack of task1
void exchangeTaskToStack( int task1Id, int task2Id, boolean toTop) {
final TaskRecord task1 = anyTaskForIdLocked(task1Id);
final TaskRecord task2 = anyTaskForIdLocked(task2Id);
if (task1 == null || task2 == null) {
return;
}
final ActivityRecord ar1 = task1.getTopActivity();
final ActivityRecord ar2 = task2.getTopActivity();
final ActivityStack stack1 = task1.stack;
final ActivityStack stack2 = task2.stack;
if (ar1 == null || ar2 == null || stack1 == null || stack2 == null) {
return;
}
int zone1 = ar1.multiWindowStyle.getZone();
int zone2 = ar2.multiWindowStyle.getZone();
// if 2-splited, freeze surface because of black screen.
if ((zone1 == MultiWindowStyle.ZONE_A && zone2 == MultiWindowStyle.ZONE_B) ||
(zone1 == MultiWindowStyle.ZONE_B && zone2 == MultiWindowStyle.ZONE_A)) {
ArrayList<IBinder> tokens = new ArrayList<IBinder>();
tokens.add(ar1.appToken);
tokens.add(ar2.appToken);
mWindowManager.prepareMultiWindowTransition(tokens, MultiWindowTransition.MW_TRANSIT_SPLIT_SWITCHED
/* { Dual-Screen */, stack1.getDisplayId()/* Dual-Screen } */);
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
if (stack1.getDisplayId() != stack2.getDisplayId()) {
mWindowManager.prepareMultiWindowTransition(tokens,MultiWindowTransition.MW_TRANSIT_SPLIT_SWITCHED,
stack2.getDisplayId());
}
}
/* Dual-Screen } */
}
// remove task in current stack
stack2.removeTask(task2, "exchangeTaskToStack from2", false, true);
stack1.removeTask(task1, "exchangeTaskToStack from1", false, true);
// add task to other stack
stack2.addTask(task1, toTop, true);
stack1.addTask(task2, toTop, true);
mWindowManager.addTask(task2Id, stack1.getStackId(), toTop, false); // needlayout.
mWindowManager.addTask(task1Id, stack2.getStackId(), toTop, true);
// notify unfocus zone in quadview
if(MultiWindowFeatures.isSupportQuadView(mService.mContext)) {
ActivityStack currentFocusedStack = getFocusedStack();
if (currentFocusedStack != null && currentFocusedStack != stack1 && currentFocusedStack != stack2) {
TaskRecord currentTask = currentFocusedStack.topTask();
if (currentTask != null) {
currentFocusedStack.notifyMultiWindowFocusChangedLocked(currentTask.getTopActivity(), MultiWindowStyle.NOTIFY_FOCUS_REASON_STACK_CHANGED, false);
}
}
}
// update zone info and MultiWindowStyle
if(task1.getTopActivity()!= null && task2.getTopActivity()!= null) {
task1.getTopActivity().multiWindowStyle.setZone(zone2);
task2.getTopActivity().multiWindowStyle.setZone(zone1);
stack1.setMultiWindowStyleForAllActivitiesInTaskLocked(task1, task1.getTopActivity().multiWindowStyle);
stack2.setMultiWindowStyleForAllActivitiesInTaskLocked(task2, task2.getTopActivity().multiWindowStyle);
stack1.notifyMultiWindowStyleChangedLocked(task1.getTopActivity(), MultiWindowStyle.NOTIFY_REASON_STYLE_CHANGED, true);
stack2.notifyMultiWindowStyleChangedLocked(task2.getTopActivity(), MultiWindowStyle.NOTIFY_REASON_STYLE_CHANGED, true);
}
// Notifying Unfocused Zone
if(MultiWindowFeatures.isSupportQuadView(mService.mContext)) {
stack2.notifyMultiWindowFocusChangedLocked(task2.getTopActivity(), MultiWindowStyle.NOTIFY_FOCUS_REASON_STACK_CHANGED, false);
}
if (toTop) {
mService.mFocusedActivity = null;
stack1.mResumedActivity = ar2;
stack2.mResumedActivity = ar1;
mService.setFocusedStack(ar1.task.stack.getStackId());
} else {
resumeTopActivitiesLocked();
}
// update pausingActivities
stack1.updatePausingActivitiesAfterMovingTaskLocked(task1, stack2);
stack2.updatePausingActivitiesAfterMovingTaskLocked(task2, stack1);
// update LRUActivities list, stack1.mLRUActivities <-> stack2.mLRUActivities
for (int index=stack1.mLRUActivities.size()-1; index>=0; index--) {
ActivityRecord r = stack1.mLRUActivities.get(index);
if (task1Id == r.task.taskId) {
stack1.mLRUActivities.remove(r);
stack2.mLRUActivities.add(r);
}
}
for (int index=stack2.mLRUActivities.size()-1; index>=0; index--) {
ActivityRecord r = stack2.mLRUActivities.get(index);
if (task2Id == r.task.taskId) {
stack2.mLRUActivities.remove(r);
stack1.mLRUActivities.add(r);
}
}
}
public boolean needMoveOnlySpecificTaskToFront(int taskId) {
TaskRecord task = anyTaskForIdLocked(taskId);
Slog.d(TAG, "needMoveOnlySpecificTaskToFront : task = " + task);
if (task == null) {
return false;
}
final ArrayList<ActivityStack> stacks = getStacks();
int N = stacks.size();
for (int i = N-1; i >= 0; i--) {
ActivityStack targetStack = stacks.get(i);
if (targetStack != null && targetStack.isFloatingStack() && isFrontStack(targetStack)) {
ActivityRecord topActivity = targetStack.topActivity();
if (topActivity != null && topActivity.task != null && task.realActivity != null && topActivity.packageName != null
&& topActivity.packageName.equals(task.realActivity.getPackageName())) {
if (task.affinity != null) {
boolean isSupportMultiInstance = mService.mMultiWindowPolicy.getEnableMultiInstance(topActivity.info, topActivity.intent);
if (task.affinity.equals(topActivity.task.affinity) && !isSupportMultiInstance) {
Slog.d(TAG, "needMoveOnlySpecificTaskToFront : Try to move task to mSpecificFloatingStack = " + mSpecificFloatingStack);
mSpecificFloatingStack = targetStack;
return true;
}
} else if (task.intent != null) {
Intent source = new Intent(task.intent);
source.setData(null);
Intent.FilterComparison sourceFilter = new Intent.FilterComparison(source);
Intent target = new Intent(topActivity.task.intent);
target.setData(null);
Intent.FilterComparison targetFilter = new Intent.FilterComparison(target);
if (task.intent.isDocument() && sourceFilter.equals(targetFilter)) {
Slog.d(TAG, "needMoveOnlySpecificTaskToFront : Try to move task to mSpecificFloatingStack = " + mSpecificFloatingStack);
mSpecificFloatingStack = targetStack;
return true;
}
}
}
}
}
return false;
}
public ActivityStack getSpecificFloatingStack() {
return mSpecificFloatingStack;
}
/* Multi-Window } */
ActivityRecord findTaskLocked(ActivityRecord r) {
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + r);
/* { Multi-Window */
ActivityRecord multiInstanceAr = null;
/* Multi-Window } */
/* { Dual-Screen */
if (DUALSCREEN_ENABLED && r.mSingleTaskForDisplay) {
// just loop twice (r's display and opposite side display)
// find r's display first
int displayNdx = r.getDisplayId();
while (true) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
ActivityRecord dOtherTask = null;
boolean atHome = false;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
final ActivityRecord backAr = stack.findTaskLocked(r, true);
if (backAr != null) {
final ActivityRecord foreAr = stack.findTaskLocked(r);
// target stack has two single task!
if (backAr.task.taskId != foreAr.task.taskId) {
if (foreAr.state == ActivityState.RESUMED) {
return backAr;
} else {
// return latest running task but...not sure target task was
// just pause or move task to back.
// check active time.. :(
return backAr.task.lastActiveTime > foreAr.task.lastActiveTime ?
backAr : foreAr;
}
} else if (displayNdx == r.getDisplayId()) {
return foreAr;
} else {
if (stack.isHomeStack()) {
// is fixed home :(
atHome = true;
if (dOtherTask != null)
return dOtherTask;
} else {
if (atHome)
return backAr;
dOtherTask = backAr;
}
}
}
}
if (displayNdx != r.getDisplayId()) break;
displayNdx = r.getDisplayId() == Display.DUAL_SCREEN_MAIN_DISPLAY ?
Display.DUAL_SCREEN_SUB_DISPLAY : Display.DUAL_SCREEN_MAIN_DISPLAY;
}
return null;
}
/* Dual-Screen } */
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (!r.isApplicationActivity() && !stack.isHomeStack()) {
/* { Dual-Screen */
if (DUALSCREEN_ENABLED && r.isSamsungHomeActivity()){
if (DEBUG_TASKS) Slog.d(TAG, "Keep going to find SamsungHome task in order to moving the task if needed");
} else {
/* Dual-Screen } */
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping stack: (home activity) " + stack);
continue;
}
}
if (!stack.mActivityContainer.isEligibleForNewTasks()) {
if (DEBUG_TASKS) Slog.d(TAG_TASKS,
"Skipping stack: (new task not allowed) " + stack);
continue;
}
final ActivityRecord ar = stack.findTaskLocked(r);
if (ar != null) {
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
if (ar.task != null && ar.task.getCoupledTask() != null) {
if (r.getDisplayId() != ar.getDisplayId()) {
continue;
}
}
}
/* Dual-Screen } */
if(ar.state == ActivityState.DESTROYED ) {
/*It's a new app launch */
acquireAppLaunchPerfLock();
// Strat IOP
/*if (mPerf_iop == null) {
mPerf_iop = new BoostFramework();
}
if (mPerf_iop != null) {
mPerf_iop.perfIOPrefetchStart(-1,r.packageName);
}*/
}
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED &&
r.intent.hasCategory(Intent.CATEGORY_LAUNCHER)) {
if (r.multiWindowStyle != null && r.multiWindowStyle.getSpecificTaskId() == ar.task.taskId) {
return ar;
}
if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) != 0) {
if(ar.multiWindowStyle != null
&& ar.multiWindowStyle.getType() != MultiWindowStyle.TYPE_NORMAL
&& ar.state == ActivityState.STOPPED) {
return ar;
} else {
multiInstanceAr = ar;
}
} else {
if (multiInstanceAr == null){
multiInstanceAr = ar;
} else {
if (multiInstanceAr.task.affinity.equals(ar.task.affinity)) {
if (ar.state == ActivityState.RESUMED
&& ar.multiWindowStyle.getType() != MultiWindowStyle.TYPE_CASCADE) {
continue;
}
if (multiInstanceAr.state == ActivityState.RESUMED
&& multiInstanceAr.multiWindowStyle.getType() != MultiWindowStyle.TYPE_CASCADE) {
multiInstanceAr = ar;
continue;
}
if (ar.state != ActivityState.RESUMED
&& multiInstanceAr.state == ActivityState.RESUMED
&& multiInstanceAr.multiWindowStyle.getType() == MultiWindowStyle.TYPE_CASCADE) {
multiInstanceAr = ar;
continue;
}
int miIndex = mService.mRecentTasks.indexOf(multiInstanceAr.task);
int arIndex = mService.mRecentTasks.indexOf(ar.task);
if (miIndex != -1 && arIndex != -1 && arIndex < miIndex) {
if (!(ar.state == ActivityState.RESUMED
&& multiInstanceAr.state != ActivityState.RESUMED))
multiInstanceAr = ar;
} else {
if (!MultiWindowFeatures.isSupportSimplificationUI(mService.mContext)
&& isFrontStack(multiInstanceAr.task.stack) && multiInstanceAr.state == ActivityState.STOPPED)
multiInstanceAr = ar;
}
}
}
}
} else {
/* Multi-Window } */
return ar;
}
}
}
}
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED && multiInstanceAr != null) {
return multiInstanceAr;
}
/* Multi-Window } */
/* Acquire perf lock during new app launch */
acquireAppLaunchPerfLock();
//Start IOP
/*if (mPerf_iop == null) {
mPerf_iop = new BoostFramework();
}
if (mPerf_iop != null) {
mPerf_iop.perfIOPrefetchStart(-1,r.packageName);
}*/
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "No task found");
return null;
}
ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityRecord ar = stacks.get(stackNdx).findActivityLocked(intent, info);
if (ar != null) {
return ar;
}
}
}
return null;
}
// SecProductFeature_KNOX.SEC_PRODUCT_FEATURE_KNOX_SUPPORT_MDM {
ActivityRecord findActivityLockedByPackage(int userId, String packageName) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityRecord ar = stacks.get(stackNdx).findActivityLockedByPackage(userId, packageName);
if (ar != null) {
return ar;
}
}
}
return null;
}
// } SecProductFeature_KNOX.SEC_PRODUCT_FEATURE_KNOX_SUPPORT_MDM
void goingToSleepLocked() {
scheduleSleepTimeout();
if (!mGoingToSleep.isHeld()) {
mGoingToSleep.acquire();
if (mLaunchingActivity.isHeld()) {
if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
throw new IllegalStateException("Calling must be system uid");
}
mLaunchingActivity.release();
mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
}
}
checkReadyForSleepLocked();
}
boolean shutdownLocked(int timeout) {
goingToSleepLocked();
boolean timedout = false;
final long endTime = System.currentTimeMillis() + timeout;
while (true) {
boolean cantShutdown = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
cantShutdown |= stacks.get(stackNdx).checkReadyForSleepLocked();
}
}
if (cantShutdown) {
long timeRemaining = endTime - System.currentTimeMillis();
if (timeRemaining > 0) {
try {
mService.wait(timeRemaining);
} catch (InterruptedException e) {
}
} else {
Slog.w(TAG, "Activity manager shutdown timed out");
timedout = true;
break;
}
} else {
break;
}
}
// Force checkReadyForSleep to complete.
mSleepTimeout = true;
checkReadyForSleepLocked();
return timedout;
}
/* { Multi-Window */
/**
* We need to arrange mTaskToRetrunTo of {@link TaskRecord} in SplitStack.
* Only 1 task which is above of HomeTask will be set as {@link ActivityRecord#HOME_ACTIVITY_TYPE}
* @param displayId; where globalTaskHistory is located
* @hide
*/
void arrangeTaskToReturnTo(int displayId) {
ArrayList<TaskRecord> globalTasks = getGlobalTaskHistoryLocked(displayId);
if (globalTasks != null && !globalTasks.isEmpty()) {
int homeTaskNdx = -1;
int recentTaskNdx = -1;
TaskRecord lastTask = null;
for (int i = globalTasks.size() - 1; i >= 0; i--) {
TaskRecord tr = globalTasks.get(i);
if(tr.stack != null && isCurrentProfileLocked(tr.userId)) {
if (tr.isHomeTask()) {
if (homeTaskNdx < 0) {
homeTaskNdx = i;
}
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
if (mService.mSamsungHomeComponentName != null && displayId == Display.DUAL_SCREEN_SUB_DISPLAY) {
tr.setTaskToReturnTo(ActivityRecord.SAMSUNG_PINNED_HOME_ACTIVITY_TYPE);
}
}
/* Dual-Screen } */
} else if (tr.isRecentTask()) {
recentTaskNdx = i;
tr.setTaskToReturnTo(ActivityRecord.APPLICATION_ACTIVITY_TYPE);
} else if (tr.stack.isSplitStack() || i < homeTaskNdx) {
tr.setTaskToReturnTo(ActivityRecord.APPLICATION_ACTIVITY_TYPE);
}
lastTask = tr;
}
}
if (homeTaskNdx < globalTasks.size() - 1 && homeTaskNdx > -1) {
TaskRecord overHomeTask = null;
for(int j = homeTaskNdx + 1 ; j < globalTasks.size() ; j++){
overHomeTask = globalTasks.get(j);
if (overHomeTask != null && overHomeTask.topRunningActivityLocked(null) != null){
break;
}
}
if (overHomeTask != null && overHomeTask.stack != null && !overHomeTask.stack.isFloatingStack()) {
/* { Dual-Screen */
if (SUPPORT_EXPANDED_MODE && DualScreenSettings.isExpandHomeModeEnabled()) {
if (!overHomeTask.isOverHomeStack()) {
TaskRecord homeTask = globalTasks.get(homeTaskNdx);
if (homeTask.isExpandHomeTask()) {
overHomeTask.setTaskToReturnTo(ActivityRecord.SAMSUNG_EXPAND_HOME_ACTIVITY_TYPE);
} else {
overHomeTask.setTaskToReturnTo(ActivityRecord.HOME_ACTIVITY_TYPE);
}
}
// Do nothing if overHomeTask is already over homeStack.
} else {
/* Dual-Screen } */
overHomeTask.setTaskToReturnTo(ActivityRecord.HOME_ACTIVITY_TYPE);
}
}
}
if (recentTaskNdx < globalTasks.size() - 1 && recentTaskNdx > -1) {
TaskRecord overRecentTask = null;
for(int j = recentTaskNdx + 1 ; j < globalTasks.size() ; j++){
overRecentTask = globalTasks.get(j);
if (overRecentTask != null && overRecentTask.topRunningActivityLocked(null) != null){
break;
}
}
if (overRecentTask != null && overRecentTask.stack != null && !overRecentTask.stack.isFloatingStack() && !overRecentTask.isOverHomeStack()) {
/* { Dual-Screen */
if (SUPPORT_EXPANDED_MODE && DualScreenSettings.isExpandHomeModeEnabled()) {
TaskRecord homeTask = homeTaskNdx < 0? getHomeTask() : globalTasks.get(homeTaskNdx);
TaskRecord recentTask = globalTasks.get(recentTaskNdx);
if (!overRecentTask.isOverHomeStack()) {
if (mUniversalTaskHistory.indexOf(recentTask) > mUniversalTaskHistory.indexOf(homeTask)) {
if (homeTask == null || homeTask.isExpandHomeTask()) {
overRecentTask.setTaskToReturnTo(ActivityRecord.SAMSUNG_EXPAND_HOME_ACTIVITY_TYPE);
} else {
overRecentTask.setTaskToReturnTo(ActivityRecord.HOME_ACTIVITY_TYPE);
}
}
}
// Do nothing if overRecentTask is already over homeStack.
} else {
/* Dual-Screen } */
overRecentTask.setTaskToReturnTo(ActivityRecord.HOME_ACTIVITY_TYPE);
}
}
}
if (homeTaskNdx < 0 && recentTaskNdx < 0) {
if (lastTask != null && lastTask.stack != null && !lastTask.stack.isMultiWindowStack()) {
/* { Dual-Screen */
if (SUPPORT_EXPANDED_MODE && DualScreenSettings.isExpandHomeModeEnabled()) {
TaskRecord homeTask = getHomeTask();
if (homeTask == null && displayId != Display.DUAL_SCREEN_EXPANDED_DISPLAY && !lastTask.isOverHomeStack()) {
lastTask.setTaskToReturnTo(ActivityRecord.SAMSUNG_EXPAND_HOME_ACTIVITY_TYPE);
}
} else {
/* Dual-Screen } */
lastTask.setTaskToReturnTo(ActivityRecord.HOME_ACTIVITY_TYPE);
}
}
}
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
mService.mDualScreenPolicy.arrangeTaskToReturnTo();
}
/* Dual-Screen } */
}
}
/* Multi-Window } */
/* { AppCore */
private final int PENDING_RESUME_TOP_ACTIVITIES_TIMEOUT_DURATION = 2000;
Runnable mPendingResumeTopActivityRunnable = new Runnable() {
@Override
public void run() {
synchronized(mService) {
resumeTopActivitiesLocked();
notifyActivityDrawnForKeyguard();
}
}
};
void comeOutOfSleepIfNeededLocked() {
comeOutOfSleepIfNeededLocked(false);
}
/* AppCore } */
void comeOutOfSleepIfNeededLocked(/* { AppCore */boolean causeKeyguardWaitingForActivityDrawn/* AppCore */) {
removeSleepTimeouts();
if (mGoingToSleep.isHeld()) {
mGoingToSleep.release();
}
/* { Dual-Screen */
int MultipleScreenState = PowerManager.DISPLAY_NONE;
if (DUALSCREEN_ENABLED) {
PowerManager pm = (PowerManager) mService.mContext.getSystemService(Context.POWER_SERVICE);
if (pm != null)
MultipleScreenState = pm.getMultipleScreenState();
}
/* Dual-Screen } */
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
/* { Dual-Screen */
//skip awake screen when just one screen is on.
if (DUALSCREEN_ENABLED) {
if ((MultipleScreenState == PowerManager.DISPLAY_ID_MAIN
&& displayNdx == Display.DUAL_SCREEN_SUB_DISPLAY)
|| (MultipleScreenState == PowerManager.DISPLAY_ID_SUB
&& displayNdx == Display.DUAL_SCREEN_MAIN_DISPLAY))
continue;
}
/* Dual-Screen } */
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
stack.awakeFromSleepingLocked();
if (isFrontStack(stack)) {
/* { AppCore */
if (!causeKeyguardWaitingForActivityDrawn) {
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
resumeTopActivitiesLocked(stack, null, null);
} else {
/* Dual-Screen } */
resumeTopActivitiesLocked();
}
} else {
mService.mHandler.removeCallbacks(mPendingResumeTopActivityRunnable);
mService.mHandler.postDelayed(mPendingResumeTopActivityRunnable, PENDING_RESUME_TOP_ACTIVITIES_TIMEOUT_DURATION);
}
/* AppCore } */
}
}
}
mGoingToSleepActivities.clear();
}
void activitySleptLocked(ActivityRecord r) {
mGoingToSleepActivities.remove(r);
checkReadyForSleepLocked();
}
void checkReadyForSleepLocked() {
if (!mService.isSleepingOrShuttingDown()) {
// Do not care.
return;
}
if (!mSleepTimeout) {
boolean dontSleep = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
dontSleep |= stacks.get(stackNdx).checkReadyForSleepLocked();
}
}
if (mStoppingActivities.size() > 0) {
// Still need to tell some activities to stop; can't sleep yet.
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to stop "
+ mStoppingActivities.size() + " activities");
scheduleIdleLocked();
dontSleep = true;
}
if (mGoingToSleepActivities.size() > 0) {
// Still need to tell some activities to sleep; can't sleep yet.
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to sleep "
+ mGoingToSleepActivities.size() + " activities");
dontSleep = true;
}
if (dontSleep) {
return;
}
}
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
ensureActivitiesVisibleLocked(null, 0);
}
/* Multi-Window } */
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
stacks.get(stackNdx).goToSleep();
}
}
removeSleepTimeouts();
if (mGoingToSleep.isHeld()) {
mGoingToSleep.release();
}
if (mService.mShuttingDown) {
mService.notifyAll();
}
}
boolean reportResumedActivityLocked(ActivityRecord r) {
final ActivityStack stack = r.task.stack;
if (isFrontStack(stack)) {
mService.updateUsageStats(r, true);
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
mService.mMultiWindowPolicy.notifyTaskStarted(r);
}
/* Multi-Window } */
}
//+ RTCC v3
if (SecProductFeature_FRAMEWORK.SEC_PRODUCT_FEATURE_FRAMEWORK_SUPPORT_SMMF_RTCC_V3 && r.isHomeActivity()) {
mService.triggerRTCC();
}
//- RTCC v3
/* MARs Managed App Restrictions*/
if (MARsPolicyManager.MARs_ENABLE && mService.mMARsPolicyManager != null) {
mService.mMARsPolicyManager.handlePackageResumedFG(r.info.packageName, r.launchedFromPackage, r.fullscreen, r.intent);
}
/* MARs */
if (allResumedActivitiesComplete(/* { Dual-Screen */r.getDisplayId()/* Dual-Screen } */)) {
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED && (r.isHomeActivity() && allResumedActivitiesVisible(/* { Dual-Screen */r.getDisplayId()/* Dual-Screen } */))) {
if (mService.mMinimizeAllPenWindowRequested) {
handleMinimizeAllPenWindow();
}
}
/* Multi-Window } */
ensureActivitiesVisibleLocked(null, 0);
/* { Dual-Screen */
if (SUPPORT_EXPANDED_MODE) {
if (allResumedActivitiesComplete(true)) {
executeAllTransition();
}
} else {
/* Dual-Screen } */
mWindowManager.executeAppTransition(/* { Dual-Screen */r.getDisplayId()/* Dual-Screen } */);
}
return true;
}
return false;
}
void handleAppCrashLocked(ProcessRecord app) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
int stackNdx = stacks.size() - 1;
while (stackNdx >= 0) {
stacks.get(stackNdx).handleAppCrashLocked(app);
stackNdx--;
}
}
}
boolean requestVisibleBehindLocked(ActivityRecord r, boolean visible) {
final ActivityStack stack = r.task.stack;
if (stack == null) {
if (DEBUG_VISIBLE_BEHIND) Slog.d(TAG_VISIBLE_BEHIND,
"requestVisibleBehind: r=" + r + " visible=" + visible + " stack is null");
return false;
}
final boolean isVisible = stack.hasVisibleBehindActivity();
if (DEBUG_VISIBLE_BEHIND) Slog.d(TAG_VISIBLE_BEHIND,
"requestVisibleBehind r=" + r + " visible=" + visible + " isVisible=" + isVisible);
final ActivityRecord top = topRunningActivityLocked();
if (top == null || top == r || (visible == isVisible)) {
if (DEBUG_VISIBLE_BEHIND) Slog.d(TAG_VISIBLE_BEHIND, "requestVisibleBehind: quick return");
stack.setVisibleBehindActivity(visible ? r : null);
return true;
}
// A non-top activity is reporting a visibility change.
if (visible && top.fullscreen) {
// Let the caller know that it can't be seen.
if (DEBUG_VISIBLE_BEHIND) Slog.d(TAG_VISIBLE_BEHIND,
"requestVisibleBehind: returning top.fullscreen=" + top.fullscreen
+ " top.state=" + top.state + " top.app=" + top.app + " top.app.thread="
+ top.app.thread);
return false;
} else if (!visible && stack.getVisibleBehindActivity() != r) {
// Only the activity set as currently visible behind should actively reset its
// visible behind state.
if (DEBUG_VISIBLE_BEHIND) Slog.d(TAG_VISIBLE_BEHIND,
"requestVisibleBehind: returning visible=" + visible
+ " stack.getVisibleBehindActivity()=" + stack.getVisibleBehindActivity()
+ " r=" + r);
return false;
}
stack.setVisibleBehindActivity(visible ? r : null);
if (!visible) {
// Make the activity immediately above r opaque.
final ActivityRecord next = stack.findNextTranslucentActivity(r);
if (next != null) {
mService.convertFromTranslucent(next.appToken);
}
}
if (top.app != null && top.app.thread != null) {
// Notify the top app of the change.
try {
top.app.thread.scheduleBackgroundVisibleBehindChanged(top.appToken, visible);
} catch (RemoteException e) {
}
}
return true;
}
// Called when WindowManager has finished animating the launchingBehind activity to the back.
void handleLaunchTaskBehindCompleteLocked(ActivityRecord r) {
r.mLaunchTaskBehind = false;
final TaskRecord task = r.task;
task.setLastThumbnail(task.stack.screenshotActivities(r));
mRecentTasks.addLocked(task);
mService.notifyTaskStackChangedLocked();
mWindowManager.setAppVisibility(r.appToken, false/* { Dual-Screen */, r.getDisplayId()/* Dual-Screen } */);
}
void scheduleLaunchTaskBehindComplete(IBinder token) {
mHandler.obtainMessage(LAUNCH_TASK_BEHIND_COMPLETE, token).sendToTarget();
}
/* { AppCore */
/**
* it will be removed soon because app could solve related issue by themselves. needless anymore.
* @deprecated
*/
void updateLastShownWhenLocked(int displayId) {
if (!(mWindowManager.isKeyguardLocked() && mWindowManager.isKeyguardSecure()) || true /* just return */) {
return;
}
synchronized(mWindowManager.getWindowManagerLock()) {
ArrayList<TaskRecord> globalTasks = getGlobalTaskHistoryLocked(displayId);
for (TaskRecord tr : globalTasks) {
for (ActivityRecord r : tr.mActivities) {
r.mIsLastShownWhenLocked = false;
mWindowManager.setAppWindowIsLastShownWhenLocked(r.appToken, false);
}
}
ActivityRecord lastShowWhenLockedActivity = null;
boolean isUpperShowWhenLockedActivityFound = false;
for (int i = globalTasks.size() - 1; i >= 0; i--) {
TaskRecord task = globalTasks.get(i);
for (int j = task.mActivities.size() - 1; j >= 0; j--) {
ActivityRecord r = task.mActivities.get(j);
if (r.finishing) {
continue;
}
if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
|| (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
continue;
}
WindowManager.LayoutParams lp = mWindowManager.getMainWindowAttributesLocked(r.appToken);
if (lp != null) {
if ((lp.flags & WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED) != 0) {
if(isUpperShowWhenLockedActivityFound == false){
isUpperShowWhenLockedActivityFound = true;
}else{
lastShowWhenLockedActivity = r;
}
} else {
if (lastShowWhenLockedActivity != null) {
lastShowWhenLockedActivity.mIsLastShownWhenLocked = true;
mWindowManager.setAppWindowIsLastShownWhenLocked(lastShowWhenLockedActivity.appToken, true);
}
return;
}
}
}
}
}//end of "synchronized"
}
/* AppCore } */
void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
/* { Dual-Screen */
if (SUPPORT_EXPANDED_MODE) {
ensureActivitiesVisibleLockedForUniversialTaskHistory(starting, configChanges);
return;
}
/* Dual-Screen } */
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final int displayId = mActivityDisplays.valueAt(displayNdx).mDisplayId;
ArrayList<TaskRecord> taskOrder = getGlobalTaskHistoryLocked(displayId);
/* { AppCore */
updateLastShownWhenLocked(displayNdx);
/* AppCore } */
int obscuredZone = MultiWindowStyle.ZONE_UNKNOWN;
int multiWindowZone = MultiWindowStyle.ZONE_UNKNOWN;
boolean bFromSplit = false;
int N = taskOrder.size();
TaskRecord homeTask = null;
TaskRecord overHomeTask = null;
// except floating stack...
/* { Virtual-Screen */
boolean invisibleVirtualScreen = false;
if (VIRTUALSCREEN_ENABLED) {
invisibleVirtualScreen = VirtualScreenManagerService.self().isVirtualScreen(displayId)
&& !VirtualScreenManagerService.self().isVisibleVirtualScreen(displayId);
}
/* Virtual-Screen } */
for (int i = N-1; i >= 0; i--) {
TaskRecord tr = taskOrder.get(i);
final ActivityStack stack = tr.stack;
boolean isMovingTaskFromCascadeToSplitStack = stack != null && stack.isFloatingStack() && tr.getTopActivityMultiWindowStyle().isSplit();
if (stack == null
|| isMovingTaskFromCascadeToSplitStack
|| (stack.isFloatingStack() && (!tr.bHidden && tr.getTopActivityMultiWindowStyle().isCascade()))) {
continue;
}
TaskRecord task = taskOrder.get(i);
ActivityRecord top = stack.topMultiPhoneWindowActivity();
//TODO
//1) top.multiWindowStyle.isEnabled(MultiWindowStyle.OPTION_TAB_MODE)
boolean isFullscreen = task.isFullscreenVisible();
int taskObscuredZone = task.getVisibleObscuredZone(false);
boolean visible = false;
if (stack.isHomeStack()) {
homeTask = tr;
} else if (overHomeTask == null && tr.isOverHomeStack()) {
overHomeTask = tr;
}
/* { Virtual-Screen */
if (VIRTUALSCREEN_ENABLED && invisibleVirtualScreen) {
visible = false;
} /* Virtual-Screen } */
else if (homeTask == null && overHomeTask != null && tr != overHomeTask
&& (obscuredZone & taskObscuredZone) == taskObscuredZone) {
visible = false;
taskObscuredZone = MultiWindowStyle.ZONE_UNKNOWN;
} else if (bFromSplit && multiWindowZone == MultiWindowStyle.ZONE_FULL &&
(taskObscuredZone == MultiWindowStyle.ZONE_FULL ||
taskObscuredZone == MultiWindowStyle.ZONE_UNKNOWN)){
visible = false;
} else if(obscuredZone != MultiWindowStyle.ZONE_FULL) {
if (taskObscuredZone == MultiWindowStyle.ZONE_UNKNOWN) {
visible = true;
}else{
visible = (obscuredZone & taskObscuredZone) != taskObscuredZone;
}
}
stack.ensureActivitiesVisibleLocked(starting, configChanges, task, visible);
if (isFullscreen) {
obscuredZone |= taskObscuredZone;
}
if (taskObscuredZone != MultiWindowStyle.ZONE_FULL &&
taskObscuredZone != MultiWindowStyle.ZONE_UNKNOWN ) {
bFromSplit = true;
}
multiWindowZone |= taskObscuredZone;
}
// only for floating stack...
for (ActivityStack stack : mActivityDisplays.valueAt(displayNdx).mStacks){
if (stack.isFloatingStack()) {
ActivityRecord ar = stack.topRunningActivityLocked(null, true);
TaskRecord task = ar == null ? null : ar.task;
if (task != null) {
stack.ensureActivitiesVisibleLocked(starting, configChanges);
}
}
}
}
} else {
/* Multi-Window } */
// First the front stacks. In case any are not fullscreen and are in front of home.
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
final int topStackNdx = stacks.size() - 1;
for (int stackNdx = topStackNdx; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
stack.ensureActivitiesVisibleLocked(starting, configChanges);
}
}
}
}
void clearOtherAppTimeTrackers(AppTimeTracker except) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
final int topStackNdx = stacks.size() - 1;
for (int stackNdx = topStackNdx; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
stack.clearOtherAppTimeTrackers(except);
}
}
}
void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
final int numStacks = stacks.size();
for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
stack.scheduleDestroyActivities(app, reason);
}
}
}
void releaseSomeActivitiesLocked(ProcessRecord app, String reason) {
// Examine all activities currently running in the process.
TaskRecord firstTask = null;
// Tasks is non-null only if two or more tasks are found.
ArraySet<TaskRecord> tasks = null;
if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Trying to release some activities in " + app);
for (int i = 0; i < app.activities.size(); i++) {
ActivityRecord r = app.activities.get(i);
// First, if we find an activity that is in the process of being destroyed,
// then we just aren't going to do anything for now; we want things to settle
// down before we try to prune more activities.
if (r.finishing || r.state == DESTROYING || r.state == DESTROYED) {
if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Abort release; already destroying: " + r);
return;
}
// Don't consider any activies that are currently not in a state where they
// can be destroyed.
if (r.visible || !r.stopped || !r.haveState || r.state == RESUMED || r.state == PAUSING
|| r.state == PAUSED || r.state == STOPPING) {
if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Not releasing in-use activity: " + r);
continue;
}
if (r.task != null) {
if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Collecting release task " + r.task
+ " from " + r);
if (firstTask == null) {
firstTask = r.task;
} else if (firstTask != r.task) {
if (tasks == null) {
tasks = new ArraySet<>();
tasks.add(firstTask);
}
tasks.add(r.task);
}
}
}
if (tasks == null) {
if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Didn't find two or more tasks to release");
return;
}
// If we have activities in multiple tasks that are in a position to be destroyed,
// let's iterate through the tasks and release the oldest one.
final int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
// Step through all stacks starting from behind, to hit the oldest things first.
for (int stackNdx = 0; stackNdx < stacks.size(); stackNdx++) {
final ActivityStack stack = stacks.get(stackNdx);
// Try to release activities in this stack; if we manage to, we are done.
if (stack.releaseSomeActivitiesLocked(app, tasks, reason) > 0) {
return;
}
}
}
}
boolean switchUserLocked(int userId, UserState uss) {
mUserStackInFront.put(mCurrentUser, mFocusedStack.getStackId());
final int restoreStackId = mUserStackInFront.get(userId, HOME_STACK_ID);
mCurrentUser = userId;
mStartingUsers.add(uss);
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
stack.switchUserLocked(userId);
TaskRecord task = stack.topTask();
if (task != null) {
mWindowManager.moveTaskToTop(task.taskId);
}
}
}
ActivityStack stack = getStack(restoreStackId);
if (stack == null) {
stack = mHomeStack;
}
final boolean homeInFront = stack.isHomeStack();
if (stack.isOnHomeDisplay()) {
TaskRecord task = stack.topTask();
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
moveStack(stack, true);
if(task != null) {
stack.mActivityContainer.moveGlobalTaskToTop(task);
}
} else {
/* Multi-Window } */
moveHomeStack(homeInFront, "switchUserOnHomeDisplay");
}
//TaskRecord task = stack.topTask();
if (task != null) {
mWindowManager.moveTaskToTop(task.taskId);
}
} else {
// Stack was moved to another display while user was swapped out.
resumeHomeStackTask(HOME_ACTIVITY_TYPE, null, "switchUserOnOtherDisplay");
}
return homeInFront;
}
/**
* Add background users to send boot completed events to.
* @param userId The user being started in the background
* @param uss The state object for the user.
*/
public void startBackgroundUserLocked(int userId, UserState uss) {
mStartingBackgroundUsers.add(uss);
}
/** Checks whether the userid is a profile of the current user. */
boolean isCurrentProfileLocked(int userId) {
if (userId == mCurrentUser) return true;
for (int i = 0; i < mService.mCurrentProfileIds.length; i++) {
if (mService.mCurrentProfileIds[i] == userId) return true;
}
return false;
}
final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
/* { Dual-Screen */
return processStoppingActivitiesLocked(remove, Display.DISPLAY_NONE);
}
final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove, int displayId) {
/* Dual-Screen } */
ArrayList<ActivityRecord> stops = null;
final boolean nowVisible = allResumedActivitiesVisible(); // Dual-Screen : stopping activities are for all display
for (int activityNdx = mStoppingActivities.size() - 1; activityNdx >= 0; --activityNdx) {
ActivityRecord s = mStoppingActivities.get(activityNdx);
final boolean waitingVisible = mWaitingVisibleActivities.contains(s);
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
if (displayId > Display.DISPLAY_NONE) {
s.dualScreenAttrs.addStopFlag(displayId);
if (!s.dualScreenAttrs.okToStop()) {
continue;
}
}
s.dualScreenAttrs.clearStopFlag();
}
/* Dual-Screen } */
if (DEBUG_ALL) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible
+ " waitingVisible=" + waitingVisible + " finishing=" + s.finishing);
if (waitingVisible && nowVisible) {
mWaitingVisibleActivities.remove(s);
if (s.finishing) {
// If this activity is finishing, it is sitting on top of
// everyone else but we now know it is no longer needed...
// so get rid of it. Otherwise, we need to go through the
// normal flow and hide it once we determine that it is
// hidden by the activities in front of it.
if (DEBUG_ALL) Slog.v(TAG, "Before stopping, can hide: " + s);
mWindowManager.setAppVisibility(s.appToken, false/* { Dual-Screen */, s.getDisplayId()/* Dual-Screen } */);
}
}
if ((!waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
if (DEBUG_ALL) Slog.v(TAG, "Ready to stop: " + s);
if (stops == null) {
stops = new ArrayList<>();
}
stops.add(s);
mStoppingActivities.remove(activityNdx);
}
}
return stops;
}
void validateTopActivitiesLocked() {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
final ActivityRecord r = stack.topRunningActivityLocked(null);
final ActivityState state = r == null ? DESTROYED : r.state;
if (isFrontStack(stack)) {
if (r == null) Slog.e(TAG,
"validateTop...: null top activity, stack=" + stack);
else {
final ActivityRecord pausing = stack.mPausingActivity;
if (pausing != null && pausing == r) Slog.e(TAG,
"validateTop...: top stack has pausing activity r=" + r
+ " state=" + state);
if (state != INITIALIZING && state != RESUMED) Slog.e(TAG,
"validateTop...: activity in front not resumed r=" + r
+ " state=" + state);
}
} else {
final ActivityRecord resumed = stack.mResumedActivity;
if (resumed != null && resumed == r) Slog.e(TAG,
"validateTop...: back stack has resumed activity r=" + r
+ " state=" + state);
if (r != null && (state == INITIALIZING || state == RESUMED)) Slog.e(TAG,
"validateTop...: activity in back resumed r=" + r + " state=" + state);
}
}
}
}
private String lockTaskModeToString() {
switch (mLockTaskModeState) {
case LOCK_TASK_MODE_LOCKED:
return "LOCKED";
case LOCK_TASK_MODE_PINNED:
return "PINNED";
case LOCK_TASK_MODE_NONE:
return "NONE";
default: return "unknown=" + mLockTaskModeState;
}
}
public void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("mFocusedStack=" + mFocusedStack);
pw.print(" mLastFocusedStack="); pw.println(mLastFocusedStack);
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
for (int i = 0; i < Display.DUAL_SCREEN_TYPE_MAX; i++) {
pw.print(prefix);
pw.printf("mHomeStacks[" + i + "]=" + mHomeStacks[i]);
pw.printf(" mFrontStacks[" + i + "]=" + mFrontStacks[i]);
pw.printf(" mLastFocusedStacks[" + i + "]=" + mLastFocusedStacks[i]);
pw.println();
}
}
/* Dual-Screen } */
pw.print(prefix); pw.println("mSleepTimeout=" + mSleepTimeout);
pw.print(prefix); pw.println("mCurTaskId=" + mCurTaskId);
pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront);
pw.print(prefix); pw.println("mActivityContainers=" + mActivityContainers);
pw.print(prefix); pw.print("mLockTaskModeState=" + lockTaskModeToString());
final SparseArray<String[]> packages = mService.mLockTaskPackages;
if (packages.size() > 0) {
pw.println(" mLockTaskPackages (userId:packages)=");
for (int i = 0; i < packages.size(); ++i) {
pw.print(prefix); pw.print(prefix); pw.print(packages.keyAt(i));
pw.print(":"); pw.println(Arrays.toString(packages.valueAt(i)));
}
}
pw.println(" mLockTaskModeTasks" + mLockTaskModeTasks);
pw.print(prefix); pw.println("mCurrentUser=" + mCurrentUser);
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
pw.println(); pw.println("GlobalTaskHistory");
for (int i = mActivityDisplays.size() - 1; i >= 0; i--) {
ActivityDisplay d = mActivityDisplays.valueAt(i);
pw.print(prefix);pw.print("ActivityDisplay #" + d.mDisplayId);
pw.println(" (" + d.mDisplayInfo.appWidth + "x" + d.mDisplayInfo.appHeight + ")");
TaskRecord tr;
ArrayList<TaskRecord> tasks = getGlobalTaskHistoryLocked(d.mDisplayId);
for (int j = tasks.size() - 1; j >= 0; j--) {
tr = tasks.get(j);
pw.print(prefix); pw.print(prefix); pw.print("TASK id #" + tr.taskId);
pw.print("\tu" + tr.userId);
pw.print("\t(Stack #" + tr.stack.mStackId + (tr.stack.isFloatingStack() ? "f)" : ")"));
pw.println("\t" + tr.affinity);
}
}
MultiWindowFacadeService.self().dumpMultiWindowSetting(pw, prefix);
}
/* Multi-Window } */
/* { Dual-Screen */
if (DUALSCREEN_ENABLED && SUPPORT_EXPANDED_MODE) {
pw.println(); pw.println("UniversialTaskHistory");
for (int j = mUniversalTaskHistory.size() - 1; j >= 0; j--) {
TaskRecord tr = mUniversalTaskHistory.get(j);
pw.print(prefix); pw.print(prefix); pw.print("TASK id #" + tr.taskId);
pw.print("\tu" + tr.userId);
pw.print("\t(Display #" + tr.stack.getDisplayId() + ")");
pw.print("\t(Stack #" + tr.stack.mStackId + (tr.stack.isFloatingStack() ? "f)" : ")"));
pw.println("\t" + tr.affinity);
}
if (mExpandedHomeTask != null) {
pw.println(); pw.println("mExpandedHomeTask");
pw.print(prefix); pw.print(prefix); pw.print("TASK id #" + mExpandedHomeTask.taskId);
pw.print("\tu" + mExpandedHomeTask.userId);
pw.print("\t(Display #" + mExpandedHomeTask.stack.getDisplayId() + ")");
pw.print("\t(Stack #" + mExpandedHomeTask.stack.mStackId + (mExpandedHomeTask.stack.isFloatingStack() ? "f)" : ")"));
pw.println("\t" + mExpandedHomeTask.affinity);
}
}
/* Dual-Screen } */
}
ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
return mFocusedStack.getDumpActivitiesLocked(name);
}
static boolean printThisActivity(PrintWriter pw, ActivityRecord activity, String dumpPackage,
boolean needSep, String prefix) {
if (activity != null) {
if (dumpPackage == null || dumpPackage.equals(activity.packageName)) {
if (needSep) {
pw.println();
}
pw.print(prefix);
pw.println(activity);
return true;
}
}
return false;
}
boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
boolean dumpClient, String dumpPackage) {
boolean printed = false;
boolean needSep = false;
for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx);
pw.print("Display #"); pw.print(activityDisplay.mDisplayId);
pw.println(" (activities from top to bottom):");
ArrayList<ActivityStack> stacks = activityDisplay.mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
StringBuilder stackHeader = new StringBuilder(128);
stackHeader.append(" Stack #");
stackHeader.append(stack.mStackId);
stackHeader.append(":");
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
stackHeader.append(stack.isHomeStack()? "[HOME STACK]" : "[APP STACK]");
stackHeader.append(" d" + stack.mDisplayId);
}
/* Dual-Screen } */
printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage,
needSep, stackHeader.toString());
printed |= dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false,
!dumpAll, false, dumpPackage, true,
" Running activities (most recent first):", null);
needSep = printed;
boolean pr = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep,
" mPausingActivity: ");
if (pr) {
printed = true;
needSep = false;
}
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED && ActivityStack.SUPPORT_MULTIPLE_PAUSING_ACTIVITIES) {
for (ActivityRecord r : stack.mPausingActivities) {
needSep = printed;
pr = printThisActivity(pw, r, dumpPackage, needSep, " mPausingActivities: ");
if (pr) {
printed = true;
needSep = false;
}
}
}
/* Multi-Window } */
pr = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep,
" mResumedActivity: ");
if (pr) {
printed = true;
needSep = false;
}
if (dumpAll) {
pr = printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep,
" mLastPausedActivity: ");
if (pr) {
printed = true;
needSep = true;
}
printed |= printThisActivity(pw, stack.mLastNoHistoryActivity, dumpPackage,
needSep, " mLastNoHistoryActivity: ");
}
needSep = printed;
}
}
printed |= dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll,
false, dumpPackage, true, " Activities waiting to finish:", null);
printed |= dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll,
false, dumpPackage, true, " Activities waiting to stop:", null);
printed |= dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
false, dumpPackage, true, " Activities waiting for another to become visible:",
null);
printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll,
false, dumpPackage, true, " Activities waiting to sleep:", null);
printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll,
false, dumpPackage, true, " Activities waiting to sleep:", null);
return printed;
}
static boolean dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
String prefix, String label, boolean complete, boolean brief, boolean client,
String dumpPackage, boolean needNL, String header1, String header2) {
TaskRecord lastTask = null;
String innerPrefix = null;
String[] args = null;
boolean printed = false;
for (int i=list.size()-1; i>=0; i--) {
final ActivityRecord r = list.get(i);
if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
continue;
}
if (innerPrefix == null) {
innerPrefix = prefix + " ";
args = new String[0];
}
printed = true;
final boolean full = !brief && (complete || !r.isInHistory());
if (needNL) {
pw.println("");
needNL = false;
}
if (header1 != null) {
pw.println(header1);
header1 = null;
}
if (header2 != null) {
pw.println(header2);
header2 = null;
}
if (lastTask != r.task) {
lastTask = r.task;
pw.print(prefix);
pw.print(full ? "* " : " ");
pw.println(lastTask);
if (full) {
lastTask.dump(pw, prefix + " ");
} else if (complete) {
// Complete + brief == give a summary. Isn't that obvious?!?
if (lastTask.intent != null) {
pw.print(prefix); pw.print(" ");
pw.println(lastTask.intent.toInsecureStringWithClip());
}
}
}
pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
pw.print(" #"); pw.print(i); pw.print(": ");
pw.println(r);
if (full) {
r.dump(pw, innerPrefix);
} else if (complete) {
// Complete + brief == give a summary. Isn't that obvious?!?
pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
if (r.app != null) {
pw.print(innerPrefix); pw.println(r.app);
}
}
if (client && r.app != null && r.app.thread != null) {
// flush anything that is already in the PrintWriter since the thread is going
// to write to the file descriptor directly
pw.flush();
try {
TransferPipe tp = new TransferPipe();
try {
r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
r.appToken, innerPrefix, args);
// Short timeout, since blocking here can
// deadlock with the application.
tp.go(fd, 2000);
} finally {
tp.kill();
}
} catch (IOException e) {
pw.println(innerPrefix + "Failure while dumping the activity: " + e);
} catch (RemoteException e) {
pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
}
needNL = true;
}
}
return printed;
}
void scheduleIdleTimeoutLocked(ActivityRecord next) {
if (DEBUG_IDLE) Slog.d(TAG_IDLE,
"scheduleIdleTimeoutLocked: Callers=" + Debug.getCallers(4));
Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
}
final void scheduleIdleLocked() {
mHandler.sendEmptyMessage(IDLE_NOW_MSG);
}
/* { Multi-Window */
final void scheduleIdleLocked(ActivityRecord r) {
if (r != null) {
if (DEBUG_IDLE) Slog.d(TAG, "scheduleIdleLocked(r): Callers=" + Debug.getCallers(4));
Message msg = mHandler.obtainMessage(IDLE_NOW_MSG, r);
mHandler.sendMessage(msg);
}
}
/* Multi-Window } */
void removeTimeoutsForActivityLocked(ActivityRecord r) {
if (DEBUG_IDLE) Slog.d(TAG_IDLE, "removeTimeoutsForActivity: Callers="
+ Debug.getCallers(4));
mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
}
final void scheduleResumeTopActivities() {
if (!mHandler.hasMessages(RESUME_TOP_ACTIVITY_MSG)) {
mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
}
}
void removeSleepTimeouts() {
mSleepTimeout = false;
mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
}
final void scheduleSleepTimeout() {
removeSleepTimeouts();
mHandler.sendEmptyMessageDelayed(SLEEP_TIMEOUT_MSG, SLEEP_TIMEOUT);
}
@Override
public void onDisplayAdded(int displayId) {
if (DEBUG_STACK) Slog.v(TAG, "Display added displayId=" + displayId);
mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_ADDED, displayId, 0));
}
@Override
public void onDisplayRemoved(int displayId) {
if (DEBUG_STACK) Slog.v(TAG, "Display removed displayId=" + displayId);
mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_REMOVED, displayId, 0));
}
@Override
public void onDisplayChanged(int displayId) {
if (DEBUG_STACK) Slog.v(TAG, "Display changed displayId=" + displayId);
mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_CHANGED, displayId, 0));
}
private void handleDisplayAdded(int displayId) {
boolean newDisplay;
synchronized (mService) {
newDisplay = mActivityDisplays.get(displayId) == null;
if (newDisplay) {
ActivityDisplay activityDisplay = new ActivityDisplay(displayId);
if (activityDisplay.mDisplay == null) {
Slog.w(TAG, "Display " + displayId + " gone before initialization complete");
return;
}
mActivityDisplays.put(displayId, activityDisplay);
/* { Dual-Screen */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
mService.mMultiWindowPolicy.initCenterBarPosition(displayId);
}
/* Dual-Screen } */
}
}
if (newDisplay) {
mWindowManager.onDisplayAdded(displayId);
}
}
private void handleDisplayRemoved(int displayId) {
synchronized (mService) {
ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
if (activityDisplay != null) {
ArrayList<ActivityStack> stacks = activityDisplay.mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
stacks.get(stackNdx).mActivityContainer.detachLocked();
}
mActivityDisplays.remove(displayId);
}
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
if (displayId < Display.DUAL_SCREEN_TYPE_MAX) {
mHomeStacks[displayId] = mFrontStacks[displayId] = null;
}
}
/* Dual-Screen } */
}
mWindowManager.onDisplayRemoved(displayId);
}
private void handleDisplayChanged(int displayId) {
synchronized (mService) {
ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
if (activityDisplay != null) {
// TODO: Update the bounds.
}
}
mWindowManager.onDisplayChanged(displayId);
}
private StackInfo getStackInfoLocked(ActivityStack stack) {
StackInfo info = new StackInfo();
mWindowManager.getStackBounds(stack.mStackId, info.bounds);
info.displayId = Display.DEFAULT_DISPLAY;
info.stackId = stack.mStackId;
ArrayList<TaskRecord> tasks = stack.getAllTasks();
final int numTasks = tasks.size();
int[] taskIds = new int[numTasks];
String[] taskNames = new String[numTasks];
for (int i = 0; i < numTasks; ++i) {
final TaskRecord task = tasks.get(i);
taskIds[i] = task.taskId;
taskNames[i] = task.origActivity != null ? task.origActivity.flattenToString()
: task.realActivity != null ? task.realActivity.flattenToString()
: task.getTopActivity() != null ? task.getTopActivity().packageName
: "unknown";
}
info.taskIds = taskIds;
info.taskNames = taskNames;
return info;
}
StackInfo getStackInfoLocked(int stackId) {
ActivityStack stack = getStack(stackId);
if (stack != null) {
return getStackInfoLocked(stack);
}
return null;
}
ArrayList<StackInfo> getAllStackInfosLocked() {
ArrayList<StackInfo> list = new ArrayList<StackInfo>();
for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int ndx = stacks.size() - 1; ndx >= 0; --ndx) {
list.add(getStackInfoLocked(stacks.get(ndx)));
}
}
return list;
}
TaskRecord getLockedTaskLocked() {
final int top = mLockTaskModeTasks.size() - 1;
if (top >= 0) {
return mLockTaskModeTasks.get(top);
}
return null;
}
boolean isLockedTask(TaskRecord task) {
return mLockTaskModeTasks.contains(task);
}
boolean isLastLockedTask(TaskRecord task) {
return mLockTaskModeTasks.size() == 1 && mLockTaskModeTasks.contains(task);
}
void removeLockedTaskLocked(final TaskRecord task) {
if (!mLockTaskModeTasks.remove(task)) {
return;
}
if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "removeLockedTaskLocked: removed " + task);
if (mLockTaskModeTasks.isEmpty()) {
// Last one.
if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "removeLockedTask: task=" + task +
" last task, reverting locktask mode. Callers=" + Debug.getCallers(3));
final Message lockTaskMsg = Message.obtain();
lockTaskMsg.arg1 = task.userId;
lockTaskMsg.what = LOCK_TASK_END_MSG;
lockTaskMsg.arg2 = mService.mCurrentUserId;
mHandler.sendMessage(lockTaskMsg);
}
}
void showLockTaskToast() {
if (mLockTaskNotify == null) {
mLockTaskNotify = new LockTaskNotify(mService.mContext);
}
/* { BikeMode Implementation */
if(CscFeature.getInstance().getString("CscFeature_Common_ConfigBikeMode").contains("bikemode")){
final int isBikeMode = Settings.System.getInt(mService.mContext.getContentResolver(), "isBikeMode", 0);
if(isBikeMode != 0) {
return;
}
}
/* BikeMode Implementation } */
mLockTaskNotify.showToast(mLockTaskModeState);
}
void showLockTaskEscapeMessageLocked(TaskRecord task) {
if (mLockTaskModeTasks.contains(task)) {
mHandler.sendEmptyMessage(SHOW_LOCK_TASK_ESCAPE_MESSAGE_MSG);
}
}
void setLockTaskModeLocked(TaskRecord task, int lockTaskModeState, String reason,
boolean andResume) {
/* TODO : MW/DUAL */
//Need to refactoring for locktaskmode for mw&dual feature
//mLockTaskModeTask value removed
if (task == null) {
// Take out of lock task mode if necessary
final TaskRecord lockedTask = getLockedTaskLocked();
if (lockedTask != null) {
removeLockedTaskLocked(lockedTask);
if (!mLockTaskModeTasks.isEmpty()) {
// There are locked tasks remaining, can only finish this task, not unlock it.
if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK,
"setLockTaskModeLocked: Tasks remaining, can't unlock");
lockedTask.performClearTaskLocked();
resumeTopActivitiesLocked();
return;
}
}
if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK,
"setLockTaskModeLocked: No tasks to unlock. Callers=" + Debug.getCallers(4));
return;
}
// Should have already been checked, but do it again.
if (task.mLockTaskAuth == LOCK_TASK_AUTH_DONT_LOCK) {
if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK,
"setLockTaskModeLocked: Can't lock due to auth");
return;
}
if (isLockTaskModeViolation(task)) {
Slog.e(TAG_LOCKTASK, "setLockTaskMode: Attempt to start an unauthorized lock task.");
return;
}
if (mLockTaskModeTasks.isEmpty()) {
// First locktask.
final Message lockTaskMsg = Message.obtain();
lockTaskMsg.obj = task.intent.getComponent().getPackageName();
lockTaskMsg.arg1 = task.userId;
lockTaskMsg.what = LOCK_TASK_START_MSG;
lockTaskMsg.arg2 = lockTaskModeState;
mHandler.sendMessage(lockTaskMsg);
}
// Add it or move it to the top.
if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "setLockTaskModeLocked: Locking to " + task +
" Callers=" + Debug.getCallers(4));
mLockTaskModeTasks.remove(task);
mLockTaskModeTasks.add(task);
if (task.mLockTaskUid == -1) {
task.mLockTaskUid = task.effectiveUid;
}
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
if (task.stack.isFloatingStack()) {
changeTypeOfTaskToNormalLocked(task);
}
mService.mMultiWindowPolicy.closePenWindow();
multiWindowSettingChangeLocked(false);
}
/* Multi-Window } */
if (andResume) {
findTaskToMoveToFrontLocked(task, 0, null, reason);
resumeTopActivitiesLocked();
}
}
boolean isLockTaskModeViolation(TaskRecord task) {
return isLockTaskModeViolation(task, false);
}
boolean isLockTaskModeViolation(TaskRecord task, boolean isNewClearTask) {
if (getLockedTaskLocked() == task && !isNewClearTask) {
return false;
}
/* { Dual-Screen */
if (DUALSCREEN_ENABLED && !mLockTaskModeTasks.isEmpty()) {
return !mLockTaskModeTasks.contains(task);
}
/* Dual-Screen }*/
final int lockTaskAuth = task.mLockTaskAuth;
switch (lockTaskAuth) {
case LOCK_TASK_AUTH_DONT_LOCK:
return !mLockTaskModeTasks.isEmpty();
case LOCK_TASK_AUTH_LAUNCHABLE_PRIV:
case LOCK_TASK_AUTH_LAUNCHABLE:
case LOCK_TASK_AUTH_WHITELISTED:
return false;
case LOCK_TASK_AUTH_PINNABLE:
// Pinnable tasks can't be launched on top of locktask tasks.
return !mLockTaskModeTasks.isEmpty();
default:
Slog.w(TAG, "isLockTaskModeViolation: invalid lockTaskAuth value=" + lockTaskAuth);
return true;
}
}
void onLockTaskPackagesUpdatedLocked() {
boolean didSomething = false;
for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord lockedTask = mLockTaskModeTasks.get(taskNdx);
final boolean wasWhitelisted =
(lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) ||
(lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED);
lockedTask.setLockTaskAuth();
final boolean isWhitelisted =
(lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) ||
(lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED);
if (wasWhitelisted && !isWhitelisted) {
// Lost whitelisting authorization. End it now.
if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "onLockTaskPackagesUpdated: removing " +
lockedTask + " mLockTaskAuth=" + lockedTask.lockTaskAuthToString());
removeLockedTaskLocked(lockedTask);
lockedTask.performClearTaskLocked();
didSomething = true;
}
}
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
stack.onLockTaskPackagesUpdatedLocked();
}
}
final ActivityRecord r = topRunningActivityLocked();
final TaskRecord task = r != null ? r.task : null;
if (mLockTaskModeTasks.isEmpty() && task != null
&& task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) {
// This task must have just been authorized.
if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK,
"onLockTaskPackagesUpdated: starting new locktask task=" + task);
setLockTaskModeLocked(task, ActivityManager.LOCK_TASK_MODE_LOCKED, "package updated",
false);
didSomething = true;
}
if (didSomething) {
resumeTopActivitiesLocked();
}
}
int getLockTaskModeState() {
return mLockTaskModeState;
}
private final class ActivityStackSupervisorHandler extends Handler {
public ActivityStackSupervisorHandler(Looper looper) {
super(looper);
}
void activityIdleInternal(ActivityRecord r) {
synchronized (mService) {
activityIdleInternalLocked(r != null ? r.appToken : null, true, null);
}
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case IDLE_TIMEOUT_MSG: {
if (DEBUG_IDLE) Slog.d(TAG_IDLE,
"handleMessage: IDLE_TIMEOUT_MSG: r=" + msg.obj);
if (mService.mDidDexOpt) {
mService.mDidDexOpt = false;
Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
nmsg.obj = msg.obj;
mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
return;
}
// We don't at this point know if the activity is fullscreen,
// so we need to be conservative and assume it isn't.
activityIdleInternal((ActivityRecord)msg.obj);
} break;
case IDLE_NOW_MSG: {
if (DEBUG_IDLE) Slog.d(TAG_IDLE, "handleMessage: IDLE_NOW_MSG: r=" + msg.obj);
activityIdleInternal((ActivityRecord)msg.obj);
} break;
case RESUME_TOP_ACTIVITY_MSG: {
synchronized (mService) {
resumeTopActivitiesLocked();
}
} break;
case SLEEP_TIMEOUT_MSG: {
synchronized (mService) {
if (mService.isSleepingOrShuttingDown()) {
Slog.w(TAG, "Sleep timeout! Sleeping now.");
mSleepTimeout = true;
checkReadyForSleepLocked();
}
}
} break;
case LAUNCH_TIMEOUT_MSG: {
if (mService.mDidDexOpt) {
mService.mDidDexOpt = false;
mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
return;
}
synchronized (mService) {
if (mLaunchingActivity.isHeld()) {
Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
if (VALIDATE_WAKE_LOCK_CALLER
&& Binder.getCallingUid() != Process.myUid()) {
throw new IllegalStateException("Calling must be system uid");
}
mLaunchingActivity.release();
}
}
} break;
case HANDLE_DISPLAY_ADDED: {
handleDisplayAdded(msg.arg1);
} break;
case HANDLE_DISPLAY_CHANGED: {
handleDisplayChanged(msg.arg1);
} break;
case HANDLE_DISPLAY_REMOVED: {
handleDisplayRemoved(msg.arg1);
} break;
case CONTAINER_CALLBACK_VISIBILITY: {
final ActivityContainer container = (ActivityContainer) msg.obj;
final IActivityContainerCallback callback = container.mCallback;
if (callback != null) {
try {
callback.setVisible(container.asBinder(), msg.arg1 == 1);
} catch (RemoteException e) {
}
}
} break;
case LOCK_TASK_START_MSG: {
// When lock task starts, we disable the status bars.
try {
if (mLockTaskNotify == null) {
mLockTaskNotify = new LockTaskNotify(mService.mContext);
}
mLockTaskNotify.show(true);
mLockTaskModeState = msg.arg2;
if (getStatusBarService() != null) {
int flags = 0;
if (mLockTaskModeState == LOCK_TASK_MODE_LOCKED) {
flags = StatusBarManager.DISABLE_MASK
& (~StatusBarManager.DISABLE_BACK);
} else if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
flags = StatusBarManager.DISABLE_MASK
& (~StatusBarManager.DISABLE_BACK)
& (~StatusBarManager.DISABLE_HOME)
& (~StatusBarManager.DISABLE_RECENT);
}
getStatusBarService().disable(flags, mToken,
mService.mContext.getPackageName());
}
mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG);
if (getDevicePolicyManager() != null) {
getDevicePolicyManager().notifyLockTaskModeChanged(true,
(String)msg.obj, msg.arg1);
}
/* { AppCore */
mWindowManager.onLockTaskModeChanged(mLockTaskModeState);
mService.onLockTaskModeChanged(true);
/* AppCore } */
} catch (RemoteException ex) {
throw new RuntimeException(ex);
}
} break;
case LOCK_TASK_END_MSG: {
// When lock task ends, we enable the status bars.
try {
if (getStatusBarService() != null) {
getStatusBarService().disableForUser(StatusBarManager.DISABLE_NONE, mToken,
mService.mContext.getPackageName(), msg.arg2);
}
mWindowManager.reenableKeyguard(mToken);
if (getDevicePolicyManager() != null) {
getDevicePolicyManager().notifyLockTaskModeChanged(false, null,
msg.arg1);
}
if (mLockTaskNotify == null) {
mLockTaskNotify = new LockTaskNotify(mService.mContext);
}
mLockTaskNotify.show(false);
try {
boolean shouldLockKeyguard = Settings.Secure.getIntForUser(
mService.mContext.getContentResolver(),
Settings.Secure.LOCK_TO_APP_EXIT_LOCKED,
mCurrentUser) != 0;
if (mLockTaskModeState == LOCK_TASK_MODE_PINNED && shouldLockKeyguard) {
IRestrictionPolicy rp = null;
if (SecProductFeature_KNOX.SEC_PRODUCT_FEATURE_KNOX_SUPPORT_MDM) {
rp = IRestrictionPolicy.Stub.asInterface(
ServiceManager.getService("restriction_policy"));
}
if (rp == null || rp.isScreenPinningAllowed(null)) {// SecProductFeature_KNOX.SEC_PRODUCT_FEATURE_KNOX_SUPPORT_MDM
mWindowManager.lockNow(null);
mWindowManager.dismissKeyguard();
new LockPatternUtils(mService.mContext)
.requireCredentialEntry(UserHandle.USER_ALL);
} else { // if screen pin is not allowed we don't show keyguard
mWindowManager.dismissKeyguard(); // SecProductFeature_KNOX.SEC_PRODUCT_FEATURE_KNOX_SUPPORT_MDM
}
}
} catch (SettingNotFoundException e) {
// No setting, don't lock.
}
} catch (RemoteException ex) {
throw new RuntimeException(ex);
} finally {
mLockTaskModeState = LOCK_TASK_MODE_NONE;
/* { AppCore */
mWindowManager.onLockTaskModeChanged(mLockTaskModeState);
mService.onLockTaskModeChanged(false);
/* AppCore } */
}
} break;
case SHOW_LOCK_TASK_ESCAPE_MESSAGE_MSG: {
if (mLockTaskNotify == null) {
mLockTaskNotify = new LockTaskNotify(mService.mContext);
}
mLockTaskNotify.showToast(LOCK_TASK_MODE_PINNED);
} break;
case CONTAINER_CALLBACK_TASK_LIST_EMPTY: {
final ActivityContainer container = (ActivityContainer) msg.obj;
final IActivityContainerCallback callback = container.mCallback;
if (callback != null) {
try {
callback.onAllActivitiesComplete(container.asBinder());
} catch (RemoteException e) {
}
}
} break;
case LAUNCH_TASK_BEHIND_COMPLETE: {
synchronized (mService) {
ActivityRecord r = ActivityRecord.forTokenLocked((IBinder) msg.obj);
if (r != null) {
handleLaunchTaskBehindCompleteLocked(r);
}
}
} break;
/* { Multi-Window */
case SHOW_TOAST_UNABLE_PENWINDOW_MSG: {
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
Context context = new ContextThemeWrapper(mService.mContext, android.R.style.Theme_DeviceDefault);
Toast.makeText(context, mService.mContext.getResources().getString(
com.android.internal.R.string.TS_PEN_WINDOW_NOT_SUPPORTED_BY_THIS_APP_TPOP), Toast.LENGTH_LONG).show();
}
} break;
case SHOW_TOAST_NOT_SUPPORT_CURRENT_SCREEN_MSG: {
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
Context context = new ContextThemeWrapper(mService.mContext, android.R.style.Theme_DeviceDefault);
Toast.makeText(context, mService.mContext.getResources().getString(
com.android.internal.R.string.TS_CURRENT_SCREEN_DOES_NOT_SUPPORT_POP_UP_VIEW_TPOP), Toast.LENGTH_LONG).show();
}
} break;
/* Multi-Window } */
/* { Dual-Screen */
case FIXED_SCREEN_MODE_CHANGED_MSG : {
mWindowManager.onFixedScreenModeChanged(msg.arg1);
// mService.onFixedScreenModeChanged(msg.arg1);
} break;
case RELEASE_FIXED_SCREEN_MODE_DIALG_MSG : {
if (mUnfixDialog == null) {
mUnfixDialogShow = false;
mUnfixDialog = new UnfixDialog(mService.mContext);
mUnfixDialog.create();
}
if (!mUnfixDialogShow) {
WindowManagerImpl wm = (WindowManagerImpl)mUnfixDialog.getWindow().getWindowManager();
wm.setDisplay(mDisplayManager.getDisplay(Display.DUAL_SCREEN_SUB_DISPLAY));
wm.addView(mUnfixDialog.getWindow().getDecorView(), mUnfixDialog.getWindow().getAttributes());
mUnfixDialogShow = true;
}
} break;
/* Dual-Screen } */
}
}
}
/* { Dual-Screen */
UnfixDialog mUnfixDialog;
boolean mUnfixDialogShow;
void initUnfixDialog() {
mUnfixDialogShow = false;
mUnfixDialog = new UnfixDialog(mService.mContext);
mUnfixDialog.create();
WindowManagerImpl wm = (WindowManagerImpl)mUnfixDialog.getWindow().getWindowManager();
wm.setDisplay(mDisplayManager.getDisplay(Display.DUAL_SCREEN_SUB_DISPLAY));
}
class UnfixDialog extends AlertDialog {
final int DO_NOTIHG_MSG = 0;
final int RELEASE_FIX_SCREEN_MODE_MSG = 1;
// pending attr for finishactivity
IBinder token;
int resultCode;
Intent resultData;
boolean finishTask;
public UnfixDialog(Context context) {
super(context);
setTitle("Unfix application");
setButton(DialogInterface.BUTTON_POSITIVE,"Unfix",mHandler.obtainMessage(RELEASE_FIX_SCREEN_MODE_MSG));
setButton(DialogInterface.BUTTON_NEGATIVE,"Cancel",mHandler.obtainMessage(DO_NOTIHG_MSG));
getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
}
private final Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case DO_NOTIHG_MSG : {
} break;
case RELEASE_FIX_SCREEN_MODE_MSG : {
if (mFixedTask != null) {
TaskRecord fixedTR = mFixedTask;
setFixedTask(null);
switch (mService.mPendingUnfixTask) {
case ActivityManagerService.PENDING_UNFIX_TASK_CALLED_BY_FINISHACTIVITY:
mService.finishActivity(token, resultCode, resultData, finishTask);
break;
case ActivityManagerService.PENDING_UNFIX_TASK_CALLED_BY_FINISHACTIVITYAFFINITY:
if (fixedTR.topRunningActivityLocked(null) != null) {
fixedTR.stack.finishActivityAffinityLocked(fixedTR.topRunningActivityLocked(null));
}
break;
case ActivityManagerService.PENDING_UNFIX_TASK_CALLED_BY_MOVETASKTOBACK:
fixedTR.stack.moveTaskToBackLocked(fixedTR.taskId);
break;
}
mService.mPendingUnfixTask = -1;
}
} break;
}
getWindow().getWindowManager().removeView(getWindow().getDecorView());
mUnfixDialogShow = false;
}
};
}
/* Dual-Screen } */
class ActivityContainer extends android.app.IActivityContainer.Stub {
final static int FORCE_NEW_TASK_FLAGS = Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION;
final int mStackId;
IActivityContainerCallback mCallback = null;
final ActivityStack mStack;
ActivityRecord mParentActivity = null;
String mIdString;
boolean mVisible = true;
/** Display this ActivityStack is currently on. Null if not attached to a Display. */
ActivityDisplay mActivityDisplay;
final static int CONTAINER_STATE_HAS_SURFACE = 0;
final static int CONTAINER_STATE_NO_SURFACE = 1;
final static int CONTAINER_STATE_FINISHING = 2;
int mContainerState = CONTAINER_STATE_HAS_SURFACE;
RuntimeException detachDebugException = null;
ActivityContainer(int stackId) {
/* { Multi-Window */
// TODO(mayu) : which is correct? ZONE_UNKNOWN? ZONE_FULL?
// activity stack supervisor give zone full. but, activity stack overwrite it to zone unknown before.
// so, I just change this to zone unknown also.
// but, multi window style default value is zone unknown.
// if we intilize with zone unknown, is no issue that found wrong stack?
this(stackId, (stackId == HOME_STACK_ID) ? HOME_STACK_TYPE : NORMAL_APP_STACK_TYPE, MultiWindowStyle.ZONE_UNKNOWN);
}
ActivityContainer(int stackId, int stackType, int zone) {
/* Multi-Window } */
synchronized (mService) {
mStackId = stackId;
/* { Multi-Window */
mStack = new ActivityStack(this, mRecentTasks, stackType, zone);
/* Multi-Window } */
mIdString = "ActivtyContainer{" + mStackId + "}";
if (DEBUG_STACK) Slog.d(TAG_STACK, "Creating " + this);
}
}
void attachToDisplayLocked(ActivityDisplay activityDisplay) {
/* { Mutli-Window */
attachToDisplayLocked(activityDisplay, null);
}
void attachToDisplayLocked(ActivityDisplay activityDisplay, Rect bounds) {
attachToDisplayLocked(activityDisplay, bounds, false);
}
void attachToDisplayLocked(ActivityDisplay activityDisplay, Rect bounds, boolean isSelectiveState) {
/* Mutli-Window } */
if (DEBUG_STACK) Slog.d(TAG_STACK, "attachToDisplayLocked: " + this
+ " to display=" + activityDisplay);
mActivityDisplay = activityDisplay;
mStack.mDisplayId = activityDisplay.mDisplayId;
mStack.mStacks = activityDisplay.mStacks;
activityDisplay.attachActivities(mStack);
mWindowManager.attachStack(mStackId, activityDisplay.mDisplayId
/* { Multi-Window */, mStack.mStackType, mStack.mStackZone, bounds, isSelectiveState/* Multi-Window } */);
}
@Override
public void attachToDisplay(int displayId) {
synchronized (mService) {
ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
if (activityDisplay == null) {
return;
}
attachToDisplayLocked(activityDisplay);
}
}
@Override
public int getDisplayId() {
synchronized (mService) {
if (mActivityDisplay != null) {
return mActivityDisplay.mDisplayId;
}
}
return -1;
}
@Override
public int getStackId() {
synchronized (mService) {
return mStackId;
}
}
@Override
public boolean injectEvent(InputEvent event) {
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mService) {
if (mActivityDisplay != null) {
return mInputManagerInternal.injectInputEvent(event,
mActivityDisplay.mDisplayId,
InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
}
}
return false;
} finally {
Binder.restoreCallingIdentity(origId);
}
}
@Override
public void release() {
synchronized (mService) {
if (mContainerState == CONTAINER_STATE_FINISHING) {
return;
}
mContainerState = CONTAINER_STATE_FINISHING;
long origId = Binder.clearCallingIdentity();
try {
mStack.finishAllActivitiesLocked(false);
removePendingActivityLaunchesLocked(mStack);
} finally {
Binder.restoreCallingIdentity(origId);
}
}
}
protected void detachLocked() {
if (DEBUG_STACK) Slog.d(TAG_STACK, "detachLocked: " + this + " from display="
+ mActivityDisplay + " Callers=" + Debug.getCallers(2));
if (mActivityDisplay != null) {
/* { Multi-Window */
// remove activity-timeout before detach the stack
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
mStack.removeTimeoutsForActivitiesLocked();
}
/* Multi-Window } */
mActivityDisplay.detachActivitiesLocked(mStack);
mActivityDisplay = null;
mStack.mDisplayId = -1;
mStack.mStacks = null;
mWindowManager.detachStack(mStackId);
if (SAFE_DEBUG) {
detachDebugException = new RuntimeException();
}
}
}
@Override
public final int startActivity(Intent intent) {
mService.enforceNotIsolatedCaller("ActivityContainer.startActivity");
final int userId = mService.handleIncomingUser(Binder.getCallingPid(),
Binder.getCallingUid(), mCurrentUser, false,
ActivityManagerService.ALLOW_FULL_ONLY, "ActivityContainer", null);
// TODO: Switch to user app stacks here.
String mimeType = intent.getType();
final Uri data = intent.getData();
if (mimeType == null && data != null && "content".equals(data.getScheme())) {
mimeType = mService.getProviderMimeType(data, userId);
}
checkEmbeddedAllowedInner(userId, intent, mimeType);
intent.addFlags(FORCE_NEW_TASK_FLAGS);
return startActivityMayWait(null, -1, null, intent, mimeType, null, null, null, null,
0, 0, null, null, null, null, false, userId, this, null);
}
@Override
public final int startActivityIntentSender(IIntentSender intentSender)
throws TransactionTooLargeException {
mService.enforceNotIsolatedCaller("ActivityContainer.startActivityIntentSender");
if (!(intentSender instanceof PendingIntentRecord)) {
throw new IllegalArgumentException("Bad PendingIntent object");
}
final int userId = mService.handleIncomingUser(Binder.getCallingPid(),
Binder.getCallingUid(), mCurrentUser, false,
ActivityManagerService.ALLOW_FULL_ONLY, "ActivityContainer", null);
final PendingIntentRecord pendingIntent = (PendingIntentRecord) intentSender;
checkEmbeddedAllowedInner(userId, pendingIntent.key.requestIntent,
pendingIntent.key.requestResolvedType);
return pendingIntent.sendInner(0, null, null, null, null, null, null, 0,
FORCE_NEW_TASK_FLAGS, FORCE_NEW_TASK_FLAGS, null, this);
}
private void checkEmbeddedAllowedInner(int userId, Intent intent, String resolvedType) {
ActivityInfo aInfo = resolveActivity(intent, resolvedType, 0, null, userId);
if (aInfo != null && (aInfo.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) {
throw new SecurityException(
"Attempt to embed activity that has not set allowEmbedded=\"true\"");
}
}
@Override
public IBinder asBinder() {
return this;
}
@Override
public void setSurface(Surface surface, int width, int height, int density) {
mService.enforceNotIsolatedCaller("ActivityContainer.attachToSurface");
}
ActivityStackSupervisor getOuter() {
return ActivityStackSupervisor.this;
}
boolean isAttachedLocked() {
return mActivityDisplay != null;
}
void getBounds(Point outBounds) {
synchronized (mService) {
if (mActivityDisplay != null) {
mActivityDisplay.getBounds(outBounds);
} else {
outBounds.set(0, 0);
}
}
}
// TODO: Make sure every change to ActivityRecord.visible results in a call to this.
void setVisible(boolean visible) {
if (mVisible != visible) {
mVisible = visible;
if (mCallback != null) {
mHandler.obtainMessage(CONTAINER_CALLBACK_VISIBILITY, visible ? 1 : 0,
0 /* unused */, this).sendToTarget();
}
}
}
void setDrawn() {
}
// You can always start a new task on a regular ActivityStack.
boolean isEligibleForNewTasks() {
return true;
}
void onTaskListEmptyLocked() {
/* { Virtual-Screen */
if (VIRTUALSCREEN_ENABLED) {
if (mActivityDisplay == null ||
(mActivityDisplay.mDisplayInfo.flags & Display.FLAG_VIRTUAL_SCREEN) != 0) {
return;
}
}
/* Virtual-Screen } */
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
return;
}
/* Dual-Screen } */
if (mActivityDisplay == null ||
(mActivityDisplay.mDisplayId == Display.DEFAULT_DISPLAY
/* { Multi-Window */
&& !(MultiWindowFeatures.MULTIWINDOW_ENABLED && mStack.isFloatingStack())
/* Multi-Window }*/
/* SEC_PRODUCT_FEATURE_COMMON_SUPPORT_WEARABLE_HMT {*/
&& !(VRApplicationPolicy.FEATURE_HMT && mStack.isVRStack())
/*} SEC_PRODUCT_FEATURE_COMMON_SUPPORT_WEARABLE_HMT*/
)) {
if (SAFE_DEBUG && detachDebugException != null) {
Slog.wtf(TAG, "ActivityContainer Display detach called before task empty.", detachDebugException);
}
return;
}
detachLocked();
deleteActivityContainer(this);
mHandler.obtainMessage(CONTAINER_CALLBACK_TASK_LIST_EMPTY, this).sendToTarget();
}
@Override
public String toString() {
return mIdString + (mActivityDisplay == null ? "N" : "A") + (mStack.isFloatingStack() ? "F" : "") + " zone=" + mStack.getZone();
}
/* { Multi-Window */
public void switchUserLocked() {
synchronized (mService) {
if (mActivityDisplay != null) {
int index = mActivityDisplay.mGlobalTaskHistory.size();
for (int i = 0; i < index;) {
TaskRecord task = mActivityDisplay.mGlobalTaskHistory.get(i);
if (isCurrentProfileLocked(task.userId)) {
if (DEBUG_TASKS) Slog.d(TAG, "switchUserLocked: stack=" + mStack.getStackId() + " moving " + task + " to top");
mActivityDisplay.mGlobalTaskHistory.remove(i);
mActivityDisplay.mGlobalTaskHistory.add(task);
--index;
// Use same value for i.
} else {
++i;
}
}
}
}
}
public void insertGlobalTaskAtTop(TaskRecord task) {
insertGlobalTaskAtTop(task, -1);
}
/*
*******************************************************************************************
* CAUTION:
* THERE IS THE SAME LOGIC IN TaskStack.java addTask() METHOD
* IF YOU WANT TO CHANGE THIS LOGIC YOU HAVE TO MODIFY TaskStack.java addTask() LOGIC ALSO
* for maintaining synchronization between mGlobalTaskHistory and mGlobalTasks
*******************************************************************************************
*/
public void insertGlobalTaskAtTop(TaskRecord task, int homeIdx) {
insertGlobalTaskAtTop(task, homeIdx, false);
}
public void insertGlobalTaskAtTop(TaskRecord task, int homeIdx, boolean showForAllUsers) {
synchronized (mService) {
if (mActivityDisplay != null) {
int taskNdx = mActivityDisplay.mGlobalTaskHistory.size();
// profiled user and not profiled user has different layer in history.
// so, if requested task is not profiled, try to find top ndx of not profiled layer.
boolean isProfiled = false;
if (showForAllUsers) {
isProfiled = true;
} else {
isProfiled = isCurrentProfileLocked(task.userId);
}
if (!isProfiled) {
// Put non-current user tasks below current user tasks.
while (--taskNdx >= 0) {
if (!isCurrentProfileLocked(mActivityDisplay.mGlobalTaskHistory.get(taskNdx).userId)) {
break;
}
}
++taskNdx;
}
// try to find top index of same type.
// floating and non floating stack will be in different layer in global task history.
if (taskNdx > 0) {
int idx = taskNdx; // idx is final target index to add
for (; idx > 0; idx--) {
if (task.stack.isHomeStack() && idx <= homeIdx) {
break;
}
TaskRecord targetTask = mActivityDisplay.mGlobalTaskHistory.get(idx - 1);
/* SEC_PRODUCT_FEATURE_COMMON_SUPPORT_WEARABLE_HMT {*/
if(VRApplicationPolicy.FEATURE_HMT) {
if (!task.stack.isVRStack() && targetTask.stack.isVRStack()) {
if(targetTask.getTaskToReturnTo() == HOME_ACTIVITY_TYPE) {
task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
targetTask.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
}
continue;
}
}
/*} SEC_PRODUCT_FEATURE_COMMON_SUPPORT_WEARABLE_HMT*/
if (isProfiled != isCurrentProfileLocked(targetTask.userId)) {
break;
}
/* { Galaxy-Desktop */
if (MultiWindowFeatures.DESKTOPMODE_ENABLED && mService.isKnoxDesktopModeLocked()) {
if (task.getLayer() >= targetTask.getLayer() ) {
if (!task.stack.isHomeStack() || (task.stack.isHomeStack() && !targetTask.stack.isFloatingStack())) {
break;
}
}
} else {
/* Galaxy-Desktop } */
if (task.getLayer() >= targetTask.getLayer()) break;
}
if ((task.multiWindowStyle.isNormal() || task.getTopActivityMultiWindowStyle().isNormal())
&& task.stack.isFloatingStack()
&& task.stack == targetTask.stack) {
// FullScreeOnly Activity's Task could be located upper than Cascade Activity's Task in the Same Stack.
break;
}
}
if (idx >= 0) {
taskNdx = idx;
}
}
mActivityDisplay.mGlobalTaskHistory.add(taskNdx, task);
}
}
}
public void add(int i, TaskRecord task) {
synchronized (mService) {
if (!mService.mSystemReady) {
return;
}
if (isAttachedLocked()) {
mActivityDisplay.mGlobalTaskHistory.add(i, task);
}
}
}
public boolean remove(TaskRecord task) {
synchronized (mService) {
if (isAttachedLocked()) {
return mActivityDisplay.mGlobalTaskHistory.remove(task);
}
return false;
}
}
public void moveGlobalTaskToTop(TaskRecord top) {
moveGlobalTaskToTop(top, false);
}
public void moveGlobalTaskToTop(TaskRecord top, boolean showForAllUsers) {
synchronized (mService) {
if (!mService.mSystemReady) {
return;
}
if (mActivityDisplay != null) {
if (top.isHomeTask()) {
int homeIdx = mActivityDisplay.mGlobalTaskHistory.indexOf(top);
mActivityDisplay.mGlobalTaskHistory.remove(top);
insertGlobalTaskAtTop(top, homeIdx);
} else {
mActivityDisplay.mGlobalTaskHistory.remove(top);
insertGlobalTaskAtTop(top, -1, showForAllUsers);
}
}
}
}
public void moveTaskToBackLocked(TaskRecord tr) {
moveTaskToBackLocked(tr, false);
}
public void moveTaskToBackLocked(TaskRecord tr, boolean forceToBottom) {
synchronized (mService) {
remove(tr);
int idx = 0;
if (tr.stack.isFloatingStack() && !forceToBottom) {
TaskRecord bottom = null;
ArrayList<TaskRecord> allTasks = tr.stack.getAllTasks();
for (int i = 0; i < allTasks.size(); i++) {
if (allTasks.get(i) != tr) {
bottom = allTasks.get(i);
break;
}
}
if (bottom != null) {
idx = getGlobalTaskHistoryLocked(/* { Dual-Screen */mActivityDisplay.mDisplayId/* Dual-Screen } */).indexOf(bottom);
}
}
add(idx, tr);
}
}
/* Multi-Window } */
}
private class VirtualActivityContainer extends ActivityContainer {
Surface mSurface;
boolean mDrawn = false;
VirtualActivityContainer(ActivityRecord parent, IActivityContainerCallback callback) {
super(getNextStackId());
mParentActivity = parent;
mCallback = callback;
mContainerState = CONTAINER_STATE_NO_SURFACE;
mIdString = "VirtualActivityContainer{" + mStackId + ", parent=" + mParentActivity + "}";
}
@Override
public void setSurface(Surface surface, int width, int height, int density) {
super.setSurface(surface, width, height, density);
synchronized (mService) {
final long origId = Binder.clearCallingIdentity();
try {
setSurfaceLocked(surface, width, height, density);
} finally {
Binder.restoreCallingIdentity(origId);
}
}
}
private void setSurfaceLocked(Surface surface, int width, int height, int density) {
if (mContainerState == CONTAINER_STATE_FINISHING) {
return;
}
VirtualActivityDisplay virtualActivityDisplay =
(VirtualActivityDisplay) mActivityDisplay;
if (virtualActivityDisplay == null) {
virtualActivityDisplay =
new VirtualActivityDisplay(width, height, density);
mActivityDisplay = virtualActivityDisplay;
mActivityDisplays.put(virtualActivityDisplay.mDisplayId, virtualActivityDisplay);
attachToDisplayLocked(virtualActivityDisplay);
}
if (mSurface != null) {
mSurface.release();
}
mSurface = surface;
if (surface != null) {
mStack.resumeTopActivityLocked(null);
} else {
mContainerState = CONTAINER_STATE_NO_SURFACE;
((VirtualActivityDisplay) mActivityDisplay).setSurface(null);
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED && ActivityStack.SUPPORT_MULTIPLE_PAUSING_ACTIVITIES) {
if (mStack.mResumedActivity != null) {
mStack.startPausingLocked(false, true, false, false);
}
} else {
/* Multi-Window } */
if (mStack.mPausingActivity == null && mStack.mResumedActivity != null) {
mStack.startPausingLocked(false, true, false, false);
}
/* { Multi-Window */
}
/* Multi-Window } */
}
setSurfaceIfReadyLocked();
if (DEBUG_STACK) Slog.d(TAG_STACK,
"setSurface: " + this + " to display=" + virtualActivityDisplay);
}
@Override
boolean isAttachedLocked() {
return mSurface != null && super.isAttachedLocked();
}
@Override
void setDrawn() {
synchronized (mService) {
mDrawn = true;
setSurfaceIfReadyLocked();
}
}
// Never start a new task on an ActivityView if it isn't explicitly specified.
@Override
boolean isEligibleForNewTasks() {
return false;
}
private void setSurfaceIfReadyLocked() {
if (DEBUG_STACK) Slog.v(TAG_STACK, "setSurfaceIfReadyLocked: mDrawn=" + mDrawn +
" mContainerState=" + mContainerState + " mSurface=" + mSurface);
if (mDrawn && mSurface != null && mContainerState == CONTAINER_STATE_NO_SURFACE) {
((VirtualActivityDisplay) mActivityDisplay).setSurface(mSurface);
mContainerState = CONTAINER_STATE_HAS_SURFACE;
}
}
}
/** Exactly one of these classes per Display in the system. Capable of holding zero or more
* attached {@link ActivityStack}s */
class ActivityDisplay {
/** Actual Display this object tracks. */
int mDisplayId;
Display mDisplay;
DisplayInfo mDisplayInfo = new DisplayInfo();
/** All of the stacks on this display. Order matters, topmost stack is in front of all other
* stacks, bottommost behind. Accessed directly by ActivityManager package classes */
final ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
ActivityRecord mVisibleBehindActivity;
/* { Multi-Window */
ArrayList<TaskRecord> mGlobalTaskHistory;
final SparseArray<ActivityStack> mZoneStacks = new SparseArray<ActivityStack>();
/* Multi-Window } */
ActivityDisplay() {
}
// After instantiation, check that mDisplay is not null before using this. The alternative
// is for this to throw an exception if mDisplayManager.getDisplay() returns null.
ActivityDisplay(int displayId) {
final Display display = mDisplayManager.getDisplay(displayId);
if (display == null) {
return;
}
init(display);
}
void init(Display display) {
mDisplay = display;
mDisplayId = display.getDisplayId();
mDisplay.getDisplayInfo(mDisplayInfo);
/* { Dual-Screen */
if (SUPPORT_EXPANDED_MODE) {
mGlobalTaskHistory = mUniversalTaskHistory;
} else {
/* Dual-Screen } */
mGlobalTaskHistory = new ArrayList<TaskRecord>();
}
}
void attachActivities(ActivityStack stack) {
if (DEBUG_STACK) Slog.v(TAG_STACK,
"attachActivities: attaching " + stack + " to displayId=" + mDisplayId);
mStacks.add(stack);
}
void detachActivitiesLocked(ActivityStack stack) {
if (DEBUG_STACK) Slog.v(TAG_STACK, "detachActivitiesLocked: detaching " + stack
+ " from displayId=" + mDisplayId);
mStacks.remove(stack);
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
for (int i = mGlobalTaskHistory.size() - 1; i >= 0; i--) {
TaskRecord task = mGlobalTaskHistory.get(i);
if (task.stack == stack) {
mGlobalTaskHistory.remove(i);
}
}
}
/* Multi-Window } */
}
void getBounds(Point bounds) {
mDisplay.getDisplayInfo(mDisplayInfo);
bounds.x = mDisplayInfo.appWidth;
bounds.y = mDisplayInfo.appHeight;
}
void setVisibleBehindActivity(ActivityRecord r) {
mVisibleBehindActivity = r;
}
boolean hasVisibleBehindActivity() {
return mVisibleBehindActivity != null;
}
@Override
public String toString() {
return "ActivityDisplay={" + mDisplayId + " numStacks=" + mStacks.size() + "}";
}
}
class VirtualActivityDisplay extends ActivityDisplay {
VirtualDisplay mVirtualDisplay;
VirtualActivityDisplay(int width, int height, int density) {
/* { Virtual-Screen */
this(width, height, density, false);
}
VirtualActivityDisplay(int width, int height, int density, boolean virtualScreen) {
/* Virtual-Screen } */
DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
/* { Virtual-Screen */
int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
if (virtualScreen) {
flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_VIRTUAL_SCREEN;
}
/* Virtual-Screen } */
mVirtualDisplay = dm.createVirtualDisplay(mService.mContext, null,
VIRTUAL_DISPLAY_BASE_NAME, width, height, density, null,
flags, null, null);
if (mVirtualDisplay == null) {
mDisplayId = Display.DISPLAY_NONE;
Slog.w(TAG, "Can't create VirtualActivityDisplay.");
return;
}
init(mVirtualDisplay.getDisplay());
mWindowManager.handleDisplayAdded(mDisplayId);
}
void setSurface(Surface surface) {
if (mVirtualDisplay != null) {
mVirtualDisplay.setSurface(surface);
}
}
@Override
void detachActivitiesLocked(ActivityStack stack) {
super.detachActivitiesLocked(stack);
if (mVirtualDisplay != null) {
mVirtualDisplay.release();
mVirtualDisplay = null;
}
}
@Override
public String toString() {
return "VirtualActivityDisplay={" + mDisplayId + "}";
}
}
private boolean isLeanbackOnlyDevice() {
boolean onLeanbackOnly = false;
try {
onLeanbackOnly = AppGlobals.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_LEANBACK_ONLY);
} catch (RemoteException e) {
// noop
}
return onLeanbackOnly;
}
// SecProductFeature_KNOX.SEC_PRODUCT_FEATURE_KNOX_SUPPORT_MDM {
// when Settings changes are not allowed block the application from start
// this is the most reliable way to block the whole Application without break
// other applications. Only widget and shortcuts are allowed
private int checkStartActivityAllowedByEDM(Intent intent, ActivityInfo aInfo, int callingUid, Bundle options, ComponentName cmp, String className) {
StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder(oldPolicy)
.permitDiskReads()
.build());
int userId = (aInfo != null) ? UserHandle.getUserId(aInfo.applicationInfo.uid) : UserHandle.USER_OWNER;
if ( cmp != null && cmp.getPackageName() != null ) {
String cmpPackageName = cmp.getPackageName();
if ( "com.android.settings".equals(cmpPackageName) ) {
try {
IRestrictionPolicy rp = IRestrictionPolicy.Stub.asInterface(ServiceManager.getService("restriction_policy"));
if (rp!=null && !rp.isSettingsChangesAllowedAsUser(false, userId)) {
boolean isActivityAllowed = false;
String activity = intent.getStringExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT);
if (activity == null) {
activity = cmp.getClassName();
}
for(String exception : RestrictionPolicy.settingsExceptions){
if (activity.equals(exception)){
isActivityAllowed=true;
break;
}
}
if (isActivityAllowed) {
intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
AuditLog.logAsUser(AuditLog.NOTICE, AuditLog.AUDIT_LOG_GROUP_APPLICATION, false, android.os.Process.myPid(), "ActivityStackSupervisor", AuditEvents.START_ACTIVITY + className
+ AuditEvents.SUCCEEDED, userId);
} else {
Slog.d(TAG, "Settings restriction policy blocks " + activity + " from starting!");
rp.isSettingsChangesAllowedAsUser(true, userId);
StrictMode.setThreadPolicy(oldPolicy);
AuditLog.logAsUser(AuditLog.NOTICE, AuditLog.AUDIT_LOG_GROUP_APPLICATION, false, android.os.Process.myPid(), "ActivityStackSupervisor", AuditEvents.START_ACTIVITY + className
+ AuditEvents.START_ACTIVITY_FAILED_SETTINGS, userId);
return ActivityManager.START_SUCCESS;
}
}
} catch (Exception e) {
e.printStackTrace();
}
} else if ( KioskMode.TASK_MANAGER_PKGNAME.equals(cmpPackageName)
|| KioskMode.CONTROL_PANEL_PKGNAME.equals(cmpPackageName) ) {
try {
IKioskMode km = IKioskMode.Stub.asInterface(ServiceManager
.getService("kioskmode"));
if (km != null && !km.isTaskManagerAllowedAsUser(true, userId)) {
StrictMode.setThreadPolicy(oldPolicy);
AuditLog.logAsUser(AuditLog.NOTICE, AuditLog.AUDIT_LOG_GROUP_APPLICATION, false, android.os.Process.myPid(), "ActivityStackSupervisor", AuditEvents.START_ACTIVITY + className
+ AuditEvents.START_ACTIVITY_FAILED_TASKMANAGER, userId);
return ActivityManager.START_SUCCESS;
}
} catch (Exception e) {
Slog.e("ActivityManager", "Is edm running?");
}
} else if ( SVOICE_PACKAGE1.equals(cmpPackageName) || SVOICE_PACKAGE2.equals(cmpPackageName) ) {
try {
IRestrictionPolicy rp = IRestrictionPolicy.Stub.asInterface(ServiceManager.getService("restriction_policy"));
if (rp!=null && (!rp.isSVoiceAllowedAsUser(true, userId) || !rp.isMicrophoneEnabledAsUser(true, userId))) {
String activity = intent.getStringExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT);
if (activity == null) {
activity = cmp.getClassName();
}
StrictMode.setThreadPolicy(oldPolicy);
AuditLog.logAsUser(AuditLog.NOTICE, AuditLog.AUDIT_LOG_GROUP_APPLICATION, false, android.os.Process.myPid(),
"ActivityStackSupervisor", AuditEvents.START_ACTIVITY + activity
+ AuditEvents.START_ACTIVITY_FAILED_SVOICE, userId);
return ActivityManager.START_SUCCESS;
}
} catch (Exception e) {
e.printStackTrace();
}
}
if ( cmp.getClassName() != null) {
try {
IPasswordPolicy pwdPolicy = IPasswordPolicy.Stub.asInterface(ServiceManager.getService("password_policy"));
ISecurityPolicy secPolicy = ISecurityPolicy.Stub.asInterface(ServiceManager.getService("security_policy"));
if ((pwdPolicy!=null && pwdPolicy.isChangeRequestedAsUser(userId) > PasswordPolicy.PWD_CHANGE_NOT_ENFORCED && !isPersona(userId)) ||
(secPolicy!=null && secPolicy.isDodBannerVisibleAsUser(userId))) {
List list = ActivityManagerNative.getDefault().getTasks(1, 0);
if (list != null && !list.isEmpty()) {
String topActivity = ((RunningTaskInfo) list.get(0)).topActivity.getClassName();
boolean isActivityAllowed = false;
boolean isTopActivityException = false;
String activity = cmp.getClassName();
for(String exception : PasswordPolicy.enforcePwdExceptions){
if (topActivity != null && topActivity.equals(exception)) {
isTopActivityException = true;
}
if (activity != null && activity.equals(exception)){
isActivityAllowed=true;
break;
}
}
if (isTopActivityException && !isActivityAllowed) {
StrictMode.setThreadPolicy(oldPolicy);
AuditLog.logAsUser(AuditLog.NOTICE, AuditLog.AUDIT_LOG_GROUP_APPLICATION, false, android.os.Process.myPid(), "ActivityStackSupervisor", AuditEvents.START_ACTIVITY + className
+ AuditEvents.START_ACTIVITY_FAILED_PASSWORD_ENFORCEMENT, userId);
return ActivityManager.START_SUCCESS;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
// check ApplicationState
try {
boolean isAllowed = EnterpriseDeviceManager.getInstance().getApplicationPolicy()
.getApplicationStateEnabledAsUser(cmpPackageName, true, userId);
if (!isAllowed) {
Slog.w("ActivityStack", "Unable to open " + cmpPackageName);
StrictMode.setThreadPolicy(oldPolicy);
return ActivityManager.START_SUCCESS;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
// If activity is not being started by EDM administrator,
// verify if its package name is at prevent start black list
if ((options == null) ||
options.getBoolean(android.app.enterprise.ApplicationPolicy.KEY_NON_SYSTEM_UID) ||
!options.getBoolean(android.app.enterprise.ApplicationPolicy.KEY_STARTED_BY_ADMIN)) {
if (aInfo != null) {
// Get information about the activity being started
String pkgName = aInfo.packageName;
ActivityRecord ar = findActivityLockedByPackage(userId, pkgName);
// Verify if activity has already been started. If so,
// does not need to prevent it from starting
if (ar == null) {
// Some apps (like Chrome) start an activity which is not kept
// at recent apps. Verify if calling uid is the same of activity
// being started
// Added validation isWidgetUsingPkg for widgets that calling the
// application that have the same package name but don't have permission
// to bypass prevent start (like memo).
PackageManager pm = mService.mContext.getPackageManager();
String callingPkgName = pm.getNameForUid(callingUid);
if (!pkgName.equals(callingPkgName) || mService.mDynamicHiddenApp.isWidgetUsingPkg(pkgName)) {
try {
IApplicationPolicy appPolicy = IApplicationPolicy.Stub.asInterface(
ServiceManager.getService("application_policy"));
if (appPolicy!=null&&appPolicy.isApplicationStartDisabledAsUser(pkgName, userId)) {
Slog.d(TAG, "Unable to start " + cmp.getPackageName() +
" which is at prevent start black list");
StrictMode.setThreadPolicy(oldPolicy);
AuditLog.logAsUser(AuditLog.NOTICE, AuditLog.AUDIT_LOG_GROUP_APPLICATION, false, android.os.Process.myPid(),
"ActivityStackSupervisor", AuditEvents.START_ACTIVITY + pkgName + AuditEvents.FAILED, userId);
return ActivityManager.START_SUCCESS;
}
else{
AuditLog.logAsUser(AuditLog.NOTICE, AuditLog.AUDIT_LOG_GROUP_APPLICATION, true, android.os.Process.myPid(),"ActivityStackSupervisor", AuditEvents.START_ACTIVITY + pkgName + AuditEvents.SUCCEEDED, userId);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
} else {
// EDM administrator is trying to start this activity. Reset options bundle
// as ApplicationPolicy.KEY_STARTED_BY_ADMIN extra is not needed anymore.
options = null;
}
StrictMode.setThreadPolicy(oldPolicy);
return -1;
}
private boolean isPersona(int userId){
boolean ret = false;
if(userId != UserHandle.USER_OWNER) {
if(SecProductFeature_KNOX.SEC_PRODUCT_FEATURE_KNOX_SUPPORT_CONTAINER) {
PersonaManager pm = (PersonaManager) mService.mContext.getSystemService(Context.PERSONA_SERVICE);
if (pm.exists(userId)) {
ret = true;
}
}
}
return ret;
}
// } SecProductFeature_KNOX.SEC_PRODUCT_FEATURE_KNOX_SUPPORT_MDM
/* { Multi-Window */
ActivityRecord topResumedActivityExceptFloatingLocked(boolean absoluteTop, int displayId) {
if(MultiWindowFeatures.MULTIWINDOW_ENABLED) {
if (mActivityDisplays.valueAt(displayId) == null) {
Slog.w(TAG, "There is no ActivityDisplay for displayId=" + displayId);
return null;
}
ArrayList<TaskRecord> taskOrder = getGlobalTaskHistoryLocked(displayId);
if (absoluteTop && taskOrder.size() > 0) {
return taskOrder.get(taskOrder.size() - 1).stack.topActivity();
}
for (int taskNdx = taskOrder.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = taskOrder.get(taskNdx);
if (task.stack != null && task.stack.mResumedActivity != null) {
if (task.stack.mResumedActivity.state == ActivityState.RESUMED
&& task.stack.mResumedActivity.multiWindowStyle.getType() != MultiWindowStyle.TYPE_CASCADE) {
return task.stack.mResumedActivity;
}
}
}
return mHomeStack != null ? mHomeStack.mResumedActivity : null;
}
return null;
}
void updateFocusedStack(ActivityStack stack, String reason) {
if (stack != null) {
if (!stack.isFloatingStack()) {
mNonFloatingFocusedStack = stack;
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
mNonFloatingFocusedStacks[stack.getDisplayId()] = stack;
}
/* Dual-Screen } */
}
} else {
mNonFloatingFocusedStack = stack;
}
if (mFocusedStack != stack) {
if (DEBUG_FOCUS || DEBUG_STACK)
Slog.d(TAG, "adjustStackFocus: Setting " + "focused stack to " + stack);
EventLog.writeEvent(EventLogTags.AM_FOCUS_STACK, (stack == null) ? -1 : stack.mStackId, reason);
if (!mWindowManager.hasLastDrawnFocusedStackFrameId()) {
mWindowManager.setLastDrawnFocusedStackFrameId(WindowManagerService.UNKOWN_STACKFRAME_ID);
}
/* { Virtual-Screen */
if (VIRTUALSCREEN_ENABLED) {
// TODO: need policy which task has to move.
if (stack != null && stack.isHomeStack()) {
TaskRecord topTask = stack.topTask();
if (!"moveTaskToBack".equals(reason)
&& topTask != null && topTask.isHomeTask()) {
VirtualScreenManagerService.self().moveTaskBackToDisplayIfNeeded(mFocusedStack.topTask(), true, false);
}
}
}
/* Virtual-Screen } */
} else {
if (DEBUG_FOCUS || DEBUG_STACK)
Slog.d(TAG, "adjustStackFocus: Focused stack already=" + stack);
}
/* { AppCore */
// To resume the activity when focusedStack is changed while Sleeping state
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
int targetDisplay = stack.getDisplayId();
if (mService.isSleeping() && mFrontStacks[targetDisplay] != stack) {
mChangedFrontStackWhileSleeping[targetDisplay] = true;
if (SAFE_DEBUG) Slog.i(TAG, "mChangedFrontStackWhileSleeping[" + targetDisplay + "]=true" + "/ mFrontStacks[" + targetDisplay + "]="
+ mFrontStacks[targetDisplay] + " / newStack=stack" + stack);
}
} else {
/* Dual-Screen } */
if (mService.isSleeping() && mFocusedStack != stack) {
mChangedFocusedStackWhileSleeping = true;
if (SAFE_DEBUG) Slog.i(TAG, "mChangedFocusedStackWhileSleeping=true" + "/ mFocusedStack="
+ mFocusedStack + " / newStack=stack" + stack);
}
}
/* AppCore } */
mFocusedStack = stack;
/* { Dual-Screen */
if (DUALSCREEN_ENABLED) {
if (stack.mDisplayId < Display.DUAL_SCREEN_TYPE_MAX) {
if (stack != null) {
mFrontStacks[stack.mDisplayId] = stack;
} else {
mFrontStacks[stack.mDisplayId] = null;
}
}
if (mFocusedStack != null) {
// TODO : in case of loose focus by activity finish....
// how can we update display id which ProcessRecord & ActivityThread has
ActivityRecord top = mFocusedStack.topRunningActivityLocked(null);
if (top != null && top.app != null && top.app.displayId != mFocusedStack.mDisplayId) {
top.app.displayId = mFocusedStack.mDisplayId;
try {
if (top.app.thread != null) {
top.app.thread.scheduleApplicationDisplayIdChanged(mFocusedStack.mDisplayId);
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
}
/* Dual-Screen } */
}
ActivityStack getNonFloatingFocusedStack() {
if (mNonFloatingFocusedStack == null) {
return mHomeStack;
}
return mNonFloatingFocusedStack;
}
/* { Dual-Screen */
ActivityStack getNonFloatingFocusedStack(int displayId) {
if (mNonFloatingFocusedStacks[displayId] == null) {
return mHomeStacks[displayId];
}
return mNonFloatingFocusedStacks[displayId];
}
private boolean mIsResumedBothCoupled = false;
final void notifyCoupledTaskStatusChangedLocked() {
boolean IsResumedBothCoupled = false;
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (ActivityStack stack : stacks) {
ActivityRecord top = null;
ActivityRecord topOfOpposite = null;
TaskRecord Opposite = null;
if (isFrontStack(stack) && (top = stack.topActivity()) != null) {
if (top.task != null && (Opposite = top.task.getCoupledTask()) != null
&& top.task.stack != null && Opposite.stack != null
&& top.task.stack.mDisplayId != Opposite.stack.mDisplayId
&& (topOfOpposite = Opposite.topRunningActivityLocked(null)) != null
&& topOfOpposite.state == ActivityState.RESUMED) {
displayNdx = mActivityDisplays.size();
IsResumedBothCoupled = true;
break;
}
}
}
}
if (IsResumedBothCoupled != mIsResumedBothCoupled) {
Intent coupledTaskStatusIntent = new Intent(
Intent.ACTION_NOTIFY_COUPLEDTASK_RESUMED_STATUS);
coupledTaskStatusIntent.putExtra(Intent.EXTRA_COUPLED_RESUMED_STATUS,
IsResumedBothCoupled);
mService.mContext.sendBroadcastAsUser(coupledTaskStatusIntent,
UserHandle.CURRENT_OR_SELF, DualScreenPolicy.USE_INTERNAL_APIS);
mIsResumedBothCoupled = IsResumedBothCoupled;
}
}
/* Dual-Screen } */
private boolean mHasMultiWindowStack = false;
boolean mHasRunningCascadeApp = false;
boolean mHasRunningSplitApp = false;
final void notifyGlobalMultiWindowStatusChangedLocked() {
boolean hasMultiWindowStack = false;
boolean hasRunningCascadeApp = false;
boolean hasRunningSplitApp = false;
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (ActivityStack stack : stacks) {
ActivityRecord top = null;
if (isFrontStack(stack) && (top = stack.topActivity()) != null) {
if (top.multiWindowStyle.getType() != MultiWindowStyle.TYPE_NORMAL) {
hasMultiWindowStack = true;
if (top.multiWindowStyle.getType() == MultiWindowStyle.TYPE_CASCADE) {
hasRunningCascadeApp = true;
} else if (top.multiWindowStyle.getType() == MultiWindowStyle.TYPE_SPLIT) {
hasRunningSplitApp = true;
}
}
}
}
}
if (hasMultiWindowStack != mHasMultiWindowStack || hasRunningCascadeApp != mHasRunningCascadeApp
|| hasRunningSplitApp != mHasRunningSplitApp) {
android.os.SystemProperties.set("sys.multiwindow.running", hasMultiWindowStack ? "1": "0");
Intent multiWindowModeIntent = new Intent(Intent.ACTION_NOTIFY_MULTIWINDOW_STATUS);
multiWindowModeIntent.putExtra(Intent.EXTRA_MULTIWINDOW_RUNNING, hasMultiWindowStack);
multiWindowModeIntent.putExtra(Intent.EXTRA_MULTIWINDOW_FREESTYLE, hasRunningCascadeApp);
multiWindowModeIntent.putExtra(Intent.EXTRA_MULTIWINDOW_SPLIT, hasRunningSplitApp);
mService.mContext.sendStickyBroadcast(multiWindowModeIntent);
mHasMultiWindowStack = hasMultiWindowStack;
mHasRunningCascadeApp = hasRunningCascadeApp;
mHasRunningSplitApp = hasRunningSplitApp;
mWindowManager.setIsCascadeRunning(hasRunningCascadeApp);
}
}
public void notifyResizeStack() {
synchronized (mService) {
ArrayList<Integer> taskIds = new ArrayList<Integer>();
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for(ActivityStack stack : stacks) {
if (stack.isNormalAppStack()) {
ArrayList<TaskRecord> tasks = stack.getAllTasks();
for(TaskRecord taskRecord : tasks) {
if (taskRecord.getTopActivity() != null && taskRecord.getTopActivity().state == ActivityState.RESUMED) {
taskIds.add(taskRecord.taskId);
}
}
}
}
}
for(int i=0; i<taskIds.size(); i++) {
TaskRecord taskRecord = anyTaskForIdLocked(taskIds.get(i));
if (taskRecord != null) {
taskRecord.stack.notifyMultiWindowStyleChangedLocked(taskRecord.getTopActivity(), MultiWindowStyle.NOTIFY_REASON_SIZE_CHANGED, true);
}
}
}
}
private ActivityRecord getTopActivityByZone(int zone) {
synchronized (mService) {
if (zone == MultiWindowStyle.ZONE_UNKNOWN) {
ActivityStack focusedStack = getFocusedStack();
if (focusedStack != null && !focusedStack.isHomeStack()) {
return focusedStack.topActivity();
}
} else {
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
int size = stacks.size();
for (int stackNdx = size - 1; stackNdx >= 0; --stackNdx) {
ActivityStack stack = stacks.get(stackNdx);
if (stack.isHomeStack()) {
continue;
}
ActivityRecord topActivity = stack.topActivity();
if (topActivity != null &&
topActivity.state == ActivityState.RESUMED &&
topActivity.multiWindowStyle.getZone() == zone) {
return topActivity;
}
}
}
}
return null;
}
}
public void changeTypeOfTaskToNormal(int zone) {
synchronized (mService) {
ActivityRecord topActivity = getTopActivityByZone(zone);
if (topActivity != null) {
final TaskRecord task = topActivity.task;
if (task != null) {
changeTypeOfTaskToNormalLocked(task);
}
}
}
}
private void changeTypeOfTaskToNormalLocked(TaskRecord task) {
if (task.stack != null) {
mService.setFocusedStack(task.stack.mStackId);
ActivityStack normalStack = getStack(MultiWindowStyle.ZONE_UNKNOWN, task.stack.mDisplayId);
if (normalStack == null) {
normalStack = createStackOnDisplay(getNextStackId(), Display.DEFAULT_DISPLAY, MultiWindowStyle.ZONE_UNKNOWN);
}
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: New stack task=" + task + " normalStackId=" + normalStack.mStackId);
updateFocusedStack(normalStack, "type-change");
moveStack(normalStack, true);
ActivityRecord top = task.getTopActivity();
if (top != null) {
MultiWindowStyle multiWindowStyle = new MultiWindowStyle(top.multiWindowStyle);
multiWindowStyle.setType(MultiWindowStyle.TYPE_NORMAL);
task.stack.setMultiWindowStyleForAllActivitiesInTaskLocked(task, multiWindowStyle);
task.stack.notifyMultiWindowStyleChangedLocked(top, MultiWindowStyle.NOTIFY_REASON_STYLE_CHANGED, true);
ArrayList<ActivityStack> stacks = task.stack.mActivityContainer.mActivityDisplay.mStacks;
for(int i = stacks.size() - 1; i > HOME_STACK_ID; i--) {
ActivityStack target = stacks.get(i);
if(!target.equals(top.task.stack) && target.mResumedActivity != null
&& target.mResumedActivity.multiWindowStyle.isSplit()) {
Bitmap tmp = target.screenshotActivities(target.mResumedActivity);
if(tmp != null) {
target.mResumedActivity.updateThumbnailLocked(tmp, null);
}
}
}
if (mFocusedStack != task.stack) {
//another side tasks must be paused.
pauseBackStacks(true, true, true);
mFocusedStack.minimalResumeActivityLocked(top);
moveTaskToStackLocked(task.taskId, mFocusedStack.getStackId(), true);
}
}
ensureActivitiesVisibleLocked(null, 0);
}
}
public boolean changeTypeOfTaskToCascade(Point touchPoint, int zone, boolean bMinimize) {
boolean result = false;
synchronized (mService) {
ActivityRecord topActivity = getTopActivityByZone(zone);
if (topActivity != null
&& !topActivity.multiWindowStyle.isEnabled(MultiWindowStyle.OPTION_DISABLE_FLOATING_WINDOW)) {
MultiWindowApplicationInfos multiWindowAppInfo = MultiWindowApplicationInfos.getInstance();
ActivityInfo info = topActivity.info;
if (info != null) {
Bundle metaData = info.applicationInfo != null ? info.applicationInfo.metaData : info.metaData;
if (!multiWindowAppInfo.isSupportScaleApp(info)
&& !(metaData != null && metaData.getBoolean(Intent.METADATA_MULTIWINDOW_PENWINDOW_ENABLE))) {
Message msg = mHandler.obtainMessage(SHOW_TOAST_UNABLE_PENWINDOW_MSG);
mHandler.sendMessageDelayed(msg, SHOW_TOAST_UNABLE_PENWINDOW_MSG);
return false;
}
result = changeTypeOfTaskToCascadeLocked(topActivity, touchPoint, bMinimize, false);
} else {
result = false;
}
} else {
if (topActivity != null) {
Message msg = mHandler.obtainMessage(SHOW_TOAST_NOT_SUPPORT_CURRENT_SCREEN_MSG);
mHandler.sendMessageDelayed(msg, SHOW_TOAST_NOT_SUPPORT_CURRENT_SCREEN_MSG);
}
}
}
return result;
}
public boolean changeTaskToMinimized(int taskId, Point iconCoordinates, boolean stayResumed) {
boolean result = false;
synchronized (mService) {
final TaskRecord task = anyTaskForIdLocked(taskId);
if (task != null) {
ActivityRecord topActivity = task.topRunningActivityLocked(null);
if(topActivity != null) {
if (topActivity.multiWindowStyle.isEnabled(MultiWindowStyle.OPTION_FULLSCREEN_MINIMIZABLE)) {
ArrayList<TaskRecord> taskOrder = topActivity.task.stack.getGlobalTaskHistoryLocked();
int nonFloatingTopTaskIndex;
for (nonFloatingTopTaskIndex = taskOrder.size()-1 ;nonFloatingTopTaskIndex >= 0; nonFloatingTopTaskIndex--) {
if (taskOrder.get(nonFloatingTopTaskIndex).stack.isFloatingStack()) {
continue;
} else {
break;
}
}
result = changeTypeOfTaskToCascadeLocked(topActivity, iconCoordinates, true, stayResumed);
if (taskOrder.get(nonFloatingTopTaskIndex).taskId == taskId && task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE) {
resumeHomeStackTask(HOME_ACTIVITY_TYPE, null, "changeTaskToMinimized", /* { Dual-Screen */topActivity.getDisplayId()/* Dual-Screen } */);
}
} else {
if (SAFE_DEBUG) {
Slog.e(TAG, "Gamemode: It cannot be converted into the minimized icon. The top Activity does not have the option OPTION_FULLSCREEN_MINIMIZABLE.("+topActivity+")");
}
}
} //end of "if(topActivity != null) {"
}
}
return result;
}
private boolean changeTypeOfTaskToCascadeLocked(ActivityRecord topActivity, Point targetPoint, boolean bMinimize, boolean stayResumed) {
boolean fromChangeTaskToMinimized = false;
if (topActivity.multiWindowStyle.getType()==MultiWindowStyle.TYPE_NORMAL && bMinimize) {
fromChangeTaskToMinimized = true;
}
Point displaySize = new Point();
float defaultPenWindowScale = mService.mMultiWindowPolicy.getDefaultScale();
int displayId = topActivity.task.stack.mDisplayId;
Display display = DisplayManagerGlobal.getInstance().getRealDisplay(displayId);
if (display != null) display.getSize(displaySize);
int windowDefWidth = (int)(displaySize.x * defaultPenWindowScale);
int windowDefHeight = (int)(displaySize.y * defaultPenWindowScale);
if (MultiWindowFeatures.SELECTIVE1ORIENTATION_ENABLED) {
int preferredOrientation = topActivity.getPreferredOrientation();
if (MultiWindowStyle.isFixedOrientation(preferredOrientation)) {
int globalOr = mService.mContext.getResources().getConfiguration().orientation;
int expectedOr = MultiWindowStyle.convertToConfigurationOrientation(preferredOrientation, globalOr);
if ((globalOr == Configuration.ORIENTATION_PORTRAIT && expectedOr == Configuration.ORIENTATION_LANDSCAPE)
|| (globalOr == Configuration.ORIENTATION_LANDSCAPE && expectedOr == Configuration.ORIENTATION_PORTRAIT)) {
float selectivePenWindowScale = mService.mMultiWindowPolicy.mSelectiveScale;
/* { Galaxy-Desktop */
if (DESKTOPMODE_ENABLED && mService.isKnoxDesktopModeLocked()) {
selectivePenWindowScale = mService.mMultiWindowPolicy.mDefDesktopScale;
}
/* Galaxy-Desktop } */
windowDefWidth = (int)(displaySize.y * selectivePenWindowScale);
windowDefHeight = (int)(displaySize.x * selectivePenWindowScale);
}
}
}
Rect rect = new Rect();
if (targetPoint != null) {
if (bMinimize) {
if (fromChangeTaskToMinimized) { //151105 In case of Game-mode, true
final int offSetX = targetPoint.x - (windowDefWidth / 2);
final int offSetY = targetPoint.y;
rect.set(0, 0, windowDefWidth, windowDefHeight);
rect.offsetTo(offSetX, offSetY);
} else {
Point point = mService.mMultiWindowPolicy.calculateMinimizePosition(displayId,
topActivity.multiWindowStyle.getZone(), displaySize);
rect.set(point.x, point.y, point.x + windowDefWidth, point.y + windowDefHeight);
}
} else {
rect.set(0, 0, windowDefWidth, windowDefHeight);
rect.offsetTo(targetPoint.x - windowDefWidth / 2, targetPoint.y);
}
} else {
if (fromChangeTaskToMinimized) { //In case of Game-mode, true
final int offSetX = (displaySize.x - windowDefWidth) / 2;
final int offSetY = (displaySize.y / 2);
rect.set(0, 0, windowDefWidth, windowDefHeight);
rect.offsetTo(offSetX, offSetY); //The minimizde Icon's default position is at the center of the display.
} else {
int statusBarHeight = mService.mContext.getResources().getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
rect.set(0, statusBarHeight, windowDefWidth, statusBarHeight + windowDefHeight);
}
}
topActivity.multiWindowStyle.setType(MultiWindowStyle.TYPE_CASCADE);
topActivity.multiWindowStyle.setOption(MultiWindowStyle.OPTION_SCALE, true);
topActivity.multiWindowStyle.setBounds(rect);
if (bMinimize) {
topActivity.multiWindowStyle.setOption(MultiWindowStyle.OPTION_MINIMIZED, true);
}
if (fromChangeTaskToMinimized) { //In case of Game-mode, true
topActivity.task.stack.setMultiWindowStyleForAllActivitiesInTaskLocked(topActivity.task, topActivity.multiWindowStyle);
topActivity.task.stack.notifyMultiWindowStyleChangedLocked(topActivity, MultiWindowStyle.NOTIFY_REASON_ARRANGE_MINIMIZED, true);
} else {
if (bMinimize) {
Bitmap tmp = topActivity.task.stack.screenshotActivities(topActivity);
if (tmp != null) {
topActivity.updateThumbnailLocked(tmp, null);
}
}
topActivity.task.stack.setMultiWindowStyleForAllActivitiesInTaskLocked(topActivity.task, topActivity.multiWindowStyle);
topActivity.task.stack.notifyMultiWindowStyleChangedLocked(topActivity, MultiWindowStyle.NOTIFY_REASON_STYLE_CHANGED, true);
}
final ActivityStack newFloatingStack = mService.mMultiWindowPolicy.adjustStackFocus(topActivity, topActivity.task, null);
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: New stack r=" + topActivity + " stackId=" + newFloatingStack.mStackId);
if (!stayResumed) {
//All tasks are going to be paused.
pauseBackStacks(true, true, true);
}
if (newFloatingStack != topActivity.task.stack) {
mWindowManager.prepareAppTransition(AppTransition.TRANSIT_MULTIWINDOW_NONE, false /* { Dual-Screen */, topActivity.getDisplayId()/* Dual-Screen } */);
/* { Galaxy-Desktop */
if (DESKTOPMODE_ENABLED && mService.isKnoxDesktopModeLocked()) {
mWindowManager.setIgnoreAdjustLayer(newFloatingStack.getStackId(), true);
newFloatingStack.mIgnoreAdjustLayer = true;
}
/* Galaxy-Desktop } */
moveTaskToStackLocked(topActivity.task.taskId, newFloatingStack.getStackId(), true);
if (!bMinimize) {
newFloatingStack.minimalResumeActivityLocked(topActivity);
}
/* { Galaxy-Desktop */
if (DESKTOPMODE_ENABLED && mService.isKnoxDesktopModeLocked()) {
mWindowManager.setIgnoreAdjustLayer(newFloatingStack.getStackId(), false);
newFloatingStack.mIgnoreAdjustLayer = false;
}
/* Galaxy-Desktop } */
}
if (bMinimize) {
int nextStackId = mService.mWindowManager.findNextFocusableFloatingStackIdFromTop();
if (nextStackId > -1) {
mService.setFocusedStack(nextStackId);
} else {
/* { Galaxy-Desktop */
if (DESKTOPMODE_ENABLED && mService.isKnoxDesktopModeLocked()) {
ActivityStack stack = getNonFloatingFocusedStack();
if (isFrontStack(stack)) {
mService.setFocusedStack(stack.mStackId);
} else {
ActivityRecord newTop = topRunningActivityLocked();
if (newTop != null) {
mService.setFocusedStack(newTop.task.stack.mStackId);
}
}
} else {
/* Galaxy-Desktop } */
mService.setFocusedStack(getNonFloatingFocusedStack().mStackId);
}
}
} else {
mService.setFocusedStack(newFloatingStack.mStackId);
}
return true;
}
public void notifyMinimizeMultiWindow(IBinder token) {
ActivityRecord r = ActivityRecord.forTokenLocked(token);
if (r != null) {
r.task.stack.onNotifyMinimizeMultiWindow(r);
}
}
public void multiWindowSettingChangeLocked(boolean value) {
if (!value) {
TaskRecord topTask = null;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx);
ActivityStack normalStack = getStack(MultiWindowStyle.ZONE_UNKNOWN, activityDisplay.mDisplayId);
int normalStackId = -1;
if (normalStack == null) {
normalStack = createStackOnDisplay(getNextStackId(), activityDisplay.mDisplayId, MultiWindowStyle.ZONE_UNKNOWN);
if (normalStack != null) {
normalStackId = normalStack.mStackId;
}
} else {
normalStackId = normalStack.mStackId;
}
mService.mMultiWindowPolicy.startFreezingTaskToReturnToLocked();
ArrayList<TaskRecord> topResumedTasks = new ArrayList();
ArrayList<TaskRecord> tasks = new ArrayList<TaskRecord>(getGlobalTaskHistoryLocked(activityDisplay.mDisplayId));
for (int taskNdx = tasks.size() -1; taskNdx >= 0; taskNdx--) {
TaskRecord task = tasks.get(taskNdx);
ActivityRecord ar = task.getTopActivity();
if (ar == null || task.stack.isFloatingStack()/* floating app will be closed */
|| task.stack.isVRStack() /* VR app should remain at VR stack */) {
continue;
}
if (ar != null && ar.state == ActivityState.RESUMED) {
if (topTask == null) {
topTask = task;
}
topResumedTasks.add(task);
continue;
}
if (task.stack.isHomeStack()) {
moveTaskToStackLocked(task.taskId, task.stack.mStackId, false, false);
continue;
}
if (ar.multiWindowStyle.getType() != MultiWindowStyle.TYPE_NORMAL) {
ar.multiWindowStyle.setType(MultiWindowStyle.TYPE_NORMAL);
task.stack.setMultiWindowStyleForAllActivitiesInTaskLocked(task, ar.multiWindowStyle);
task.stack.notifyMultiWindowStyleChangedLocked(ar, MultiWindowStyle.NOTIFY_REASON_STYLE_CHANGED, true);
}
moveTaskToStackLocked(task.taskId, normalStackId, false, false);
}
for (int taskNdx = topResumedTasks.size() - 1; taskNdx >= 0; taskNdx--) {
TaskRecord task = topResumedTasks.remove(taskNdx);
ActivityRecord ar = task.getTopActivity();
if (task.stack.isHomeStack()) {
moveTaskToStackLocked(task.taskId, task.stack.mStackId, true, true);
} else {
if (ar != null && ar.multiWindowStyle.getType() != MultiWindowStyle.TYPE_NORMAL) {
ar.multiWindowStyle.setType(MultiWindowStyle.TYPE_NORMAL);
task.stack.setMultiWindowStyleForAllActivitiesInTaskLocked(task, ar.multiWindowStyle);
task.stack.notifyMultiWindowStyleChangedLocked(ar, MultiWindowStyle.NOTIFY_REASON_STYLE_CHANGED, true);
}
moveTaskToStackLocked(task.taskId, normalStackId, true, true);
}
}
mService.mMultiWindowPolicy.stopFreezingTaskToReturnToLocked();
arrangeTaskToReturnTo(activityDisplay.mDisplayId);
}
if (topTask != null) {
updateFocusedStack(topTask.stack, "by turning off multi winodw setting");
}
resumeTopActivitiesLocked();
}
}
/*
* Could be null when homeStack was detached.
*/
public ActivityDisplay getDefaultDisplay() {
return mHomeStack.mActivityContainer.mActivityDisplay;
}
ArrayList<Integer> getStackOrder(boolean allStack, ActivityDisplay display) {
/* { Dual-Screen */
return getStackOrder(allStack, display, true);
}
ArrayList<Integer> getStackOrder(boolean allStack, ActivityDisplay display, boolean includeFinishing) {
/* Dual-Screen } */
/* { Dual-Screen */
if (DUALSCREEN_ENABLED && SUPPORT_EXPANDED_MODE) {
// if display is null, return universial stack order
} else {
/* Dual-Screen } */
if (display == null) {
return null;
}
}
ArrayList<Integer> resultStackOrder = new ArrayList<Integer>();
/* { Dual-Screen */
// ArrayList<TaskRecord> taskOrder = display.mGlobalTaskHistory;
ArrayList<TaskRecord> taskOrder;
if (DUALSCREEN_ENABLED && SUPPORT_EXPANDED_MODE && display == null) {
taskOrder = mUniversalTaskHistory;
} else {
/* Dual-Screen } */
taskOrder = getGlobalTaskHistoryLocked(display.mDisplayId);
}
TaskRecord taskInfo;
ActivityStack stack;
int mask = MultiWindowStyle.ZONE_UNKNOWN;
for (int i = taskOrder.size() - 1; i >= 0; i--) {
taskInfo = taskOrder.get(i);
stack = taskInfo.stack;
if (stack == null) {
continue;
}
ActivityRecord ar = taskInfo.topRunningActivityLocked(null);
if (!includeFinishing) {
if (ar == null) {
continue;
}
}
if (!allStack) {
if (!stack.isFloatingStack()) {
if (ar != null && !ar.task.bHidden) {
mask |= ar.multiWindowStyle.getZone();
} else {
continue;
}
}
}
if (!resultStackOrder.contains(stack.mStackId)) {
resultStackOrder.add(stack.mStackId);
}
if(!allStack){
if(stack.isNormalAppStack() &&
(mask == MultiWindowStyle.ZONE_FULL || mask == MultiWindowStyle.ZONE_UNKNOWN)) {
break;
}
}
}
return resultStackOrder;
}
/**
* return true or false on basis if we have callScreen scenario
*/
private boolean needsCascadeForceHidden() {
if (mService.mLockScreenShown == mService.LOCK_SCREEN_HIDDEN && !mService.mKeyguardGoingAway) {
if (mService.mWindowManager.isKeyguardLocked()) {
return true;
}
}
return false;
}
/**
* function for setting pinup flag whenever we have CallScreen Pinup scenario
*/
void updateCascadeHiddenFlag(boolean resumed) {
boolean needsFlags = needsCascadeForceHidden();
boolean flagChanged = false;
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (ActivityStack stack : stacks) {
if (stack.isFloatingStack()) {
ActivityRecord top = stack.topRunningActivityLocked(null, true);
if (top != null && top.multiWindowStyle.getType() == MultiWindowStyle.TYPE_CASCADE) {
if (top.multiWindowStyle.isEnabled(MultiWindowStyle.OPTION_HIDDEN) != needsFlags) {
flagChanged = true;
MultiWindowStyle multiWindowStyle = new MultiWindowStyle(top.multiWindowStyle);
multiWindowStyle.setOption(MultiWindowStyle.OPTION_HIDDEN, needsFlags);
stack.setMultiWindowStyleForAllActivitiesInTaskLocked(top.task, multiWindowStyle);
}
}
}
}
}
if (flagChanged) {
if (needsFlags) {
mService.mStackSupervisor.pauseBackStacks(false, true, true);
} else if (resumed) {
mService.mStackSupervisor.resumeTopActivitiesLocked();
}
}
ActivityStack focusedStack = getFocusedStack();
if (focusedStack != null) {
ActivityRecord top = focusedStack.topRunningActivityLocked(null, true);
if (top != null && top.multiWindowStyle.isEnabled(MultiWindowStyle.OPTION_HIDDEN)) {
int nextStackId = mService.mWindowManager.findNextFocusableFloatingStackIdFromTop();
if (nextStackId > -1) {
mService.setFocusedStack(nextStackId);
} else {
mService.setFocusedStack(getNonFloatingFocusedStack().mStackId);
}
}
}
}
public int getStackCount(int stackType) {
int count = 0;
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
if (stacks.get(stackNdx).mStackType == stackType) {
count++;
}
}
}
return count;
}
private static final ArrayList<TaskRecord> sEmptyGlobalTaskHistory = new ArrayList<TaskRecord>() {
@Override
public boolean add(TaskRecord object) {
throw new IllegalAccessError();
}
@Override
public void add(int index, TaskRecord object) {
throw new IllegalAccessError();
}
@Override
public boolean addAll(Collection<? extends TaskRecord> collection) {
throw new IllegalAccessError();
}
@Override
public boolean addAll(int index, Collection<? extends TaskRecord> collection) {
throw new IllegalAccessError();
}
@Override
public void clear() {
throw new IllegalAccessError();
}
@Override
public TaskRecord remove(int index) {
throw new IllegalAccessError();
}
@Override
public boolean remove(Object object) {
throw new IllegalAccessError();
}
@Override
public TaskRecord set(int index, TaskRecord object) {
throw new IllegalAccessError();
}
@Override
public boolean removeAll(Collection<?> collection) {
throw new IllegalAccessError();
}
@Override
public boolean retainAll(Collection<?> collection) {
throw new IllegalAccessError();
}
};
/** Mapping from displayId to display current state */
private final SparseArray<ArrayList<TaskRecord>> mTmpDisplayTaskHistoryList =
new SparseArray<ArrayList<TaskRecord>>();
public ArrayList<TaskRecord> getGlobalTaskHistoryLocked(int displayId) {
ActivityDisplay d = mActivityDisplays.get(displayId);
if (d == null) {
return sEmptyGlobalTaskHistory;
}
/* { Dual-Screen */
if (SUPPORT_EXPANDED_MODE) {
ArrayList<TaskRecord> displayTaskHistory = mTmpDisplayTaskHistoryList.get(displayId);
if (displayTaskHistory == null) {
displayTaskHistory = new ArrayList<TaskRecord>();
mTmpDisplayTaskHistoryList.put(displayId, displayTaskHistory);
}
displayTaskHistory.clear();
for (TaskRecord task : mUniversalTaskHistory) {
if (task.displayId == displayId) {
displayTaskHistory.add(task);
}
}
return displayTaskHistory;
}
/* Dual-Screen } */
return d.mGlobalTaskHistory;
}
ActivityStack getHomeStack() {
return mHomeStack;
}
/* { Dual-Screen */
ActivityStack getHomeStack(int displayId) {
if (DUALSCREEN_ENABLED) {
if (displayId < Display.DUAL_SCREEN_TYPE_MAX) {
if (mHomeStacks[displayId] == null) {
if (DESKTOP_MODE_ENABLED
&& displayId == Display.DUAL_SCREEN_EXTERNAL_DISPLAY) {
if (createStackOnDisplay(SAMSUNG_HOME_STACK_ID, displayId) != null) {
mHomeStacks[displayId] = getStack(SAMSUNG_HOME_STACK_ID);
return mHomeStacks[displayId];
}
}
} else {
return mHomeStacks[displayId];
}
}
}
return mHomeStack;
}
ArrayList<ActivityStack> getStacks(DualScreen screen) {
if (screen != null) {
int displayId = screen.getDisplayId();
ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
return activityDisplay.mStacks;
}
return null;
}
void removeAllStacks(int displayId) {
if (DUALSCREEN_ENABLED && displayId < Display.DUAL_SCREEN_TYPE_MAX) {
ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
if (activityDisplay != null) {
ArrayList<ActivityStack> stacks = activityDisplay.mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
ActivityStack stack = stacks.get(stackNdx);
activityDisplay.detachActivitiesLocked(stack);
stack.mDisplayId = -1;
stack.mStacks = null;
mWindowManager.detachStack(stack.getStackId());
}
stacks.clear();
}
mHomeStacks[displayId] = mFrontStacks[displayId] = null;
mService.setFocusedStack(getFocusedStack().mStackId);
}
}
ArrayList<ActivityRecord> processFinishingActivitiesLocked(boolean remove, int displayId) {
int N = mFinishingActivities.size();
ArrayList<ActivityRecord> finishs = new ArrayList<ActivityRecord>();
for (int i=0; i<N; i++) {
ActivityRecord f = mFinishingActivities.get(i);
if (displayId > Display.DISPLAY_NONE) {
f.dualScreenAttrs.addFinishFlag(displayId);
if (!f.dualScreenAttrs.okToFinish()) {
continue;
}
}
f.dualScreenAttrs.clearFinishFlag();
finishs.add(f);
if (remove) {
mFinishingActivities.remove(i);
N--;
i--;
}
}
return finishs;
}
void setFixedTask(TaskRecord fixedTask) {
if (mFixedTask != fixedTask) {
if (fixedTask == null) {
mFixedTask.fixed = false;
}
final Message fixedTaskMsg = Message.obtain();
fixedTaskMsg.what = FIXED_SCREEN_MODE_CHANGED_MSG;
fixedTaskMsg.arg1 = fixedTask != null? fixedTask.taskId : -1;
mFixedTask = fixedTask;
mHandler.sendMessage(fixedTaskMsg);
}
}
void endFixedScreenModeIfTaskEnding(TaskRecord task) {
if (mFixedTask != null && mFixedTask == task) {
Slog.secD(TAG, "Fixed task dismissed due to endFixedScreenModeIfTaskEnding");
setFixedTask(null);
}
}
TaskRecord getFixedTask() {
return mFixedTask;
}
boolean isInFixedScreenMode() {
return mFixedTask != null;
}
void showFixTaskDialog(){
final Message fixedTaskMsg = Message.obtain();
fixedTaskMsg.what = RELEASE_FIXED_SCREEN_MODE_DIALG_MSG;
mHandler.sendMessage(fixedTaskMsg);
}
int getScreenZone(ActivityStack stack) {
return convertDisplayIdToScreenZone(stack.getDisplayId());
}
public static int convertDisplayIdToScreenZone(int displayId) {
int obscuredZone = DUAL_SCREEN_ZONE_UNKNOWN;
if (displayId == Display.DUAL_SCREEN_MAIN_DISPLAY) {
obscuredZone = DUAL_SCREEN_ZONE_MAIN;
} else if (displayId == Display.DUAL_SCREEN_SUB_DISPLAY){
obscuredZone = DUAL_SCREEN_ZONE_SUB;
} else if (displayId == Display.DUAL_SCREEN_EXPANDED_DISPLAY){
obscuredZone = DUAL_SCREEN_ZONE_FULL;
}
return obscuredZone;
}
public static int convertScreenZoneToDisplayId(int screenZone) {
if (screenZone == DUAL_SCREEN_ZONE_MAIN) {
return Display.DUAL_SCREEN_MAIN_DISPLAY;
} else if (screenZone == DUAL_SCREEN_ZONE_SUB) {
return Display.DUAL_SCREEN_SUB_DISPLAY;
} else if (screenZone == DUAL_SCREEN_ZONE_FULL) {
return Display.DUAL_SCREEN_EXPANDED_DISPLAY;
} else {
return Display.DISPLAY_NONE;
}
}
void ensureActivitiesVisibleLockedForUniversialTaskHistory(ActivityRecord starting, int configChanges) {
ArrayList<TaskRecord> taskOrder = mUniversalTaskHistory;
int obscuredScreenZone = DUAL_SCREEN_ZONE_UNKNOWN;
int screenState = mService.mDualScreenPolicy.getScreenStateLocked() | mService.mDualScreenPolicy.getCurrentScreenStateLocked();
if (screenState == DUAL_SCREEN_ZONE_MAIN) {
obscuredScreenZone = DUAL_SCREEN_ZONE_SUB;
} else if (screenState == DUAL_SCREEN_ZONE_SUB) {
obscuredScreenZone = DUAL_SCREEN_ZONE_MAIN;
}
int obscuredZones[] = new int[mActivityDisplays.size()];
for (int i = 0; i < obscuredZones.length; i++) {
obscuredZones[i] = MultiWindowStyle.ZONE_UNKNOWN;
}
int N = taskOrder.size();
// except floating stack...
for (int i = N - 1; i >= 0; i--) {
TaskRecord task = taskOrder.get(i);
final ActivityStack stack = task.stack;
/* { AppCore */ // defect from Svace WGID 30425
if (stack == null) {
continue;
}
/* AppCore } */
final int displayId = stack.getDisplayId();
if (stack.isFloatingStack() &&
(!task.bHidden && task.getTopActivityMultiWindowStyle().isCascade())) {
continue;
}
//ActivityRecord top = stack.topMultiPhoneWindowActivity();
// TODO
// 1) top.multiWindowStyle.isEnabled(MultiWindowStyle.OPTION_TAB_MODE)
int taskScreenZone = task.getScreenZone();
int lastObscuredScreenZone = obscuredScreenZone;
boolean visible = false;
SparseArray<Integer> taskDisplayObscuredZones = task.getDisplayObscuredZones(false);
/* { Dual-Screen */
if ((taskScreenZone & obscuredScreenZone) == taskScreenZone) {
visible = false;
} else {
int NZ = taskDisplayObscuredZones.size();
for (int zoneNdx = 0; zoneNdx < NZ; zoneNdx++) {
int zoneDisplayId = taskDisplayObscuredZones.keyAt(zoneNdx);
int taskObscuredZone = taskDisplayObscuredZones.get(zoneDisplayId, MultiWindowStyle.ZONE_UNKNOWN);
boolean isFullscreen = task.isFullscreenVisible(zoneDisplayId);
if (taskObscuredZone == MultiWindowStyle.ZONE_UNKNOWN) {
if (!visible) {
visible = obscuredZones[zoneDisplayId] != MultiWindowStyle.ZONE_FULL;
}
} else {
if (!visible) {
visible = (obscuredZones[zoneDisplayId] & taskObscuredZone) != taskObscuredZone;
}
}
if (isFullscreen) {
obscuredZones[zoneDisplayId] |= taskObscuredZone;
}
if (obscuredZones[zoneDisplayId] == MultiWindowStyle.ZONE_FULL) {
obscuredScreenZone |= convertDisplayIdToScreenZone(zoneDisplayId);
}
}
}
stack.ensureActivitiesVisibleLocked(starting, configChanges, task, visible, lastObscuredScreenZone);
}
// only for floating stack...
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
for (ActivityStack stack : mActivityDisplays.valueAt(displayNdx).mStacks) {
if (stack.isFloatingStack() && isFrontStack(stack)) {
ActivityRecord ar = stack.topRunningActivityLocked(null, true);
TaskRecord task = ar == null ? null : ar.task;
if (task != null) {
stack.ensureActivitiesVisibleLocked(starting, configChanges);
}
}
}
}
}
void comeOutOfSleepForDisplayLocked(int displayId) {
if (mGoingToSleep.isHeld()) {
mGoingToSleep.release();
}
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayId).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
stack.awakeFromSleepingLocked();
if (isFrontStack(stack)) {
resumeTopActivitiesLocked(stack,null,null);
}
}
mGoingToSleepActivities.clear();
}
void goingToSleepForDisplayLocked(int displayId) {
if (!mGoingToSleep.isHeld()) {
mGoingToSleep.acquire();
if (mLaunchingActivity.isHeld()) {
mLaunchingActivity.release();
mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
}
}
boolean dontSleep = false;
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayId).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
dontSleep |= stacks.get(stackNdx).checkReadyForSleepLocked();
}
if (mStoppingActivities.size() > 0) {
// Still need to tell some activities to stop; can't sleep yet.
if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to stop "
+ mStoppingActivities.size() + " activities");
scheduleIdleLocked();
dontSleep = true;
}
if (mGoingToSleepActivities.size() > 0) {
// Still need to tell some activities to sleep; can't sleep yet.
if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to sleep "
+ mGoingToSleepActivities.size() + " activities");
dontSleep = true;
}
if (dontSleep) {
return;
}
/* { Multi-Window */
if (MultiWindowFeatures.MULTIWINDOW_ENABLED) {
ensureActivitiesVisibleLocked(null, 0);
}
/* Multi-Window } */
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
stacks.get(stackNdx).goToSleep();
}
if (mGoingToSleep.isHeld()) {
mGoingToSleep.release();
}
}
void moveTaskToScreenLocked(TaskRecord task, int toDisplayId, boolean toTop, boolean doResumeTop, boolean doAnimation) {
moveTaskToScreenLocked(task, toDisplayId, toTop, doResumeTop, doAnimation, false, false);
}
void moveTaskToScreenLocked(TaskRecord task, int toDisplayId, boolean toTop, boolean doResumeTop, boolean doAnimation, boolean forceDoAnimation, boolean byArrangeFullViewPolicy) {
if (!DualScreenFeatures.DUALSCREEN_ENABLED) {
return;
}
if (DEBUG_DUALSCREEN) {
Slog.d(TAG, "moveTaskToScreenLocked() : " + task + " toDisplayId=" + toDisplayId
+ " caller=" + Debug.getCallers(2));
}
if (task == null) {
Slog.w(TAG, "Cannot move a task to target display because task is null");
return;
}
ActivityRecord topActivity = task.getTopActivity();
if (topActivity == null) {
Slog.w(TAG, "Cannot move a task to target display because topActivity is null");
return;
}
DualScreen fromScreen = DualScreenUtils.displayIdToScreen(task.displayId);
DualScreen toScreen = DualScreenUtils.displayIdToScreen(toDisplayId);
int taskScreenZone = task.getScreenZone();
mService.mDualScreenPolicy.updateScreenForAllActivitiesInTask(task, toScreen);
ActivityStack targetStack = computeStackFocus(topActivity, false, null);
// animation will be applied when both MAIN screen and SUB screen is on
final boolean allScreenOn = mService.isScreenOn(Display.DUAL_SCREEN_MAIN_DISPLAY)
&& mService.isScreenOn(Display.DUAL_SCREEN_SUB_DISPLAY);
final boolean amsAllScreenOn = mService.mScreenState[Display.DUAL_SCREEN_MAIN_DISPLAY] == Display.STATE_ON
&& mService.mScreenState[Display.DUAL_SCREEN_SUB_DISPLAY] == Display.STATE_ON;
if (DEBUG_DUALSCREEN) {
Slog.d(TAG, "moveTaskToScreenLocked() : allScreenOn=" + allScreenOn
+ " amsAllScreenOn=" + amsAllScreenOn + " topActivity.nowVisible="
+ topActivity.nowVisible + " state=" + topActivity.state
+ " isFrontStack="+isFrontStack(targetStack));
}
if (task.equals(getFixedTask()) && fromScreen == DualScreen.SUB) {
setFixedTask(null);
}
if (topActivity.nowVisible) {
if (topActivity.state != ActivityState.RESUMED && !forceDoAnimation) {
targetStack.mNoAnimActivities.add(topActivity);
moveTaskToStackLocked(task.taskId, targetStack.mStackId, toTop, doResumeTop);
if (toTop) {
if (DEBUG_DUALSCREEN) {
Slog.d(TAG, "moveTaskToScreenLocked() : moveToFront");
}
targetStack.moveToFront("moveTaskToScreen");
}
} else if (allScreenOn && doAnimation && toTop) {
mWindowManager.prepareDualScreenTaskMoveTransition(
topActivity.appToken, fromScreen, toScreen);
moveTaskToStackLocked(task.taskId, targetStack.mStackId, toTop, doResumeTop);
targetStack.moveToFront("moveTaskToScreen");
ensureActivitiesVisibleLocked(null, 0);
} else {
topActivity.frozenBeforeDestroy = true;
if (topActivity.mayFreezeScreenLocked(topActivity.app)) {
topActivity.startFreezingScreenLocked(topActivity.app,
ActivityInfo.CONFIG_DISPLAYID);
}
mWindowManager.requestReportDrawn(topActivity.appToken);
//mWindowManager.fadeOutDualScreenTransitionIfNeeded(); // is it needed?
moveTaskToStackLocked(task.taskId, targetStack.mStackId, toTop, doResumeTop);
if (toTop /*&& !isFrontStack(targetStack)*/) {
if (DEBUG_DUALSCREEN) {
Slog.d(TAG, "moveTaskToScreenLocked() : moveToFront");
}
targetStack.moveToFront("moveTaskToScreen");
}
ensureActivitiesVisibleLocked(null, 0);
// topActivity.stopFreezingScreenLocked(false);
}
} else {
if (byArrangeFullViewPolicy) {
if (toTop) {
mWindowManager.setAppVisibility(topActivity.appToken, true, targetStack.getDisplayId());
}
} else if (doAnimation) {
mWindowManager.prepareAppTransition(AppTransition.TRANSIT_TASK_TO_FRONT, false, targetStack.getDisplayId());
}
moveTaskToStackLocked(task.taskId, targetStack.mStackId, toTop, doResumeTop);
}
EventLog.writeEvent(EventLogTags.DS_MOVE_TASK_TO_SCREEN, task.taskId,
topActivity.shortComponentName, targetStack.getDisplayId());
// Activity life cycle has not been updated if top task move to another screen.
// Hence update activeTime for the task moved.
task.touchActiveTime();
mService.mDualScreenPolicy.setFullViewHomeStatusLocked(topActivity);
}
void scheduleMovePrevSamsungHomeTasks(TaskRecord samsungHomeTask) {
if (mSamsungHomeTask != samsungHomeTask) {
mNeedToMovePrevSamsungHomeTasks = true;
mSamsungHomeTask = samsungHomeTask;
}
}
void movePrevSamsungHomeTasksLocked(TaskRecord excludeTask) {
if (excludeTask != null) {
ActivityRecord topActivity = excludeTask.getTopActivity();
if (topActivity != null
&& topActivity.isSamsungHomeActivity() && !topActivity.isNotResolverActivity()) {
// If topActivity is resolverActivity, do not remove samsungHomeTasks.
return;
}
}
ArrayList<TaskRecord> tasksWillBeMoved = new ArrayList<TaskRecord>();
ActivityStack samsungHomeStack = getStack(SAMSUNG_HOME_STACK_ID);
ArrayList<TaskRecord> tasks = samsungHomeStack.getAllTasks();
for (TaskRecord task : tasks) {
if (task.isSamsungHomeTask() && task != excludeTask) {
tasksWillBeMoved.add(task);
}
}
for (TaskRecord tr : tasksWillBeMoved) {
for (ActivityRecord ar : tr.mActivities) {
ar.mActivityType = ActivityRecord.APPLICATION_ACTIVITY_TYPE;
}
tr.taskType = ActivityRecord.APPLICATION_ACTIVITY_TYPE;
tr.fixed = false;
// Move prev SubHomeTasks to AppStack
ActivityRecord topActivity = tr.getTopActivity();
if (topActivity == null) {
Slog.d(TAG, "Cannot move a task to target stack because topActivity is null");
continue;
}
ActivityStack targetStack = computeStackFocus(topActivity, false, null, false);
moveTaskToStackLocked(tr.taskId, targetStack.getStackId(), false, false);
}
}
void sendExpandRequestToExpandableActivityLocked(int reason) {
if (!DUALSCREEN_ENABLED)
return;
if (DEBUG_DUALSCREEN) {
Slog.d(TAG, "sendExpandRequestToExpandableActivityLocked() : reason=" + reason
+ " caller=" + Debug.getCallers(2));
}
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < Display.DUAL_SCREEN_SUB_DISPLAY + 1; ++displayNdx) {
if (!mService.isScreenOn(displayNdx))
continue;
ActivityRecord top = topRunningActivityLocked(null, displayNdx);
if (top != null) {
int oppositeDisplayId = (displayNdx == Display.DUAL_SCREEN_MAIN_DISPLAY)
? Display.DUAL_SCREEN_SUB_DISPLAY : Display.DUAL_SCREEN_MAIN_DISPLAY;
ActivityRecord oppositeTop = topRunningActivityLocked(null, oppositeDisplayId);
if (top.state == ActivityState.RESUMED
&& !top.isHomeActivity() && (oppositeTop == null || (oppositeTop != null
&& (oppositeTop.isRecentsActivity() || oppositeTop.isHomeActivity())))
&& top.isExpandable
&& top.task != null && top.task.getCoupledTask() == null
&& top.task.stack != null) {
top.task.stack.sendExpandRequestToActivityLocked(top, reason);
break;
}
}
}
}
void sendShrinkRequestToAllResumedActivityLocked(int toDisplayId, int reason) {
if (!DUALSCREEN_ENABLED)
return;
if (DEBUG_DUALSCREEN) {
Slog.d(TAG, "sendShrinkRequestToAllResumedActivityLocked() : reason=" + reason
+ " caller=" + Debug.getCallers(2));
}
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (ActivityStack stack : stacks) {
ActivityRecord top = null;
ActivityRecord topActivityOfCoupledTask = null;
TaskRecord coupledTask = null;
if (isFrontStack(stack) && (top = stack.topActivity()) != null) {
if (top.task != null
&& (coupledTask = top.task.getCoupledTask()) != null
&& top.task.stack.mDisplayId != coupledTask.stack.mDisplayId
&& (topActivityOfCoupledTask = coupledTask.topRunningActivityLocked(null)) != null
&& topActivityOfCoupledTask.state == ActivityState.RESUMED) {
stack.sendShrinkRequestToActivityLocked(top, toDisplayId, reason);
stack.sendShrinkRequestToActivityLocked(topActivityOfCoupledTask, toDisplayId, reason);
displayNdx = mActivityDisplays.size();
break;
}
}
}
}
}
void executeAllTransition() {
boolean changed = false;
for (int displayNdx = 0; displayNdx < DUAL_SCREEN_TYPE_MAX; displayNdx++) {
changed |= mWindowManager.executeAppTransition(displayNdx, false);
}
if (changed) {
mWindowManager.performLayoutForAppTransition();
}
}
/* Dual-Screen } */
void handleMinimizeAllPenWindow(){
synchronized (mService) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
/* { Virtual-Screen */
if (VIRTUALSCREEN_ENABLED) {
ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx);
if (VirtualScreenManagerService.self().isVirtualScreen(activityDisplay.mDisplayId)) {
continue;
}
}
/* Virtual-Screen } */
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
ActivityRecord top = stack.topRunningActivityLocked(null);
if (stack.isFloatingStack()) {
ArrayList<TaskRecord> allTasks = stack.getAllTasks();
// send minimized messsage to all tasks for
// supporting inherit task policy
for (int i = allTasks.size() - 1; i >= 0; i--) {
TaskRecord curTask = allTasks.get(i);
if (curTask.userId != mService.mCurrentUserId) {
if(!PersonaManager.isKnoxId(curTask.userId)){
continue;
} else {
//Knox penwindow is also minimized when needed if current user is owner.
if(mService.mCurrentUserId != UserHandle.USER_OWNER){
continue;
}
}
}
top = curTask.getTopActivity();
if (top != null && top.task != null) {
int N = top.task.mActivities.size();
for (int j = N - 1; j >= 0; j--) {
ActivityRecord cr = top.task.mActivities .get(j);
if (cr.task != null && cr.visible && !cr.finishing) {
cr.minimizePenWindowRequested = true;
stack.notifyMultiWindowStyleChangedLocked(cr,
MultiWindowStyle.NOTIFY_REASON_ARRANGE_MINIMIZED, true);
}
}
}
}
}
}
}
mService.mMinimizeAllPenWindowRequested = false;
}
}
/* Multi-Window } */
/* { CuVasChecker */
private boolean checkCUVas(ActivityRecord sr, Intent intent) {
String simNum = "";
String imsi = "";
TelephonyManager telephonyManager = null;
telephonyManager = (TelephonyManager) mService.mContext.getSystemService(Context.TELEPHONY_SERVICE);
if (telephonyManager == null) {
return false;
}
if (telephonyManager.isMultiSimEnabled() && (MultiSimManager.getInsertedSimCount() > 1)) {
int currentDataActiveSim = SubscriptionManager.getPhoneId(SubscriptionManager.getDefaultDataSubId());
if (SubscriptionManager.isValidPhoneId(currentDataActiveSim)) {
imsi = MultiSimManager.getSubscriberId(currentDataActiveSim);
}
} else {
imsi = telephonyManager.getSubscriberId();
}
if (imsi != null && imsi.length() > 4) {
simNum = imsi.substring(0, 5);
}
ConnectivityManager connMgr = (ConnectivityManager)mService.mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo wifiNetwork = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
boolean checkFlag = false;
String[] packages = null;
String[] classes = null;
if ("46001".equals(CscFeature.getInstance().getString(CscFeatureTagFramework.TAG_CSCFEATURE_FRAMEWORK_CHECKVALIDAPP4SPECIFICMCCMNC)) &&
!("46001".equals(simNum) || "45407".equals(simNum) || "46009".equals(simNum)) && wifiNetwork.getState() != NetworkInfo.State.CONNECTED) {
packages = new String[] { "com.neusoft.td.android.wo116114", "com.android.wo3g", "com.infinit.wostore.ui", "com.sinovatech.unicom.ui", "com.neusoft.td.android.wo116114" ,"com.asiainfo.android", "com.asiainfo.android", "com.samsung.wo3g", "com.samsung.mobilebusinesshall",
"com.neusoft.td.android.wo116114", "cn.com.wo", "com.infinit.wostore.ui" };
classes = new String[] { "com.neusoft.td.android.wo116114.ui.main.MainActivity", "com.android.wo3g.wo3g", "com.infinit.wostore.ui.ZBeginActivity","com.sinovatech.unicom.ui.WelcomeClient",
"com.neusoft.td.android.wo116114.activity.WelcomeActivity","com.asiainfo.android.MainActivity", "com.asiainfo.mail.ui.LoginAcivity","com.samsung.wo3g.wo3g", "com.samsung.mobilebusinesshall.MobileBusinessHall",
"com.neusoft.td.android.wo116114.activity.StartActivity", "cn.com.wo.ui.TipActivity", "com.infinit.wostore.ui.BeginActivity" };
} else if ("46000".equals(CscFeature.getInstance().getString(CscFeatureTagFramework.TAG_CSCFEATURE_FRAMEWORK_CHECKVALIDAPP4SPECIFICMCCMNC)) &&
!("46000".equals(simNum) || "46002".equals(simNum) || "46007".equals(simNum))) {
packages = new String[] { "com.aspire.mm", "com.autonavi.cmccmap", "com.cmcc.mobilevideo", "cmccwm.mobilemusic", "com.chinamobile.cmccwifi",
"cn.emagsoftware.gamehall", "com.hisunflytone.android", "com.huawei.pisa.activity", "com.sec.android.app.customerservice" };
}
if (packages != null) {
if ("46001".equals(CscFeature.getInstance().getString(CscFeatureTagFramework.TAG_CSCFEATURE_FRAMEWORK_CHECKVALIDAPP4SPECIFICMCCMNC))) {
if (sr == null)
return checkFlag;
Intent in = sr.intent;
if (in != null && in.getComponent() != null && in.getComponent().getPackageName() != null && intent.getComponent() != null) {
if (in.getComponent().getPackageName().equals(intent.getComponent().getPackageName()))
return checkFlag;
}
if (intent.getComponent() != null && intent.getComponent().getPackageName() != null && intent.getComponent().getClassName() != null) {
for (int i=0; i < classes.length; i++) {
if (intent.getComponent().getPackageName().equals(packages[i]) && intent.getComponent().getClassName().equals(classes[i])) {
checkFlag = true;
break;
}
}
}
} else if ("46000".equals(CscFeature.getInstance().getString(CscFeatureTagFramework.TAG_CSCFEATURE_FRAMEWORK_CHECKVALIDAPP4SPECIFICMCCMNC))) {
if (intent.getComponent() != null && intent.getComponent().getPackageName() != null) {
for (int i=0; i < packages.length; i++) {
if (intent.getComponent().getPackageName().equals(packages[i])) {
checkFlag = true;
break;
}
}
}
}
}
return checkFlag;
}
/* CuVasChecker } */
//KNOX2.3_CONTAINER_START
private static final String ANDROID_INTERNAL_PKGNAME = "com.android.internal.app";
private boolean isKnoxmode() {
Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
intentToResolve.addCategory(Intent.CATEGORY_HOME);
List<ResolveInfo> ris = mService.mContext.getPackageManager().queryIntentActivities(intentToResolve, 0);
ResolveInfo HomeReceiver = ris.get(0);
if(HomeReceiver != null && HomeReceiver.activityInfo.name.contains(ANDROID_INTERNAL_PKGNAME)) {
return true;
}
return false;
}
public void hideMultiWindowsLocked(int targetUserId) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.sec.knox.foldercontainer","com.sec.knox.foldercontainer.MultiwindowLockActivity"));
intent.putExtra("userid", targetUserId);
ActivityRecord top = stack.topRunningActivityLocked(null);
List<ResolveInfo> ris = mService.mContext.getPackageManager()
.queryIntentActivitiesAsUser(intent, PackageManager.GET_META_DATA, 0);
ResolveInfo ri = null;
for (int i=0; ris != null && i<ris.size(); i++) {
if ((ris.get(i).activityInfo.applicationInfo.flags
& ApplicationInfo.FLAG_SYSTEM) != 0) {
ri = ris.get(i);
break;
}
}
ArrayList<TaskRecord> allTasks = stack.getAllTasks();
if(allTasks.size() < 1) {
continue;
}
TaskRecord curTask = allTasks.get(allTasks.size()-1);
if (top != null && ri != null && top.userId == targetUserId){
if (stack.isFloatingStack() || (isFrontStack(stack) && stack.getZone() != MultiWindowStyle.ZONE_FULL && stack.getZone() != MultiWindowStyle.ZONE_UNKNOWN)){
if (!curTask.getTopActivityMultiWindowStyle().isNormal()) {
intent.setMultiWindowStyle(curTask.getTopActivityMultiWindowStyle());
intent.putExtra("pkgName", top.packageName);
startActivityLocked(null, intent, null, ri.activityInfo,
null, null, null, null, 0, 0, 0, null, 0, 0, 0, null, false, false, null, null,
curTask);
}
}
}
}
}
}
public boolean isKnoxMultiWindowExistLocked(int userId){
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
ActivityRecord top = stack.topRunningActivityLocked(null);
if (top != null && PersonaManager.isKnoxId(top.userId)){
if (stack.isFloatingStack() || (isFrontStack(stack) && stack.getZone() != MultiWindowStyle.ZONE_FULL && stack.getZone() != MultiWindowStyle.ZONE_UNKNOWN)){
return true;
}
}
}
}
return false;
}
//KNOX2.3_CONTAINER_END
/* { AppCore */
private boolean isProfiledUserLocked(int userId, int taskUserId) {
final List<UserInfo> profiles = mService.getUserManagerLocked().getProfiles(
userId, false /* enabledOnly */);
for (UserInfo user : profiles) {
if (user.id == taskUserId) {
return true;
}
}
return false;
}
/* AppCore } */
/* { AppCore moveTaskToBack-keepAlive */
int getNumberOfKeepAliveActivitiesLocked() {
int count = 0;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
count += stack.getNumberOfKeepAliveActivitiesLocked();
}
}
return count;
}
/* AppCore moveTaskToBack-keepAlive } */
/* { KDM_Start */
public static final int APP_START = 0;
public static final int APP_STOP = 1;
public static final int APP_UPDATE = 2;
private String[] mHiddenPkgString = {
"android", "system"
};
void notifyAppsStatusToTaskBar(int status, TaskRecord task, ComponentName component, String callingPkg) {
for (String pkg : mHiddenPkgString) { // block system package.
if (pkg.equals(component.getPackageName())) {
return;
}
}
try {
IStatusBarService statusbar = getStatusBarService();
if (statusbar != null) {
statusbar.updateKnoxDesktopTaskBar(status, task.taskId, task.userId,
task.stack.mStackId, task.stack.mStackType, component, callingPkg);
}
} catch (RemoteException e) {
Slog.e(TAG, "RemoteException when notifyAppsStatusToTaskBar", e);
// re-acquire status bar service next time it is needed.
}
}
/* KDM_End } */
// For Anti-Phishing
private boolean scanIntent(Context context, Intent intent, int callerUid) {
String action = intent.getAction();
if(action == null) return false;
if(!action.equals("android.intent.action.VIEW")) return false;
String data = intent.getDataString();
if(data == null || context == null) return false;
String src_package = context.getPackageManager().getNameForUid(callerUid);
ComponentName component = intent.getComponent();
String dest_package = component.getPackageName();
String dest_class = component.getClassName();
if(!dest_class.equals(RESOLVER_NAME) && !src_package.equals(dest_package) && !src_package.equals(APH_PACKAGE_NAME)) {
Intent intent_to_scan = new Intent();
intent_to_scan.setClassName(APH_PACKAGE_NAME, APH_SERVICE_NAME);
intent_to_scan.putExtra(DEST_PACKAGE, dest_package);
intent_to_scan.putExtra(DEST_CLASS, dest_class);
intent_to_scan.putExtra(SCAN_URL, data);
try {
context.startService(intent_to_scan);
return true;
} catch (Exception ex) {
return false;
}
}
return false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment