summaryrefslogtreecommitdiff
path: root/com/android/server
diff options
context:
space:
mode:
Diffstat (limited to 'com/android/server')
-rw-r--r--com/android/server/AppOpsService.java38
-rw-r--r--com/android/server/BatteryService.java421
-rw-r--r--com/android/server/IntentResolver.java27
-rw-r--r--com/android/server/SystemServer.java10
-rw-r--r--com/android/server/VibratorService.java24
-rw-r--r--com/android/server/accessibility/AccessibilityInputFilter.java20
-rw-r--r--com/android/server/accessibility/AutoclickController.java36
-rw-r--r--com/android/server/accessibility/BaseEventStreamTransformation.java31
-rw-r--r--com/android/server/accessibility/EventStreamTransformation.java37
-rw-r--r--com/android/server/accessibility/KeyboardInterceptor.java35
-rw-r--r--com/android/server/accessibility/MagnificationController.java19
-rw-r--r--com/android/server/accessibility/MagnificationGestureHandler.java382
-rw-r--r--com/android/server/accessibility/MotionEventInjector.java41
-rw-r--r--com/android/server/accessibility/TouchExplorer.java40
-rw-r--r--com/android/server/am/ActivityDisplay.java150
-rw-r--r--com/android/server/am/ActivityManagerDebugConfig.java8
-rw-r--r--com/android/server/am/ActivityManagerService.java640
-rw-r--r--com/android/server/am/ActivityManagerShellCommand.java100
-rw-r--r--com/android/server/am/ActivityMetricsLogger.java3
-rw-r--r--com/android/server/am/ActivityRecord.java72
-rw-r--r--com/android/server/am/ActivityStack.java215
-rw-r--r--com/android/server/am/ActivityStackSupervisor.java528
-rw-r--r--com/android/server/am/ActivityStarter.java133
-rw-r--r--com/android/server/am/AppTaskImpl.java150
-rw-r--r--com/android/server/am/BatteryStatsService.java25
-rw-r--r--com/android/server/am/BroadcastFilter.java24
-rw-r--r--com/android/server/am/BroadcastQueue.java52
-rw-r--r--com/android/server/am/BroadcastRecord.java11
-rw-r--r--com/android/server/am/KeyguardController.java10
-rw-r--r--com/android/server/am/LaunchingTaskPositioner.java211
-rw-r--r--com/android/server/am/LockTaskController.java10
-rw-r--r--com/android/server/am/ProcessRecord.java18
-rw-r--r--com/android/server/am/ReceiverList.java31
-rw-r--r--com/android/server/am/RecentTasks.java1040
-rw-r--r--com/android/server/am/ServiceRecord.java20
-rw-r--r--com/android/server/am/TaskPersister.java19
-rw-r--r--com/android/server/am/TaskRecord.java135
-rw-r--r--com/android/server/appwidget/AppWidgetServiceImpl.java49
-rw-r--r--com/android/server/audio/PlaybackActivityMonitor.java8
-rw-r--r--com/android/server/autofill/AutofillManagerServiceImpl.java34
-rw-r--r--com/android/server/autofill/Session.java43
-rw-r--r--com/android/server/backup/BackupManagerService.java67
-rw-r--r--com/android/server/backup/RefactoredBackupManagerService.java68
-rw-r--r--com/android/server/backup/Trampoline.java29
-rw-r--r--com/android/server/clipboard/ClipboardService.java3
-rw-r--r--com/android/server/connectivity/Tethering.java1
-rw-r--r--com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java52
-rw-r--r--com/android/server/display/AutomaticBrightnessController.java2
-rw-r--r--com/android/server/display/DisplayPowerController.java33
-rw-r--r--com/android/server/job/controllers/TimeController.java32
-rw-r--r--com/android/server/location/GnssLocationProvider.java6
-rw-r--r--com/android/server/media/MediaSessionRecord.java8
-rw-r--r--com/android/server/media/MediaSessionService.java36
-rw-r--r--com/android/server/notification/NotificationManagerService.java38
-rw-r--r--com/android/server/notification/ZenModeFiltering.java21
-rw-r--r--com/android/server/notification/ZenModeHelper.java24
-rw-r--r--com/android/server/pm/LauncherAppsService.java33
-rw-r--r--com/android/server/pm/PackageDexOptimizer.java17
-rw-r--r--com/android/server/pm/PackageInstallerSession.java11
-rw-r--r--com/android/server/pm/PackageManagerService.java317
-rw-r--r--com/android/server/pm/Settings.java29
-rw-r--r--com/android/server/pm/SharedUserSetting.java9
-rw-r--r--com/android/server/pm/ShortcutBitmapSaver.java10
-rw-r--r--com/android/server/pm/ShortcutLauncher.java53
-rw-r--r--com/android/server/pm/ShortcutPackage.java295
-rw-r--r--com/android/server/pm/ShortcutPackageInfo.java138
-rw-r--r--com/android/server/pm/ShortcutPackageItem.java46
-rw-r--r--com/android/server/pm/ShortcutParser.java6
-rw-r--r--com/android/server/pm/ShortcutRequestPinProcessor.java12
-rw-r--r--com/android/server/pm/ShortcutService.java153
-rw-r--r--com/android/server/pm/ShortcutUser.java3
-rw-r--r--com/android/server/pm/UserRestrictionsUtils.java2
-rw-r--r--com/android/server/pm/permission/BasePermission.java27
-rw-r--r--com/android/server/pm/permission/PermissionManagerInternal.java22
-rw-r--r--com/android/server/pm/permission/PermissionManagerService.java273
-rw-r--r--com/android/server/pm/permission/PermissionSettings.java117
-rw-r--r--com/android/server/policy/GlobalActions.java3
-rw-r--r--com/android/server/policy/PhoneWindowManager.java147
-rw-r--r--com/android/server/stats/StatsCompanionService.java136
-rw-r--r--com/android/server/statusbar/StatusBarManagerInternal.java1
-rw-r--r--com/android/server/statusbar/StatusBarManagerService.java7
-rw-r--r--com/android/server/tv/TvInputHardwareManager.java14
-rw-r--r--com/android/server/usb/UsbAlsaManager.java9
-rw-r--r--com/android/server/usb/UsbHostManager.java2
-rw-r--r--com/android/server/wifi/SelfRecovery.java2
-rw-r--r--com/android/server/wifi/WifiNative.java9
-rw-r--r--com/android/server/wifi/WifiStateMachine.java5
-rw-r--r--com/android/server/wifi/WifiStateMachinePrime.java3
-rw-r--r--com/android/server/wifi/WificondControl.java9
-rw-r--r--com/android/server/wifi/scanner/WificondScannerImpl.java16
-rw-r--r--com/android/server/wifi/util/InformationElementUtil.java4
-rw-r--r--com/android/server/wm/AppWindowToken.java5
-rw-r--r--com/android/server/wm/BlackFrame.java11
-rw-r--r--com/android/server/wm/CircularDisplayMask.java12
-rw-r--r--com/android/server/wm/ConfigurationContainer.java15
-rw-r--r--com/android/server/wm/DimLayer.java11
-rw-r--r--com/android/server/wm/DisplayContent.java337
-rw-r--r--com/android/server/wm/DockedStackDividerController.java23
-rw-r--r--com/android/server/wm/EmulatorDisplayOverlay.java11
-rw-r--r--com/android/server/wm/InputMonitor.java3
-rw-r--r--com/android/server/wm/PinnedStackController.java3
-rw-r--r--com/android/server/wm/RootWindowContainer.java11
-rw-r--r--com/android/server/wm/ScreenRotationAnimation.java17
-rw-r--r--com/android/server/wm/StackWindowController.java11
-rw-r--r--com/android/server/wm/Task.java16
-rw-r--r--com/android/server/wm/TaskPositioner.java3
-rw-r--r--com/android/server/wm/TaskSnapshotController.java4
-rw-r--r--com/android/server/wm/TaskStack.java93
-rw-r--r--com/android/server/wm/WallpaperController.java4
-rw-r--r--com/android/server/wm/WindowContainer.java4
-rw-r--r--com/android/server/wm/WindowManagerDebugConfig.java1
-rw-r--r--com/android/server/wm/WindowManagerService.java22
-rw-r--r--com/android/server/wm/WindowState.java48
-rw-r--r--com/android/server/wm/WindowStateAnimator.java11
-rw-r--r--com/android/server/wm/WindowSurfaceController.java259
-rw-r--r--com/android/server/wm/WindowSurfacePlacer.java3
116 files changed, 3524 insertions, 4674 deletions
diff --git a/com/android/server/AppOpsService.java b/com/android/server/AppOpsService.java
index 4ffa5f1f..50b8df2a 100644
--- a/com/android/server/AppOpsService.java
+++ b/com/android/server/AppOpsService.java
@@ -491,8 +491,7 @@ public class AppOpsService extends IAppOpsService.Stub {
return Collections.emptyList();
}
synchronized (this) {
- Ops pkgOps = getOpsRawLocked(uid, resolvedPackageName, false /* edit */,
- false /* uidMismatchExpected */);
+ Ops pkgOps = getOpsRawLocked(uid, resolvedPackageName, false);
if (pkgOps == null) {
return null;
}
@@ -531,8 +530,7 @@ public class AppOpsService extends IAppOpsService.Stub {
private void pruneOp(Op op, int uid, String packageName) {
if (op.time == 0 && op.rejectTime == 0) {
- Ops ops = getOpsRawLocked(uid, packageName, false /* edit */,
- false /* uidMismatchExpected */);
+ Ops ops = getOpsRawLocked(uid, packageName, false);
if (ops != null) {
ops.remove(op.op);
if (ops.size() <= 0) {
@@ -1048,9 +1046,7 @@ public class AppOpsService extends IAppOpsService.Stub {
public int checkPackage(int uid, String packageName) {
Preconditions.checkNotNull(packageName);
synchronized (this) {
- Ops ops = getOpsRawLocked(uid, packageName, true /* edit */,
- true /* uidMismatchExpected */);
- if (ops != null) {
+ if (getOpsRawLocked(uid, packageName, true) != null) {
return AppOpsManager.MODE_ALLOWED;
} else {
return AppOpsManager.MODE_ERRORED;
@@ -1094,8 +1090,7 @@ public class AppOpsService extends IAppOpsService.Stub {
private int noteOperationUnchecked(int code, int uid, String packageName,
int proxyUid, String proxyPackageName) {
synchronized (this) {
- Ops ops = getOpsRawLocked(uid, packageName, true /* edit */,
- false /* uidMismatchExpected */);
+ Ops ops = getOpsRawLocked(uid, packageName, true);
if (ops == null) {
if (DEBUG) Log.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
+ " package " + packageName);
@@ -1153,8 +1148,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
ClientState client = (ClientState)token;
synchronized (this) {
- Ops ops = getOpsRawLocked(uid, resolvedPackageName, true /* edit */,
- false /* uidMismatchExpected */);
+ Ops ops = getOpsRawLocked(uid, resolvedPackageName, true);
if (ops == null) {
if (DEBUG) Log.d(TAG, "startOperation: no op for code " + code + " uid " + uid
+ " package " + resolvedPackageName);
@@ -1280,8 +1274,7 @@ public class AppOpsService extends IAppOpsService.Stub {
return uidState;
}
- private Ops getOpsRawLocked(int uid, String packageName, boolean edit,
- boolean uidMismatchExpected) {
+ private Ops getOpsRawLocked(int uid, String packageName, boolean edit) {
UidState uidState = getUidStateLocked(uid, edit);
if (uidState == null) {
return null;
@@ -1333,12 +1326,10 @@ public class AppOpsService extends IAppOpsService.Stub {
if (pkgUid != uid) {
// Oops! The package name is not valid for the uid they are calling
// under. Abort.
- if (!uidMismatchExpected) {
- RuntimeException ex = new RuntimeException("here");
- ex.fillInStackTrace();
- Slog.w(TAG, "Bad call: specified package " + packageName
- + " under uid " + uid + " but it is really " + pkgUid, ex);
- }
+ RuntimeException ex = new RuntimeException("here");
+ ex.fillInStackTrace();
+ Slog.w(TAG, "Bad call: specified package " + packageName
+ + " under uid " + uid + " but it is really " + pkgUid, ex);
return null;
}
} finally {
@@ -1368,8 +1359,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
private Op getOpLocked(int code, int uid, String packageName, boolean edit) {
- Ops ops = getOpsRawLocked(uid, packageName, edit,
- false /* uidMismatchExpected */);
+ Ops ops = getOpsRawLocked(uid, packageName, edit);
if (ops == null) {
return null;
}
@@ -1403,8 +1393,7 @@ public class AppOpsService extends IAppOpsService.Stub {
if (AppOpsManager.opAllowSystemBypassRestriction(code)) {
// If we are the system, bypass user restrictions for certain codes
synchronized (this) {
- Ops ops = getOpsRawLocked(uid, packageName, true /* edit */,
- false /* uidMismatchExpected */);
+ Ops ops = getOpsRawLocked(uid, packageName, true);
if ((ops != null) && ops.isPrivileged) {
return false;
}
@@ -1724,8 +1713,7 @@ public class AppOpsService extends IAppOpsService.Stub {
out.startTag(null, "uid");
out.attribute(null, "n", Integer.toString(pkg.getUid()));
synchronized (this) {
- Ops ops = getOpsRawLocked(pkg.getUid(), pkg.getPackageName(),
- false /* edit */, false /* uidMismatchExpected */);
+ Ops ops = getOpsRawLocked(pkg.getUid(), pkg.getPackageName(), false);
// Should always be present as the list of PackageOps is generated
// from Ops.
if (ops != null) {
diff --git a/com/android/server/BatteryService.java b/com/android/server/BatteryService.java
index 47be0a70..5106c8d7 100644
--- a/com/android/server/BatteryService.java
+++ b/com/android/server/BatteryService.java
@@ -24,7 +24,6 @@ import android.os.PowerManager;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.ShellCommand;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
import com.android.internal.util.DumpUtils;
import com.android.server.am.BatteryStatsService;
@@ -36,10 +35,6 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
-import android.hidl.manager.V1_0.IServiceManager;
-import android.hidl.manager.V1_0.IServiceNotification;
-import android.hardware.health.V2_0.HealthInfo;
-import android.hardware.health.V2_0.IHealth;
import android.os.BatteryManager;
import android.os.BatteryManagerInternal;
import android.os.BatteryProperties;
@@ -67,9 +62,6 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
-import java.util.Arrays;
-import java.util.List;
-import java.util.NoSuchElementException;
/**
* <p>BatteryService monitors the charging status, and charge level of the device
@@ -126,8 +118,8 @@ public final class BatteryService extends SystemService {
private final Object mLock = new Object();
- private HealthInfo mHealthInfo;
- private final HealthInfo mLastHealthInfo = new HealthInfo();
+ private BatteryProperties mBatteryProps;
+ private final BatteryProperties mLastBatteryProps = new BatteryProperties();
private boolean mBatteryLevelCritical;
private int mLastBatteryStatus;
private int mLastBatteryHealth;
@@ -259,16 +251,16 @@ public final class BatteryService extends SystemService {
private boolean isPoweredLocked(int plugTypeSet) {
// assume we are powered if battery state is unknown so
// the "stay on while plugged in" option will work.
- if (mHealthInfo.legacy.batteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN) {
+ if (mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN) {
return true;
}
- if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_AC) != 0 && mHealthInfo.legacy.chargerAcOnline) {
+ if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_AC) != 0 && mBatteryProps.chargerAcOnline) {
return true;
}
- if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_USB) != 0 && mHealthInfo.legacy.chargerUsbOnline) {
+ if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_USB) != 0 && mBatteryProps.chargerUsbOnline) {
return true;
}
- if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0 && mHealthInfo.legacy.chargerWirelessOnline) {
+ if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0 && mBatteryProps.chargerWirelessOnline) {
return true;
}
return false;
@@ -285,15 +277,15 @@ public final class BatteryService extends SystemService {
* (becomes <= mLowBatteryWarningLevel).
*/
return !plugged
- && mHealthInfo.legacy.batteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
- && mHealthInfo.legacy.batteryLevel <= mLowBatteryWarningLevel
+ && mBatteryProps.batteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
+ && mBatteryProps.batteryLevel <= mLowBatteryWarningLevel
&& (oldPlugged || mLastBatteryLevel > mLowBatteryWarningLevel);
}
private void shutdownIfNoPowerLocked() {
// shut down gracefully if our battery is critically low and we are not powered.
// wait until the system has booted before attempting to display the shutdown dialog.
- if (mHealthInfo.legacy.batteryLevel == 0 && !isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)) {
+ if (mBatteryProps.batteryLevel == 0 && !isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)) {
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -314,7 +306,7 @@ public final class BatteryService extends SystemService {
// shut down gracefully if temperature is too high (> 68.0C by default)
// wait until the system has booted before attempting to display the
// shutdown dialog.
- if (mHealthInfo.legacy.batteryTemperature > mShutdownBatteryTemperature) {
+ if (mBatteryProps.batteryTemperature > mShutdownBatteryTemperature) {
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -334,66 +326,25 @@ public final class BatteryService extends SystemService {
private void update(BatteryProperties props) {
synchronized (mLock) {
if (!mUpdatesStopped) {
- mHealthInfo = new HealthInfo();
- copy(mHealthInfo, props);
+ mBatteryProps = props;
// Process the new values.
processValuesLocked(false);
} else {
- copy(mLastHealthInfo, props);
+ mLastBatteryProps.set(props);
}
}
}
- private static void copy(HealthInfo dst, HealthInfo src) {
- dst.legacy.chargerAcOnline = src.legacy.chargerAcOnline;
- dst.legacy.chargerUsbOnline = src.legacy.chargerUsbOnline;
- dst.legacy.chargerWirelessOnline = src.legacy.chargerWirelessOnline;
- dst.legacy.maxChargingCurrent = src.legacy.maxChargingCurrent;
- dst.legacy.maxChargingVoltage = src.legacy.maxChargingVoltage;
- dst.legacy.batteryStatus = src.legacy.batteryStatus;
- dst.legacy.batteryHealth = src.legacy.batteryHealth;
- dst.legacy.batteryPresent = src.legacy.batteryPresent;
- dst.legacy.batteryLevel = src.legacy.batteryLevel;
- dst.legacy.batteryVoltage = src.legacy.batteryVoltage;
- dst.legacy.batteryTemperature = src.legacy.batteryTemperature;
- dst.legacy.batteryCurrent = src.legacy.batteryCurrent;
- dst.legacy.batteryCycleCount = src.legacy.batteryCycleCount;
- dst.legacy.batteryFullCharge = src.legacy.batteryFullCharge;
- dst.legacy.batteryChargeCounter = src.legacy.batteryChargeCounter;
- dst.legacy.batteryTechnology = src.legacy.batteryTechnology;
- dst.batteryCurrentAverage = src.batteryCurrentAverage;
- dst.batteryCapacity = src.batteryCapacity;
- dst.energyCounter = src.energyCounter;
- }
-
- // TODO(b/62229583): remove this function when BatteryProperties are completely replaced.
- private static void copy(HealthInfo dst, BatteryProperties src) {
- dst.legacy.chargerAcOnline = src.chargerAcOnline;
- dst.legacy.chargerUsbOnline = src.chargerUsbOnline;
- dst.legacy.chargerWirelessOnline = src.chargerWirelessOnline;
- dst.legacy.maxChargingCurrent = src.maxChargingCurrent;
- dst.legacy.maxChargingVoltage = src.maxChargingVoltage;
- dst.legacy.batteryStatus = src.batteryStatus;
- dst.legacy.batteryHealth = src.batteryHealth;
- dst.legacy.batteryPresent = src.batteryPresent;
- dst.legacy.batteryLevel = src.batteryLevel;
- dst.legacy.batteryVoltage = src.batteryVoltage;
- dst.legacy.batteryTemperature = src.batteryTemperature;
- dst.legacy.batteryFullCharge = src.batteryFullCharge;
- dst.legacy.batteryChargeCounter = src.batteryChargeCounter;
- dst.legacy.batteryTechnology = src.batteryTechnology;
- }
-
private void processValuesLocked(boolean force) {
boolean logOutlier = false;
long dischargeDuration = 0;
- mBatteryLevelCritical = (mHealthInfo.legacy.batteryLevel <= mCriticalBatteryLevel);
- if (mHealthInfo.legacy.chargerAcOnline) {
+ mBatteryLevelCritical = (mBatteryProps.batteryLevel <= mCriticalBatteryLevel);
+ if (mBatteryProps.chargerAcOnline) {
mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
- } else if (mHealthInfo.legacy.chargerUsbOnline) {
+ } else if (mBatteryProps.chargerUsbOnline) {
mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
- } else if (mHealthInfo.legacy.chargerWirelessOnline) {
+ } else if (mBatteryProps.chargerWirelessOnline) {
mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
} else {
mPlugType = BATTERY_PLUGGED_NONE;
@@ -401,17 +352,30 @@ public final class BatteryService extends SystemService {
if (DEBUG) {
Slog.d(TAG, "Processing new values: "
- + "info=" + mHealthInfo
+ + "chargerAcOnline=" + mBatteryProps.chargerAcOnline
+ + ", chargerUsbOnline=" + mBatteryProps.chargerUsbOnline
+ + ", chargerWirelessOnline=" + mBatteryProps.chargerWirelessOnline
+ + ", maxChargingCurrent" + mBatteryProps.maxChargingCurrent
+ + ", maxChargingVoltage" + mBatteryProps.maxChargingVoltage
+ + ", batteryStatus=" + mBatteryProps.batteryStatus
+ + ", batteryHealth=" + mBatteryProps.batteryHealth
+ + ", batteryPresent=" + mBatteryProps.batteryPresent
+ + ", batteryLevel=" + mBatteryProps.batteryLevel
+ + ", batteryTechnology=" + mBatteryProps.batteryTechnology
+ + ", batteryVoltage=" + mBatteryProps.batteryVoltage
+ + ", batteryChargeCounter=" + mBatteryProps.batteryChargeCounter
+ + ", batteryFullCharge=" + mBatteryProps.batteryFullCharge
+ + ", batteryTemperature=" + mBatteryProps.batteryTemperature
+ ", mBatteryLevelCritical=" + mBatteryLevelCritical
+ ", mPlugType=" + mPlugType);
}
// Let the battery stats keep track of the current level.
try {
- mBatteryStats.setBatteryState(mHealthInfo.legacy.batteryStatus, mHealthInfo.legacy.batteryHealth,
- mPlugType, mHealthInfo.legacy.batteryLevel, mHealthInfo.legacy.batteryTemperature,
- mHealthInfo.legacy.batteryVoltage, mHealthInfo.legacy.batteryChargeCounter,
- mHealthInfo.legacy.batteryFullCharge);
+ mBatteryStats.setBatteryState(mBatteryProps.batteryStatus, mBatteryProps.batteryHealth,
+ mPlugType, mBatteryProps.batteryLevel, mBatteryProps.batteryTemperature,
+ mBatteryProps.batteryVoltage, mBatteryProps.batteryChargeCounter,
+ mBatteryProps.batteryFullCharge);
} catch (RemoteException e) {
// Should never happen.
}
@@ -419,16 +383,16 @@ public final class BatteryService extends SystemService {
shutdownIfNoPowerLocked();
shutdownIfOverTempLocked();
- if (force || (mHealthInfo.legacy.batteryStatus != mLastBatteryStatus ||
- mHealthInfo.legacy.batteryHealth != mLastBatteryHealth ||
- mHealthInfo.legacy.batteryPresent != mLastBatteryPresent ||
- mHealthInfo.legacy.batteryLevel != mLastBatteryLevel ||
+ if (force || (mBatteryProps.batteryStatus != mLastBatteryStatus ||
+ mBatteryProps.batteryHealth != mLastBatteryHealth ||
+ mBatteryProps.batteryPresent != mLastBatteryPresent ||
+ mBatteryProps.batteryLevel != mLastBatteryLevel ||
mPlugType != mLastPlugType ||
- mHealthInfo.legacy.batteryVoltage != mLastBatteryVoltage ||
- mHealthInfo.legacy.batteryTemperature != mLastBatteryTemperature ||
- mHealthInfo.legacy.maxChargingCurrent != mLastMaxChargingCurrent ||
- mHealthInfo.legacy.maxChargingVoltage != mLastMaxChargingVoltage ||
- mHealthInfo.legacy.batteryChargeCounter != mLastChargeCounter ||
+ mBatteryProps.batteryVoltage != mLastBatteryVoltage ||
+ mBatteryProps.batteryTemperature != mLastBatteryTemperature ||
+ mBatteryProps.maxChargingCurrent != mLastMaxChargingCurrent ||
+ mBatteryProps.maxChargingVoltage != mLastMaxChargingVoltage ||
+ mBatteryProps.batteryChargeCounter != mLastChargeCounter ||
mInvalidCharger != mLastInvalidCharger)) {
if (mPlugType != mLastPlugType) {
@@ -437,33 +401,33 @@ public final class BatteryService extends SystemService {
// There's no value in this data unless we've discharged at least once and the
// battery level has changed; so don't log until it does.
- if (mDischargeStartTime != 0 && mDischargeStartLevel != mHealthInfo.legacy.batteryLevel) {
+ if (mDischargeStartTime != 0 && mDischargeStartLevel != mBatteryProps.batteryLevel) {
dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;
logOutlier = true;
EventLog.writeEvent(EventLogTags.BATTERY_DISCHARGE, dischargeDuration,
- mDischargeStartLevel, mHealthInfo.legacy.batteryLevel);
+ mDischargeStartLevel, mBatteryProps.batteryLevel);
// make sure we see a discharge event before logging again
mDischargeStartTime = 0;
}
} else if (mPlugType == BATTERY_PLUGGED_NONE) {
// charging -> discharging or we just powered up
mDischargeStartTime = SystemClock.elapsedRealtime();
- mDischargeStartLevel = mHealthInfo.legacy.batteryLevel;
+ mDischargeStartLevel = mBatteryProps.batteryLevel;
}
}
- if (mHealthInfo.legacy.batteryStatus != mLastBatteryStatus ||
- mHealthInfo.legacy.batteryHealth != mLastBatteryHealth ||
- mHealthInfo.legacy.batteryPresent != mLastBatteryPresent ||
+ if (mBatteryProps.batteryStatus != mLastBatteryStatus ||
+ mBatteryProps.batteryHealth != mLastBatteryHealth ||
+ mBatteryProps.batteryPresent != mLastBatteryPresent ||
mPlugType != mLastPlugType) {
EventLog.writeEvent(EventLogTags.BATTERY_STATUS,
- mHealthInfo.legacy.batteryStatus, mHealthInfo.legacy.batteryHealth, mHealthInfo.legacy.batteryPresent ? 1 : 0,
- mPlugType, mHealthInfo.legacy.batteryTechnology);
+ mBatteryProps.batteryStatus, mBatteryProps.batteryHealth, mBatteryProps.batteryPresent ? 1 : 0,
+ mPlugType, mBatteryProps.batteryTechnology);
}
- if (mHealthInfo.legacy.batteryLevel != mLastBatteryLevel) {
+ if (mBatteryProps.batteryLevel != mLastBatteryLevel) {
// Don't do this just from voltage or temperature changes, that is
// too noisy.
EventLog.writeEvent(EventLogTags.BATTERY_LEVEL,
- mHealthInfo.legacy.batteryLevel, mHealthInfo.legacy.batteryVoltage, mHealthInfo.legacy.batteryTemperature);
+ mBatteryProps.batteryLevel, mBatteryProps.batteryVoltage, mBatteryProps.batteryTemperature);
}
if (mBatteryLevelCritical && !mLastBatteryLevelCritical &&
mPlugType == BATTERY_PLUGGED_NONE) {
@@ -476,16 +440,16 @@ public final class BatteryService extends SystemService {
if (!mBatteryLevelLow) {
// Should we now switch in to low battery mode?
if (mPlugType == BATTERY_PLUGGED_NONE
- && mHealthInfo.legacy.batteryLevel <= mLowBatteryWarningLevel) {
+ && mBatteryProps.batteryLevel <= mLowBatteryWarningLevel) {
mBatteryLevelLow = true;
}
} else {
// Should we now switch out of low battery mode?
if (mPlugType != BATTERY_PLUGGED_NONE) {
mBatteryLevelLow = false;
- } else if (mHealthInfo.legacy.batteryLevel >= mLowBatteryCloseWarningLevel) {
+ } else if (mBatteryProps.batteryLevel >= mLowBatteryCloseWarningLevel) {
mBatteryLevelLow = false;
- } else if (force && mHealthInfo.legacy.batteryLevel >= mLowBatteryWarningLevel) {
+ } else if (force && mBatteryProps.batteryLevel >= mLowBatteryWarningLevel) {
// If being forced, the previous state doesn't matter, we will just
// absolutely check to see if we are now above the warning level.
mBatteryLevelLow = false;
@@ -532,7 +496,7 @@ public final class BatteryService extends SystemService {
}
});
} else if (mSentLowBatteryBroadcast &&
- mHealthInfo.legacy.batteryLevel >= mLowBatteryCloseWarningLevel) {
+ mBatteryProps.batteryLevel >= mLowBatteryCloseWarningLevel) {
mSentLowBatteryBroadcast = false;
final Intent statusIntent = new Intent(Intent.ACTION_BATTERY_OKAY);
statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
@@ -558,16 +522,16 @@ public final class BatteryService extends SystemService {
logOutlierLocked(dischargeDuration);
}
- mLastBatteryStatus = mHealthInfo.legacy.batteryStatus;
- mLastBatteryHealth = mHealthInfo.legacy.batteryHealth;
- mLastBatteryPresent = mHealthInfo.legacy.batteryPresent;
- mLastBatteryLevel = mHealthInfo.legacy.batteryLevel;
+ mLastBatteryStatus = mBatteryProps.batteryStatus;
+ mLastBatteryHealth = mBatteryProps.batteryHealth;
+ mLastBatteryPresent = mBatteryProps.batteryPresent;
+ mLastBatteryLevel = mBatteryProps.batteryLevel;
mLastPlugType = mPlugType;
- mLastBatteryVoltage = mHealthInfo.legacy.batteryVoltage;
- mLastBatteryTemperature = mHealthInfo.legacy.batteryTemperature;
- mLastMaxChargingCurrent = mHealthInfo.legacy.maxChargingCurrent;
- mLastMaxChargingVoltage = mHealthInfo.legacy.maxChargingVoltage;
- mLastChargeCounter = mHealthInfo.legacy.batteryChargeCounter;
+ mLastBatteryVoltage = mBatteryProps.batteryVoltage;
+ mLastBatteryTemperature = mBatteryProps.batteryTemperature;
+ mLastMaxChargingCurrent = mBatteryProps.maxChargingCurrent;
+ mLastMaxChargingVoltage = mBatteryProps.maxChargingVoltage;
+ mLastChargeCounter = mBatteryProps.batteryChargeCounter;
mLastBatteryLevelCritical = mBatteryLevelCritical;
mLastInvalidCharger = mInvalidCharger;
}
@@ -579,26 +543,38 @@ public final class BatteryService extends SystemService {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_REPLACE_PENDING);
- int icon = getIconLocked(mHealthInfo.legacy.batteryLevel);
+ int icon = getIconLocked(mBatteryProps.batteryLevel);
intent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
- intent.putExtra(BatteryManager.EXTRA_STATUS, mHealthInfo.legacy.batteryStatus);
- intent.putExtra(BatteryManager.EXTRA_HEALTH, mHealthInfo.legacy.batteryHealth);
- intent.putExtra(BatteryManager.EXTRA_PRESENT, mHealthInfo.legacy.batteryPresent);
- intent.putExtra(BatteryManager.EXTRA_LEVEL, mHealthInfo.legacy.batteryLevel);
+ intent.putExtra(BatteryManager.EXTRA_STATUS, mBatteryProps.batteryStatus);
+ intent.putExtra(BatteryManager.EXTRA_HEALTH, mBatteryProps.batteryHealth);
+ intent.putExtra(BatteryManager.EXTRA_PRESENT, mBatteryProps.batteryPresent);
+ intent.putExtra(BatteryManager.EXTRA_LEVEL, mBatteryProps.batteryLevel);
intent.putExtra(BatteryManager.EXTRA_SCALE, BATTERY_SCALE);
intent.putExtra(BatteryManager.EXTRA_ICON_SMALL, icon);
intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);
- intent.putExtra(BatteryManager.EXTRA_VOLTAGE, mHealthInfo.legacy.batteryVoltage);
- intent.putExtra(BatteryManager.EXTRA_TEMPERATURE, mHealthInfo.legacy.batteryTemperature);
- intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mHealthInfo.legacy.batteryTechnology);
+ intent.putExtra(BatteryManager.EXTRA_VOLTAGE, mBatteryProps.batteryVoltage);
+ intent.putExtra(BatteryManager.EXTRA_TEMPERATURE, mBatteryProps.batteryTemperature);
+ intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mBatteryProps.batteryTechnology);
intent.putExtra(BatteryManager.EXTRA_INVALID_CHARGER, mInvalidCharger);
- intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_CURRENT, mHealthInfo.legacy.maxChargingCurrent);
- intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE, mHealthInfo.legacy.maxChargingVoltage);
- intent.putExtra(BatteryManager.EXTRA_CHARGE_COUNTER, mHealthInfo.legacy.batteryChargeCounter);
+ intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_CURRENT, mBatteryProps.maxChargingCurrent);
+ intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE, mBatteryProps.maxChargingVoltage);
+ intent.putExtra(BatteryManager.EXTRA_CHARGE_COUNTER, mBatteryProps.batteryChargeCounter);
if (DEBUG) {
- Slog.d(TAG, "Sending ACTION_BATTERY_CHANGED. scale:" + BATTERY_SCALE
- + ", info:" + mHealthInfo.toString());
+ Slog.d(TAG, "Sending ACTION_BATTERY_CHANGED. level:" + mBatteryProps.batteryLevel +
+ ", scale:" + BATTERY_SCALE + ", status:" + mBatteryProps.batteryStatus +
+ ", health:" + mBatteryProps.batteryHealth +
+ ", present:" + mBatteryProps.batteryPresent +
+ ", voltage: " + mBatteryProps.batteryVoltage +
+ ", temperature: " + mBatteryProps.batteryTemperature +
+ ", technology: " + mBatteryProps.batteryTechnology +
+ ", AC powered:" + mBatteryProps.chargerAcOnline +
+ ", USB powered:" + mBatteryProps.chargerUsbOnline +
+ ", Wireless powered:" + mBatteryProps.chargerWirelessOnline +
+ ", icon:" + icon + ", invalid charger:" + mInvalidCharger +
+ ", maxChargingCurrent:" + mBatteryProps.maxChargingCurrent +
+ ", maxChargingVoltage:" + mBatteryProps.maxChargingVoltage +
+ ", chargeCounter:" + mBatteryProps.batteryChargeCounter);
}
mHandler.post(new Runnable() {
@@ -659,14 +635,14 @@ public final class BatteryService extends SystemService {
long durationThreshold = Long.parseLong(durationThresholdString);
int dischargeThreshold = Integer.parseInt(dischargeThresholdString);
if (duration <= durationThreshold &&
- mDischargeStartLevel - mHealthInfo.legacy.batteryLevel >= dischargeThreshold) {
+ mDischargeStartLevel - mBatteryProps.batteryLevel >= dischargeThreshold) {
// If the discharge cycle is bad enough we want to know about it.
logBatteryStatsLocked();
}
if (DEBUG) Slog.v(TAG, "duration threshold: " + durationThreshold +
" discharge threshold: " + dischargeThreshold);
if (DEBUG) Slog.v(TAG, "duration: " + duration + " discharge: " +
- (mDischargeStartLevel - mHealthInfo.legacy.batteryLevel));
+ (mDischargeStartLevel - mBatteryProps.batteryLevel));
} catch (NumberFormatException e) {
Slog.e(TAG, "Invalid DischargeThresholds GService string: " +
durationThresholdString + " or " + dischargeThresholdString);
@@ -675,14 +651,14 @@ public final class BatteryService extends SystemService {
}
private int getIconLocked(int level) {
- if (mHealthInfo.legacy.batteryStatus == BatteryManager.BATTERY_STATUS_CHARGING) {
+ if (mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_CHARGING) {
return com.android.internal.R.drawable.stat_sys_battery_charge;
- } else if (mHealthInfo.legacy.batteryStatus == BatteryManager.BATTERY_STATUS_DISCHARGING) {
+ } else if (mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_DISCHARGING) {
return com.android.internal.R.drawable.stat_sys_battery;
- } else if (mHealthInfo.legacy.batteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING
- || mHealthInfo.legacy.batteryStatus == BatteryManager.BATTERY_STATUS_FULL) {
+ } else if (mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING
+ || mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_FULL) {
if (isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)
- && mHealthInfo.legacy.batteryLevel >= 100) {
+ && mBatteryProps.batteryLevel >= 100) {
return com.android.internal.R.drawable.stat_sys_battery_charge;
} else {
return com.android.internal.R.drawable.stat_sys_battery;
@@ -744,11 +720,11 @@ public final class BatteryService extends SystemService {
getContext().enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
if (!mUpdatesStopped) {
- copy(mLastHealthInfo, mHealthInfo);
+ mLastBatteryProps.set(mBatteryProps);
}
- mHealthInfo.legacy.chargerAcOnline = false;
- mHealthInfo.legacy.chargerUsbOnline = false;
- mHealthInfo.legacy.chargerWirelessOnline = false;
+ mBatteryProps.chargerAcOnline = false;
+ mBatteryProps.chargerUsbOnline = false;
+ mBatteryProps.chargerWirelessOnline = false;
long ident = Binder.clearCallingIdentity();
try {
mUpdatesStopped = true;
@@ -775,30 +751,30 @@ public final class BatteryService extends SystemService {
}
try {
if (!mUpdatesStopped) {
- copy(mLastHealthInfo, mHealthInfo);
+ mLastBatteryProps.set(mBatteryProps);
}
boolean update = true;
switch (key) {
case "present":
- mHealthInfo.legacy.batteryPresent = Integer.parseInt(value) != 0;
+ mBatteryProps.batteryPresent = Integer.parseInt(value) != 0;
break;
case "ac":
- mHealthInfo.legacy.chargerAcOnline = Integer.parseInt(value) != 0;
+ mBatteryProps.chargerAcOnline = Integer.parseInt(value) != 0;
break;
case "usb":
- mHealthInfo.legacy.chargerUsbOnline = Integer.parseInt(value) != 0;
+ mBatteryProps.chargerUsbOnline = Integer.parseInt(value) != 0;
break;
case "wireless":
- mHealthInfo.legacy.chargerWirelessOnline = Integer.parseInt(value) != 0;
+ mBatteryProps.chargerWirelessOnline = Integer.parseInt(value) != 0;
break;
case "status":
- mHealthInfo.legacy.batteryStatus = Integer.parseInt(value);
+ mBatteryProps.batteryStatus = Integer.parseInt(value);
break;
case "level":
- mHealthInfo.legacy.batteryLevel = Integer.parseInt(value);
+ mBatteryProps.batteryLevel = Integer.parseInt(value);
break;
case "temp":
- mHealthInfo.legacy.batteryTemperature = Integer.parseInt(value);
+ mBatteryProps.batteryTemperature = Integer.parseInt(value);
break;
case "invalid":
mInvalidCharger = Integer.parseInt(value);
@@ -830,7 +806,7 @@ public final class BatteryService extends SystemService {
try {
if (mUpdatesStopped) {
mUpdatesStopped = false;
- copy(mHealthInfo, mLastHealthInfo);
+ mBatteryProps.set(mLastBatteryProps);
processValuesFromShellLocked(pw, opts);
}
} finally {
@@ -857,20 +833,20 @@ public final class BatteryService extends SystemService {
if (mUpdatesStopped) {
pw.println(" (UPDATES STOPPED -- use 'reset' to restart)");
}
- pw.println(" AC powered: " + mHealthInfo.legacy.chargerAcOnline);
- pw.println(" USB powered: " + mHealthInfo.legacy.chargerUsbOnline);
- pw.println(" Wireless powered: " + mHealthInfo.legacy.chargerWirelessOnline);
- pw.println(" Max charging current: " + mHealthInfo.legacy.maxChargingCurrent);
- pw.println(" Max charging voltage: " + mHealthInfo.legacy.maxChargingVoltage);
- pw.println(" Charge counter: " + mHealthInfo.legacy.batteryChargeCounter);
- pw.println(" status: " + mHealthInfo.legacy.batteryStatus);
- pw.println(" health: " + mHealthInfo.legacy.batteryHealth);
- pw.println(" present: " + mHealthInfo.legacy.batteryPresent);
- pw.println(" level: " + mHealthInfo.legacy.batteryLevel);
+ pw.println(" AC powered: " + mBatteryProps.chargerAcOnline);
+ pw.println(" USB powered: " + mBatteryProps.chargerUsbOnline);
+ pw.println(" Wireless powered: " + mBatteryProps.chargerWirelessOnline);
+ pw.println(" Max charging current: " + mBatteryProps.maxChargingCurrent);
+ pw.println(" Max charging voltage: " + mBatteryProps.maxChargingVoltage);
+ pw.println(" Charge counter: " + mBatteryProps.batteryChargeCounter);
+ pw.println(" status: " + mBatteryProps.batteryStatus);
+ pw.println(" health: " + mBatteryProps.batteryHealth);
+ pw.println(" present: " + mBatteryProps.batteryPresent);
+ pw.println(" level: " + mBatteryProps.batteryLevel);
pw.println(" scale: " + BATTERY_SCALE);
- pw.println(" voltage: " + mHealthInfo.legacy.batteryVoltage);
- pw.println(" temperature: " + mHealthInfo.legacy.batteryTemperature);
- pw.println(" technology: " + mHealthInfo.legacy.batteryTechnology);
+ pw.println(" voltage: " + mBatteryProps.batteryVoltage);
+ pw.println(" temperature: " + mBatteryProps.batteryTemperature);
+ pw.println(" technology: " + mBatteryProps.batteryTechnology);
} else {
Shell shell = new Shell();
shell.exec(mBinderService, null, fd, null, args, null, new ResultReceiver(null));
@@ -884,25 +860,25 @@ public final class BatteryService extends SystemService {
synchronized (mLock) {
proto.write(BatteryServiceDumpProto.ARE_UPDATES_STOPPED, mUpdatesStopped);
int batteryPluggedValue = BatteryServiceDumpProto.BATTERY_PLUGGED_NONE;
- if (mHealthInfo.legacy.chargerAcOnline) {
+ if (mBatteryProps.chargerAcOnline) {
batteryPluggedValue = BatteryServiceDumpProto.BATTERY_PLUGGED_AC;
- } else if (mHealthInfo.legacy.chargerUsbOnline) {
+ } else if (mBatteryProps.chargerUsbOnline) {
batteryPluggedValue = BatteryServiceDumpProto.BATTERY_PLUGGED_USB;
- } else if (mHealthInfo.legacy.chargerWirelessOnline) {
+ } else if (mBatteryProps.chargerWirelessOnline) {
batteryPluggedValue = BatteryServiceDumpProto.BATTERY_PLUGGED_WIRELESS;
}
proto.write(BatteryServiceDumpProto.PLUGGED, batteryPluggedValue);
- proto.write(BatteryServiceDumpProto.MAX_CHARGING_CURRENT, mHealthInfo.legacy.maxChargingCurrent);
- proto.write(BatteryServiceDumpProto.MAX_CHARGING_VOLTAGE, mHealthInfo.legacy.maxChargingVoltage);
- proto.write(BatteryServiceDumpProto.CHARGE_COUNTER, mHealthInfo.legacy.batteryChargeCounter);
- proto.write(BatteryServiceDumpProto.STATUS, mHealthInfo.legacy.batteryStatus);
- proto.write(BatteryServiceDumpProto.HEALTH, mHealthInfo.legacy.batteryHealth);
- proto.write(BatteryServiceDumpProto.IS_PRESENT, mHealthInfo.legacy.batteryPresent);
- proto.write(BatteryServiceDumpProto.LEVEL, mHealthInfo.legacy.batteryLevel);
+ proto.write(BatteryServiceDumpProto.MAX_CHARGING_CURRENT, mBatteryProps.maxChargingCurrent);
+ proto.write(BatteryServiceDumpProto.MAX_CHARGING_VOLTAGE, mBatteryProps.maxChargingVoltage);
+ proto.write(BatteryServiceDumpProto.CHARGE_COUNTER, mBatteryProps.batteryChargeCounter);
+ proto.write(BatteryServiceDumpProto.STATUS, mBatteryProps.batteryStatus);
+ proto.write(BatteryServiceDumpProto.HEALTH, mBatteryProps.batteryHealth);
+ proto.write(BatteryServiceDumpProto.IS_PRESENT, mBatteryProps.batteryPresent);
+ proto.write(BatteryServiceDumpProto.LEVEL, mBatteryProps.batteryLevel);
proto.write(BatteryServiceDumpProto.SCALE, BATTERY_SCALE);
- proto.write(BatteryServiceDumpProto.VOLTAGE, mHealthInfo.legacy.batteryVoltage);
- proto.write(BatteryServiceDumpProto.TEMPERATURE, mHealthInfo.legacy.batteryTemperature);
- proto.write(BatteryServiceDumpProto.TECHNOLOGY, mHealthInfo.legacy.batteryTechnology);
+ proto.write(BatteryServiceDumpProto.VOLTAGE, mBatteryProps.batteryVoltage);
+ proto.write(BatteryServiceDumpProto.TEMPERATURE, mBatteryProps.batteryTemperature);
+ proto.write(BatteryServiceDumpProto.TECHNOLOGY, mBatteryProps.batteryTechnology);
}
proto.flush();
}
@@ -935,8 +911,8 @@ public final class BatteryService extends SystemService {
* Synchronize on BatteryService.
*/
public void updateLightsLocked() {
- final int level = mHealthInfo.legacy.batteryLevel;
- final int status = mHealthInfo.legacy.batteryStatus;
+ final int level = mBatteryProps.batteryLevel;
+ final int status = mBatteryProps.batteryStatus;
if (level < mLowBatteryWarningLevel) {
if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
// Solid red when battery is charging
@@ -1009,7 +985,7 @@ public final class BatteryService extends SystemService {
@Override
public int getBatteryLevel() {
synchronized (mLock) {
- return mHealthInfo.legacy.batteryLevel;
+ return mBatteryProps.batteryLevel;
}
}
@@ -1027,121 +1003,4 @@ public final class BatteryService extends SystemService {
}
}
}
-
- /**
- * HealthServiceWrapper wraps the internal IHealth service and refreshes the service when
- * necessary.
- *
- * On new registration of IHealth service, {@link #onRegistration onRegistration} is called and
- * the internal service is refreshed.
- * On death of an existing IHealth service, the internal service is NOT cleared to avoid
- * race condition between death notification and new service notification. Hence,
- * a caller must check for transaction errors when calling into the service.
- *
- * @hide Should only be used internally.
- */
- @VisibleForTesting
- static final class HealthServiceWrapper {
- private static final String TAG = "HealthServiceWrapper";
- public static final String INSTANCE_HEALTHD = "backup";
- public static final String INSTANCE_VENDOR = "default";
- // All interesting instances, sorted by priority high -> low.
- private static final List<String> sAllInstances =
- Arrays.asList(INSTANCE_VENDOR, INSTANCE_HEALTHD);
-
- private final IServiceNotification mNotification = new Notification();
- private Callback mCallback;
- private IHealthSupplier mHealthSupplier;
-
- /**
- * init should be called after constructor. For testing purposes, init is not called by
- * constructor.
- */
- HealthServiceWrapper() {
- }
-
- /**
- * Start monitoring registration of new IHealth services. Only instances that are in
- * {@code sAllInstances} and in device / framework manifest are used. This function should
- * only be called once.
- * @throws RemoteException transaction error when talking to IServiceManager
- * @throws NoSuchElementException if one of the following cases:
- * - No service manager;
- * - none of {@code sAllInstances} are in manifests (i.e. not
- * available on this device), or none of these instances are available to current
- * process.
- * @throws NullPointerException when callback is null or supplier is null
- */
- void init(Callback callback,
- IServiceManagerSupplier managerSupplier,
- IHealthSupplier healthSupplier)
- throws RemoteException, NoSuchElementException, NullPointerException {
- if (callback == null || managerSupplier == null || healthSupplier == null)
- throw new NullPointerException();
-
- mCallback = callback;
- mHealthSupplier = healthSupplier;
-
- IServiceManager manager = managerSupplier.get();
- for (String name : sAllInstances) {
- if (manager.getTransport(IHealth.kInterfaceName, name) ==
- IServiceManager.Transport.EMPTY) {
- continue;
- }
-
- manager.registerForNotifications(IHealth.kInterfaceName, name, mNotification);
- Slog.i(TAG, "health: HealthServiceWrapper listening to instance " + name);
- return;
- }
-
- throw new NoSuchElementException(String.format(
- "No IHealth service instance among %s is available. Perhaps no permission?",
- sAllInstances.toString()));
- }
-
- interface Callback {
- /**
- * This function is invoked asynchronously when a new and related IServiceNotification
- * is received.
- * @param service the recently retrieved service from IServiceManager.
- * Can be a dead service before service notification of a new service is delivered.
- * Implementation must handle cases for {@link RemoteException}s when calling
- * into service.
- * @param instance instance name.
- */
- void onRegistration(IHealth service, String instance);
- }
-
- /**
- * Supplier of services.
- * Must not return null; throw {@link NoSuchElementException} if a service is not available.
- */
- interface IServiceManagerSupplier {
- IServiceManager get() throws NoSuchElementException, RemoteException;
- }
- /**
- * Supplier of services.
- * Must not return null; throw {@link NoSuchElementException} if a service is not available.
- */
- interface IHealthSupplier {
- IHealth get(String instanceName) throws NoSuchElementException, RemoteException;
- }
-
- private class Notification extends IServiceNotification.Stub {
- @Override
- public final void onRegistration(String interfaceName, String instanceName,
- boolean preexisting) {
- if (!IHealth.kInterfaceName.equals(interfaceName)) return;
- if (!sAllInstances.contains(instanceName)) return;
- try {
- IHealth service = mHealthSupplier.get(instanceName);
- Slog.i(TAG, "health: new instance registered " + instanceName);
- mCallback.onRegistration(service, instanceName);
- } catch (NoSuchElementException | RemoteException ex) {
- Slog.e(TAG, "health: Cannot get instance '" + instanceName + "': " +
- ex.getMessage() + ". Perhaps no permission?");
- }
- }
- }
- }
}
diff --git a/com/android/server/IntentResolver.java b/com/android/server/IntentResolver.java
index 119c9df6..40499c96 100644
--- a/com/android/server/IntentResolver.java
+++ b/com/android/server/IntentResolver.java
@@ -38,8 +38,6 @@ import android.util.Printer;
import android.content.Intent;
import android.content.IntentFilter;
-import android.util.proto.ProtoOutputStream;
-
import com.android.internal.util.FastPrintWriter;
/**
@@ -281,31 +279,6 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
return printedSomething;
}
- void writeProtoMap(ProtoOutputStream proto, long fieldId, ArrayMap<String, F[]> map) {
- int N = map.size();
- for (int mapi = 0; mapi < N; mapi++) {
- long token = proto.start(fieldId);
- proto.write(IntentResolverProto.ArrayMapEntry.KEY, map.keyAt(mapi));
- for (F f : map.valueAt(mapi)) {
- if (f != null) {
- proto.write(IntentResolverProto.ArrayMapEntry.VALUES, f.toString());
- }
- }
- proto.end(token);
- }
- }
-
- public void writeToProto(ProtoOutputStream proto, long fieldId) {
- long token = proto.start(fieldId);
- writeProtoMap(proto, IntentResolverProto.FULL_MIME_TYPES, mTypeToFilter);
- writeProtoMap(proto, IntentResolverProto.BASE_MIME_TYPES, mBaseTypeToFilter);
- writeProtoMap(proto, IntentResolverProto.WILD_MIME_TYPES, mWildTypeToFilter);
- writeProtoMap(proto, IntentResolverProto.SCHEMES, mSchemeToFilter);
- writeProtoMap(proto, IntentResolverProto.NON_DATA_ACTIONS, mActionToFilter);
- writeProtoMap(proto, IntentResolverProto.MIME_TYPED_ACTIONS, mTypedActionToFilter);
- proto.end(token);
- }
-
public boolean dump(PrintWriter out, String title, String prefix, String packageName,
boolean printFilter, boolean collapseDuplicates) {
String innerPrefix = prefix + " ";
diff --git a/com/android/server/SystemServer.java b/com/android/server/SystemServer.java
index 49dd5285..92cbd3d5 100644
--- a/com/android/server/SystemServer.java
+++ b/com/android/server/SystemServer.java
@@ -125,7 +125,6 @@ import java.util.Timer;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
-import static android.os.IServiceManager.DUMP_PRIORITY_CRITICAL;
import static android.view.Display.DEFAULT_DISPLAY;
public final class SystemServer {
@@ -825,8 +824,7 @@ public final class SystemServer {
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore, new PhoneWindowManager());
- ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
- DUMP_PRIORITY_CRITICAL);
+ ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
traceEnd();
@@ -1642,7 +1640,11 @@ public final class SystemServer {
traceEnd();
traceBeginAndSlog("MakePackageManagerServiceReady");
- mPackageManagerService.systemReady();
+ try {
+ mPackageManagerService.systemReady();
+ } catch (Throwable e) {
+ reportWtf("making Package Manager Service ready", e);
+ }
traceEnd();
traceBeginAndSlog("MakeDisplayManagerServiceReady");
diff --git a/com/android/server/VibratorService.java b/com/android/server/VibratorService.java
index 8b79b9dd..046eb761 100644
--- a/com/android/server/VibratorService.java
+++ b/com/android/server/VibratorService.java
@@ -373,24 +373,12 @@ public class VibratorService extends IVibratorService.Stub
if (mCurrentVibration.hasLongerTimeout(newOneShot.getTiming())
&& newOneShot.getAmplitude() == currentOneShot.getAmplitude()) {
if (DEBUG) {
- Slog.d(TAG, "Ignoring incoming vibration in favor of current vibration");
+ Slog.e(TAG, "Ignoring incoming vibration in favor of current vibration");
}
return;
}
}
- // If the current vibration is repeating and the incoming one is non-repeating, then ignore
- // the non-repeating vibration. This is so that we don't cancel vibrations that are meant
- // to grab the attention of the user, like ringtones and alarms, in favor of one-shot
- // vibrations that are likely quite short.
- if (!isRepeatingVibration(effect)
- && mCurrentVibration != null && isRepeatingVibration(mCurrentVibration.mEffect)) {
- if (DEBUG) {
- Slog.d(TAG, "Ignoring incoming vibration in favor of alarm vibration");
- }
- return;
- }
-
Vibration vib = new Vibration(token, effect, usageHint, uid, opPkg);
// Only link against waveforms since they potentially don't have a finish if
@@ -416,16 +404,6 @@ public class VibratorService extends IVibratorService.Stub
}
}
- private static boolean isRepeatingVibration(VibrationEffect effect) {
- if (effect instanceof VibrationEffect.Waveform) {
- final VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) effect;
- if (waveform.getRepeatIndex() >= 0) {
- return true;
- }
- }
- return false;
- }
-
private void addToPreviousVibrationsLocked(Vibration vib) {
if (mPreviousVibrations.size() > mPreviousVibrationsLimit) {
mPreviousVibrations.removeFirst();
diff --git a/com/android/server/accessibility/AccessibilityInputFilter.java b/com/android/server/accessibility/AccessibilityInputFilter.java
index f6fcaae4..c60647fa 100644
--- a/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -19,9 +19,6 @@ package com.android.server.accessibility;
import android.content.Context;
import android.os.Handler;
import android.os.PowerManager;
-import android.util.DebugUtils;
-import android.util.ExceptionUtils;
-import android.util.Log;
import android.util.Pools.SimplePool;
import android.util.Slog;
import android.util.SparseBooleanArray;
@@ -34,7 +31,6 @@ import android.view.MotionEvent;
import android.view.WindowManagerPolicy;
import android.view.accessibility.AccessibilityEvent;
-import com.android.internal.util.BitUtils;
import com.android.server.LocalServices;
/**
@@ -192,7 +188,6 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
}
if (mEventHandler == null) {
- if (DEBUG) Slog.d(TAG, "mEventHandler == null for event " + event);
super.onInputEvent(event, policyFlags);
return;
}
@@ -344,8 +339,6 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
MotionEvent transformedEvent = MotionEvent.obtain(event);
mEventHandler.onMotionEvent(transformedEvent, event, policyFlags);
transformedEvent.recycle();
- } else {
- if (DEBUG) Slog.d(TAG, "mEventHandler == null for " + event);
}
}
@@ -373,20 +366,11 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
}
@Override
- public EventStreamTransformation getNext() {
- return null;
- }
-
- @Override
public void clearEvents(int inputSource) {
/* do nothing */
}
void setUserAndEnabledFeatures(int userId, int enabledFeatures) {
- if (DEBUG) {
- Slog.i(TAG, "setUserAndEnabledFeatures(userId = " + userId + ", enabledFeatures = 0x"
- + Integer.toHexString(enabledFeatures) + ")");
- }
if (mEnabledFeatures == enabledFeatures && mUserId == userId) {
return;
}
@@ -413,8 +397,6 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
}
private void enableFeatures() {
- if (DEBUG) Slog.i(TAG, "enableFeatures()");
-
resetStreamState();
if ((mEnabledFeatures & FLAG_FEATURE_AUTOCLICK) != 0) {
@@ -461,7 +443,7 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
*/
private void addFirstEventHandler(EventStreamTransformation handler) {
if (mEventHandler != null) {
- handler.setNext(mEventHandler);
+ handler.setNext(mEventHandler);
} else {
handler.setNext(this);
}
diff --git a/com/android/server/accessibility/AutoclickController.java b/com/android/server/accessibility/AutoclickController.java
index f5b0eb1e..892e9da4 100644
--- a/com/android/server/accessibility/AutoclickController.java
+++ b/com/android/server/accessibility/AutoclickController.java
@@ -23,12 +23,15 @@ import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.provider.Settings;
+import android.util.Slog;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.MotionEvent.PointerCoords;
import android.view.MotionEvent.PointerProperties;
+import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
/**
@@ -52,10 +55,11 @@ import android.view.accessibility.AccessibilityManager;
*
* Each instance is associated to a single user (and it does not handle user switch itself).
*/
-public class AutoclickController extends BaseEventStreamTransformation {
+public class AutoclickController implements EventStreamTransformation {
private static final String LOG_TAG = AutoclickController.class.getSimpleName();
+ private EventStreamTransformation mNext;
private final Context mContext;
private final int mUserId;
@@ -84,7 +88,9 @@ public class AutoclickController extends BaseEventStreamTransformation {
mClickScheduler.cancel();
}
- super.onMotionEvent(event, rawEvent, policyFlags);
+ if (mNext != null) {
+ mNext.onMotionEvent(event, rawEvent, policyFlags);
+ }
}
@Override
@@ -97,7 +103,21 @@ public class AutoclickController extends BaseEventStreamTransformation {
}
}
- super.onKeyEvent(event, policyFlags);
+ if (mNext != null) {
+ mNext.onKeyEvent(event, policyFlags);
+ }
+ }
+
+ @Override
+ public void onAccessibilityEvent(AccessibilityEvent event) {
+ if (mNext != null) {
+ mNext.onAccessibilityEvent(event);
+ }
+ }
+
+ @Override
+ public void setNext(EventStreamTransformation next) {
+ mNext = next;
}
@Override
@@ -106,7 +126,9 @@ public class AutoclickController extends BaseEventStreamTransformation {
mClickScheduler.cancel();
}
- super.clearEvents(inputSource);
+ if (mNext != null) {
+ mNext.clearEvents(inputSource);
+ }
}
@Override
@@ -396,7 +418,7 @@ public class AutoclickController extends BaseEventStreamTransformation {
* Creates and forwards click event sequence.
*/
private void sendClick() {
- if (mLastMotionEvent == null || getNext() == null) {
+ if (mLastMotionEvent == null || mNext == null) {
return;
}
@@ -426,10 +448,10 @@ public class AutoclickController extends BaseEventStreamTransformation {
MotionEvent upEvent = MotionEvent.obtain(downEvent);
upEvent.setAction(MotionEvent.ACTION_UP);
- AutoclickController.super.onMotionEvent(downEvent, downEvent, mEventPolicyFlags);
+ mNext.onMotionEvent(downEvent, downEvent, mEventPolicyFlags);
downEvent.recycle();
- AutoclickController.super.onMotionEvent(upEvent, upEvent, mEventPolicyFlags);
+ mNext.onMotionEvent(upEvent, upEvent, mEventPolicyFlags);
upEvent.recycle();
}
diff --git a/com/android/server/accessibility/BaseEventStreamTransformation.java b/com/android/server/accessibility/BaseEventStreamTransformation.java
deleted file mode 100644
index ce54586c..00000000
--- a/com/android/server/accessibility/BaseEventStreamTransformation.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- ** Copyright 2017, The Android Open Source Project
- **
- ** Licensed under the Apache License, Version 2.0 (the "License");
- ** you may not use this file except in compliance with the License.
- ** You may obtain a copy of the License at
- **
- ** http://www.apache.org/licenses/LICENSE-2.0
- **
- ** Unless required by applicable law or agreed to in writing, software
- ** distributed under the License is distributed on an "AS IS" BASIS,
- ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ** See the License for the specific language governing permissions and
- ** limitations under the License.
- */
-
-package com.android.server.accessibility;
-
-abstract class BaseEventStreamTransformation implements EventStreamTransformation {
- private EventStreamTransformation mNext;
-
- @Override
- public void setNext(EventStreamTransformation next) {
- mNext = next;
- }
-
- @Override
- public EventStreamTransformation getNext() {
- return mNext;
- }
-} \ No newline at end of file
diff --git a/com/android/server/accessibility/EventStreamTransformation.java b/com/android/server/accessibility/EventStreamTransformation.java
index 7982996e..fdc40984 100644
--- a/com/android/server/accessibility/EventStreamTransformation.java
+++ b/com/android/server/accessibility/EventStreamTransformation.java
@@ -65,12 +65,7 @@ interface EventStreamTransformation {
* @param rawEvent The raw motion event.
* @param policyFlags Policy flags for the event.
*/
- default void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
- EventStreamTransformation next = getNext();
- if (next != null) {
- next.onMotionEvent(event, rawEvent, policyFlags);
- }
- }
+ public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags);
/**
* Receives a key event.
@@ -78,24 +73,14 @@ interface EventStreamTransformation {
* @param event The key event.
* @param policyFlags Policy flags for the event.
*/
- default void onKeyEvent(KeyEvent event, int policyFlags) {
- EventStreamTransformation next = getNext();
- if (next != null) {
- next.onKeyEvent(event, policyFlags);
- }
- }
+ public void onKeyEvent(KeyEvent event, int policyFlags);
/**
* Receives an accessibility event.
*
* @param event The accessibility event.
*/
- default void onAccessibilityEvent(AccessibilityEvent event) {
- EventStreamTransformation next = getNext();
- if (next != null) {
- next.onAccessibilityEvent(event);
- }
- };
+ public void onAccessibilityEvent(AccessibilityEvent event);
/**
* Sets the next transformation.
@@ -105,26 +90,14 @@ interface EventStreamTransformation {
public void setNext(EventStreamTransformation next);
/**
- * Gets the next transformation.
- *
- * @return The next transformation.
- */
- public EventStreamTransformation getNext();
-
- /**
* Clears internal state associated with events from specific input source.
*
* @param inputSource The input source class for which transformation state should be cleared.
*/
- default void clearEvents(int inputSource) {
- EventStreamTransformation next = getNext();
- if (next != null) {
- next.clearEvents(inputSource);
- }
- }
+ public void clearEvents(int inputSource);
/**
* Destroys this transformation.
*/
- default void onDestroy() {}
+ public void onDestroy();
}
diff --git a/com/android/server/accessibility/KeyboardInterceptor.java b/com/android/server/accessibility/KeyboardInterceptor.java
index 77249452..f00a9540 100644
--- a/com/android/server/accessibility/KeyboardInterceptor.java
+++ b/com/android/server/accessibility/KeyboardInterceptor.java
@@ -22,12 +22,14 @@ import android.os.SystemClock;
import android.util.Pools;
import android.util.Slog;
import android.view.KeyEvent;
+import android.view.MotionEvent;
import android.view.WindowManagerPolicy;
+import android.view.accessibility.AccessibilityEvent;
/**
* Intercepts key events and forwards them to accessibility manager service.
*/
-public class KeyboardInterceptor extends BaseEventStreamTransformation implements Handler.Callback {
+public class KeyboardInterceptor implements EventStreamTransformation, Handler.Callback {
private static final int MESSAGE_PROCESS_QUEUED_EVENTS = 1;
private static final String LOG_TAG = "KeyboardInterceptor";
@@ -35,6 +37,7 @@ public class KeyboardInterceptor extends BaseEventStreamTransformation implement
private final WindowManagerPolicy mPolicy;
private final Handler mHandler;
+ private EventStreamTransformation mNext;
private KeyEventHolder mEventQueueStart;
private KeyEventHolder mEventQueueEnd;
@@ -62,6 +65,13 @@ public class KeyboardInterceptor extends BaseEventStreamTransformation implement
}
@Override
+ public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+ if (mNext != null) {
+ mNext.onMotionEvent(event, rawEvent, policyFlags);
+ }
+ }
+
+ @Override
public void onKeyEvent(KeyEvent event, int policyFlags) {
/*
* Certain keys have system-level behavior that affects accessibility services.
@@ -80,6 +90,29 @@ public class KeyboardInterceptor extends BaseEventStreamTransformation implement
}
@Override
+ public void onAccessibilityEvent(AccessibilityEvent event) {
+ if (mNext != null) {
+ mNext.onAccessibilityEvent(event);
+ }
+ }
+
+ @Override
+ public void setNext(EventStreamTransformation next) {
+ mNext = next;
+ }
+
+ @Override
+ public void clearEvents(int inputSource) {
+ if (mNext != null) {
+ mNext.clearEvents(inputSource);
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ }
+
+ @Override
public boolean handleMessage(Message msg) {
if (msg.what != MESSAGE_PROCESS_QUEUED_EVENTS) {
Slog.e(LOG_TAG, "Unexpected message type");
diff --git a/com/android/server/accessibility/MagnificationController.java b/com/android/server/accessibility/MagnificationController.java
index a10b7a20..98b8e6b7 100644
--- a/com/android/server/accessibility/MagnificationController.java
+++ b/com/android/server/accessibility/MagnificationController.java
@@ -56,7 +56,6 @@ import java.util.Locale;
* constraints.
*/
class MagnificationController implements Handler.Callback {
- private static final boolean DEBUG = false;
private static final String LOG_TAG = "MagnificationController";
public static final float MIN_SCALE = 1.0f;
@@ -510,12 +509,6 @@ class MagnificationController implements Handler.Callback {
private boolean setScaleAndCenterLocked(float scale, float centerX, float centerY,
boolean animate, int id) {
- if (DEBUG) {
- Slog.i(LOG_TAG,
- "setScaleAndCenterLocked(scale = " + scale + ", centerX = " + centerX
- + ", centerY = " + centerY + ", animate = " + animate + ", id = " + id
- + ")");
- }
final boolean changed = updateMagnificationSpecLocked(scale, centerX, centerY);
sendSpecToAnimation(mCurrentMagnificationSpec, animate);
if (isMagnifying() && (id != INVALID_ID)) {
@@ -542,9 +535,7 @@ class MagnificationController implements Handler.Callback {
final float nonNormOffsetX = mCurrentMagnificationSpec.offsetX - offsetX;
final float nonNormOffsetY = mCurrentMagnificationSpec.offsetY - offsetY;
- if (updateCurrentSpecWithOffsetsLocked(nonNormOffsetX, nonNormOffsetY)) {
- onMagnificationChangedLocked();
- }
+ updateCurrentSpecWithOffsetsLocked(nonNormOffsetX, nonNormOffsetY);
if (id != INVALID_ID) {
mIdOfLastServiceToMagnify = id;
}
@@ -642,11 +633,6 @@ class MagnificationController implements Handler.Callback {
}
private boolean updateCurrentSpecWithOffsetsLocked(float nonNormOffsetX, float nonNormOffsetY) {
- if (DEBUG) {
- Slog.i(LOG_TAG,
- "updateCurrentSpecWithOffsetsLocked(nonNormOffsetX = " + nonNormOffsetX
- + ", nonNormOffsetY = " + nonNormOffsetY + ")");
- }
boolean changed = false;
final float offsetX = MathUtils.constrain(nonNormOffsetX, getMinOffsetXLocked(), 0);
if (Float.compare(mCurrentMagnificationSpec.offsetX, offsetX) != 0) {
@@ -764,9 +750,6 @@ class MagnificationController implements Handler.Callback {
}
private void sendSpecToAnimation(MagnificationSpec spec, boolean animate) {
- if (DEBUG) {
- Slog.i(LOG_TAG, "sendSpecToAnimation(spec = " + spec + ", animate = " + animate + ")");
- }
if (Thread.currentThread().getId() == mMainThreadId) {
mSpecAnimationBridge.updateSentSpecMainThread(spec, animate);
} else {
diff --git a/com/android/server/accessibility/MagnificationGestureHandler.java b/com/android/server/accessibility/MagnificationGestureHandler.java
index 9b2b4eb7..d6452f87 100644
--- a/com/android/server/accessibility/MagnificationGestureHandler.java
+++ b/com/android/server/accessibility/MagnificationGestureHandler.java
@@ -42,12 +42,14 @@ import android.util.Slog;
import android.util.TypedValue;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
+import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.MotionEvent.PointerCoords;
import android.view.MotionEvent.PointerProperties;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.OnScaleGestureListener;
import android.view.ViewConfiguration;
+import android.view.accessibility.AccessibilityEvent;
import com.android.internal.annotations.VisibleForTesting;
@@ -100,23 +102,31 @@ import com.android.internal.annotations.VisibleForTesting;
* 7. The magnification scale will be persisted in settings and in the cloud.
*/
@SuppressWarnings("WeakerAccess")
-class MagnificationGestureHandler extends BaseEventStreamTransformation {
- private static final String LOG_TAG = "MagnificationGestureHandler";
+class MagnificationGestureHandler implements EventStreamTransformation {
+ private static final String LOG_TAG = "MagnificationEventHandler";
private static final boolean DEBUG_ALL = false;
private static final boolean DEBUG_STATE_TRANSITIONS = false || DEBUG_ALL;
private static final boolean DEBUG_DETECTING = false || DEBUG_ALL;
- private static final boolean DEBUG_PANNING_SCALING = false || DEBUG_ALL;
+ private static final boolean DEBUG_PANNING = false || DEBUG_ALL;
+
+ /** @see #handleMotionEventStateDelegating */
+ @VisibleForTesting static final int STATE_DELEGATING = 1;
+ /** @see DetectingStateHandler */
+ @VisibleForTesting static final int STATE_DETECTING = 2;
+ /** @see ViewportDraggingStateHandler */
+ @VisibleForTesting static final int STATE_VIEWPORT_DRAGGING = 3;
+ /** @see PanningScalingStateHandler */
+ @VisibleForTesting static final int STATE_PANNING_SCALING = 4;
private static final float MIN_SCALE = 2.0f;
private static final float MAX_SCALE = 5.0f;
@VisibleForTesting final MagnificationController mMagnificationController;
- @VisibleForTesting final DelegatingState mDelegatingState;
- @VisibleForTesting final DetectingState mDetectingState;
- @VisibleForTesting final PanningScalingState mPanningScalingState;
- @VisibleForTesting final ViewportDraggingState mViewportDraggingState;
+ @VisibleForTesting final DetectingStateHandler mDetectingStateHandler;
+ @VisibleForTesting final PanningScalingStateHandler mPanningScalingStateHandler;
+ @VisibleForTesting final ViewportDraggingStateHandler mViewportDraggingStateHandler;
private final ScreenStateReceiver mScreenStateReceiver;
@@ -128,12 +138,21 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
final boolean mDetectTripleTap;
/**
- * Whether {@link DetectingState#mShortcutTriggered shortcut} is enabled
+ * Whether {@link #mShortcutTriggered shortcut} is enabled
*/
final boolean mDetectShortcutTrigger;
- @VisibleForTesting State mCurrentState;
- @VisibleForTesting State mPreviousState;
+ EventStreamTransformation mNext;
+
+ @VisibleForTesting int mCurrentState;
+ @VisibleForTesting int mPreviousState;
+
+ @VisibleForTesting boolean mShortcutTriggered;
+
+ /**
+ * Time of last {@link MotionEvent#ACTION_DOWN} while in {@link #STATE_DELEGATING}
+ */
+ long mDelegatingStateDownTime;
private PointerCoords[] mTempPointerCoords;
private PointerProperties[] mTempPointerProperties;
@@ -155,10 +174,10 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
boolean detectShortcutTrigger) {
mMagnificationController = magnificationController;
- mDelegatingState = new DelegatingState();
- mDetectingState = new DetectingState(context);
- mViewportDraggingState = new ViewportDraggingState();
- mPanningScalingState = new PanningScalingState(context);
+ mDetectingStateHandler = new DetectingStateHandler(context);
+ mViewportDraggingStateHandler = new ViewportDraggingStateHandler();
+ mPanningScalingStateHandler =
+ new PanningScalingStateHandler(context);
mDetectTripleTap = detectTripleTap;
mDetectShortcutTrigger = detectShortcutTrigger;
@@ -170,29 +189,62 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
mScreenStateReceiver = null;
}
- transitionTo(mDetectingState);
+ transitionTo(STATE_DETECTING);
}
@Override
public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
- if (DEBUG_ALL) Slog.i(LOG_TAG, "onMotionEvent(" + event + ")");
-
if ((!mDetectTripleTap && !mDetectShortcutTrigger)
|| !event.isFromSource(SOURCE_TOUCHSCREEN)) {
dispatchTransformedEvent(event, rawEvent, policyFlags);
return;
}
+ // Local copy to avoid dispatching the same event to more than one state handler
+ // in case mPanningScalingStateHandler changes mCurrentState
+ int currentState = mCurrentState;
+ mPanningScalingStateHandler.onMotionEvent(event, rawEvent, policyFlags);
+ switch (currentState) {
+ case STATE_DELEGATING: {
+ handleMotionEventStateDelegating(event, rawEvent, policyFlags);
+ }
+ break;
+ case STATE_DETECTING: {
+ mDetectingStateHandler.onMotionEvent(event, rawEvent, policyFlags);
+ }
+ break;
+ case STATE_VIEWPORT_DRAGGING: {
+ mViewportDraggingStateHandler.onMotionEvent(event, rawEvent, policyFlags);
+ }
+ break;
+ case STATE_PANNING_SCALING: {
+ // mPanningScalingStateHandler handles events only
+ // if this is the current state since it uses ScaleGestureDetector
+ // and a GestureDetector which need well formed event stream.
+ }
+ break;
+ default: {
+ throw new IllegalStateException("Unknown state: " + currentState);
+ }
+ }
+ }
- handleEventWith(mCurrentState, event, rawEvent, policyFlags);
+ @Override
+ public void onKeyEvent(KeyEvent event, int policyFlags) {
+ if (mNext != null) {
+ mNext.onKeyEvent(event, policyFlags);
+ }
}
- private void handleEventWith(State stateHandler,
- MotionEvent event, MotionEvent rawEvent, int policyFlags) {
- // To keep InputEventConsistencyVerifiers within GestureDetectors happy
- mPanningScalingState.mScrollGestureDetector.onTouchEvent(event);
- mPanningScalingState.mScaleGestureDetector.onTouchEvent(event);
+ @Override
+ public void onAccessibilityEvent(AccessibilityEvent event) {
+ if (mNext != null) {
+ mNext.onAccessibilityEvent(event);
+ }
+ }
- stateHandler.onMotionEvent(event, rawEvent, policyFlags);
+ @Override
+ public void setNext(EventStreamTransformation next) {
+ mNext = next;
}
@Override
@@ -201,16 +253,13 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
clearAndTransitionToStateDetecting();
}
- super.clearEvents(inputSource);
+ if (mNext != null) {
+ mNext.clearEvents(inputSource);
+ }
}
@Override
public void onDestroy() {
- if (DEBUG_STATE_TRANSITIONS) {
- Slog.i(LOG_TAG, "onDestroy(); delayed = "
- + MotionEventInfo.toString(mDetectingState.mDelayedEventQueue));
- }
-
if (mScreenStateReceiver != null) {
mScreenStateReceiver.unregister();
}
@@ -223,21 +272,59 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
if (wasMagnifying) {
clearAndTransitionToStateDetecting();
} else {
- mDetectingState.toggleShortcutTriggered();
+ toggleShortcutTriggered();
}
}
}
+ private void toggleShortcutTriggered() {
+ setShortcutTriggered(!mShortcutTriggered);
+ }
+
+ private void setShortcutTriggered(boolean state) {
+ if (mShortcutTriggered == state) {
+ return;
+ }
+
+ mShortcutTriggered = state;
+ mMagnificationController.setForceShowMagnifiableBounds(state);
+ }
+
void clearAndTransitionToStateDetecting() {
- mCurrentState = mDelegatingState;
- mDetectingState.clear();
- mViewportDraggingState.clear();
- mPanningScalingState.clear();
+ setShortcutTriggered(false);
+ mCurrentState = STATE_DETECTING;
+ mDetectingStateHandler.clear();
+ mViewportDraggingStateHandler.clear();
+ mPanningScalingStateHandler.clear();
+ }
+
+ private void handleMotionEventStateDelegating(MotionEvent event,
+ MotionEvent rawEvent, int policyFlags) {
+ if (event.getActionMasked() == ACTION_UP) {
+ transitionTo(STATE_DETECTING);
+ }
+ delegateEvent(event, rawEvent, policyFlags);
+ }
+
+ void delegateEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+ if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ mDelegatingStateDownTime = event.getDownTime();
+ }
+ if (mNext != null) {
+ // We cache some events to see if the user wants to trigger magnification.
+ // If no magnification is triggered we inject these events with adjusted
+ // time and down time to prevent subsequent transformations being confused
+ // by stale events. After the cached events, which always have a down, are
+ // injected we need to also update the down time of all subsequent non cached
+ // events. All delegated events cached and non-cached are delivered here.
+ event.setDownTime(mDelegatingStateDownTime);
+ dispatchTransformedEvent(event, rawEvent, policyFlags);
+ }
}
private void dispatchTransformedEvent(MotionEvent event, MotionEvent rawEvent,
int policyFlags) {
- if (DEBUG_ALL) Slog.i(LOG_TAG, "dispatchTransformedEvent(event = " + event + ")");
+ if (mNext == null) return; // Nowhere to dispatch to
// If the touchscreen event is within the magnified portion of the screen we have
// to change its location to be where the user thinks he is poking the
@@ -264,7 +351,7 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
coords, 0, 0, 1.0f, 1.0f, event.getDeviceId(), 0, event.getSource(),
event.getFlags());
}
- super.onMotionEvent(event, rawEvent, policyFlags);
+ mNext.onMotionEvent(event, rawEvent, policyFlags);
}
private PointerCoords[] getTempPointerCoordsWithMinSize(int size) {
@@ -299,10 +386,9 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
return mTempPointerProperties;
}
- private void transitionTo(State state) {
+ private void transitionTo(int state) {
if (DEBUG_STATE_TRANSITIONS) {
- Slog.i(LOG_TAG,
- (State.nameOf(mCurrentState) + " -> " + State.nameOf(state)
+ Slog.i(LOG_TAG, (stateToString(mCurrentState) + " -> " + stateToString(state)
+ " at " + asList(copyOfRange(new RuntimeException().getStackTrace(), 1, 5)))
.replace(getClass().getName(), ""));
}
@@ -310,40 +396,40 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
mCurrentState = state;
}
- interface State {
- void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags);
+ private static String stateToString(int state) {
+ switch (state) {
+ case STATE_DELEGATING: return "STATE_DELEGATING";
+ case STATE_DETECTING: return "STATE_DETECTING";
+ case STATE_VIEWPORT_DRAGGING: return "STATE_VIEWPORT_DRAGGING";
+ case STATE_PANNING_SCALING: return "STATE_PANNING_SCALING";
+ case 0: return "0";
+ default: throw new IllegalArgumentException("Unknown state: " + state);
+ }
+ }
- default void clear() {}
+ private interface MotionEventHandler {
- default String name() {
- return getClass().getSimpleName();
- }
+ void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags);
- static String nameOf(@Nullable State s) {
- return s != null ? s.name() : "null";
- }
+ void clear();
}
/**
* This class determines if the user is performing a scale or pan gesture.
*
- * Unlike when {@link ViewportDraggingState dragging the viewport}, in panning mode the viewport
- * moves in the same direction as the fingers, and allows to easily and precisely scale the
- * magnification level.
- * This makes it the preferred mode for one-off adjustments, due to its precision and ease of
- * triggering.
+ * @see #STATE_PANNING_SCALING
*/
- final class PanningScalingState extends SimpleOnGestureListener
- implements OnScaleGestureListener, State {
+ final class PanningScalingStateHandler extends SimpleOnGestureListener
+ implements OnScaleGestureListener, MotionEventHandler {
private final ScaleGestureDetector mScaleGestureDetector;
- private final GestureDetector mScrollGestureDetector;
+ private final GestureDetector mGestureDetector;
final float mScalingThreshold;
float mInitialScaleFactor = -1;
boolean mScaling;
- public PanningScalingState(Context context) {
+ public PanningScalingStateHandler(Context context) {
final TypedValue scaleValue = new TypedValue();
context.getResources().getValue(
com.android.internal.R.dimen.config_screen_magnification_scaling_threshold,
@@ -351,27 +437,35 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
mScalingThreshold = scaleValue.getFloat();
mScaleGestureDetector = new ScaleGestureDetector(context, this);
mScaleGestureDetector.setQuickScaleEnabled(false);
- mScrollGestureDetector = new GestureDetector(context, this);
+ mGestureDetector = new GestureDetector(context, this);
}
@Override
public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
- int action = event.getActionMasked();
+ // Dispatches #onScaleBegin, #onScale, #onScaleEnd
+ mScaleGestureDetector.onTouchEvent(event);
+ // Dispatches #onScroll
+ mGestureDetector.onTouchEvent(event);
+ if (mCurrentState != STATE_PANNING_SCALING) {
+ return;
+ }
+
+ int action = event.getActionMasked();
if (action == ACTION_POINTER_UP
&& event.getPointerCount() == 2 // includes the pointer currently being released
- && mPreviousState == mViewportDraggingState) {
+ && mPreviousState == STATE_VIEWPORT_DRAGGING) {
- persistScaleAndTransitionTo(mViewportDraggingState);
+ persistScaleAndTransitionTo(STATE_VIEWPORT_DRAGGING);
} else if (action == ACTION_UP) {
- persistScaleAndTransitionTo(mDetectingState);
+ persistScaleAndTransitionTo(STATE_DETECTING);
}
}
- public void persistScaleAndTransitionTo(State state) {
+ public void persistScaleAndTransitionTo(int state) {
mMagnificationController.persistScale();
clear();
transitionTo(state);
@@ -380,16 +474,16 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
@Override
public boolean onScroll(MotionEvent first, MotionEvent second,
float distanceX, float distanceY) {
- if (mCurrentState != mPanningScalingState) {
+ if (mCurrentState != STATE_PANNING_SCALING) {
return true;
}
- if (DEBUG_PANNING_SCALING) {
+ if (DEBUG_PANNING) {
Slog.i(LOG_TAG, "Panned content by scrollX: " + distanceX
+ " scrollY: " + distanceY);
}
mMagnificationController.offsetMagnifiedRegion(distanceX, distanceY,
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
- return /* event consumed: */ true;
+ return true;
}
@Override
@@ -400,8 +494,12 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
return false;
}
final float deltaScale = detector.getScaleFactor() - mInitialScaleFactor;
- mScaling = abs(deltaScale) > mScalingThreshold;
- return mScaling;
+ if (abs(deltaScale) > mScalingThreshold) {
+ mScaling = true;
+ return true;
+ } else {
+ return false;
+ }
}
final float initialScale = mMagnificationController.getScale();
@@ -425,15 +523,14 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
final float pivotX = detector.getFocusX();
final float pivotY = detector.getFocusY();
- if (DEBUG_PANNING_SCALING) Slog.i(LOG_TAG, "Scaled content to: " + scale + "x");
mMagnificationController.setScale(scale, pivotX, pivotY, false,
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
- return /* handled: */ true;
+ return true;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
- return /* continue recognizing: */ (mCurrentState == mPanningScalingState);
+ return (mCurrentState == STATE_PANNING_SCALING);
}
@Override
@@ -449,7 +546,7 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
@Override
public String toString() {
- return "PanningScalingState{" +
+ return "MagnifiedContentInteractionStateHandler{" +
"mInitialScaleFactor=" + mInitialScaleFactor +
", mScaling=" + mScaling +
'}';
@@ -461,11 +558,9 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
* determined that the user is performing a single-finger drag of the
* magnification viewport.
*
- * Unlike when {@link PanningScalingState panning}, the viewport moves in the opposite direction
- * of the finger, and any part of the screen is reachable without lifting the finger.
- * This makes it the preferable mode for tasks like reading text spanning full screen width.
+ * @see #STATE_VIEWPORT_DRAGGING
*/
- final class ViewportDraggingState implements State {
+ final class ViewportDraggingStateHandler implements MotionEventHandler {
/** Whether to disable zoom after dragging ends */
boolean mZoomedInBeforeDrag;
@@ -477,7 +572,7 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
switch (action) {
case ACTION_POINTER_DOWN: {
clear();
- transitionTo(mPanningScalingState);
+ transitionTo(STATE_PANNING_SCALING);
}
break;
case ACTION_MOVE: {
@@ -499,7 +594,7 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
case ACTION_UP: {
if (!mZoomedInBeforeDrag) zoomOff();
clear();
- transitionTo(mDetectingState);
+ transitionTo(STATE_DETECTING);
}
break;
@@ -518,51 +613,25 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
@Override
public String toString() {
- return "ViewportDraggingState{" +
+ return "ViewportDraggingStateHandler{" +
"mZoomedInBeforeDrag=" + mZoomedInBeforeDrag +
", mLastMoveOutsideMagnifiedRegion=" + mLastMoveOutsideMagnifiedRegion +
'}';
}
}
- final class DelegatingState implements State {
- /**
- * Time of last {@link MotionEvent#ACTION_DOWN} while in {@link DelegatingState}
- */
- public long mLastDelegatedDownEventTime;
-
- @Override
- public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
- if (event.getActionMasked() == ACTION_UP) {
- transitionTo(mDetectingState);
- }
-
- if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
- mLastDelegatedDownEventTime = event.getDownTime();
- }
- if (getNext() != null) {
- // We cache some events to see if the user wants to trigger magnification.
- // If no magnification is triggered we inject these events with adjusted
- // time and down time to prevent subsequent transformations being confused
- // by stale events. After the cached events, which always have a down, are
- // injected we need to also update the down time of all subsequent non cached
- // events. All delegated events cached and non-cached are delivered here.
- event.setDownTime(mLastDelegatedDownEventTime);
- dispatchTransformedEvent(event, rawEvent, policyFlags);
- }
- }
- }
-
/**
* This class handles motion events when the event dispatch has not yet
* determined what the user is doing. It watches for various tap events.
+ *
+ * @see #STATE_DETECTING
*/
- final class DetectingState implements State, Handler.Callback {
+ final class DetectingStateHandler implements MotionEventHandler, Handler.Callback {
private static final int MESSAGE_ON_TRIPLE_TAP_AND_HOLD = 1;
private static final int MESSAGE_TRANSITION_TO_DELEGATING_STATE = 2;
- final int mLongTapMinDelay;
+ final int mLongTapMinDelay = ViewConfiguration.getJumpTapTimeout();
final int mSwipeMinDistance;
final int mMultiTapMaxDelay;
final int mMultiTapMaxDistance;
@@ -573,12 +642,9 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
private MotionEvent mLastUp;
private MotionEvent mPreLastUp;
- @VisibleForTesting boolean mShortcutTriggered;
-
Handler mHandler = new Handler(this);
- public DetectingState(Context context) {
- mLongTapMinDelay = ViewConfiguration.getLongPressTimeout();
+ public DetectingStateHandler(Context context) {
mMultiTapMaxDelay = ViewConfiguration.getDoubleTapTimeout()
+ context.getResources().getInteger(
com.android.internal.R.integer.config_screen_magnification_multi_tap_adjustment);
@@ -595,7 +661,7 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
}
break;
case MESSAGE_TRANSITION_TO_DELEGATING_STATE: {
- transitionToDelegatingStateAndClear();
+ transitionToDelegatingState(/* andClear */ true);
}
break;
default: {
@@ -616,12 +682,12 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
if (!mMagnificationController.magnificationRegionContains(
event.getX(), event.getY())) {
- transitionToDelegatingStateAndClear();
+ transitionToDelegatingState(/* andClear */ !mShortcutTriggered);
} else if (isMultiTapTriggered(2 /* taps */)) {
// 3tap and hold
- afterLongTapTimeoutTransitionToDraggingState(event);
+ delayedTransitionToDraggingState(event);
} else if (mDetectTripleTap
// If magnified, delay an ACTION_DOWN for mMultiTapMaxDelay
@@ -629,21 +695,21 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
// STATE_PANNING_SCALING(triggerable with ACTION_POINTER_DOWN)
|| mMagnificationController.isMagnifying()) {
- afterMultiTapTimeoutTransitionToDelegatingState();
+ delayedTransitionToDelegatingState();
} else {
// Delegate pending events without delay
- transitionToDelegatingStateAndClear();
+ transitionToDelegatingState(/* andClear */ true);
}
}
break;
case ACTION_POINTER_DOWN: {
if (mMagnificationController.isMagnifying()) {
- transitionTo(mPanningScalingState);
+ transitionTo(STATE_PANNING_SCALING);
clear();
} else {
- transitionToDelegatingStateAndClear();
+ transitionToDelegatingState(/* andClear */ true);
}
}
break;
@@ -656,7 +722,7 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
&& !isMultiTapTriggered(2 /* taps */)) {
// Swipe detected - delegate skipping timeout
- transitionToDelegatingStateAndClear();
+ transitionToDelegatingState(/* andClear */ true);
}
}
break;
@@ -667,7 +733,7 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
if (!mMagnificationController.magnificationRegionContains(
event.getX(), event.getY())) {
- transitionToDelegatingStateAndClear();
+ transitionToDelegatingState(/* andClear */ !mShortcutTriggered);
} else if (isMultiTapTriggered(3 /* taps */)) {
@@ -676,11 +742,12 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
} else if (
// Possible to be false on: 3tap&drag -> scale -> PTR_UP -> UP
isFingerDown()
- //TODO long tap should never happen here
- && ((timeBetween(mLastDown, mLastUp) >= mLongTapMinDelay)
- || (distance(mLastDown, mLastUp) >= mSwipeMinDistance))) {
+ //TODO long tap should never happen here
+ && (timeBetween(mLastDown, /* mLastUp */ event) >= mLongTapMinDelay)
+ || distance(mLastDown, /* mLastUp */ event)
+ >= mSwipeMinDistance) {
- transitionToDelegatingStateAndClear();
+ transitionToDelegatingState(/* andClear */ true);
}
}
@@ -728,15 +795,15 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
return MotionEventInfo.countOf(mDelayedEventQueue, ACTION_UP);
}
- /** -> {@link DelegatingState} */
- public void afterMultiTapTimeoutTransitionToDelegatingState() {
+ /** -> {@link #STATE_DELEGATING} */
+ public void delayedTransitionToDelegatingState() {
mHandler.sendEmptyMessageDelayed(
MESSAGE_TRANSITION_TO_DELEGATING_STATE,
mMultiTapMaxDelay);
}
- /** -> {@link ViewportDraggingState} */
- public void afterLongTapTimeoutTransitionToDraggingState(MotionEvent event) {
+ /** -> {@link #STATE_VIEWPORT_DRAGGING} */
+ public void delayedTransitionToDraggingState(MotionEvent event) {
mHandler.sendMessageDelayed(
mHandler.obtainMessage(MESSAGE_ON_TRIPLE_TAP_AND_HOLD, event),
ViewConfiguration.getLongPressTimeout());
@@ -779,7 +846,11 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
MotionEventInfo info = mDelayedEventQueue;
mDelayedEventQueue = info.mNext;
- handleEventWith(mDelegatingState, info.event, info.rawEvent, info.policyFlags);
+ // Because MagnifiedInteractionStateHandler requires well-formed event stream
+ mPanningScalingStateHandler.onMotionEvent(
+ info.event, info.rawEvent, info.policyFlags);
+
+ delegateEvent(info.event, info.rawEvent, info.policyFlags);
info.recycle();
}
@@ -797,10 +868,10 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
mLastUp = null;
}
- void transitionToDelegatingStateAndClear() {
- transitionTo(mDelegatingState);
+ void transitionToDelegatingState(boolean andClear) {
+ transitionTo(STATE_DELEGATING);
sendDelayedMotionEvents();
- clear();
+ if (andClear) clear();
}
private void onTripleTap(MotionEvent up) {
@@ -824,40 +895,24 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
if (DEBUG_DETECTING) Slog.i(LOG_TAG, "onTripleTapAndHold()");
clear();
- mViewportDraggingState.mZoomedInBeforeDrag =
+ mViewportDraggingStateHandler.mZoomedInBeforeDrag =
mMagnificationController.isMagnifying();
zoomOn(down.getX(), down.getY());
- transitionTo(mViewportDraggingState);
+ transitionTo(STATE_VIEWPORT_DRAGGING);
}
@Override
public String toString() {
- return "DetectingState{" +
+ return "DetectingStateHandler{" +
"tapCount()=" + tapCount() +
- ", mShortcutTriggered=" + mShortcutTriggered +
", mDelayedEventQueue=" + MotionEventInfo.toString(mDelayedEventQueue) +
'}';
}
-
- void toggleShortcutTriggered() {
- setShortcutTriggered(!mShortcutTriggered);
- }
-
- void setShortcutTriggered(boolean state) {
- if (mShortcutTriggered == state) {
- return;
- }
-
- mShortcutTriggered = state;
- mMagnificationController.setForceShowMagnifiableBounds(state);
- }
}
private void zoomOn(float centerX, float centerY) {
- if (DEBUG_DETECTING) Slog.i(LOG_TAG, "zoomOn(" + centerX + ", " + centerY + ")");
-
final float scale = MathUtils.constrain(
mMagnificationController.getPersistedScale(),
MIN_SCALE, MAX_SCALE);
@@ -868,8 +923,6 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
}
private void zoomOff() {
- if (DEBUG_DETECTING) Slog.i(LOG_TAG, "zoomOff()");
-
mMagnificationController.reset(/* animate */ true);
}
@@ -882,15 +935,16 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
@Override
public String toString() {
- return "MagnificationGesture{" +
- "mDetectingState=" + mDetectingState +
- ", mDelegatingState=" + mDelegatingState +
- ", mMagnifiedInteractionState=" + mPanningScalingState +
- ", mViewportDraggingState=" + mViewportDraggingState +
+ return "MagnificationGestureHandler{" +
+ "mDetectingStateHandler=" + mDetectingStateHandler +
+ ", mMagnifiedInteractionStateHandler=" + mPanningScalingStateHandler +
+ ", mViewportDraggingStateHandler=" + mViewportDraggingStateHandler +
", mDetectTripleTap=" + mDetectTripleTap +
", mDetectShortcutTrigger=" + mDetectShortcutTrigger +
- ", mCurrentState=" + State.nameOf(mCurrentState) +
- ", mPreviousState=" + State.nameOf(mPreviousState) +
+ ", mCurrentState=" + stateToString(mCurrentState) +
+ ", mPreviousState=" + stateToString(mPreviousState) +
+ ", mShortcutTriggered=" + mShortcutTriggered +
+ ", mDelegatingStateDownTime=" + mDelegatingStateDownTime +
", mMagnificationController=" + mMagnificationController +
'}';
}
@@ -997,7 +1051,7 @@ class MagnificationGestureHandler extends BaseEventStreamTransformation {
@Override
public void onReceive(Context context, Intent intent) {
- mGestureHandler.mDetectingState.setShortcutTriggered(false);
+ mGestureHandler.setShortcutTriggered(false);
}
}
}
diff --git a/com/android/server/accessibility/MotionEventInjector.java b/com/android/server/accessibility/MotionEventInjector.java
index b6b78129..48041adb 100644
--- a/com/android/server/accessibility/MotionEventInjector.java
+++ b/com/android/server/accessibility/MotionEventInjector.java
@@ -30,13 +30,13 @@ import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.InputDevice;
+import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.WindowManagerPolicy;
-
+import android.view.accessibility.AccessibilityEvent;
import com.android.internal.os.SomeArgs;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
/**
@@ -45,7 +45,7 @@ import java.util.List;
* <p>
* All methods except {@code injectEvents} must be called only from the main thread.
*/
-public class MotionEventInjector extends BaseEventStreamTransformation implements Handler.Callback {
+public class MotionEventInjector implements EventStreamTransformation, Handler.Callback {
private static final String LOG_TAG = "MotionEventInjector";
private static final int MESSAGE_SEND_MOTION_EVENT = 1;
private static final int MESSAGE_INJECT_EVENTS = 2;
@@ -68,6 +68,7 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement
private final Handler mHandler;
private final SparseArray<Boolean> mOpenGesturesInProgress = new SparseArray<>();
+ private EventStreamTransformation mNext;
private IAccessibilityServiceClient mServiceInterfaceForCurrentGesture;
private IntArray mSequencesInProgress = new IntArray(5);
private boolean mIsDestroyed = false;
@@ -116,6 +117,25 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement
}
@Override
+ public void onKeyEvent(KeyEvent event, int policyFlags) {
+ if (mNext != null) {
+ mNext.onKeyEvent(event, policyFlags);
+ }
+ }
+
+ @Override
+ public void onAccessibilityEvent(AccessibilityEvent event) {
+ if (mNext != null) {
+ mNext.onAccessibilityEvent(event);
+ }
+ }
+
+ @Override
+ public void setNext(EventStreamTransformation next) {
+ mNext = next;
+ }
+
+ @Override
public void clearEvents(int inputSource) {
/*
* Reset state for motion events passing through so we won't send a cancel event for
@@ -167,7 +187,7 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement
return;
}
- if (getNext() == null) {
+ if (mNext == null) {
notifyService(serviceInterface, sequence, false);
return;
}
@@ -242,24 +262,17 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement
int continuedPointerId = mStrokeIdToPointerId
.get(touchPoint.mContinuedStrokeId, -1);
if (continuedPointerId == -1) {
- Slog.w(LOG_TAG, "Can't continue gesture due to unknown continued stroke id in "
- + touchPoint);
return false;
}
mStrokeIdToPointerId.put(touchPoint.mStrokeId, continuedPointerId);
int lastPointIndex = findPointByStrokeId(
mLastTouchPoints, mNumLastTouchPoints, touchPoint.mContinuedStrokeId);
if (lastPointIndex < 0) {
- Slog.w(LOG_TAG, "Can't continue gesture due continued gesture id of "
- + touchPoint + " not matching any previous strokes in "
- + Arrays.asList(mLastTouchPoints));
return false;
}
if (mLastTouchPoints[lastPointIndex].mIsEndOfPath
|| (mLastTouchPoints[lastPointIndex].mX != touchPoint.mX)
|| (mLastTouchPoints[lastPointIndex].mY != touchPoint.mY)) {
- Slog.w(LOG_TAG, "Can't continue gesture due to points mismatch between "
- + mLastTouchPoints[lastPointIndex] + " and " + touchPoint);
return false;
}
// Update the last touch point to match the continuation, so the gestures will
@@ -279,8 +292,8 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement
private void sendMotionEventToNext(MotionEvent event, MotionEvent rawEvent,
int policyFlags) {
- if (getNext() != null) {
- super.onMotionEvent(event, rawEvent, policyFlags);
+ if (mNext != null) {
+ mNext.onMotionEvent(event, rawEvent, policyFlags);
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
mOpenGesturesInProgress.put(event.getSource(), true);
}
@@ -292,7 +305,7 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement
}
private void cancelAnyGestureInProgress(int source) {
- if ((getNext() != null) && mOpenGesturesInProgress.get(source, false)) {
+ if ((mNext != null) && mOpenGesturesInProgress.get(source, false)) {
long now = SystemClock.uptimeMillis();
MotionEvent cancelEvent =
obtainMotionEvent(now, now, MotionEvent.ACTION_CANCEL, getLastTouchPoints(), 1);
diff --git a/com/android/server/accessibility/TouchExplorer.java b/com/android/server/accessibility/TouchExplorer.java
index a32686df..e380f2c6 100644
--- a/com/android/server/accessibility/TouchExplorer.java
+++ b/com/android/server/accessibility/TouchExplorer.java
@@ -55,8 +55,7 @@ import java.util.List;
*
* @hide
*/
-class TouchExplorer extends BaseEventStreamTransformation
- implements AccessibilityGestureDetector.Listener {
+class TouchExplorer implements EventStreamTransformation, AccessibilityGestureDetector.Listener {
private static final boolean DEBUG = false;
@@ -132,6 +131,9 @@ class TouchExplorer extends BaseEventStreamTransformation
// the two dragging pointers as opposed to use the location of the primary one.
private final int mScaledMinPointerDistanceToUseMiddleLocation;
+ // The handler to which to delegate events.
+ private EventStreamTransformation mNext;
+
// Helper class to track received pointers.
private final ReceivedPointerTracker mReceivedPointerTracker;
@@ -196,7 +198,9 @@ class TouchExplorer extends BaseEventStreamTransformation
if (inputSource == InputDevice.SOURCE_TOUCHSCREEN) {
clear();
}
- super.clearEvents(inputSource);
+ if (mNext != null) {
+ mNext.clearEvents(inputSource);
+ }
}
@Override
@@ -254,9 +258,16 @@ class TouchExplorer extends BaseEventStreamTransformation
}
@Override
+ public void setNext(EventStreamTransformation next) {
+ mNext = next;
+ }
+
+ @Override
public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
if (!event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)) {
- super.onMotionEvent(event, rawEvent, policyFlags);
+ if (mNext != null) {
+ mNext.onMotionEvent(event, rawEvent, policyFlags);
+ }
return;
}
@@ -300,6 +311,13 @@ class TouchExplorer extends BaseEventStreamTransformation
}
@Override
+ public void onKeyEvent(KeyEvent event, int policyFlags) {
+ if (mNext != null) {
+ mNext.onKeyEvent(event, policyFlags);
+ }
+ }
+
+ @Override
public void onAccessibilityEvent(AccessibilityEvent event) {
final int eventType = event.getEventType();
@@ -335,7 +353,9 @@ class TouchExplorer extends BaseEventStreamTransformation
mLastTouchedWindowId = event.getWindowId();
} break;
}
- super.onAccessibilityEvent(event);
+ if (mNext != null) {
+ mNext.onAccessibilityEvent(event);
+ }
}
@Override
@@ -949,10 +969,12 @@ class TouchExplorer extends BaseEventStreamTransformation
// Make sure that the user will see the event.
policyFlags |= WindowManagerPolicy.FLAG_PASS_TO_USER;
- // TODO: For now pass null for the raw event since the touch
- // explorer is the last event transformation and it does
- // not care about the raw event.
- super.onMotionEvent(event, null, policyFlags);
+ if (mNext != null) {
+ // TODO: For now pass null for the raw event since the touch
+ // explorer is the last event transformation and it does
+ // not care about the raw event.
+ mNext.onMotionEvent(event, null, policyFlags);
+ }
mInjectedPointerTracker.onMotionEvent(event);
diff --git a/com/android/server/am/ActivityDisplay.java b/com/android/server/am/ActivityDisplay.java
index 6ed05552..8bcbfbef 100644
--- a/com/android/server/am/ActivityDisplay.java
+++ b/com/android/server/am/ActivityDisplay.java
@@ -16,7 +16,9 @@
package com.android.server.am;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.ActivityManager.StackId.getStackIdForWindowingMode;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
@@ -46,14 +48,13 @@ import android.view.Display;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wm.ConfigurationContainer;
-import java.io.PrintWriter;
import java.util.ArrayList;
/**
* Exactly one of these classes per Display in the system. Capable of holding zero or more
* attached {@link ActivityStack}s.
*/
-class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
+class ActivityDisplay extends ConfigurationContainer {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityDisplay" : TAG_AM;
private static final String TAG_STACK = TAG + POSTFIX_STACK;
@@ -67,7 +68,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
/** 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 */
- private final ArrayList<ActivityStack> mStacks = new ArrayList<>();
+ final ArrayList<ActivityStack> mStacks = new ArrayList<>();
/** Array of all UIDs that are present on the display. */
private IntArray mDisplayAccessUIDs = new IntArray();
@@ -79,13 +80,6 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
private boolean mSleeping;
- // Cached reference to some special stacks we tend to get a lot so we don't need to loop
- // through the list to find them.
- private ActivityStack mHomeStack = null;
- private ActivityStack mRecentsStack = null;
- private ActivityStack mPinnedStack = null;
- private ActivityStack mSplitScreenPrimaryStack = null;
-
ActivityDisplay(ActivityStackSupervisor supervisor, int displayId) {
mSupervisor = supervisor;
mDisplayId = displayId;
@@ -104,7 +98,6 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
}
if (DEBUG_STACK) Slog.v(TAG_STACK, "addChild: attaching " + stack
+ " to displayId=" + mDisplayId + " position=" + position);
- addStackReferenceIfNeeded(stack);
positionChildAt(stack, position);
mSupervisor.mService.updateSleepIfNeededLocked();
}
@@ -113,7 +106,6 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
if (DEBUG_STACK) Slog.v(TAG_STACK, "removeChild: detaching " + stack
+ " from displayId=" + mDisplayId);
mStacks.remove(stack);
- removeStackReferenceIfNeeded(stack);
mSupervisor.mService.updateSleepIfNeededLocked();
}
@@ -158,16 +150,6 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
* @see ConfigurationContainer#isCompatible(int, int)
*/
<T extends ActivityStack> T getStack(int windowingMode, int activityType) {
- if (activityType == ACTIVITY_TYPE_HOME) {
- return (T) mHomeStack;
- } else if (activityType == ACTIVITY_TYPE_RECENTS) {
- return (T) mRecentsStack;
- }
- if (windowingMode == WINDOWING_MODE_PINNED) {
- return (T) mPinnedStack;
- } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
- return (T) mSplitScreenPrimaryStack;
- }
for (int i = mStacks.size() - 1; i >= 0; --i) {
final ActivityStack stack = mStacks.get(i);
// TODO: Should undefined windowing and activity type be compatible with standard type?
@@ -231,14 +213,10 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
if (windowingMode == WINDOWING_MODE_UNDEFINED) {
// TODO: Should be okay to have stacks with with undefined windowing mode long term, but
// have to set them to something for now due to logic that depending on them.
- windowingMode = getWindowingMode(); // Put in current display's windowing mode
- if (windowingMode == WINDOWING_MODE_UNDEFINED) {
- // Else fullscreen for now...
- windowingMode = WINDOWING_MODE_FULLSCREEN;
- }
+ windowingMode = WINDOWING_MODE_FULLSCREEN;
}
- final boolean inSplitScreenMode = hasSplitScreenPrimaryStack();
+ final boolean inSplitScreenMode = hasSplitScreenStack();
if (!inSplitScreenMode
&& windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY) {
// Switch to fullscreen windowing mode if we are not in split-screen mode and we are
@@ -250,7 +228,24 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
}
- final int stackId = mSupervisor.getNextStackId();
+ int stackId = INVALID_STACK_ID;
+ if (mDisplayId == DEFAULT_DISPLAY && (activityType == ACTIVITY_TYPE_STANDARD
+ || activityType == ACTIVITY_TYPE_UNDEFINED)) {
+ // TODO: Will be removed once we are no longer using static stack ids.
+ stackId = getStackIdForWindowingMode(windowingMode);
+ if (stackId == INVALID_STACK_ID) {
+ // Whatever...put in fullscreen stack for now.
+ stackId = FULLSCREEN_WORKSPACE_STACK_ID;
+ }
+ final T stack = getStack(stackId);
+ if (stack != null) {
+ return stack;
+ }
+ }
+
+ if (stackId == INVALID_STACK_ID) {
+ stackId = mSupervisor.getNextStackId();
+ }
final T stack = createStackUnchecked(windowingMode, activityType, stackId, onTop);
@@ -296,7 +291,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
if (stack.getWindowingMode() != windowingMode) {
continue;
}
- mSupervisor.removeStack(stack);
+ mSupervisor.removeStackLocked(stack.mStackId);
}
}
}
@@ -311,63 +306,12 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
for (int i = mStacks.size() - 1; i >= 0; --i) {
final ActivityStack stack = mStacks.get(i);
if (stack.getActivityType() == activityType) {
- mSupervisor.removeStack(stack);
+ mSupervisor.removeStackLocked(stack.mStackId);
}
}
}
}
- void onStackWindowingModeChanged(ActivityStack stack) {
- removeStackReferenceIfNeeded(stack);
- addStackReferenceIfNeeded(stack);
- }
-
- private void addStackReferenceIfNeeded(ActivityStack stack) {
- final int activityType = stack.getActivityType();
- final int windowingMode = stack.getWindowingMode();
-
- if (activityType == ACTIVITY_TYPE_HOME) {
- if (mHomeStack != null && mHomeStack != stack) {
- throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
- + mHomeStack + " already exist on display=" + this + " stack=" + stack);
- }
- mHomeStack = stack;
- } else if (activityType == ACTIVITY_TYPE_RECENTS) {
- if (mRecentsStack != null && mRecentsStack != stack) {
- throw new IllegalArgumentException("addStackReferenceIfNeeded: recents stack="
- + mRecentsStack + " already exist on display=" + this + " stack=" + stack);
- }
- mRecentsStack = stack;
- }
- if (windowingMode == WINDOWING_MODE_PINNED) {
- if (mPinnedStack != null && mPinnedStack != stack) {
- throw new IllegalArgumentException("addStackReferenceIfNeeded: pinned stack="
- + mPinnedStack + " already exist on display=" + this
- + " stack=" + stack);
- }
- mPinnedStack = stack;
- } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
- if (mSplitScreenPrimaryStack != null && mSplitScreenPrimaryStack != stack) {
- throw new IllegalArgumentException("addStackReferenceIfNeeded:"
- + " split-screen-primary" + " stack=" + mSplitScreenPrimaryStack
- + " already exist on display=" + this + " stack=" + stack);
- }
- mSplitScreenPrimaryStack = stack;
- }
- }
-
- private void removeStackReferenceIfNeeded(ActivityStack stack) {
- if (stack == mHomeStack) {
- mHomeStack = null;
- } else if (stack == mRecentsStack) {
- mRecentsStack = null;
- } else if (stack == mPinnedStack) {
- mPinnedStack = null;
- } else if (stack == mSplitScreenPrimaryStack) {
- mSplitScreenPrimaryStack = null;
- }
- }
-
/** Returns the top visible stack activity type that isn't in the exclude windowing mode. */
int getTopVisibleStackActivityType(int excludeWindowingMode) {
for (int i = mStacks.size() - 1; i >= 0; --i) {
@@ -382,42 +326,20 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
return ACTIVITY_TYPE_UNDEFINED;
}
- /**
- * Get the topmost stack on the display. It may be different from focused stack, because
- * focus may be on another display.
- */
- ActivityStack getTopStack() {
- return mStacks.isEmpty() ? null : mStacks.get(mStacks.size() - 1);
+ ActivityStack getSplitScreenStack() {
+ return getStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
}
- boolean isTopStack(ActivityStack stack) {
- return stack == getTopStack();
- }
-
- int getIndexOf(ActivityStack stack) {
- return mStacks.indexOf(stack);
- }
-
- void onLockTaskPackagesUpdated() {
- for (int i = mStacks.size() - 1; i >= 0; --i) {
- mStacks.get(i).onLockTaskPackagesUpdated();
- }
- }
-
- ActivityStack getSplitScreenPrimaryStack() {
- return mSplitScreenPrimaryStack;
- }
-
- boolean hasSplitScreenPrimaryStack() {
- return mSplitScreenPrimaryStack != null;
+ boolean hasSplitScreenStack() {
+ return getSplitScreenStack() != null;
}
PinnedActivityStack getPinnedStack() {
- return (PinnedActivityStack) mPinnedStack;
+ return getStack(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
}
boolean hasPinnedStack() {
- return mPinnedStack != null;
+ return getPinnedStack() != null;
}
@Override
@@ -431,7 +353,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
}
@Override
- protected ActivityStack getChildAt(int index) {
+ protected ConfigurationContainer getChildAt(int index) {
return mStacks.get(index);
}
@@ -479,10 +401,6 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
mSleeping = asleep;
}
- public void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + "displayId=" + mDisplayId + " mStacks=" + mStacks);
- }
-
public void writeToProto(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
super.writeToProto(proto, CONFIGURATION_CONTAINER);
diff --git a/com/android/server/am/ActivityManagerDebugConfig.java b/com/android/server/am/ActivityManagerDebugConfig.java
index ceb2ad62..3a9bf125 100644
--- a/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/com/android/server/am/ActivityManagerDebugConfig.java
@@ -59,6 +59,7 @@ class ActivityManagerDebugConfig {
static final boolean DEBUG_FOCUS = false;
static final boolean DEBUG_IDLE = DEBUG_ALL_ACTIVITIES || false;
static final boolean DEBUG_IMMERSIVE = DEBUG_ALL || false;
+ static final boolean DEBUG_LOCKSCREEN = DEBUG_ALL || false;
static final boolean DEBUG_LOCKTASK = DEBUG_ALL || false;
static final boolean DEBUG_LRU = DEBUG_ALL || false;
static final boolean DEBUG_MU = DEBUG_ALL || false;
@@ -73,10 +74,10 @@ class ActivityManagerDebugConfig {
static final boolean DEBUG_PROVIDER = DEBUG_ALL || false;
static final boolean DEBUG_PSS = DEBUG_ALL || false;
static final boolean DEBUG_RECENTS = DEBUG_ALL || false;
- static final boolean DEBUG_RECENTS_TRIM_TASKS = DEBUG_RECENTS || false;
static final boolean DEBUG_RELEASE = DEBUG_ALL_ACTIVITIES || false;
static final boolean DEBUG_RESULTS = DEBUG_ALL || false;
static final boolean DEBUG_SAVED_STATE = DEBUG_ALL_ACTIVITIES || false;
+ static final boolean DEBUG_SCREENSHOTS = DEBUG_ALL_ACTIVITIES || false;
static final boolean DEBUG_SERVICE = DEBUG_ALL || false;
static final boolean DEBUG_FOREGROUND_SERVICE = DEBUG_ALL || false;
static final boolean DEBUG_SERVICE_EXECUTING = DEBUG_ALL || false;
@@ -84,6 +85,7 @@ class ActivityManagerDebugConfig {
static final boolean DEBUG_STATES = DEBUG_ALL_ACTIVITIES || false;
static final boolean DEBUG_SWITCH = DEBUG_ALL || false;
static final boolean DEBUG_TASKS = DEBUG_ALL || false;
+ static final boolean DEBUG_THUMBNAILS = DEBUG_ALL || false;
static final boolean DEBUG_TRANSITION = DEBUG_ALL || false;
static final boolean DEBUG_UID_OBSERVERS = DEBUG_ALL || false;
static final boolean DEBUG_URI_PERMISSION = DEBUG_ALL || false;
@@ -103,6 +105,7 @@ class ActivityManagerDebugConfig {
static final String POSTFIX_FOCUS = (APPEND_CATEGORY_NAME) ? "_Focus" : "";
static final String POSTFIX_IDLE = (APPEND_CATEGORY_NAME) ? "_Idle" : "";
static final String POSTFIX_IMMERSIVE = (APPEND_CATEGORY_NAME) ? "_Immersive" : "";
+ static final String POSTFIX_LOCKSCREEN = (APPEND_CATEGORY_NAME) ? "_LockScreen" : "";
static final String POSTFIX_LOCKTASK = (APPEND_CATEGORY_NAME) ? "_LockTask" : "";
static final String POSTFIX_LRU = (APPEND_CATEGORY_NAME) ? "_LRU" : "";
static final String POSTFIX_MU = "_MU";
@@ -119,6 +122,7 @@ class ActivityManagerDebugConfig {
static final String POSTFIX_RELEASE = (APPEND_CATEGORY_NAME) ? "_Release" : "";
static final String POSTFIX_RESULTS = (APPEND_CATEGORY_NAME) ? "_Results" : "";
static final String POSTFIX_SAVED_STATE = (APPEND_CATEGORY_NAME) ? "_SavedState" : "";
+ static final String POSTFIX_SCREENSHOTS = (APPEND_CATEGORY_NAME) ? "_Screenshots" : "";
static final String POSTFIX_SERVICE = (APPEND_CATEGORY_NAME) ? "_Service" : "";
static final String POSTFIX_SERVICE_EXECUTING =
(APPEND_CATEGORY_NAME) ? "_ServiceExecuting" : "";
@@ -126,11 +130,13 @@ class ActivityManagerDebugConfig {
static final String POSTFIX_STATES = (APPEND_CATEGORY_NAME) ? "_States" : "";
static final String POSTFIX_SWITCH = (APPEND_CATEGORY_NAME) ? "_Switch" : "";
static final String POSTFIX_TASKS = (APPEND_CATEGORY_NAME) ? "_Tasks" : "";
+ static final String POSTFIX_THUMBNAILS = (APPEND_CATEGORY_NAME) ? "_Thumbnails" : "";
static final String POSTFIX_TRANSITION = (APPEND_CATEGORY_NAME) ? "_Transition" : "";
static final String POSTFIX_UID_OBSERVERS = (APPEND_CATEGORY_NAME)
? "_UidObservers" : "";
static final String POSTFIX_URI_PERMISSION = (APPEND_CATEGORY_NAME) ? "_UriPermission" : "";
static final String POSTFIX_USER_LEAVING = (APPEND_CATEGORY_NAME) ? "_UserLeaving" : "";
static final String POSTFIX_VISIBILITY = (APPEND_CATEGORY_NAME) ? "_Visibility" : "";
+ static final String POSTFIX_VISIBLE_BEHIND = (APPEND_CATEGORY_NAME) ? "_VisibleBehind" : "";
}
diff --git a/com/android/server/am/ActivityManagerService.java b/com/android/server/am/ActivityManagerService.java
index f17c9ac3..e6fe6204 100644
--- a/com/android/server/am/ActivityManagerService.java
+++ b/com/android/server/am/ActivityManagerService.java
@@ -27,10 +27,18 @@ import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManager.RESIZE_MODE_PRESERVE_WINDOW;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.ActivityManager.StackId.getWindowingModeForStackId;
+import static android.app.ActivityManager.StackId.isStaticStack;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
@@ -49,9 +57,6 @@ import static android.content.res.Configuration.UI_MODE_TYPE_TELEVISION;
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
import static android.os.Build.VERSION_CODES.N;
-import static android.os.IServiceManager.DUMP_PRIORITY_CRITICAL;
-import static android.os.IServiceManager.DUMP_PRIORITY_HIGH;
-import static android.os.IServiceManager.DUMP_PRIORITY_NORMAL;
import static android.os.Process.BLUETOOTH_UID;
import static android.os.Process.FIRST_APPLICATION_UID;
import static android.os.Process.FIRST_ISOLATED_UID;
@@ -132,6 +137,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESSES;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESS_OBSERVERS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROVIDER;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PSS;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SERVICE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
@@ -176,6 +182,7 @@ import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
+import static com.android.server.am.proto.ActivityManagerServiceProto.ACTIVITIES;
import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_OPEN;
import static com.android.server.wm.AppTransition.TRANSIT_NONE;
import static com.android.server.wm.AppTransition.TRANSIT_TASK_IN_PLACE;
@@ -192,6 +199,7 @@ import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
+import android.app.ActivityManager.StackId;
import android.app.ActivityManager.StackInfo;
import android.app.ActivityManager.TaskSnapshot;
import android.app.ActivityManagerInternal;
@@ -208,6 +216,7 @@ import android.app.ContentProviderHolder;
import android.app.Dialog;
import android.app.IActivityController;
import android.app.IActivityManager;
+import android.app.IAppTask;
import android.app.IApplicationThread;
import android.app.IInstrumentationWatcher;
import android.app.INotificationManager;
@@ -395,9 +404,6 @@ import com.android.server.SystemServiceManager;
import com.android.server.ThreadPriorityBooster;
import com.android.server.Watchdog;
import com.android.server.am.ActivityStack.ActivityState;
-import com.android.server.am.proto.ActivityManagerServiceProto;
-import com.android.server.am.proto.BroadcastProto;
-import com.android.server.am.proto.StickyBroadcastProto;
import com.android.server.firewall.IntentFirewall;
import com.android.server.job.JobSchedulerInternal;
import com.android.server.pm.Installer;
@@ -733,6 +739,9 @@ public class ActivityManagerService extends IActivityManager.Stub
doDump(fd, pw, new String[] {"associations"});
}
doDump(fd, pw, new String[] {"processes"});
+ doDump(fd, pw, new String[] {"-v", "all"});
+ doDump(fd, pw, new String[] {"service", "all"});
+ doDump(fd, pw, new String[] {"provider", "all"});
}
@Override
@@ -744,8 +753,6 @@ public class ActivityManagerService extends IActivityManager.Stub
public boolean canShowErrorDialogs() {
return mShowDialogs && !mSleeping && !mShuttingDown
&& !mKeyguardController.isKeyguardShowing(DEFAULT_DISPLAY)
- && !mUserController.hasUserRestriction(UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS,
- mUserController.getCurrentUserId())
&& !(UserManager.isDeviceInDemoMode(mContext)
&& mUserController.getCurrentUser().isDemo());
}
@@ -1710,6 +1717,7 @@ public class ActivityManagerService extends IActivityManager.Stub
static final int PUSH_TEMP_WHITELIST_UI_MSG = 68;
static final int SERVICE_FOREGROUND_CRASH_MSG = 69;
static final int DISPATCH_OOM_ADJ_OBSERVER_MSG = 70;
+ static final int TOP_APP_KILLED_BY_LMK_MSG = 73;
static final int NOTIFY_VR_KEYGUARD_MSG = 74;
static final int FIRST_ACTIVITY_STACK_MSG = 100;
@@ -1730,6 +1738,9 @@ public class ActivityManagerService extends IActivityManager.Stub
*/
private boolean mUserIsMonkey;
+ /** Flag whether the device has a Recents UI */
+ boolean mHasRecents;
+
/** The dimensions of the thumbnails in the Recents UI. */
int mThumbnailWidth;
int mThumbnailHeight;
@@ -1935,6 +1946,17 @@ public class ActivityManagerService extends IActivityManager.Stub
dispatchProcessDied(pid, uid);
break;
}
+ case TOP_APP_KILLED_BY_LMK_MSG: {
+ final String appName = (String) msg.obj;
+ final AlertDialog d = new BaseErrorDialog(mUiContext);
+ d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
+ d.setTitle(mUiContext.getText(R.string.top_app_killed_title));
+ d.setMessage(mUiContext.getString(R.string.top_app_killed_message, appName));
+ d.setButton(DialogInterface.BUTTON_POSITIVE, mUiContext.getText(R.string.close),
+ obtainMessage(DISMISS_DIALOG_UI_MSG, d));
+ d.show();
+ break;
+ }
case DISPATCH_UIDS_CHANGED_UI_MSG: {
dispatchUidsChanged();
} break;
@@ -2089,8 +2111,7 @@ public class ActivityManagerService extends IActivityManager.Stub
String text = mContext.getString(R.string.heavy_weight_notification,
context.getApplicationInfo().loadLabel(context.getPackageManager()));
Notification notification =
- new Notification.Builder(context,
- SystemNotificationChannels.HEAVY_WEIGHT_APP)
+ new Notification.Builder(context, SystemNotificationChannels.DEVELOPER)
.setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
.setWhen(0)
.setOngoing(true)
@@ -2124,7 +2145,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
try {
inm.cancelNotificationWithTag("android", null,
- SystemMessage.NOTE_HEAVY_WEIGHT_NOTIFICATION, msg.arg1);
+ SystemMessage.NOTE_HEAVY_WEIGHT_NOTIFICATION, msg.arg1);
} catch (RuntimeException e) {
Slog.w(ActivityManagerService.TAG,
"Error canceling notification for service", e);
@@ -2482,16 +2503,13 @@ public class ActivityManagerService extends IActivityManager.Stub
public void setSystemProcess() {
try {
- ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,
- DUMP_PRIORITY_CRITICAL | DUMP_PRIORITY_NORMAL);
+ ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
- ServiceManager.addService("meminfo", new MemBinder(this), /* allowIsolated= */ false,
- DUMP_PRIORITY_HIGH | DUMP_PRIORITY_NORMAL);
+ ServiceManager.addService("meminfo", new MemBinder(this));
ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
ServiceManager.addService("dbinfo", new DbBinder(this));
if (MONITOR_CPU_USAGE) {
- ServiceManager.addService("cpuinfo", new CpuBinder(this),
- /* allowIsolated= */ false, DUMP_PRIORITY_CRITICAL);
+ ServiceManager.addService("cpuinfo", new CpuBinder(this));
}
ServiceManager.addService("permission", new PermissionController(this));
ServiceManager.addService("processinfo", new ProcessInfoService(this));
@@ -2522,6 +2540,7 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (this) {
mWindowManager = wm;
mStackSupervisor.setWindowManager(wm);
+ mActivityStarter.setWindowManager(wm);
mLockTaskController.setWindowManager(wm);
}
}
@@ -2763,9 +2782,8 @@ public class ActivityManagerService extends IActivityManager.Stub
mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
mTaskChangeNotificationController =
new TaskChangeNotificationController(this, mStackSupervisor, mHandler);
- mActivityStarter = new ActivityStarter(this);
+ mActivityStarter = new ActivityStarter(this, mStackSupervisor);
mRecentTasks = new RecentTasks(this, mStackSupervisor);
- mStackSupervisor.setRecentTasks(mRecentTasks);
mLockTaskController = new LockTaskController(mContext, mStackSupervisor, mHandler);
mProcessCpuThread = new Thread("CpuTracker") {
@@ -3223,12 +3241,11 @@ public class ActivityManagerService extends IActivityManager.Stub
// stack implementation changes in the future, keep in mind that the use of the fullscreen
// stack is a means to move the activity to the main display and a moveActivityToDisplay()
// option would be a better choice here.
- if (r.requestedVrComponent != null && r.getDisplayId() != DEFAULT_DISPLAY) {
+ if (r.requestedVrComponent != null && r.getStackId() >= FIRST_DYNAMIC_STACK_ID) {
Slog.i(TAG, "Moving " + r.shortComponentName + " from stack " + r.getStackId()
+ " to main stack for VR");
- final ActivityStack stack = mStackSupervisor.getDefaultDisplay().getOrCreateStack(
- WINDOWING_MODE_FULLSCREEN, r.getActivityType(), true /* toTop */);
- moveTaskToStack(r.getTask().taskId, stack.mStackId, true /* toTop */);
+ setTaskWindowingMode(r.getTask().taskId,
+ WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY, true /* toTop */);
}
mHandler.sendMessage(
mHandler.obtainMessage(VR_MODE_CHANGE_MSG, 0, 0, r));
@@ -5078,12 +5095,11 @@ public class ActivityManagerService extends IActivityManager.Stub
}
synchronized(this) {
- final ProcessRecord proc = mHeavyWeightProcess;
- if (proc == null) {
+ if (mHeavyWeightProcess == null) {
return;
}
- ArrayList<ActivityRecord> activities = new ArrayList<>(proc.activities);
+ ArrayList<ActivityRecord> activities = new ArrayList<>(mHeavyWeightProcess.activities);
for (int i = 0; i < activities.size(); i++) {
ActivityRecord r = activities.get(i);
if (!r.finishing && r.isInStackLocked()) {
@@ -5093,7 +5109,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
- proc.userId, 0));
+ mHeavyWeightProcess.userId, 0));
mHeavyWeightProcess = null;
}
}
@@ -5412,6 +5428,7 @@ public class ActivityManagerService extends IActivityManager.Stub
boolean doLowMem = app.instr == null;
boolean doOomAdj = doLowMem;
if (!app.killedByAm) {
+ maybeNotifyTopAppKilled(app);
Slog.i(TAG, "Process " + app.processName + " (pid " + pid + ") has died: "
+ ProcessList.makeOomAdjString(app.setAdj)
+ ProcessList.makeProcStateString(app.setProcState));
@@ -5445,6 +5462,23 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
+ /** Show system error dialog when a top app is killed by LMK */
+ void maybeNotifyTopAppKilled(ProcessRecord app) {
+ if (!shouldNotifyTopAppKilled(app)) {
+ return;
+ }
+
+ Message msg = mHandler.obtainMessage(TOP_APP_KILLED_BY_LMK_MSG);
+ msg.obj = mContext.getPackageManager().getApplicationLabel(app.info);
+ mUiHandler.sendMessage(msg);
+ }
+
+ /** Only show notification when the top app is killed on low ram devices */
+ private boolean shouldNotifyTopAppKilled(ProcessRecord app) {
+ return app.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP &&
+ ActivityManager.isLowRamDeviceStatic();
+ }
+
/**
* If a stack trace dump file is configured, dump process stack traces.
* @param clearTraces causes the dump file to be erased prior to the new
@@ -5929,7 +5963,16 @@ public class ActivityManagerService extends IActivityManager.Stub
if (appInfo != null) {
forceStopPackageLocked(packageName, appInfo.uid, "clear data");
- mRecentTasks.removeTasksByPackageName(packageName, resolvedUserId);
+ // Remove all tasks match the cleared application package and user
+ for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
+ final TaskRecord tr = mRecentTasks.get(i);
+ final String taskPackageName =
+ tr.getBaseIntent().getComponent().getPackageName();
+ if (tr.userId != resolvedUserId) continue;
+ if (!taskPackageName.equals(packageName)) continue;
+ mStackSupervisor.removeTaskByIdLocked(tr.taskId, false,
+ REMOVE_FROM_RECENTS);
+ }
}
}
@@ -6510,7 +6553,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
// Clean-up disabled tasks
- mRecentTasks.cleanupDisabledPackageTasksLocked(packageName, disabledClasses, userId);
+ cleanupDisabledPackageTasksLocked(packageName, disabledClasses, userId);
// Clean-up disabled services.
mServices.bringDownDisabledPackageServicesLocked(
@@ -8041,8 +8084,8 @@ public class ActivityManagerService extends IActivityManager.Stub
}
private boolean isInPictureInPictureMode(ActivityRecord r) {
- if (r == null || r.getStack() == null || !r.inPinnedWindowingMode()
- || r.getStack().isInStackLocked(r) == null) {
+ if (r == null || r.getStack() == null || !r.getStack().isPinnedStack() ||
+ r.getStack().isInStackLocked(r) == null) {
return false;
}
@@ -8136,7 +8179,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// Only update the saved args from the args that are set
r.pictureInPictureArgs.copyOnlySet(params);
- if (r.inPinnedWindowingMode()) {
+ if (r.getStack().getStackId() == PINNED_STACK_ID) {
// If the activity is already in picture-in-picture, update the pinned stack now
// if it is not already expanding to fullscreen. Otherwise, the arguments will
// be used the next time the activity enters PiP
@@ -9757,12 +9800,35 @@ public class ActivityManagerService extends IActivityManager.Stub
public List<IBinder> getAppTasks(String callingPackage) {
int callingUid = Binder.getCallingUid();
long ident = Binder.clearCallingIdentity();
- try {
- synchronized(this) {
- return mRecentTasks.getAppTasksList(callingUid, callingPackage);
+
+ synchronized(this) {
+ ArrayList<IBinder> list = new ArrayList<IBinder>();
+ try {
+ if (DEBUG_ALL) Slog.v(TAG, "getAppTasks");
+
+ final int N = mRecentTasks.size();
+ for (int i = 0; i < N; i++) {
+ TaskRecord tr = mRecentTasks.get(i);
+ // Skip tasks that do not match the caller. We don't need to verify
+ // callingPackage, because we are also limiting to callingUid and know
+ // that will limit to the correct security sandbox.
+ if (tr.effectiveUid != callingUid) {
+ continue;
+ }
+ Intent intent = tr.getBaseIntent();
+ if (intent == null ||
+ !callingPackage.equals(intent.getComponent().getPackageName())) {
+ continue;
+ }
+ ActivityManager.RecentTaskInfo taskInfo =
+ createRecentTaskInfoFromTaskRecord(tr);
+ AppTaskImpl taskImpl = new AppTaskImpl(taskInfo.persistentId, callingUid);
+ list.add(taskImpl.asBinder());
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
- } finally {
- Binder.restoreCallingIdentity(ident);
+ return list;
}
}
@@ -9785,6 +9851,58 @@ public class ActivityManagerService extends IActivityManager.Stub
return list;
}
+ /**
+ * Creates a new RecentTaskInfo from a TaskRecord.
+ */
+ private ActivityManager.RecentTaskInfo createRecentTaskInfoFromTaskRecord(TaskRecord tr) {
+ // Update the task description to reflect any changes in the task stack
+ tr.updateTaskDescription();
+
+ // Compose the recent task info
+ ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
+ rti.id = tr.getTopActivity() == null ? INVALID_TASK_ID : tr.taskId;
+ rti.persistentId = tr.taskId;
+ rti.baseIntent = new Intent(tr.getBaseIntent());
+ rti.origActivity = tr.origActivity;
+ rti.realActivity = tr.realActivity;
+ rti.description = tr.lastDescription;
+ rti.stackId = tr.getStackId();
+ rti.userId = tr.userId;
+ rti.taskDescription = new ActivityManager.TaskDescription(tr.lastTaskDescription);
+ rti.firstActiveTime = tr.firstActiveTime;
+ rti.lastActiveTime = tr.lastActiveTime;
+ rti.affiliatedTaskId = tr.mAffiliatedTaskId;
+ rti.affiliatedTaskColor = tr.mAffiliatedTaskColor;
+ rti.numActivities = 0;
+ if (tr.mBounds != null) {
+ rti.bounds = new Rect(tr.mBounds);
+ }
+ rti.supportsSplitScreenMultiWindow = tr.supportsSplitScreenWindowingMode();
+ rti.resizeMode = tr.mResizeMode;
+ rti.configuration.setTo(tr.getConfiguration());
+
+ ActivityRecord base = null;
+ ActivityRecord top = null;
+ ActivityRecord tmp;
+
+ for (int i = tr.mActivities.size() - 1; i >= 0; --i) {
+ tmp = tr.mActivities.get(i);
+ if (tmp.finishing) {
+ continue;
+ }
+ base = tmp;
+ if (top == null || (top.state == ActivityState.INITIALIZING)) {
+ top = base;
+ }
+ rti.numActivities++;
+ }
+
+ rti.baseActivity = (base != null) ? base.intent.getComponent() : null;
+ rti.topActivity = (top != null) ? top.intent.getComponent() : null;
+
+ return rti;
+ }
+
private boolean isGetTasksAllowed(String caller, int callingPid, int callingUid) {
boolean allowed = checkPermission(android.Manifest.permission.REAL_GET_TASKS,
callingPid, callingUid) == PackageManager.PERMISSION_GRANTED;
@@ -9818,15 +9936,118 @@ public class ActivityManagerService extends IActivityManager.Stub
final int callingUid = Binder.getCallingUid();
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid, userId,
false, ALLOW_FULL_ONLY, "getRecentTasks", null);
- final boolean allowed = isGetTasksAllowed("getRecentTasks", Binder.getCallingPid(),
- callingUid);
- final boolean detailed = checkCallingPermission(
- android.Manifest.permission.GET_DETAILED_TASKS)
- == PackageManager.PERMISSION_GRANTED;
+ final boolean includeProfiles = (flags & ActivityManager.RECENT_INCLUDE_PROFILES) != 0;
+ final boolean withExcluded = (flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0;
synchronized (this) {
- return mRecentTasks.getRecentTasks(maxNum, flags, allowed, detailed, userId,
+ final boolean allowed = isGetTasksAllowed("getRecentTasks", Binder.getCallingPid(),
callingUid);
+ final boolean detailed = checkCallingPermission(
+ android.Manifest.permission.GET_DETAILED_TASKS)
+ == PackageManager.PERMISSION_GRANTED;
+
+ if (!isUserRunning(userId, ActivityManager.FLAG_AND_UNLOCKED)) {
+ Slog.i(TAG, "user " + userId + " is still locked. Cannot load recents");
+ return ParceledListSlice.emptyList();
+ }
+ mRecentTasks.loadUserRecentsLocked(userId);
+
+ final int recentsCount = mRecentTasks.size();
+ ArrayList<ActivityManager.RecentTaskInfo> res =
+ new ArrayList<>(maxNum < recentsCount ? maxNum : recentsCount);
+
+ final Set<Integer> includedUsers;
+ if (includeProfiles) {
+ includedUsers = mUserController.getProfileIds(userId);
+ } else {
+ includedUsers = new HashSet<>();
+ }
+ includedUsers.add(Integer.valueOf(userId));
+
+ for (int i = 0; i < recentsCount && maxNum > 0; i++) {
+ TaskRecord tr = mRecentTasks.get(i);
+ // Only add calling user or related users recent tasks
+ if (!includedUsers.contains(Integer.valueOf(tr.userId))) {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, not user: " + tr);
+ continue;
+ }
+
+ if (tr.realActivitySuspended) {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, activity suspended: " + tr);
+ continue;
+ }
+
+ // Return the entry if desired by the caller. We always return
+ // the first entry, because callers always expect this to be the
+ // foreground app. We may filter others if the caller has
+ // not supplied RECENT_WITH_EXCLUDED and there is some reason
+ // we should exclude the entry.
+
+ if (i == 0
+ || withExcluded
+ || (tr.intent == null)
+ || ((tr.intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
+ == 0)) {
+ if (!allowed) {
+ // If the caller doesn't have the GET_TASKS permission, then only
+ // allow them to see a small subset of tasks -- their own and home.
+ if (!tr.isActivityTypeHome() && tr.effectiveUid != callingUid) {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, not allowed: " + tr);
+ continue;
+ }
+ }
+ final ActivityStack stack = tr.getStack();
+ if ((flags & ActivityManager.RECENT_IGNORE_HOME_AND_RECENTS_STACK_TASKS) != 0) {
+ if (stack != null && stack.isHomeOrRecentsStack()) {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
+ "Skipping, home or recents stack task: " + tr);
+ continue;
+ }
+ }
+ if ((flags & ActivityManager.RECENT_INGORE_DOCKED_STACK_TOP_TASK) != 0) {
+ if (stack != null && stack.isDockedStack() && stack.topTask() == tr) {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
+ "Skipping, top task in docked stack: " + tr);
+ continue;
+ }
+ }
+ if ((flags & ActivityManager.RECENT_INGORE_PINNED_STACK_TASKS) != 0) {
+ if (stack != null && stack.isPinnedStack()) {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
+ "Skipping, pinned stack task: " + tr);
+ continue;
+ }
+ }
+ if (tr.autoRemoveRecents && tr.getTopActivity() == null) {
+ // Don't include auto remove tasks that are finished or finishing.
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
+ "Skipping, auto-remove without activity: " + tr);
+ continue;
+ }
+ if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0
+ && !tr.isAvailable) {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
+ "Skipping, unavail real act: " + tr);
+ continue;
+ }
+
+ if (!tr.mUserSetupComplete) {
+ // Don't include task launched while user is not done setting-up.
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
+ "Skipping, user setup not complete: " + tr);
+ continue;
+ }
+
+ ActivityManager.RecentTaskInfo rti = createRecentTaskInfoFromTaskRecord(tr);
+ if (!detailed) {
+ rti.baseIntent.replaceExtras((Bundle)null);
+ }
+
+ res.add(rti);
+ maxNum--;
+ }
+ }
+ return new ParceledListSlice<>(res);
}
}
@@ -9898,10 +10119,23 @@ public class ActivityManagerService extends IActivityManager.Stub
TaskRecord task = new TaskRecord(this,
mStackSupervisor.getNextTaskIdForUserLocked(r.userId),
ainfo, intent, description);
- if (!mRecentTasks.addToBottom(task)) {
+
+ int trimIdx = mRecentTasks.trimForTaskLocked(task, false);
+ if (trimIdx >= 0) {
+ // If this would have caused a trim, then we'll abort because that
+ // means it would be added at the end of the list but then just removed.
return INVALID_TASK_ID;
}
- r.getStack().addTask(task, !ON_TOP, "addAppTask");
+
+ final int N = mRecentTasks.size();
+ if (N >= (ActivityManager.getMaxRecentTasksStatic()-1)) {
+ final TaskRecord tr = mRecentTasks.remove(N - 1);
+ tr.removedFromRecents();
+ }
+
+ task.inRecents = true;
+ mRecentTasks.add(task);
+ r.getStack().addTask(task, false, "addAppTask");
// TODO: Send the thumbnail to WM to store it.
@@ -10117,6 +10351,38 @@ public class ActivityManagerService extends IActivityManager.Stub
mWindowManager.executeAppTransition();
}
+ private void removeTasksByPackageNameLocked(String packageName, int userId) {
+ // Remove all tasks with activities in the specified package from the list of recent tasks
+ for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
+ TaskRecord tr = mRecentTasks.get(i);
+ if (tr.userId != userId) continue;
+
+ ComponentName cn = tr.intent.getComponent();
+ if (cn != null && cn.getPackageName().equals(packageName)) {
+ // If the package name matches, remove the task.
+ mStackSupervisor.removeTaskByIdLocked(tr.taskId, true, REMOVE_FROM_RECENTS);
+ }
+ }
+ }
+
+ private void cleanupDisabledPackageTasksLocked(String packageName, Set<String> filterByClasses,
+ int userId) {
+
+ for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
+ TaskRecord tr = mRecentTasks.get(i);
+ if (userId != UserHandle.USER_ALL && tr.userId != userId) {
+ continue;
+ }
+
+ ComponentName cn = tr.intent.getComponent();
+ final boolean sameComponent = cn != null && cn.getPackageName().equals(packageName)
+ && (filterByClasses == null || filterByClasses.contains(cn.getClassName()));
+ if (sameComponent) {
+ mStackSupervisor.removeTaskByIdLocked(tr.taskId, false, REMOVE_FROM_RECENTS);
+ }
+ }
+ }
+
@Override
public void removeStack(int stackId) {
enforceCallingPermission(Manifest.permission.MANAGE_ACTIVITY_STACKS, "removeStack()");
@@ -10124,14 +10390,11 @@ public class ActivityManagerService extends IActivityManager.Stub
final long ident = Binder.clearCallingIdentity();
try {
final ActivityStack stack = mStackSupervisor.getStack(stackId);
- if (stack == null) {
- return;
- }
- if (!stack.isActivityTypeStandardOrUndefined()) {
+ if (stack != null && !stack.isActivityTypeStandardOrUndefined()) {
throw new IllegalArgumentException(
"Removing non-standard stack is not allowed.");
}
- mStackSupervisor.removeStack(stack);
+ mStackSupervisor.removeStackLocked(stackId);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -10346,7 +10609,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
final ActivityStack stack = r.getStack();
- if (stack == null || !stack.inFreeformWindowingMode()) {
+ if (stack == null || stack.mStackId != FREEFORM_WORKSPACE_STACK_ID) {
throw new IllegalStateException(
"exitFreeformMode: You can only go fullscreen from freeform.");
}
@@ -10414,20 +10677,27 @@ public class ActivityManagerService extends IActivityManager.Stub
if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToStack: moving task=" + taskId
+ " to stackId=" + stackId + " toTop=" + toTop);
+ if (stackId == DOCKED_STACK_ID) {
+ mWindowManager.setDockedStackCreateState(DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT,
+ null /* initialBounds */);
+ }
- final ActivityStack stack = mStackSupervisor.getStack(stackId);
+ ActivityStack stack = mStackSupervisor.getStack(stackId);
if (stack == null) {
- throw new IllegalStateException(
- "moveTaskToStack: No stack for stackId=" + stackId);
+ if (!isStaticStack(stackId)) {
+ throw new IllegalStateException(
+ "moveTaskToStack: No stack for stackId=" + stackId);
+ }
+ final ActivityDisplay display = task.getStack().getDisplay();
+ final int windowingMode =
+ getWindowingModeForStackId(stackId, display.hasSplitScreenStack());
+ stack = display.getOrCreateStack(windowingMode,
+ task.getStack().getActivityType(), toTop);
}
if (!stack.isActivityTypeStandardOrUndefined()) {
throw new IllegalArgumentException("moveTaskToStack: Attempt to move task "
+ taskId + " to stack " + stackId);
}
- if (stack.inSplitScreenPrimaryWindowingMode()) {
- mWindowManager.setDockedStackCreateState(
- DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, null /* initialBounds */);
- }
task.reparent(stack, toTop, REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, !DEFER_RESUME,
"moveTaskToStack");
} finally {
@@ -10497,9 +10767,9 @@ public class ActivityManagerService extends IActivityManager.Stub
try {
synchronized (this) {
final ActivityStack stack =
- mStackSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack();
+ mStackSupervisor.getDefaultDisplay().getSplitScreenStack();
if (toTop) {
- mStackSupervisor.resizeStackLocked(stack, null /* destBounds */,
+ mStackSupervisor.resizeStackLocked(stack.mStackId, null /* destBounds */,
null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
true /* preserveWindows */, true /* allowResizeInDockedMode */,
!DEFER_RESUME);
@@ -10592,12 +10862,7 @@ public class ActivityManagerService extends IActivityManager.Stub
stack.animateResizePinnedStack(null /* sourceHintBounds */, destBounds,
animationDuration, false /* fromFullscreen */);
} else {
- final ActivityStack stack = mStackSupervisor.getStack(stackId);
- if (stack == null) {
- Slog.w(TAG, "resizeStack: stackId " + stackId + " not found.");
- return;
- }
- mStackSupervisor.resizeStackLocked(stack, destBounds, null /* tempTaskBounds */,
+ mStackSupervisor.resizeStackLocked(stackId, destBounds, null /* tempTaskBounds */,
null /* tempTaskInsetBounds */, preserveWindows,
allowResizeInDockedMode, !DEFER_RESUME);
}
@@ -12673,10 +12938,6 @@ public class ActivityManagerService extends IActivityManager.Stub
throw new IllegalArgumentException("Provided bugreport type is not correct, value: "
+ bugreportType);
}
- // Always log caller, even if it does not have permission to dump.
- String type = extraOptions == null ? "bugreport" : extraOptions;
- Slog.i(TAG, type + " requested by UID " + Binder.getCallingUid());
-
enforceCallingPermission(android.Manifest.permission.DUMP, "requestBugReport");
if (extraOptions != null) {
SystemProperties.set("dumpstate.options", extraOptions);
@@ -13884,6 +14145,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// Load resources only after the current configuration has been set.
final Resources res = mContext.getResources();
+ mHasRecents = res.getBoolean(com.android.internal.R.bool.config_hasRecents);
mThumbnailWidth = res.getDimensionPixelSize(
com.android.internal.R.dimen.thumbnail_width);
mThumbnailHeight = res.getDimensionPixelSize(
@@ -14842,31 +15104,10 @@ public class ActivityManagerService extends IActivityManager.Stub
long origId = Binder.clearCallingIdentity();
if (useProto) {
+ //TODO: Options when dumping proto
final ProtoOutputStream proto = new ProtoOutputStream(fd);
- String cmd = opti < args.length ? args[opti] : "";
- opti++;
-
- if ("activities".equals(cmd) || "a".equals(cmd)) {
- // output proto is ActivityStackSupervisorProto
- synchronized (this) {
- writeActivitiesToProtoLocked(proto);
- }
- } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
- // output proto is BroadcastProto
- synchronized (this) {
- writeBroadcastsToProtoLocked(proto);
- }
- } else {
- // default option, dump everything, output is ActivityManagerServiceProto
- synchronized (this) {
- long activityToken = proto.start(ActivityManagerServiceProto.ACTIVITIES);
- writeActivitiesToProtoLocked(proto);
- proto.end(activityToken);
-
- long broadcastToken = proto.start(ActivityManagerServiceProto.BROADCASTS);
- writeBroadcastsToProtoLocked(proto);
- proto.end(broadcastToken);
- }
+ synchronized (this) {
+ writeActivitiesToProtoLocked(proto);
}
proto.flush();
Binder.restoreCallingIdentity(origId);
@@ -14892,9 +15133,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
} else if ("recents".equals(cmd) || "r".equals(cmd)) {
synchronized (this) {
- if (mRecentTasks != null) {
- mRecentTasks.dump(pw, true /* dumpAll */, dumpPackage);
- }
+ dumpRecentsLocked(fd, pw, args, opti, true, dumpPackage);
}
} else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
String[] newArgs;
@@ -15115,9 +15354,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
- if (mRecentTasks != null) {
- mRecentTasks.dump(pw, dumpAll, dumpPackage);
- }
+ dumpRecentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
pw.println();
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
@@ -15187,9 +15424,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
- if (mRecentTasks != null) {
- mRecentTasks.dump(pw, dumpAll, dumpPackage);
- }
+ dumpRecentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
pw.println();
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
@@ -15223,8 +15458,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
private void writeActivitiesToProtoLocked(ProtoOutputStream proto) {
- // The output proto of "activity --proto activities" is ActivityStackSupervisorProto
- mStackSupervisor.writeToProto(proto);
+ mStackSupervisor.writeToProto(proto, ACTIVITIES);
}
private void dumpLastANRLocked(PrintWriter pw) {
@@ -15276,6 +15510,42 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
+ void dumpRecentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
+ int opti, boolean dumpAll, String dumpPackage) {
+ pw.println("ACTIVITY MANAGER RECENT TASKS (dumpsys activity recents)");
+
+ boolean printedAnything = false;
+
+ if (mRecentTasks != null && mRecentTasks.size() > 0) {
+ boolean printedHeader = false;
+
+ final int N = mRecentTasks.size();
+ for (int i=0; i<N; i++) {
+ TaskRecord tr = mRecentTasks.get(i);
+ if (dumpPackage != null) {
+ if (tr.realActivity == null ||
+ !dumpPackage.equals(tr.realActivity.getPackageName())) {
+ continue;
+ }
+ }
+ if (!printedHeader) {
+ pw.println(" Recent tasks:");
+ printedHeader = true;
+ printedAnything = true;
+ }
+ pw.print(" * Recent #"); pw.print(i); pw.print(": ");
+ pw.println(tr);
+ if (dumpAll) {
+ mRecentTasks.get(i).dump(pw, " ");
+ }
+ }
+ }
+
+ if (!printedAnything) {
+ pw.println(" (nothing)");
+ }
+ }
+
void dumpAssociationsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
pw.println("ACTIVITY MANAGER ASSOCIATIONS (dumpsys activity associations)");
@@ -16102,40 +16372,6 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
- void writeBroadcastsToProtoLocked(ProtoOutputStream proto) {
- if (mRegisteredReceivers.size() > 0) {
- Iterator it = mRegisteredReceivers.values().iterator();
- while (it.hasNext()) {
- ReceiverList r = (ReceiverList)it.next();
- r.writeToProto(proto, BroadcastProto.RECEIVER_LIST);
- }
- }
- mReceiverResolver.writeToProto(proto, BroadcastProto.RECEIVER_RESOLVER);
- for (BroadcastQueue q : mBroadcastQueues) {
- q.writeToProto(proto, BroadcastProto.BROADCAST_QUEUE);
- }
- for (int user=0; user<mStickyBroadcasts.size(); user++) {
- long token = proto.start(BroadcastProto.STICKY_BROADCASTS);
- proto.write(StickyBroadcastProto.USER, mStickyBroadcasts.keyAt(user));
- for (Map.Entry<String, ArrayList<Intent>> ent
- : mStickyBroadcasts.valueAt(user).entrySet()) {
- long actionToken = proto.start(StickyBroadcastProto.ACTIONS);
- proto.write(StickyBroadcastProto.StickyAction.NAME, ent.getKey());
- for (Intent intent : ent.getValue()) {
- intent.writeToProto(proto, StickyBroadcastProto.StickyAction.INTENTS,
- false, true, true, false);
- }
- proto.end(actionToken);
- }
- proto.end(token);
- }
-
- long handlerToken = proto.start(BroadcastProto.HANDLER);
- proto.write(BroadcastProto.MainHandler.HANDLER, mHandler.toString());
- mHandler.getLooper().writeToProto(proto, BroadcastProto.MainHandler.LOOPER);
- proto.end(handlerToken);
- }
-
void dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll, String dumpPackage) {
boolean needSep = false;
@@ -19124,7 +19360,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// Remove all permissions granted from/to this package
removeUriPermissionsForPackageLocked(ssp, userId, true);
- mRecentTasks.removeTasksByPackageName(ssp, userId);
+ removeTasksByPackageNameLocked(ssp, userId);
mServices.forceStopPackageLocked(ssp, userId);
@@ -20461,10 +20697,9 @@ public class ActivityManagerService extends IActivityManager.Stub
/** Helper method that requests bounds from WM and applies them to stack. */
private void resizeStackWithBoundsFromWindowManager(int stackId, boolean deferResume) {
final Rect newStackBounds = new Rect();
- final ActivityStack stack = mStackSupervisor.getStack(stackId);
- stack.getBoundsForNewConfiguration(newStackBounds);
+ mStackSupervisor.getStack(stackId).getBoundsForNewConfiguration(newStackBounds);
mStackSupervisor.resizeStackLocked(
- stack, !newStackBounds.isEmpty() ? newStackBounds : null /* bounds */,
+ stackId, !newStackBounds.isEmpty() ? newStackBounds : null /* bounds */,
null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
false /* preserveWindows */, false /* allowResizeInDockedMode */, deferResume);
}
@@ -24132,6 +24367,125 @@ public class ActivityManagerService extends IActivityManager.Stub
}
/**
+ * An implementation of IAppTask, that allows an app to manage its own tasks via
+ * {@link android.app.ActivityManager.AppTask}. We keep track of the callingUid to ensure that
+ * only the process that calls getAppTasks() can call the AppTask methods.
+ */
+ class AppTaskImpl extends IAppTask.Stub {
+ private int mTaskId;
+ private int mCallingUid;
+
+ public AppTaskImpl(int taskId, int callingUid) {
+ mTaskId = taskId;
+ mCallingUid = callingUid;
+ }
+
+ private void checkCaller() {
+ if (mCallingUid != Binder.getCallingUid()) {
+ throw new SecurityException("Caller " + mCallingUid
+ + " does not match caller of getAppTasks(): " + Binder.getCallingUid());
+ }
+ }
+
+ @Override
+ public void finishAndRemoveTask() {
+ checkCaller();
+
+ synchronized (ActivityManagerService.this) {
+ long origId = Binder.clearCallingIdentity();
+ try {
+ // We remove the task from recents to preserve backwards
+ if (!mStackSupervisor.removeTaskByIdLocked(mTaskId, false,
+ REMOVE_FROM_RECENTS)) {
+ throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+ }
+
+ @Override
+ public ActivityManager.RecentTaskInfo getTaskInfo() {
+ checkCaller();
+
+ synchronized (ActivityManagerService.this) {
+ long origId = Binder.clearCallingIdentity();
+ try {
+ TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(mTaskId);
+ if (tr == null) {
+ throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
+ }
+ return createRecentTaskInfoFromTaskRecord(tr);
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+ }
+
+ @Override
+ public void moveToFront() {
+ checkCaller();
+ // Will bring task to front if it already has a root activity.
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized (this) {
+ mStackSupervisor.startActivityFromRecentsInner(mTaskId, null);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
+ @Override
+ public int startActivity(IBinder whoThread, String callingPackage,
+ Intent intent, String resolvedType, Bundle bOptions) {
+ checkCaller();
+
+ int callingUser = UserHandle.getCallingUserId();
+ TaskRecord tr;
+ IApplicationThread appThread;
+ synchronized (ActivityManagerService.this) {
+ tr = mStackSupervisor.anyTaskForIdLocked(mTaskId);
+ if (tr == null) {
+ throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
+ }
+ appThread = IApplicationThread.Stub.asInterface(whoThread);
+ if (appThread == null) {
+ throw new IllegalArgumentException("Bad app thread " + appThread);
+ }
+ }
+ return mActivityStarter.startActivityMayWait(appThread, -1, callingPackage, intent,
+ resolvedType, null, null, null, null, 0, 0, null, null,
+ null, bOptions, false, callingUser, tr, "AppTaskImpl");
+ }
+
+ @Override
+ public void setExcludeFromRecents(boolean exclude) {
+ checkCaller();
+
+ synchronized (ActivityManagerService.this) {
+ long origId = Binder.clearCallingIdentity();
+ try {
+ TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(mTaskId);
+ if (tr == null) {
+ throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
+ }
+ Intent intent = tr.getBaseIntent();
+ if (exclude) {
+ intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ } else {
+ intent.setFlags(intent.getFlags()
+ & ~Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+ }
+ }
+
+ /**
* Kill processes for the user with id userId and that depend on the package named packageName
*/
@Override
diff --git a/com/android/server/am/ActivityManagerShellCommand.java b/com/android/server/am/ActivityManagerShellCommand.java
index f03d2d53..4c934232 100644
--- a/com/android/server/am/ActivityManagerShellCommand.java
+++ b/com/android/server/am/ActivityManagerShellCommand.java
@@ -73,8 +73,10 @@ import java.util.List;
import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
import static android.app.ActivityManager.RESIZE_MODE_USER;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.INVALID_DISPLAY;
@@ -84,6 +86,15 @@ final class ActivityManagerShellCommand extends ShellCommand {
public static final String NO_CLASS_ERROR_CODE = "Error type 3";
private static final String SHELL_PACKAGE_NAME = "com.android.shell";
+ // Is the object moving in a positive direction?
+ private static final boolean MOVING_FORWARD = true;
+ // Is the object moving in the horizontal plan?
+ private static final boolean MOVING_HORIZONTALLY = true;
+ // Is the object current point great then its target point?
+ private static final boolean GREATER_THAN_TARGET = true;
+ // Amount we reduce the stack size by when testing a task re-size.
+ private static final int STACK_BOUNDS_INSET = 10;
+
// IPC interface to activity manager -- don't need to do additional security checks.
final IActivityManager mInterface;
@@ -1933,6 +1944,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
return runStackInfo(pw);
case "move-top-activity-to-pinned-stack":
return runMoveTopActivityToPinnedStack(pw);
+ case "size-docked-stack-test":
+ return runStackSizeDockedStackTest(pw);
case "remove":
return runStackRemove(pw);
default:
@@ -2130,6 +2143,89 @@ final class ActivityManagerShellCommand extends ShellCommand {
return 0;
}
+ int runStackSizeDockedStackTest(PrintWriter pw) throws RemoteException {
+ final PrintWriter err = getErrPrintWriter();
+ final int stepSize = Integer.parseInt(getNextArgRequired());
+ final String side = getNextArgRequired();
+ final String delayStr = getNextArg();
+ final int delayMs = (delayStr != null) ? Integer.parseInt(delayStr) : 0;
+
+ ActivityManager.StackInfo info = mInterface.getStackInfo(
+ WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
+ if (info == null) {
+ err.println("Docked stack doesn't exist");
+ return -1;
+ }
+ if (info.bounds == null) {
+ err.println("Docked stack doesn't have a bounds");
+ return -1;
+ }
+ Rect bounds = info.bounds;
+
+ final boolean horizontalGrowth = "l".equals(side) || "r".equals(side);
+ final int changeSize = (horizontalGrowth ? bounds.width() : bounds.height()) / 2;
+ int currentPoint;
+ switch (side) {
+ case "l":
+ currentPoint = bounds.left;
+ break;
+ case "r":
+ currentPoint = bounds.right;
+ break;
+ case "t":
+ currentPoint = bounds.top;
+ break;
+ case "b":
+ currentPoint = bounds.bottom;
+ break;
+ default:
+ err.println("Unknown growth side: " + side);
+ return -1;
+ }
+
+ final int startPoint = currentPoint;
+ final int minPoint = currentPoint - changeSize;
+ final int maxPoint = currentPoint + changeSize;
+
+ int maxChange;
+ pw.println("Shrinking docked stack side=" + side);
+ pw.flush();
+ while (currentPoint > minPoint) {
+ maxChange = Math.min(stepSize, currentPoint - minPoint);
+ currentPoint -= maxChange;
+ setBoundsSide(bounds, side, currentPoint);
+ int res = resizeStack(DOCKED_STACK_ID, bounds, delayMs);
+ if (res < 0) {
+ return res;
+ }
+ }
+
+ pw.println("Growing docked stack side=" + side);
+ pw.flush();
+ while (currentPoint < maxPoint) {
+ maxChange = Math.min(stepSize, maxPoint - currentPoint);
+ currentPoint += maxChange;
+ setBoundsSide(bounds, side, currentPoint);
+ int res = resizeStack(DOCKED_STACK_ID, bounds, delayMs);
+ if (res < 0) {
+ return res;
+ }
+ }
+
+ pw.println("Back to Original size side=" + side);
+ pw.flush();
+ while (currentPoint > startPoint) {
+ maxChange = Math.min(stepSize, currentPoint - startPoint);
+ currentPoint -= maxChange;
+ setBoundsSide(bounds, side, currentPoint);
+ int res = resizeStack(DOCKED_STACK_ID, bounds, delayMs);
+ if (res < 0) {
+ return res;
+ }
+ }
+ return 0;
+ }
+
void setBoundsSide(Rect bounds, String side, int value) {
switch (side) {
case "l":
@@ -2591,6 +2687,10 @@ final class ActivityManagerShellCommand extends ShellCommand {
pw.println(" Change docked stack to <LEFT,TOP,RIGHT,BOTTOM>");
pw.println(" and supplying temporary different task bounds indicated by");
pw.println(" <TASK_LEFT,TOP,RIGHT,BOTTOM>");
+ pw.println(" size-docked-stack-test: <STEP_SIZE> <l|t|r|b> [DELAY_MS]");
+ pw.println(" Test command for sizing docked stack by");
+ pw.println(" <STEP_SIZE> increments from the side <l>eft, <t>op, <r>ight, or <b>ottom");
+ pw.println(" applying the optional [DELAY_MS] between each step.");
pw.println(" move-top-activity-to-pinned-stack: <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>");
pw.println(" Moves the top activity from");
pw.println(" <STACK_ID> to the pinned stack using <LEFT,TOP,RIGHT,BOTTOM> for the");
diff --git a/com/android/server/am/ActivityMetricsLogger.java b/com/android/server/am/ActivityMetricsLogger.java
index 93c0f772..fdcb8c69 100644
--- a/com/android/server/am/ActivityMetricsLogger.java
+++ b/com/android/server/am/ActivityMetricsLogger.java
@@ -5,7 +5,6 @@ import static android.app.ActivityManager.START_TASK_TO_FRONT;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManagerInternal.APP_TRANSITION_TIMEOUT;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
@@ -128,7 +127,7 @@ class ActivityMetricsLogger {
case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
mWindowState = WINDOW_STATE_SIDE_BY_SIDE;
break;
- case WINDOWING_MODE_FREEFORM:
+ case WINDOW_STATE_FREEFORM:
mWindowState = WINDOW_STATE_FREEFORM;
break;
default:
diff --git a/com/android/server/am/ActivityRecord.java b/com/android/server/am/ActivityRecord.java
index 2c72a4db..7b0b942a 100644
--- a/com/android/server/am/ActivityRecord.java
+++ b/com/android/server/am/ActivityRecord.java
@@ -17,7 +17,9 @@
package com.android.server.am;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.TaskDescription.ATTR_TASKDESCRIPTION_PREFIX;
import static android.app.ActivityOptions.ANIM_CLIP_REVEAL;
import static android.app.ActivityOptions.ANIM_CUSTOM;
@@ -58,10 +60,6 @@ import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
import static android.content.pm.ActivityInfo.PERSIST_ACROSS_REBOOTS;
import static android.content.pm.ActivityInfo.PERSIST_ROOT_ONLY;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
@@ -286,7 +284,6 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
int configChangeFlags; // which config values have changed
private boolean keysPaused; // has key dispatching been paused for it?
int launchMode; // the launch mode activity attribute.
- int lockTaskLaunchMode; // the lockTaskMode manifest attribute, subject to override
boolean visible; // does this activity's window need to be shown?
boolean visibleIgnoringKeyguard; // is this activity visible, ignoring the fact that Keyguard
// might hide this activity?
@@ -423,13 +420,9 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
if (iconFilename != null || taskDescription.getLabel() != null ||
taskDescription.getPrimaryColor() != 0) {
pw.print(prefix); pw.print("taskDescription:");
+ pw.print(" iconFilename="); pw.print(taskDescription.getIconFilename());
pw.print(" label=\""); pw.print(taskDescription.getLabel());
pw.print("\"");
- pw.print(" icon="); pw.print(taskDescription.getInMemoryIcon() != null
- ? taskDescription.getInMemoryIcon().getByteCount() + " bytes"
- : "null");
- pw.print(" iconResource="); pw.print(taskDescription.getIconResource());
- pw.print(" iconFilename="); pw.print(taskDescription.getIconFilename());
pw.print(" primaryColor=");
pw.println(Integer.toHexString(taskDescription.getPrimaryColor()));
pw.print(prefix + " backgroundColor=");
@@ -439,6 +432,9 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
pw.print(prefix + " navigationBarColor=");
pw.println(Integer.toHexString(taskDescription.getNavigationBarColor()));
}
+ if (iconFilename == null && taskDescription.getIcon() != null) {
+ pw.print(prefix); pw.println("taskDescription contains Bitmap");
+ }
}
if (results != null) {
pw.print(prefix); pw.print("results="); pw.println(results);
@@ -665,7 +661,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
return;
}
- final boolean inPictureInPictureMode = inPinnedWindowingMode() && targetStackBounds != null;
+ final boolean inPictureInPictureMode = (task.getStackId() == PINNED_STACK_ID) &&
+ (targetStackBounds != null);
if (inPictureInPictureMode != mLastReportedPictureInPictureMode || forceUpdate) {
// Picture-in-picture mode changes also trigger a multi-window mode change as well, so
// update that here in order
@@ -687,6 +684,10 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
}
}
+ boolean isFreeform() {
+ return task != null && task.getStackId() == FREEFORM_WORKSPACE_STACK_ID;
+ }
+
@Override
protected int getChildCount() {
// {@link ActivityRecord} is a leaf node and has no children.
@@ -830,6 +831,23 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
hasBeenLaunched = false;
mStackSupervisor = supervisor;
+ mRotationAnimationHint = aInfo.rotationAnimation;
+
+ if (options != null) {
+ pendingOptions = options;
+ mLaunchTaskBehind = pendingOptions.getLaunchTaskBehind();
+
+ final int rotationAnimation = pendingOptions.getRotationAnimationHint();
+ // Only override manifest supplied option if set.
+ if (rotationAnimation >= 0) {
+ mRotationAnimationHint = rotationAnimation;
+ }
+ PendingIntent usageReport = pendingOptions.getUsageTimeReport();
+ if (usageReport != null) {
+ appTimeTracker = new AppTimeTracker(usageReport);
+ }
+ }
+
// This starts out true, since the initial state of an activity is that we have everything,
// and we shouldn't never consider it lacking in state to be removed if it dies.
haveState = true;
@@ -896,32 +914,6 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
mShowWhenLocked = (aInfo.flags & FLAG_SHOW_WHEN_LOCKED) != 0;
mTurnScreenOn = (aInfo.flags & FLAG_TURN_SCREEN_ON) != 0;
-
- mRotationAnimationHint = aInfo.rotationAnimation;
- lockTaskLaunchMode = aInfo.lockTaskLaunchMode;
- if (appInfo.isPrivilegedApp() && (lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_ALWAYS
- || lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_NEVER)) {
- lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
- }
-
- if (options != null) {
- pendingOptions = options;
- mLaunchTaskBehind = options.getLaunchTaskBehind();
-
- final int rotationAnimation = pendingOptions.getRotationAnimationHint();
- // Only override manifest supplied option if set.
- if (rotationAnimation >= 0) {
- mRotationAnimationHint = rotationAnimation;
- }
- final PendingIntent usageReport = pendingOptions.getUsageTimeReport();
- if (usageReport != null) {
- appTimeTracker = new AppTimeTracker(usageReport);
- }
- final boolean useLockTask = pendingOptions.getLockTaskMode();
- if (useLockTask && lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_DEFAULT) {
- lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
- }
- }
}
AppWindowContainerController getWindowContainerController() {
@@ -956,7 +948,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
// update the initial multi-window modes so that the callbacks are scheduled correctly when
// the user leaves that mode.
mLastReportedMultiWindowMode = !task.mFullscreen;
- mLastReportedPictureInPictureMode = inPinnedWindowingMode();
+ mLastReportedPictureInPictureMode = (task.getStackId() == PINNED_STACK_ID);
}
void removeWindowContainer() {
@@ -1559,7 +1551,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
// On devices that support leanback only (Android TV), Recents activity can only be
// visible if the home stack is the focused stack or we are in split-screen mode.
final ActivityDisplay display = getDisplay();
- boolean hasSplitScreenStack = display != null && display.hasSplitScreenPrimaryStack();
+ boolean hasSplitScreenStack = display != null && display.hasSplitScreenStack();
isVisible = hasSplitScreenStack || mStackSupervisor.isFocusedStack(getStack());
}
@@ -2747,8 +2739,6 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
void setShowWhenLocked(boolean showWhenLocked) {
mShowWhenLocked = showWhenLocked;
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0 /* configChanges */,
- false /* preserveWindows */);
}
/**
diff --git a/com/android/server/am/ActivityStack.java b/com/android/server/am/ActivityStack.java
index f0811dda..1940ca2b 100644
--- a/com/android/server/am/ActivityStack.java
+++ b/com/android/server/am/ActivityStack.java
@@ -16,25 +16,27 @@
package com.android.server.am;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.app.WindowConfiguration.activityTypeToString;
-import static android.app.WindowConfiguration.windowingModeToString;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
-import static android.view.Display.INVALID_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
import static com.android.server.am.ActivityDisplay.POSITION_BOTTOM;
import static com.android.server.am.ActivityDisplay.POSITION_TOP;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE;
@@ -98,6 +100,7 @@ import static java.lang.Integer.MAX_VALUE;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
+import android.app.ActivityManager.StackId;
import android.app.ActivityOptions;
import android.app.AppGlobals;
import android.app.IActivityController;
@@ -107,7 +110,6 @@ import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
-import android.graphics.Point;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Binder;
@@ -190,6 +192,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// finished destroying itself.
private static final int DESTROY_TIMEOUT = 10 * 1000;
+ // How long until we reset a task when the user returns to it. Currently
+ // disabled.
+ private static final long ACTIVITY_INACTIVE_RESET_TIME = 0;
+
// Set to false to disable the preview that is shown while a new activity
// is being started.
private static final boolean SHOW_APP_STARTING_PREVIEW = true;
@@ -346,11 +352,12 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
private final SparseArray<Rect> mTmpBounds = new SparseArray<>();
private final SparseArray<Rect> mTmpInsetBounds = new SparseArray<>();
private final Rect mTmpRect2 = new Rect();
- private final Point mTmpSize = new Point();
/** Run all ActivityStacks through this */
protected final ActivityStackSupervisor mStackSupervisor;
+ private final LaunchingTaskPositioner mTaskPositioner;
+
private boolean mTopActivityOccludesKeyguard;
private ActivityRecord mTopDismissingKeyguardActivity;
@@ -453,6 +460,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
mWindowManager = mService.mWindowManager;
mStackId = stackId;
mCurrentUser = mService.mUserController.getCurrentUserId();
+ mTaskPositioner = mStackId == FREEFORM_WORKSPACE_STACK_ID
+ ? new LaunchingTaskPositioner() : null;
mTmpRect2.setEmpty();
setWindowingMode(windowingMode);
setActivityType(activityType);
@@ -470,16 +479,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return mWindowContainerController;
}
- @Override
- public void onConfigurationChanged(Configuration newParentConfig) {
- final int prevWindowingMode = getWindowingMode();
- super.onConfigurationChanged(newParentConfig);
- final ActivityDisplay display = getDisplay();
- if (display != null && prevWindowingMode != getWindowingMode()) {
- display.onStackWindowingModeChanged(this);
- }
- }
-
/** Adds the stack to specified display and calls WindowManager to do the same. */
void reparent(ActivityDisplay activityDisplay, boolean onTop) {
removeFromDisplay();
@@ -503,11 +502,14 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
mDisplayId = activityDisplay.mDisplayId;
mBounds = bounds != null ? new Rect(bounds) : null;
mFullscreen = mBounds == null;
-
+ if (mTaskPositioner != null) {
+ mTaskPositioner.setDisplay(activityDisplay.mDisplay);
+ mTaskPositioner.configure(mBounds);
+ }
onParentChanged();
activityDisplay.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM);
- if (inSplitScreenPrimaryWindowingMode()) {
+ if (mStackId == DOCKED_STACK_ID) {
// If we created a docked stack we want to resize it so it resizes all other stacks
// in the system.
mStackSupervisor.resizeDockedStackLocked(
@@ -531,6 +533,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
display.removeChild(this);
}
mDisplayId = INVALID_DISPLAY;
+ if (mTaskPositioner != null) {
+ mTaskPositioner.reset();
+ }
}
/** Removes the stack completely. Also calls WindowManager to do the same on its side. */
@@ -634,6 +639,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
void setBounds(Rect bounds) {
mBounds = mFullscreen ? null : new Rect(bounds);
+ if (mTaskPositioner != null) {
+ mTaskPositioner.configure(bounds);
+ }
}
ActivityRecord topRunningActivityLocked() {
@@ -810,6 +818,14 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return isActivityTypeHome() || isActivityTypeRecents();
}
+ final boolean isDockedStack() {
+ return mStackId == DOCKED_STACK_ID;
+ }
+
+ final boolean isPinnedStack() {
+ return mStackId == PINNED_STACK_ID;
+ }
+
final boolean isOnHomeDisplay() {
return mDisplayId == DEFAULT_DISPLAY;
}
@@ -1489,9 +1505,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
* needed. A stack is considered translucent if it don't contain a visible or
* starting (about to be visible) activity that is fullscreen (opaque).
* @param starting The currently starting activity or null if there is none.
- * @param stackBehind The stack directly behind this one.
+ * @param stackBehindId The id of the stack directly behind this one.
*/
- private boolean isStackTranslucent(ActivityRecord starting, ActivityStack stackBehind) {
+ private boolean isStackTranslucent(ActivityRecord starting, int stackBehindId) {
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
final ArrayList<ActivityRecord> activities = task.mActivities;
@@ -1516,6 +1532,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return false;
}
+ final ActivityStack stackBehind = mStackSupervisor.getStack(stackBehindId);
final boolean stackBehindHomeOrRecent = stackBehind != null
&& stackBehind.isHomeOrRecentsStack();
if (!isHomeOrRecentsStack() && r.frontOfTask && task.isOverHomeStack()
@@ -1536,10 +1553,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
&& !mForceHidden;
}
- boolean isTopStackOnDisplay() {
- return getDisplay().isTopStack(this);
- }
-
/**
* Returns true if the stack should be visible.
*
@@ -1550,15 +1563,23 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return false;
}
- final ActivityDisplay display = getDisplay();
- if (isTopStackOnDisplay() || mStackSupervisor.isFocusedStack(this)) {
+ if (mStackSupervisor.isFrontStackOnDisplay(this) || mStackSupervisor.isFocusedStack(this)) {
return true;
}
- final int stackIndex = display.getIndexOf(this);
+ final ActivityDisplay display = getDisplay();
+ final ArrayList<ActivityStack> displayStacks = display.mStacks;
+ final int stackIndex = displayStacks.indexOf(this);
+
+ if (stackIndex == displayStacks.size() - 1) {
+ Slog.wtf(TAG,
+ "Stack=" + this + " isn't front stack but is at the top of the stack list");
+ return false;
+ }
// Check position and visibility of this stack relative to the front stack on its display.
- final ActivityStack topStack = getDisplay().getTopStack();
+ final ActivityStack topStack = getTopStackOnDisplay();
+ final int topStackId = topStack.mStackId;
final int windowingMode = getWindowingMode();
final int activityType = getActivityType();
@@ -1566,7 +1587,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// If the assistant stack is focused and translucent, then the docked stack is always
// visible
if (topStack.isActivityTypeAssistant()) {
- return topStack.isStackTranslucent(starting, this);
+ return topStack.isStackTranslucent(starting, DOCKED_STACK_ID);
}
return true;
}
@@ -1575,31 +1596,34 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// A case would be if recents stack exists but has no tasks and is below the docked stack
// and home stack is below recents
if (activityType == ACTIVITY_TYPE_HOME) {
- final ActivityStack splitScreenStack = display.getSplitScreenPrimaryStack();
- int dockedStackIndex = display.getIndexOf(splitScreenStack);
+ final ActivityStack splitScreenStack = display.getStack(
+ WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
+ int dockedStackIndex = displayStacks.indexOf(splitScreenStack);
if (dockedStackIndex > stackIndex && stackIndex != dockedStackIndex - 1) {
return false;
}
}
// Find the first stack behind front stack that actually got something visible.
- int stackBehindTopIndex = display.getIndexOf(topStack) - 1;
+ int stackBehindTopIndex = displayStacks.indexOf(topStack) - 1;
while (stackBehindTopIndex >= 0 &&
- display.getChildAt(stackBehindTopIndex).topRunningActivityLocked() == null) {
+ displayStacks.get(stackBehindTopIndex).topRunningActivityLocked() == null) {
stackBehindTopIndex--;
}
final ActivityStack stackBehindTop = (stackBehindTopIndex >= 0)
- ? display.getChildAt(stackBehindTopIndex) : null;
+ ? displayStacks.get(stackBehindTopIndex) : null;
+ int stackBehindTopId = INVALID_STACK_ID;
int stackBehindTopWindowingMode = WINDOWING_MODE_UNDEFINED;
int stackBehindTopActivityType = ACTIVITY_TYPE_UNDEFINED;
if (stackBehindTop != null) {
+ stackBehindTopId = stackBehindTop.mStackId;
stackBehindTopWindowingMode = stackBehindTop.getWindowingMode();
stackBehindTopActivityType = stackBehindTop.getActivityType();
}
final boolean alwaysOnTop = topStack.getWindowConfiguration().isAlwaysOnTop();
if (topStack.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY || alwaysOnTop) {
- if (this == stackBehindTop) {
+ if (stackIndex == stackBehindTopIndex) {
// Stacks directly behind the docked or pinned stack are always visible.
return true;
} else if (alwaysOnTop && stackIndex == stackBehindTopIndex - 1) {
@@ -1608,13 +1632,14 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
if (stackBehindTopWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
return true;
} else if (stackBehindTopActivityType == ACTIVITY_TYPE_ASSISTANT) {
- return stackBehindTop.isStackTranslucent(starting, this);
+ return displayStacks.get(stackBehindTopIndex).isStackTranslucent(
+ starting, mStackId);
}
}
}
if (topStack.isBackdropToTranslucentActivity()
- && topStack.isStackTranslucent(starting, stackBehindTop)) {
+ && topStack.isStackTranslucent(starting, stackBehindTopId)) {
// Stacks behind the fullscreen or assistant stack with a translucent activity are
// always visible so they can act as a backdrop to the translucent activity.
// For example, dialog activities
@@ -1632,15 +1657,14 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
}
- if (isOnHomeDisplay()) {
- // Visibility of any stack on default display should have been determined by the
- // conditions above.
+ if (StackId.isStaticStack(mStackId)
+ || isHomeOrRecentsStack() || isActivityTypeAssistant()) {
+ // Visibility of any static stack should have been determined by the conditions above.
return false;
}
- final int stackCount = display.getChildCount();
- for (int i = stackIndex + 1; i < stackCount; i++) {
- final ActivityStack stack = display.getChildAt(i);
+ for (int i = stackIndex + 1; i < displayStacks.size(); i++) {
+ final ActivityStack stack = displayStacks.get(i);
if (!stack.mFullscreen && !stack.hasFullscreenTask()) {
continue;
@@ -1651,7 +1675,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return false;
}
- if (!stack.isStackTranslucent(starting, null /* stackBehind */)) {
+ if (!stack.isStackTranslucent(starting, INVALID_STACK_ID)) {
return false;
}
}
@@ -1777,8 +1801,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
makeInvisible(r);
}
}
- final int windowingMode = getWindowingMode();
- if (windowingMode == WINDOWING_MODE_FREEFORM) {
+ if (mStackId == FREEFORM_WORKSPACE_STACK_ID) {
// The visibility of tasks and the activities they contain in freeform stack are
// determined individually unlike other stacks where the visibility or fullscreen
// status of an activity in a previous task affects other.
@@ -1793,8 +1816,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// show activities in the next application stack behind them vs. another
// task in the home stack like recents.
behindFullscreenActivity = true;
- } else if (windowingMode == WINDOWING_MODE_FULLSCREEN
- || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
+ } else if (mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Skipping after task=" + task
+ " returning to non-application type=" + task.getTaskToReturnTo());
// Once we reach a fullscreen stack task that has a running activity and should
@@ -1830,32 +1852,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
/**
- * Returns true if this stack should be resized to match the bounds specified by
- * {@link ActivityOptions#setLaunchBounds} when launching an activity into the stack.
- */
- boolean resizeStackWithLaunchBounds() {
- return inPinnedWindowingMode();
- }
-
- /**
- * Returns true if we try to maintain focus in the current stack when the top activity finishes.
- */
- private boolean keepFocusInStackIfPossible() {
- final int windowingMode = getWindowingMode();
- return windowingMode == WINDOWING_MODE_FREEFORM
- || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
- || windowingMode == WINDOWING_MODE_PINNED;
- }
-
- /**
- * Returns true if the top task in the task is allowed to return home when finished and
- * there are other tasks in the stack.
- */
- boolean allowTopTaskToReturnHome() {
- return !inPinnedWindowingMode();
- }
-
- /**
* @return the top most visible activity that wants to dismiss Keyguard
*/
ActivityRecord getTopDismissingKeyguardActivity() {
@@ -1871,7 +1867,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
*/
boolean checkKeyguardVisibility(ActivityRecord r, boolean shouldBeVisible,
boolean isTop) {
- final boolean isInPinnedStack = r.inPinnedWindowingMode();
+ final boolean isInPinnedStack = r.getStack().getStackId() == PINNED_STACK_ID;
final boolean keyguardShowing = mStackSupervisor.mKeyguardController.isKeyguardShowing(
mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY);
final boolean keyguardLocked = mStackSupervisor.mKeyguardController.isKeyguardLocked();
@@ -2169,7 +2165,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
mResumedActivity = r;
r.state = ActivityState.RESUMED;
mService.setResumedActivityUncheckLocked(r, reason);
- mStackSupervisor.mRecentTasks.add(r.getTask());
+ mStackSupervisor.addRecentActivity(r);
}
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
@@ -2576,8 +2572,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
Slog.i(TAG, "Restarting because process died: " + next);
if (!next.hasBeenLaunched) {
next.hasBeenLaunched = true;
- } else if (SHOW_APP_STARTING_PREVIEW && lastStack != null
- && lastStack.isTopStackOnDisplay()) {
+ } else if (SHOW_APP_STARTING_PREVIEW && lastStack != null &&
+ mStackSupervisor.isFrontStackOnDisplay(lastStack)) {
next.showStartingWindow(null /* prev */, false /* newTask */,
false /* taskSwitch */);
}
@@ -2621,7 +2617,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
private boolean resumeTopActivityInNextFocusableStack(ActivityRecord prev,
ActivityOptions options, String reason) {
- if (adjustFocusToNextFocusableStackLocked(reason)) {
+ if ((!mFullscreen || !isOnHomeDisplay()) && adjustFocusToNextFocusableStackLocked(reason)) {
// Try to move focus to the next visible stack with a running activity if this
// stack is not covering the entire screen or is on a secondary display (with no home
// stack).
@@ -2750,8 +2746,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// make underlying task focused when this one will be finished.
int returnToType = isLastTaskOverHome
? task.getTaskToReturnTo() : ACTIVITY_TYPE_STANDARD;
- if (fromHomeOrRecents && allowTopTaskToReturnHome()) {
- returnToType = topTask == null ? ACTIVITY_TYPE_HOME : topTask.getActivityType();
+ if (fromHomeOrRecents && StackId.allowTopTaskToReturnHome(mStackId)) {
+ returnToType = topTask == null
+ ? ACTIVITY_TYPE_HOME : topTask.getActivityType();
}
task.setTaskToReturnTo(returnToType);
}
@@ -2904,7 +2901,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// Ensure the caller has requested not to trigger auto-enter PiP
return false;
}
- if (pipCandidate == null || pipCandidate.inPinnedWindowingMode()) {
+ if (pipCandidate == null || pipCandidate.getStackId() == PINNED_STACK_ID) {
// Ensure that we do not trigger entering PiP an activity on the pinned stack
return false;
}
@@ -3189,8 +3186,15 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop,
ActivityRecord newActivity) {
- final boolean forceReset =
+ boolean forceReset =
(newActivity.info.flags & ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
+ if (ACTIVITY_INACTIVE_RESET_TIME > 0
+ && taskTop.getTask().getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
+ if ((newActivity.info.flags & ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
+ forceReset = true;
+ }
+ }
+
final TaskRecord task = taskTop.getTask();
/** False until we evaluate the TaskRecord associated with taskTop. Switches to true
@@ -3287,7 +3291,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
final String myReason = reason + " adjustFocus";
if (next != r) {
- if (next != null && keepFocusInStackIfPossible() && isFocusable()) {
+ if (next != null && StackId.keepFocusInStackIfPossible(mStackId) && isFocusable()) {
// For freeform, docked, and pinned stacks we always keep the focus within the
// stack as long as there is a running activity.
return;
@@ -3753,7 +3757,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
if (mode == FINISH_IMMEDIATELY
|| (prevState == ActivityState.PAUSED
- && (mode == FINISH_AFTER_PAUSE || inPinnedWindowingMode()))
+ && (mode == FINISH_AFTER_PAUSE || mStackId == PINNED_STACK_ID))
|| finishingActivityInNonFocusedStack
|| prevState == STOPPING
|| prevState == STOPPED
@@ -4432,7 +4436,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
AppTimeTracker timeTracker, String reason) {
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);
- final ActivityStack topStack = getDisplay().getTopStack();
+ final ActivityStack topStack = getTopStackOnDisplay();
final ActivityRecord topActivity = topStack != null ? topStack.topActivity() : null;
final int numTasks = mTaskHistory.size();
final int index = mTaskHistory.indexOf(tr);
@@ -4460,9 +4464,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// Don't refocus if invisible to current user
final ActivityRecord top = tr.getTopActivity();
if (top == null || !top.okToShowLocked()) {
- if (top != null) {
- mStackSupervisor.mRecentTasks.add(top.getTask());
- }
+ mStackSupervisor.addRecentActivity(top);
ActivityOptions.abort(options);
return;
}
@@ -4522,7 +4524,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// If we have a watcher, preflight the move before committing to it. First check
// for *other* available tasks, but if none are available, then try again allowing the
// current task to be selected.
- if (isTopStackOnDisplay() && mService.mController != null) {
+ if (mStackSupervisor.isFrontStackOnDisplay(this) && mService.mController != null) {
ActivityRecord next = topRunningActivityLocked(null, taskId);
if (next == null) {
next = topRunningActivityLocked(null, 0);
@@ -4569,8 +4571,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
mWindowContainerController.positionChildAtBottom(tr.getWindowContainerController());
}
- if (inPinnedWindowingMode()) {
- mStackSupervisor.removeStack(this);
+ if (mStackId == PINNED_STACK_ID) {
+ mStackSupervisor.removeStackLocked(PINNED_STACK_ID);
return true;
}
@@ -4602,6 +4604,15 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return true;
}
+ /**
+ * Get the topmost stack on the current display. It may be different from focused stack, because
+ * focus may be on another display.
+ */
+ private ActivityStack getTopStackOnDisplay() {
+ final ArrayList<ActivityStack> stacks = getDisplay().mStacks;
+ return stacks.isEmpty() ? null : stacks.get(stacks.size() - 1);
+ }
+
static void logStartActivity(int tag, ActivityRecord r, TaskRecord task) {
final Uri data = r.intent.getData();
final String strData = data != null ? data.toSafeString() : null;
@@ -4676,7 +4687,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
for (int i = mTaskHistory.size() - 1; i >= 0; i--) {
final TaskRecord task = mTaskHistory.get(i);
if (task.isResizeable()) {
- if (inFreeformWindowingMode()) {
+ if (mStackId == FREEFORM_WORKSPACE_STACK_ID) {
// For freeform stack we don't adjust the size of the tasks to match that
// of the stack, but we do try to make sure the tasks are still contained
// with the bounds of the stack.
@@ -4878,7 +4889,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
if (focusedStack && topTask) {
// Give the latest time to ensure foreground task can be sorted
// at the first, because lastActiveTime of creating task is 0.
- ci.lastActiveTime = SystemClock.elapsedRealtime();
+ ci.lastActiveTime = System.currentTimeMillis();
topTask = false;
}
@@ -5058,7 +5069,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
if (task.autoRemoveFromRecents() || isVoiceSession) {
// Task creator asked to remove this when done, or this task was a voice
// interaction, so it should not remain on the recent tasks list.
- mStackSupervisor.mRecentTasks.remove(task);
+ mStackSupervisor.removeTaskFromRecents(task);
}
task.removeWindowContainer();
@@ -5086,7 +5097,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
task.setStack(null);
// Notify if a task from the pinned stack is being removed (or moved depending on the mode)
- if (inPinnedWindowingMode()) {
+ if (mStackId == PINNED_STACK_ID) {
mService.mTaskChangeNotificationController.notifyActivityUnpinned();
}
}
@@ -5109,12 +5120,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
boolean layoutTaskInStack(TaskRecord task, ActivityInfo.WindowLayout windowLayout) {
- if (!task.inFreeformWindowingMode()) {
+ if (mTaskPositioner == null) {
return false;
}
- mStackSupervisor.getLaunchingTaskPositioner()
- .updateDefaultBounds(task, mTaskHistory, windowLayout);
-
+ mTaskPositioner.updateDefaultBounds(task, mTaskHistory, windowLayout);
return true;
}
@@ -5239,12 +5248,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
@Override
public String toString() {
return "ActivityStack{" + Integer.toHexString(System.identityHashCode(this))
- + " stackId=" + mStackId + " type=" + activityTypeToString(getActivityType())
- + " mode=" + windowingModeToString(getWindowingMode()) + ", "
- + mTaskHistory.size() + " tasks}";
+ + " stackId=" + mStackId + ", " + mTaskHistory.size() + " tasks}";
}
- void onLockTaskPackagesUpdated() {
+ void onLockTaskPackagesUpdatedLocked() {
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
mTaskHistory.get(taskNdx).setLockTaskAuth();
}
diff --git a/com/android/server/am/ActivityStackSupervisor.java b/com/android/server/am/ActivityStackSupervisor.java
index 5c91e3cc..da2827a6 100644
--- a/com/android/server/am/ActivityStackSupervisor.java
+++ b/com/android/server/am/ActivityStackSupervisor.java
@@ -21,7 +21,11 @@ import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.Manifest.permission.START_ANY_ACTIVITY;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
@@ -31,13 +35,10 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.app.WindowConfiguration.activityTypeToString;
-import static android.app.WindowConfiguration.windowingModeToString;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
@@ -46,7 +47,6 @@ import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.Display.TYPE_VIRTUAL;
-
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_PICTURE_IN_PICTURE_EXPANDED_TO_FULLSCREEN;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
@@ -86,13 +86,12 @@ import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
-import static com.android.server.am.proto.ActivityStackSupervisorProto.CONFIGURATION_CONTAINER;
import static com.android.server.am.proto.ActivityStackSupervisorProto.DISPLAYS;
import static com.android.server.am.proto.ActivityStackSupervisorProto.FOCUSED_STACK_ID;
import static com.android.server.am.proto.ActivityStackSupervisorProto.KEYGUARD_CONTROLLER;
import static com.android.server.am.proto.ActivityStackSupervisorProto.RESUMED_ACTIVITY;
+import static com.android.server.am.proto.ActivityStackSupervisorProto.CONFIGURATION_CONTAINER;
import static com.android.server.wm.AppTransition.TRANSIT_DOCK_TASK_FROM_RECENTS;
-
import static java.lang.Integer.MAX_VALUE;
import android.Manifest;
@@ -103,6 +102,7 @@ import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
+import android.app.ActivityManager.StackId;
import android.app.ActivityManager.StackInfo;
import android.app.ActivityManagerInternal.SleepToken;
import android.app.ActivityOptions;
@@ -176,8 +176,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Set;
-public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener,
- RecentTasks.Callbacks {
+public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStackSupervisor" : TAG_AM;
private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
private static final String TAG_IDLE = TAG + POSTFIX_IDLE;
@@ -287,7 +286,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
final ActivityManagerService mService;
- RecentTasks mRecentTasks;
+ private RecentTasks mRecentTasks;
final ActivityStackSupervisorHandler mHandler;
@@ -295,10 +294,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
WindowManagerService mWindowManager;
DisplayManager mDisplayManager;
- LaunchingTaskPositioner mTaskPositioner = new LaunchingTaskPositioner();
-
/** Counter for next free stack ID to use for dynamic activity stacks. */
- private int mNextFreeStackId = 0;
+ private int mNextFreeStackId = FIRST_DYNAMIC_STACK_ID;
/**
* Maps the task identifier that activities are currently being started in to the userId of the
@@ -579,7 +576,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void setRecentTasks(RecentTasks recentTasks) {
mRecentTasks = recentTasks;
- mRecentTasks.registerCallback(this);
}
/**
@@ -631,6 +627,15 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return stack != null && stack == mFocusedStack;
}
+ /** The top most stack on its display. */
+ boolean isFrontStackOnDisplay(ActivityStack stack) {
+ return isFrontOfStackList(stack, stack.getDisplay().mStacks);
+ }
+
+ private boolean isFrontOfStackList(ActivityStack stack, List<ActivityStack> stackList) {
+ return stack == stackList.get((stackList.size() - 1));
+ }
+
/** NOTE: Should only be called from {@link ActivityStack#moveToFront} */
void setFocusStackUnchecked(String reason, ActivityStack focusCandidate) {
if (!focusCandidate.isFocusable()) {
@@ -726,9 +731,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ ActivityStack stack = stacks.get(stackNdx);
final TaskRecord task = stack.taskForIdLocked(id);
if (task != null) {
return task;
@@ -744,7 +749,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// Otherwise, check the recent tasks and return if we find it there and we are not restoring
// the task from recents
if (DEBUG_RECENTS) Slog.v(TAG_RECENTS, "Looking for task id=" + id + " in recents");
- final TaskRecord task = mRecentTasks.getTask(id);
+ final TaskRecord task = mRecentTasks.taskForIdLocked(id);
if (task == null) {
if (DEBUG_RECENTS) {
@@ -771,10 +776,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
ActivityRecord isInAnyStackLocked(IBinder token) {
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- final ActivityRecord r = stack.isInStackLocked(token);
+ 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;
}
@@ -812,21 +816,18 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void lockAllProfileTasks(@UserIdInt int userId) {
mWindowManager.deferSurfaceLayout();
try {
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- final List<TaskRecord> tasks = stack.getAllTasks();
- for (int taskNdx = tasks.size() - 1; taskNdx >= 0; taskNdx--) {
- final TaskRecord task = tasks.get(taskNdx);
-
- // Check the task for a top activity belonging to userId, or returning a
- // result to an activity belonging to userId. Example case: a document
- // picker for personal files, opened by a work app, should still get locked.
- if (taskTopActivityIsUser(task, userId)) {
- mService.mTaskChangeNotificationController.notifyTaskProfileLocked(
- task.taskId, userId);
- }
+ final List<ActivityStack> stacks = getStacks();
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; stackNdx--) {
+ final List<TaskRecord> tasks = stacks.get(stackNdx).getAllTasks();
+ for (int taskNdx = tasks.size() - 1; taskNdx >= 0; taskNdx--) {
+ final TaskRecord task = tasks.get(taskNdx);
+
+ // Check the task for a top activity belonging to userId, or returning a result
+ // to an activity belonging to userId. Example case: a document picker for
+ // personal files, opened by a work app, should still get locked.
+ if (taskTopActivityIsUser(task, userId)) {
+ mService.mTaskChangeNotificationController.notifyTaskProfileLocked(
+ task.taskId, userId);
}
}
}
@@ -857,7 +858,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// [u*MAX_TASK_IDS_PER_USER, (u+1)*MAX_TASK_IDS_PER_USER-1], so if MAX_TASK_IDS_PER_USER
// was 10, user 0 could only have taskIds 0 to 9, user 1: 10 to 19, user 2: 20 to 29, so on.
int candidateTaskId = nextTaskIdForUser(currentTaskId, userId);
- while (mRecentTasks.containsTaskId(candidateTaskId, userId)
+ while (mRecentTasks.taskIdTakenForUserLocked(candidateTaskId, userId)
|| anyTaskForIdLocked(
candidateTaskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) != null) {
candidateTaskId = nextTaskIdForUser(candidateTaskId, userId);
@@ -892,9 +893,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
final String processName = app.processName;
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
if (!isFocusedStack(stack)) {
continue;
}
@@ -927,9 +928,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
boolean allResumedActivitiesIdle() {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
if (!isFocusedStack(stack) || stack.numActivities() == 0) {
continue;
}
@@ -948,9 +949,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
boolean allResumedActivitiesComplete() {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
if (isFocusedStack(stack)) {
final ActivityRecord r = stack.mResumedActivity;
if (r != null && r.state != RESUMED) {
@@ -967,12 +968,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return true;
}
- private boolean allResumedActivitiesVisible() {
+ boolean allResumedActivitiesVisible() {
boolean foundResumed = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ 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 || mActivitiesWaitingForVisibleActivity.contains(r)) {
@@ -996,9 +997,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) {
boolean someActivityPaused = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
if (!isFocusedStack(stack) && stack.mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
" mResumedActivity=" + stack.mResumedActivity);
@@ -1013,9 +1014,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
boolean allPausedActivitiesComplete() {
boolean pausing = true;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ 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.mPausingActivity;
if (r != null && r.state != PAUSED && r.state != STOPPED && r.state != STOPPING) {
if (DEBUG_STATES) {
@@ -1033,10 +1034,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void cancelInitializingActivities() {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- stack.cancelInitializingActivities();
+ ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ stacks.get(stackNdx).cancelInitializingActivities();
}
}
}
@@ -1134,10 +1134,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
for (int i = mTmpOrderedDisplayIds.size() - 1; i >= 0; --i) {
final int displayId = mTmpOrderedDisplayIds.get(i);
- final ActivityDisplay display = mActivityDisplays.get(displayId);
- for (int j = display.getChildCount() - 1; j >= 0; --j) {
- final ActivityStack stack = display.getChildAt(j);
- if (stack != focusedStack && stack.isTopStackOnDisplay() && stack.isFocusable()) {
+ final List<ActivityStack> stacks = mActivityDisplays.get(displayId).mStacks;
+ if (stacks == null) {
+ continue;
+ }
+ for (int j = stacks.size() - 1; j >= 0; --j) {
+ final ActivityStack stack = stacks.get(j);
+ if (stack != focusedStack && isFrontStackOnDisplay(stack) && stack.isFocusable()) {
r = stack.topRunningActivityLocked();
if (r != null) {
return r;
@@ -1153,9 +1156,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
ArrayList<ArrayList<RunningTaskInfo>> runningTaskLists = new ArrayList<>();
final int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ 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<>();
runningTaskLists.add(stackTaskList);
stack.getTasksLocked(stackTaskList, callingUid, allowed);
@@ -1604,16 +1607,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
- // Check if someone tries to launch an unwhitelisted activity into LockTask mode.
- final boolean lockTaskMode = options.getLockTaskMode();
- if (lockTaskMode && !mService.mLockTaskController.isPackageWhitelisted(
- UserHandle.getUserId(callingUid), aInfo.packageName)) {
- final String msg = "Permission Denial: starting " + intent.toString()
- + " from " + callerApp + " (pid=" + callingPid
- + ", uid=" + callingUid + ") with lockTaskMode=true";
- Slog.w(TAG, msg);
- throw new SecurityException(msg);
- }
}
return true;
@@ -1935,10 +1928,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
boolean handleAppDiedLocked(ProcessRecord app) {
boolean hasVisibleActivities = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- hasVisibleActivities |= stack.handleAppDiedLocked(app);
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ hasVisibleActivities |= stacks.get(stackNdx).handleAppDiedLocked(app);
}
}
return hasVisibleActivities;
@@ -1946,10 +1938,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void closeSystemDialogsLocked() {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- stack.closeSystemDialogsLocked();
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ stacks.get(stackNdx).closeSystemDialogsLocked();
}
}
}
@@ -1975,9 +1966,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
boolean doit, boolean evenPersistent, int userId) {
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ 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.finishDisabledPackageActivitiesLocked(
packageName, filterByClasses, doit, evenPersistent, userId)) {
didSomething = true;
@@ -1997,9 +1988,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// hosted by the process that is actually still the foreground.
ProcessRecord fgApp = null;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
if (isFocusedStack(stack)) {
if (stack.mResumedActivity != null) {
fgApp = stack.mResumedActivity.app;
@@ -2049,10 +2040,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void updateActivityApplicationInfoLocked(ApplicationInfo aInfo) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- stack.updateActivityApplicationInfoLocked(aInfo);
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ stacks.get(stackNdx).updateActivityApplicationInfoLocked(aInfo);
}
}
}
@@ -2061,10 +2051,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
TaskRecord finishedTask = null;
ActivityStack focusedStack = getFocusedStack();
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- final int numStacks = display.getChildCount();
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ final int numStacks = stacks.size();
for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ final ActivityStack stack = stacks.get(stackNdx);
TaskRecord t = stack.finishTopRunningActivityLocked(app, reason);
if (stack == focusedStack || finishedTask == null) {
finishedTask = t;
@@ -2076,10 +2066,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void finishVoiceTask(IVoiceInteractionSession session) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- final int numStacks = display.getChildCount();
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ final int numStacks = stacks.size();
for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ final ActivityStack stack = stacks.get(stackNdx);
stack.finishVoiceTask(session);
}
}
@@ -2115,8 +2105,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// moveTaskToStackUncheckedLocked() should already placed the task on top,
// still need moveTaskToFrontLocked() below for any transition settings.
}
- if (stack.resizeStackWithLaunchBounds()) {
- resizeStackLocked(stack, bounds, null /* tempTaskBounds */,
+ if (StackId.resizeStackWithLaunchBounds(stack.mStackId)) {
+ resizeStackLocked(stack.mStackId, bounds, null /* tempTaskBounds */,
null /* tempTaskInsetBounds */, !PRESERVE_WINDOWS,
true /* allowResizeInDockedMode */, !DEFER_RESUME);
} else {
@@ -2135,7 +2125,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
"findTaskToMoveToFront: moved to front of stack=" + currentStack);
handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY,
- currentStack, forceNonResizeable);
+ currentStack.mStackId, forceNonResizeable);
}
boolean canUseActivityOptionsLaunchBounds(ActivityOptions options) {
@@ -2149,10 +2139,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
|| mService.mSupportsFreeformWindowManagement;
}
- LaunchingTaskPositioner getLaunchingTaskPositioner() {
- return mTaskPositioner;
- }
-
protected <T extends ActivityStack> T getStack(int stackId) {
for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
final T stack = mActivityDisplays.valueAt(i).getStack(stackId);
@@ -2330,8 +2316,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
final ActivityDisplay display = getActivityDisplayOrCreateLocked(displayId);
if (display != null) {
- for (int i = display.getChildCount() - 1; i >= 0; --i) {
- stack = (T) display.getChildAt(i);
+ for (int i = display.mStacks.size() - 1; i >= 0; --i) {
+ stack = (T) display.mStacks.get(i);
if (stack.isCompatible(windowingMode, activityType)) {
return stack;
}
@@ -2399,8 +2385,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
// Return the topmost valid stack on the display.
- for (int i = activityDisplay.getChildCount() - 1; i >= 0; --i) {
- final ActivityStack stack = activityDisplay.getChildAt(i);
+ for (int i = activityDisplay.mStacks.size() - 1; i >= 0; --i) {
+ final ActivityStack stack = activityDisplay.mStacks.get(i);
if (isValidLaunchStack(stack, displayId, r)) {
return stack;
}
@@ -2431,13 +2417,25 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY: return r.supportsSplitScreenWindowingMode();
}
- if (!stack.isOnHomeDisplay()) {
+ if (StackId.isDynamicStack(stack.mStackId)) {
return r.canBeLaunchedOnDisplay(displayId);
}
Slog.e(TAG, "isValidLaunchStack: Unexpected stack=" + stack);
return false;
}
+ ArrayList<ActivityStack> getStacks() {
+ ArrayList<ActivityStack> allStacks = new ArrayList<>();
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ allStacks.addAll(mActivityDisplays.valueAt(displayNdx).mStacks);
+ }
+ return allStacks;
+ }
+
+ ArrayList<ActivityStack> getStacksOnDefaultDisplay() {
+ return mActivityDisplays.valueAt(DEFAULT_DISPLAY).mStacks;
+ }
+
/**
* Get next focusable stack in the system. This will search across displays and stacks
* in last-focused order for a focusable and visible stack, different from the target stack.
@@ -2452,9 +2450,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
for (int i = mTmpOrderedDisplayIds.size() - 1; i >= 0; --i) {
final int displayId = mTmpOrderedDisplayIds.get(i);
// If a display is registered in WM, it must also be available in AM.
- final ActivityDisplay display = getActivityDisplayOrCreateLocked(displayId);
- for (int j = display.getChildCount() - 1; j >= 0; --j) {
- final ActivityStack stack = display.getChildAt(j);
+ @SuppressWarnings("ConstantConditions")
+ final List<ActivityStack> stacks = getActivityDisplayOrCreateLocked(displayId).mStacks;
+ for (int j = stacks.size() - 1; j >= 0; --j) {
+ final ActivityStack stack = stacks.get(j);
if (stack != currentFocus && stack.isFocusable()
&& stack.shouldBeVisible(null)) {
return stack;
@@ -2512,17 +2511,20 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return null;
}
- void resizeStackLocked(ActivityStack stack, Rect bounds, Rect tempTaskBounds,
- Rect tempTaskInsetBounds, boolean preserveWindows, boolean allowResizeInDockedMode,
- boolean deferResume) {
-
- if (stack.inSplitScreenPrimaryWindowingMode()) {
+ void resizeStackLocked(int stackId, Rect bounds, Rect tempTaskBounds, Rect tempTaskInsetBounds,
+ boolean preserveWindows, boolean allowResizeInDockedMode, boolean deferResume) {
+ if (stackId == DOCKED_STACK_ID) {
resizeDockedStackLocked(bounds, tempTaskBounds, tempTaskInsetBounds, null, null,
preserveWindows, deferResume);
return;
}
+ final ActivityStack stack = getStack(stackId);
+ if (stack == null) {
+ Slog.w(TAG, "resizeStack: stackId " + stackId + " not found.");
+ return;
+ }
- final boolean splitScreenActive = getDefaultDisplay().hasSplitScreenPrimaryStack();
+ final boolean splitScreenActive = getDefaultDisplay().hasSplitScreenStack();
if (!allowResizeInDockedMode
&& !stack.getWindowConfiguration().tasksAreFloating() && splitScreenActive) {
// If the docked stack exists, don't resize non-floating stacks independently of the
@@ -2530,7 +2532,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return;
}
- Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeStack_" + stack.mStackId);
+ Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeStack_" + stackId);
mWindowManager.deferSurfaceLayout();
try {
if (stack.supportsSplitScreenWindowingMode()) {
@@ -2582,7 +2584,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
/**
* TODO: This should just change the windowing mode and resize vs. actually moving task around.
- * Can do that once we are no longer using static stack ids.
+ * Can do that once we are no longer using static stack ids. Specially when
+ * {@link ActivityManager.StackId#FULLSCREEN_WORKSPACE_STACK_ID} is removed.
*/
private void moveTasksToFullscreenStackInSurfaceTransaction(ActivityStack fromStack,
int toDisplayId, boolean onTop) {
@@ -2597,12 +2600,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// We are moving all tasks from the docked stack to the fullscreen stack,
// which is dismissing the docked stack, so resize all other stacks to
// fullscreen here already so we don't end up with resize trashing.
- for (int i = toDisplay.getChildCount() - 1; i >= 0; --i) {
- final ActivityStack otherStack = toDisplay.getChildAt(i);
+ final ArrayList<ActivityStack> displayStacks = toDisplay.mStacks;
+ for (int i = displayStacks.size() - 1; i >= 0; --i) {
+ final ActivityStack otherStack = displayStacks.get(i);
if (!otherStack.inSplitScreenSecondaryWindowingMode()) {
continue;
}
- resizeStackLocked(otherStack, null, null, null, PRESERVE_WINDOWS,
+ resizeStackLocked(otherStack.mStackId, null, null, null, PRESERVE_WINDOWS,
true /* allowResizeInDockedMode */, DEFER_RESUME);
}
@@ -2693,7 +2697,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return;
}
- final ActivityStack stack = getDefaultDisplay().getSplitScreenPrimaryStack();
+ final ActivityStack stack = getDefaultDisplay().getStack(
+ WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
if (stack == null) {
Slog.w(TAG, "resizeDockedStackLocked: docked stack not found");
return;
@@ -2722,10 +2727,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// static stacks need to be adjusted so they don't overlap with the docked stack.
// We get the bounds to use from window manager which has been adjusted for any
// screen controls and is also the same for all stacks.
- final ActivityDisplay display = getDefaultDisplay();
+ final ArrayList<ActivityStack> stacks = getStacksOnDefaultDisplay();
final Rect otherTaskRect = new Rect();
- for (int i = display.getChildCount() - 1; i >= 0; --i) {
- final ActivityStack current = display.getChildAt(i);
+ for (int i = stacks.size() - 1; i >= 0; --i) {
+ final ActivityStack current = stacks.get(i);
if (current.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
continue;
}
@@ -2739,7 +2744,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
tempRect /* outStackBounds */,
otherTaskRect /* outTempTaskBounds */, true /* ignoreVisibility */);
- resizeStackLocked(current, !tempRect.isEmpty() ? tempRect : null,
+ resizeStackLocked(current.mStackId, !tempRect.isEmpty() ? tempRect : null,
!otherTaskRect.isEmpty() ? otherTaskRect : tempOtherTaskBounds,
tempOtherTaskInsetBounds, preserveWindows,
true /* allowResizeInDockedMode */, deferResume);
@@ -2757,7 +2762,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void resizePinnedStackLocked(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
// TODO(multi-display): Pinned stack display should be passed in.
- final PinnedActivityStack stack = getDefaultDisplay().getPinnedStack();
+ final PinnedActivityStack stack = getDefaultDisplay().getStack(
+ WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
if (stack == null) {
Slog.w(TAG, "resizePinnedStackLocked: pinned stack not found");
return;
@@ -2795,7 +2801,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
}
- private void removeStackInSurfaceTransaction(ActivityStack stack) {
+ private void removeStackInSurfaceTransaction(int stackId) {
+ final ActivityStack stack = getStack(stackId);
+ if (stack == null) {
+ return;
+ }
+
final ArrayList<TaskRecord> tasks = stack.getAllTasks();
if (stack.getWindowingMode() == WINDOWING_MODE_PINNED) {
/**
@@ -2825,12 +2836,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
/**
- * Removes the stack associated with the given {@param stack}. If the {@param stack} is the
+ * Removes the stack associated with the given {@param stackId}. If the {@param stackId} is the
* pinned stack, then its tasks are not explicitly removed when the stack is destroyed, but
* instead moved back onto the fullscreen stack.
*/
- void removeStack(ActivityStack stack) {
- mWindowManager.inSurfaceTransaction(() -> removeStackInSurfaceTransaction(stack));
+ void removeStackLocked(int stackId) {
+ mWindowManager.inSurfaceTransaction(() -> removeStackInSurfaceTransaction(stackId));
}
/**
@@ -2881,9 +2892,23 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return false;
}
+ void addRecentActivity(ActivityRecord r) {
+ if (r == null) {
+ return;
+ }
+ final TaskRecord task = r.getTask();
+ mRecentTasks.addLocked(task);
+ task.touchActiveTime();
+ }
+
+ void removeTaskFromRecents(TaskRecord task) {
+ mRecentTasks.remove(task);
+ task.removedFromRecents();
+ }
+
void cleanUpRemovedTaskLocked(TaskRecord tr, boolean killProcess, boolean removeFromRecents) {
if (removeFromRecents) {
- mRecentTasks.remove(tr);
+ removeTaskFromRecents(tr);
}
ComponentName component = tr.getBaseIntent().getComponent();
if (component == null) {
@@ -2954,7 +2979,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
int getNextStackId() {
while (true) {
- if (getStack(mNextFreeStackId) == null) {
+ if (mNextFreeStackId >= FIRST_DYNAMIC_STACK_ID
+ && getStack(mNextFreeStackId) == null) {
break;
}
mNextFreeStackId++;
@@ -2963,8 +2989,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
/**
- * Called to restore the state of the task into the stack that it's supposed to go into.
- *
+ * Restores a recent task to a stack
* @param task The recent task to be restored.
* @param aOptions The activity options to use for restoration.
* @return true if the task has been restored successfully.
@@ -2995,22 +3020,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return true;
}
- @Override
- public void onRecentTaskAdded(TaskRecord task) {
- task.touchActiveTime();
- }
-
- @Override
- public void onRecentTaskRemoved(TaskRecord task, boolean wasTrimmed) {
- if (wasTrimmed) {
- // Task was trimmed from the recent tasks list -- remove the active task record as well
- // since the user won't really be able to go back to it
- removeTaskByIdLocked(task.taskId, false /* killProcess */,
- false /* removeFromRecents */);
- }
- task.removedFromRecents();
- }
-
/**
* Move stack with all its existing content to specified display.
* @param stackId Id of stack to move.
@@ -3151,7 +3160,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// Resize the pinned stack to match the current size of the task the activity we are
// going to be moving is currently contained in. We do this to have the right starting
// animation bounds for the pinned stack to the desired bounds the caller wants.
- resizeStackLocked(stack, task.mBounds, null /* tempTaskBounds */,
+ resizeStackLocked(PINNED_STACK_ID, task.mBounds, null /* tempTaskBounds */,
null /* tempTaskInsetBounds */, !PRESERVE_WINDOWS,
true /* allowResizeInDockedMode */, !DEFER_RESUME);
@@ -3248,9 +3257,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
ActivityRecord affinityMatch = null;
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + r);
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ 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.hasCompatibleActivityType(stack)) {
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping stack: (mismatch activity/stack) "
+ stack);
@@ -3283,13 +3292,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
ActivityRecord findActivityLocked(Intent intent, ActivityInfo info,
- boolean compareIntentFilters) {
+ boolean compareIntentFilters) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- final ActivityRecord ar = stack.findActivityLocked(
- intent, info, compareIntentFilters);
+ 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, compareIntentFilters);
if (ar != null) {
return ar;
}
@@ -3383,8 +3391,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
// Set the sleeping state of the stacks on the display.
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ final ArrayList<ActivityStack> stacks = display.mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
if (displayShouldSleep) {
stack.goToSleepIfPossible(false /* shuttingDown */);
} else {
@@ -3446,13 +3455,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
private boolean putStacksToSleepLocked(boolean allowDelay, boolean shuttingDown) {
boolean allSleep = true;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
if (allowDelay) {
- allSleep &= stack.goToSleepIfPossible(shuttingDown);
+ allSleep &= stacks.get(stackNdx).goToSleepIfPossible(shuttingDown);
} else {
- stack.goToSleep();
+ stacks.get(stackNdx).goToSleep();
}
}
}
@@ -3477,10 +3485,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void handleAppCrashLocked(ProcessRecord app) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- stack.handleAppCrashLocked(app);
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ int stackNdx = stacks.size() - 1;
+ while (stackNdx >= 0) {
+ stacks.get(stackNdx).handleAppCrashLocked(app);
+ stackNdx--;
}
}
}
@@ -3491,7 +3500,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
final ActivityStack stack = task.getStack();
r.mLaunchTaskBehind = false;
- mRecentTasks.add(task);
+ mRecentTasks.addLocked(task);
mService.mTaskChangeNotificationController.notifyTaskStackChanged();
r.setVisibility(false);
@@ -3513,9 +3522,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
try {
// 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 ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ 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, preserveWindows);
}
}
@@ -3526,9 +3536,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ 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.addStartingWindowsForVisibleActivities(taskSwitch);
}
}
@@ -3544,20 +3555,20 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
mTaskLayersChanged = false;
for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); displayNdx++) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
int baseLayer = 0;
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- baseLayer += stack.rankTaskLayers(baseLayer);
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ baseLayer += stacks.get(stackNdx).rankTaskLayers(baseLayer);
}
}
}
void clearOtherAppTimeTrackers(AppTimeTracker except) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ 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);
}
}
@@ -3565,9 +3576,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ 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);
}
}
@@ -3619,11 +3631,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// let's iterate through the tasks and release the oldest one.
final int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- final int stackCount = display.getChildCount();
+ 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 < stackCount; stackNdx++) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ 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;
@@ -3635,14 +3646,14 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
boolean switchUserLocked(int userId, UserState uss) {
final int focusStackId = mFocusedStack.getStackId();
// We dismiss the docked stack whenever we switch users.
- final ActivityStack dockedStack = getDefaultDisplay().getSplitScreenPrimaryStack();
+ final ActivityStack dockedStack = getDefaultDisplay().getSplitScreenStack();
if (dockedStack != null) {
moveTasksToFullscreenStackLocked(dockedStack, mFocusedStack == dockedStack);
}
// Also dismiss the pinned stack whenever we switch users. Removing the pinned stack will
// also cause all tasks to be moved to the fullscreen stack at a position that is
// appropriate.
- removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
+ removeStackLocked(PINNED_STACK_ID);
mUserStackInFront.put(mCurrentUser, focusStackId);
final int restoreStackId = mUserStackInFront.get(userId, mHomeStack.mStackId);
@@ -3650,9 +3661,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
mStartingUsers.add(uss);
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ 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) {
@@ -3750,9 +3761,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void validateTopActivitiesLocked() {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ 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();
final ActivityState state = r == null ? DESTROYED : r.state;
if (isFocusedStack(stack)) {
@@ -3787,7 +3798,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront);
for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
final ActivityDisplay display = mActivityDisplays.valueAt(i);
- display.dump(pw, prefix);
+ pw.println(prefix + "displayId=" + display.mDisplayId + " mStacks=" + display.mStacks);
}
if (!mWaitingForActivityVisible.isEmpty()) {
pw.print(prefix); pw.println("mWaitingForActivityVisible=");
@@ -3800,7 +3811,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
mService.mLockTaskController.dump(pw, prefix);
}
- public void writeToProto(ProtoOutputStream proto) {
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
super.writeToProto(proto, CONFIGURATION_CONTAINER);
for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx);
@@ -3816,6 +3828,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
} else {
proto.write(FOCUSED_STACK_ID, INVALID_STACK_ID);
}
+ proto.end(token);
}
/**
@@ -3844,9 +3857,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
ArrayList<ActivityRecord> activities = new ArrayList<>();
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ ActivityStack stack = stacks.get(stackNdx);
if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) {
activities.addAll(stack.getDumpActivitiesLocked(name));
}
@@ -3879,13 +3892,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx);
pw.print("Display #"); pw.print(activityDisplay.mDisplayId);
pw.println(" (activities from top to bottom):");
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ ArrayList<ActivityStack> stacks = activityDisplay.mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
pw.println();
- pw.println(" Stack #" + stack.mStackId
- + ": type=" + activityTypeToString(stack.getActivityType())
- + " mode=" + windowingModeToString(stack.getWindowingMode()));
+ pw.println(" Stack #" + stack.mStackId + ":");
pw.println(" mFullscreen=" + stack.mFullscreen);
pw.println(" isSleeping=" + stack.shouldSleepActivities());
pw.println(" mBounds=" + stack.mBounds);
@@ -4129,29 +4140,30 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
synchronized (mService) {
- final ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
- if (activityDisplay == null) {
- return;
- }
- final boolean destroyContentOnRemoval
- = activityDisplay.shouldDestroyContentOnRemove();
- while (activityDisplay.getChildCount() > 0) {
- final ActivityStack stack = activityDisplay.getChildAt(0);
- if (destroyContentOnRemoval) {
- moveStackToDisplayLocked(stack.mStackId, DEFAULT_DISPLAY, false /* onTop */);
- stack.finishAllActivitiesLocked(true /* immediately */);
- } else {
- // Moving all tasks to fullscreen stack, because it's guaranteed to be
- // a valid launch stack for all activities. This way the task history from
- // external display will be preserved on primary after move.
- moveTasksToFullscreenStackLocked(stack, true /* onTop */);
+ ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+ if (activityDisplay != null) {
+ final boolean destroyContentOnRemoval
+ = activityDisplay.shouldDestroyContentOnRemove();
+ final ArrayList<ActivityStack> stacks = activityDisplay.mStacks;
+ while (!stacks.isEmpty()) {
+ final ActivityStack stack = stacks.get(0);
+ if (destroyContentOnRemoval) {
+ moveStackToDisplayLocked(stack.mStackId, DEFAULT_DISPLAY,
+ false /* onTop */);
+ stack.finishAllActivitiesLocked(true /* immediately */);
+ } else {
+ // Moving all tasks to fullscreen stack, because it's guaranteed to be
+ // a valid launch stack for all activities. This way the task history from
+ // external display will be preserved on primary after move.
+ moveTasksToFullscreenStackLocked(stack, true /* onTop */);
+ }
}
- }
- releaseSleepTokens(activityDisplay);
+ releaseSleepTokens(activityDisplay);
- mActivityDisplays.remove(displayId);
- mWindowManager.onDisplayRemoved(displayId);
+ mActivityDisplays.remove(displayId);
+ mWindowManager.onDisplayRemoved(displayId);
+ }
}
}
@@ -4223,7 +4235,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
info.userId = stack.mCurrentUser;
info.visible = stack.shouldBeVisible(null);
// A stack might be not attached to a display.
- info.position = display != null ? display.getIndexOf(stack) : 0;
+ info.position = display != null ? display.mStacks.indexOf(stack) : 0;
info.configuration.setTo(stack.getConfiguration());
ArrayList<TaskRecord> tasks = stack.getAllTasks();
@@ -4269,25 +4281,25 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
ArrayList<StackInfo> getAllStackInfosLocked() {
ArrayList<StackInfo> list = new ArrayList<>();
for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- list.add(getStackInfo(stack));
+ ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int ndx = stacks.size() - 1; ndx >= 0; --ndx) {
+ list.add(getStackInfo(stacks.get(ndx)));
}
}
return list;
}
void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredWindowingMode,
- int preferredDisplayId, ActivityStack actualStack) {
+ int preferredDisplayId, int actualStackId) {
handleNonResizableTaskIfNeeded(task, preferredWindowingMode, preferredDisplayId,
- actualStack, false /* forceNonResizable */);
+ actualStackId, false /* forceNonResizable */);
}
void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredWindowingMode,
- int preferredDisplayId, ActivityStack actualStack, boolean forceNonResizable) {
+ int preferredDisplayId, int actualStackId, boolean forceNonResizable) {
final boolean isSecondaryDisplayPreferred =
(preferredDisplayId != DEFAULT_DISPLAY && preferredDisplayId != INVALID_DISPLAY);
+ final ActivityStack actualStack = getStack(actualStackId);
final boolean inSplitScreenMode = actualStack != null
&& actualStack.inSplitScreenWindowingMode();
if (((!inSplitScreenMode && preferredWindowingMode != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)
@@ -4303,8 +4315,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// The task landed on an inappropriate display somehow, move it to the default
// display.
// TODO(multi-display): Find proper stack for the task on the default display.
- mService.setTaskWindowingMode(task.taskId,
- WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY, true /* toTop */);
+ mService.moveTaskToStack(task.taskId, FULLSCREEN_WORKSPACE_STACK_ID,
+ true /* toTop */);
launchOnSecondaryDisplayFailed = true;
} else {
// The task might have landed on a display different from requested.
@@ -4334,9 +4346,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// Dismiss docked stack. If task appeared to be in docked stack but is not resizable -
// we need to move it to top of fullscreen stack, otherwise it will be covered.
- final ActivityStack dockedStack = task.getStack().getDisplay().getSplitScreenPrimaryStack();
+ final ActivityStack dockedStack = task.getStack().getDisplay().getSplitScreenStack();
if (dockedStack != null) {
- moveTasksToFullscreenStackLocked(dockedStack, actualStack == dockedStack);
+ moveTasksToFullscreenStackLocked(dockedStack,
+ actualStackId == dockedStack.getStackId());
}
} else if (topActivity != null && topActivity.isNonResizableOrForcedResizable()
&& !topActivity.noDisplay) {
@@ -4389,7 +4402,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void scheduleUpdatePictureInPictureModeIfNeeded(TaskRecord task, ActivityStack prevStack) {
final ActivityStack stack = task.getStack();
if (prevStack == null || prevStack == stack
- || (!prevStack.inPinnedWindowingMode() && !stack.inPinnedWindowingMode())) {
+ || (prevStack.mStackId != PINNED_STACK_ID && stack.mStackId != PINNED_STACK_ID)) {
return;
}
@@ -4548,13 +4561,14 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
if (display == null) {
return null;
}
- for (int i = display.getChildCount() - 1; i >= 0; i--) {
- if (display.getChildAt(i) == stack && i > 0) {
- return display.getChildAt(i - 1);
+ final ArrayList<ActivityStack> stacks = display.mStacks;
+ for (int i = stacks.size() - 1; i >= 0; i--) {
+ if (stacks.get(i) == stack && i > 0) {
+ return stacks.get(i - 1);
}
}
throw new IllegalStateException("Failed to find a stack behind stack=" + stack
- + " in=" + display);
+ + " in=" + stacks);
}
/**
@@ -4667,8 +4681,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
for (int i = mActivityDisplays.size() - 1; i >= 0; i--) {
final ActivityDisplay display = mActivityDisplays.valueAt(i);
// Traverse all stacks on a display.
- for (int j = display.getChildCount() - 1; j >= 0; --j) {
- final ActivityStack stack = display.getChildAt(j);
+ for (int j = display.mStacks.size() - 1; j >= 0; j--) {
+ final ActivityStack stack = display.mStacks.get(j);
// Get top activity from a visible stack and add it to the list.
if (stack.shouldBeVisible(null /* starting */)) {
final ActivityRecord top = stack.topActivity();
diff --git a/com/android/server/am/ActivityStarter.java b/com/android/server/am/ActivityStarter.java
index 6f74d851..d444c663 100644
--- a/com/android/server/am/ActivityStarter.java
+++ b/com/android/server/am/ActivityStarter.java
@@ -26,9 +26,15 @@ import static android.app.ActivityManager.START_RETURN_INTENT_TO_CALLER;
import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
import static android.app.ActivityManager.START_SUCCESS;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
+import static android.app.ActivityManager.StackId;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.ActivityManager.StackId.isDynamicStack;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
@@ -115,6 +121,7 @@ import com.android.internal.app.HeavyWeightSwitcherActivity;
import com.android.internal.app.IVoiceInteractor;
import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
import com.android.server.pm.InstantAppResolver;
+import com.android.server.wm.WindowManagerService;
import java.io.PrintWriter;
import java.text.DateFormat;
@@ -133,11 +140,11 @@ class ActivityStarter {
private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
- private static final int INVALID_LAUNCH_MODE = -1;
private final ActivityManagerService mService;
private final ActivityStackSupervisor mSupervisor;
private final ActivityStartInterceptor mInterceptor;
+ private WindowManagerService mWindowManager;
final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
@@ -147,7 +154,9 @@ class ActivityStarter {
private int mCallingUid;
private ActivityOptions mOptions;
- private int mLaunchMode;
+ private boolean mLaunchSingleTop;
+ private boolean mLaunchSingleInstance;
+ private boolean mLaunchSingleTask;
private boolean mLaunchTaskBehind;
private int mLaunchFlags;
@@ -157,7 +166,6 @@ class ActivityStarter {
private boolean mDoResume;
private int mStartFlags;
private ActivityRecord mSourceRecord;
-
// The display to launch the activity onto, barring any strong reason to do otherwise.
private int mPreferredDisplayId;
@@ -187,6 +195,8 @@ class ActivityStarter {
private IVoiceInteractionSession mVoiceSession;
private IVoiceInteractor mVoiceInteractor;
+ private boolean mUsingVr2dDisplay;
+
// Last home activity record we attempted to start
private final ActivityRecord[] mLastHomeActivityStartRecord = new ActivityRecord[1];
// The result of the last home activity we attempted to start.
@@ -206,9 +216,11 @@ class ActivityStarter {
mCallingUid = -1;
mOptions = null;
+ mLaunchSingleTop = false;
+ mLaunchSingleInstance = false;
+ mLaunchSingleTask = false;
mLaunchTaskBehind = false;
mLaunchFlags = 0;
- mLaunchMode = INVALID_LAUNCH_MODE;
mLaunchBounds = null;
@@ -236,13 +248,16 @@ class ActivityStarter {
mVoiceSession = null;
mVoiceInteractor = null;
+ mUsingVr2dDisplay = false;
+
mIntentDelivered = false;
}
- ActivityStarter(ActivityManagerService service) {
+ ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
mService = service;
- mSupervisor = mService.mStackSupervisor;
+ mSupervisor = supervisor;
mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
+ mUsingVr2dDisplay = false;
}
int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
@@ -595,41 +610,38 @@ class ActivityStarter {
mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
}
- ActivityStack startedActivityStack = null;
+ int startedActivityStackId = INVALID_STACK_ID;
final ActivityStack currentStack = r.getStack();
if (currentStack != null) {
- startedActivityStack = currentStack;
+ startedActivityStackId = currentStack.mStackId;
} else if (mTargetStack != null) {
- startedActivityStack = targetStack;
+ startedActivityStackId = targetStack.mStackId;
}
- if (startedActivityStack == null) {
- return;
- }
-
- if (startedActivityStack.inSplitScreenPrimaryWindowingMode()) {
- final ActivityStack homeStack = mSupervisor.mHomeStack;
+ if (startedActivityStackId == DOCKED_STACK_ID) {
+ final ActivityStack homeStack = mSupervisor.getDefaultDisplay().getStack(
+ WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME);
final boolean homeStackVisible = homeStack != null && homeStack.isVisible();
if (homeStackVisible) {
// We launch an activity while being in home stack, which means either launcher or
// recents into docked stack. We don't want the launched activity to be alone in a
// docked stack, so we want to immediately launch recents too.
if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
- mService.mWindowManager.showRecentApps(true /* fromHome */);
+ mWindowManager.showRecentApps(true /* fromHome */);
}
return;
}
boolean clearedTask = (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK) && (mReuseTask != null);
- if (startedActivityStack.inPinnedWindowingMode()
- && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP
- || clearedTask)) {
+ if (startedActivityStackId == PINNED_STACK_ID && (result == START_TASK_TO_FRONT
+ || result == START_DELIVERED_TO_TOP || clearedTask)) {
// The activity was already running in the pinned stack so it wasn't started, but either
// brought to the front or the new intent was delivered to it since it was already in
// front. Notify anyone interested in this piece of information.
mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
clearedTask);
+ return;
}
}
@@ -1050,7 +1062,7 @@ class ActivityStarter {
// operations.
if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| isDocumentLaunchesIntoExisting(mLaunchFlags)
- || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
+ || mLaunchSingleInstance || mLaunchSingleTask) {
final TaskRecord task = reusedActivity.getTask();
// In this situation we want to remove all activities from the task up to the one
@@ -1133,7 +1145,7 @@ class ActivityStarter {
&& top.userId == mStartActivity.userId
&& top.app != null && top.app.thread != null
&& ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
- || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK));
+ || mLaunchSingleTop || mLaunchSingleTask);
if (dontStart) {
// For paranoia, make sure we have correctly resumed the top activity.
topStack.mLastPausedActivity = null;
@@ -1152,7 +1164,7 @@ class ActivityStarter {
// Don't use mStartActivity.task to show the toast. We're not starting a new activity
// but reusing 'top'. Fields in mStartActivity may not be fully initialized.
mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredWindowingMode,
- preferredLaunchDisplayId, topStack);
+ preferredLaunchDisplayId, topStack.mStackId);
return START_DELIVERED_TO_TOP;
}
@@ -1215,7 +1227,7 @@ class ActivityStarter {
mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
// Go ahead and tell window manager to execute app transition for this activity
// since the app transition will not be triggered through the resume channel.
- mService.mWindowManager.executeAppTransition();
+ mWindowManager.executeAppTransition();
} else {
// If the target stack was not previously focusable (previous top running activity
// on that stack was not visible) then any prior calls to move the stack to the
@@ -1228,13 +1240,13 @@ class ActivityStarter {
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
- } else if (mStartActivity != null) {
- mSupervisor.mRecentTasks.add(mStartActivity.getTask());
+ } else {
+ mSupervisor.addRecentActivity(mStartActivity);
}
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode,
- preferredLaunchDisplayId, mTargetStack);
+ preferredLaunchDisplayId, mTargetStack.mStackId);
return START_SUCCESS;
}
@@ -1256,13 +1268,13 @@ class ActivityStarter {
mLaunchBounds = getOverrideBounds(r, options, inTask);
- mLaunchMode = r.launchMode;
-
+ mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
+ mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
+ mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
mLaunchFlags = adjustLaunchFlagsToDocumentMode(
- r, LAUNCH_SINGLE_INSTANCE == mLaunchMode,
- LAUNCH_SINGLE_TASK == mLaunchMode, mIntent.getFlags());
+ r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
mLaunchTaskBehind = r.mLaunchTaskBehind
- && !isLaunchModeOneOf(LAUNCH_SINGLE_TASK, LAUNCH_SINGLE_INSTANCE)
+ && !mLaunchSingleTask && !mLaunchSingleInstance
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
sendNewTaskResultRequestIfNeeded();
@@ -1372,7 +1384,7 @@ class ActivityStarter {
// 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 (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
+ if (mLaunchSingleInstance || mLaunchSingleTask) {
if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
ActivityOptions.abort(mOptions);
throw new IllegalArgumentException("Trying to launch singleInstance/Task "
@@ -1415,7 +1427,7 @@ class ActivityStarter {
// in any task/stack, however it could launch other activities like ResolverActivity,
// and we want those to stay in the original task.
if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
- && mSourceRecord.inFreeformWindowingMode()) {
+ && mSourceRecord.isFreeform()) {
mAddingToTask = true;
}
}
@@ -1434,7 +1446,7 @@ class ActivityStarter {
// instance... this new activity it is starting must go on its
// own task.
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
- } else if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
+ } else if (mLaunchSingleInstance || mLaunchSingleTask) {
// The activity being started is a single instance... it always
// gets launched into its own task.
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
@@ -1485,7 +1497,7 @@ class ActivityStarter {
// launch this as a new task behind the current one.
boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
(mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
- || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK);
+ || mLaunchSingleInstance || mLaunchSingleTask;
// 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.
@@ -1495,7 +1507,7 @@ class ActivityStarter {
final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
intentActivity = task != null ? task.getTopActivity() : null;
} else if (putIntoExistingTask) {
- if (LAUNCH_SINGLE_INSTANCE == mLaunchMode) {
+ if (mLaunchSingleInstance) {
// There can be one and only one instance of single instance activity in the
// history, and it is always in its own unique task, so we do a special search.
intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
@@ -1504,7 +1516,7 @@ class ActivityStarter {
// For the launch adjacent case we only want to put the activity in an existing
// task if the activity already exists in the history.
intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
- !(LAUNCH_SINGLE_TASK == mLaunchMode));
+ !mLaunchSingleTask);
} else {
// Otherwise find the best task to put the activity in.
intentActivity = mSupervisor.findTaskLocked(mStartActivity, mPreferredDisplayId);
@@ -1533,6 +1545,7 @@ class ActivityStarter {
if (DEBUG_STACK) {
Slog.d(TAG, "getSourceDisplayId :" + displayId);
}
+ mUsingVr2dDisplay = true;
return displayId;
}
@@ -1654,7 +1667,7 @@ class ActivityStarter {
}
mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(),
- WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY, mTargetStack);
+ WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY, mTargetStack.mStackId);
// If the caller has requested that the target task be reset, then do so.
if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
@@ -1706,7 +1719,7 @@ class ActivityStarter {
// mTaskToReturnTo values and we don't want to overwrite them accidentally.
mMovedOtherTask = true;
} else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
- || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
+ || mLaunchSingleInstance || mLaunchSingleTask) {
ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
mLaunchFlags);
if (top == null) {
@@ -1735,8 +1748,7 @@ class ActivityStarter {
// 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 (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
- || LAUNCH_SINGLE_TOP == mLaunchMode)
+ if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
&& intentActivity.realActivity.equals(mStartActivity.realActivity)) {
if (intentActivity.frontOfTask) {
intentActivity.getTask().setIntent(mStartActivity);
@@ -1940,7 +1952,7 @@ class ActivityStarter {
if (top != null && top.realActivity.equals(mStartActivity.realActivity)
&& top.userId == mStartActivity.userId) {
if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
- || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)) {
+ || mLaunchSingleTop || mLaunchSingleTask) {
mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
mStartActivity.appTimeTracker, "inTaskToFront");
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
@@ -1989,9 +2001,9 @@ class ActivityStarter {
return;
}
- final ActivityStack stack = task.getStack();
- if (stack != null && stack.resizeStackWithLaunchBounds()) {
- mService.resizeStack(stack.mStackId, bounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
+ final int stackId = task.getStackId();
+ if (StackId.resizeStackWithLaunchBounds(stackId)) {
+ mService.resizeStack(stackId, bounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
} else {
task.updateOverrideConfiguration(bounds);
}
@@ -2103,10 +2115,11 @@ class ActivityStarter {
}
if (stack == null) {
// We first try to put the task in the first dynamic stack on home display.
- final ActivityDisplay display = mSupervisor.getDefaultDisplay();
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- stack = display.getChildAt(stackNdx);
- if (!stack.isOnHomeDisplay()) {
+ final ArrayList<ActivityStack> homeDisplayStacks =
+ mSupervisor.getStacksOnDefaultDisplay();
+ for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ stack = homeDisplayStacks.get(stackNdx);
+ if (isDynamicStack(stack.mStackId)) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
"computeStackFocus: Setting focused stack=" + stack);
return stack;
@@ -2125,6 +2138,7 @@ class ActivityStarter {
private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
final ActivityStack focusedStack = mSupervisor.mFocusedStack;
final boolean canUseFocusedStack;
+ final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
if (focusedStack.isActivityTypeAssistant()) {
canUseFocusedStack = r.isActivityTypeAssistant();
} else {
@@ -2147,7 +2161,7 @@ class ActivityStarter {
default:
// Dynamic stacks behave similarly to the fullscreen stack and can contain any
// resizeable task.
- canUseFocusedStack = !focusedStack.isOnHomeDisplay()
+ canUseFocusedStack = isDynamicStack(focusedStackId)
&& r.canBeLaunchedOnDisplay(focusedStack.mDisplayId);
}
}
@@ -2163,8 +2177,7 @@ class ActivityStarter {
return mReuseTask.getStack();
}
- final int vrDisplayId = mPreferredDisplayId == mService.mVr2dDisplayId
- ? mPreferredDisplayId : INVALID_DISPLAY;
+ final int vrDisplayId = mUsingVr2dDisplay ? mPreferredDisplayId : INVALID_DISPLAY;
final ActivityStack launchStack = mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP,
vrDisplayId);
@@ -2192,7 +2205,7 @@ class ActivityStarter {
return mSupervisor.mFocusedStack;
}
- if (parentStack != null && parentStack.inSplitScreenPrimaryWindowingMode()) {
+ if (parentStack != null && parentStack.isDockedStack()) {
// If parent was in docked stack, the natural place to launch another activity
// will be fullscreen, so it can appear alongside the docked window.
final int activityType = mSupervisor.resolveActivityType(r, mOptions, task);
@@ -2202,8 +2215,8 @@ class ActivityStarter {
// If the parent is not in the docked stack, we check if there is docked window
// and if yes, we will launch into that stack. If not, we just put the new
// activity into parent's stack, because we can't find a better place.
- final ActivityStack dockedStack =
- mSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack();
+ final ActivityStack dockedStack = mSupervisor.getDefaultDisplay().getStack(
+ WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
if (dockedStack != null && !dockedStack.shouldBeVisible(r)) {
// There is a docked stack, but it isn't visible, so we can't launch into that.
return null;
@@ -2223,8 +2236,8 @@ class ActivityStarter {
return newBounds;
}
- private boolean isLaunchModeOneOf(int mode1, int mode2) {
- return mode1 == mLaunchMode || mode2 == mLaunchMode;
+ void setWindowManager(WindowManagerService wm) {
+ mWindowManager = wm;
}
static boolean isDocumentLaunchesIntoExisting(int flags) {
@@ -2305,11 +2318,11 @@ class ActivityStarter {
}
pw.print(prefix);
pw.print("mLaunchSingleTop=");
- pw.print(LAUNCH_SINGLE_TOP == mLaunchMode);
+ pw.print(mLaunchSingleTop);
pw.print(" mLaunchSingleInstance=");
- pw.print(LAUNCH_SINGLE_INSTANCE == mLaunchMode);
+ pw.print(mLaunchSingleInstance);
pw.print(" mLaunchSingleTask=");
- pw.println(LAUNCH_SINGLE_TASK == mLaunchMode);
+ pw.println(mLaunchSingleTask);
pw.print(prefix);
pw.print("mLaunchFlags=0x");
pw.print(Integer.toHexString(mLaunchFlags));
diff --git a/com/android/server/am/AppTaskImpl.java b/com/android/server/am/AppTaskImpl.java
deleted file mode 100644
index a4e2e70e..00000000
--- a/com/android/server/am/AppTaskImpl.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.am;
-
-import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
-
-import android.app.ActivityManager;
-import android.app.IAppTask;
-import android.app.IApplicationThread;
-import android.content.Intent;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.UserHandle;
-
-/**
- * An implementation of IAppTask, that allows an app to manage its own tasks via
- * {@link android.app.ActivityManager.AppTask}. We keep track of the callingUid to ensure that
- * only the process that calls getAppTasks() can call the AppTask methods.
- */
-class AppTaskImpl extends IAppTask.Stub {
- private ActivityManagerService mService;
-
- private int mTaskId;
- private int mCallingUid;
-
- public AppTaskImpl(ActivityManagerService service, int taskId, int callingUid) {
- mService = service;
- mTaskId = taskId;
- mCallingUid = callingUid;
- }
-
- private void checkCaller() {
- if (mCallingUid != Binder.getCallingUid()) {
- throw new SecurityException("Caller " + mCallingUid
- + " does not match caller of getAppTasks(): " + Binder.getCallingUid());
- }
- }
-
- @Override
- public void finishAndRemoveTask() {
- checkCaller();
-
- synchronized (mService) {
- long origId = Binder.clearCallingIdentity();
- try {
- // We remove the task from recents to preserve backwards
- if (!mService.mStackSupervisor.removeTaskByIdLocked(mTaskId, false,
- REMOVE_FROM_RECENTS)) {
- throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
- }
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
- }
-
- @Override
- public ActivityManager.RecentTaskInfo getTaskInfo() {
- checkCaller();
-
- synchronized (mService) {
- long origId = Binder.clearCallingIdentity();
- try {
- TaskRecord tr = mService.mStackSupervisor.anyTaskForIdLocked(mTaskId);
- if (tr == null) {
- throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
- }
- return RecentTasks.createRecentTaskInfo(tr);
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
- }
-
- @Override
- public void moveToFront() {
- checkCaller();
- // Will bring task to front if it already has a root activity.
- final long origId = Binder.clearCallingIdentity();
- try {
- synchronized (this) {
- mService.mStackSupervisor.startActivityFromRecentsInner(mTaskId, null);
- }
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
-
- @Override
- public int startActivity(IBinder whoThread, String callingPackage,
- Intent intent, String resolvedType, Bundle bOptions) {
- checkCaller();
-
- int callingUser = UserHandle.getCallingUserId();
- TaskRecord tr;
- IApplicationThread appThread;
- synchronized (mService) {
- tr = mService.mStackSupervisor.anyTaskForIdLocked(mTaskId);
- if (tr == null) {
- throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
- }
- appThread = IApplicationThread.Stub.asInterface(whoThread);
- if (appThread == null) {
- throw new IllegalArgumentException("Bad app thread " + appThread);
- }
- }
- return mService.mActivityStarter.startActivityMayWait(appThread, -1, callingPackage,
- intent, resolvedType, null, null, null, null, 0, 0, null, null,
- null, bOptions, false, callingUser, tr, "AppTaskImpl");
- }
-
- @Override
- public void setExcludeFromRecents(boolean exclude) {
- checkCaller();
-
- synchronized (mService) {
- long origId = Binder.clearCallingIdentity();
- try {
- TaskRecord tr = mService.mStackSupervisor.anyTaskForIdLocked(mTaskId);
- if (tr == null) {
- throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
- }
- Intent intent = tr.getBaseIntent();
- if (exclude) {
- intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- } else {
- intent.setFlags(intent.getFlags()
- & ~Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- }
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
- }
-} \ No newline at end of file
diff --git a/com/android/server/am/BatteryStatsService.java b/com/android/server/am/BatteryStatsService.java
index 68ed9aec..7c9cd00e 100644
--- a/com/android/server/am/BatteryStatsService.java
+++ b/com/android/server/am/BatteryStatsService.java
@@ -297,12 +297,26 @@ public final class BatteryStatsService extends IBatteryStats.Stub
void noteProcessStart(String name, int uid) {
synchronized (mStats) {
mStats.noteProcessStartLocked(name, uid);
+
+ // TODO: remove this once we figure out properly where and how
+ // PROCESS_EVENT = 1112
+ // KEY_STATE = 1
+ // KEY_PACKAGE_NAME: 1002
+ // KEY_UID: 2
+ StatsLog.writeArray(1112, 1, 1, 1002, name, 2, uid);
}
}
void noteProcessCrash(String name, int uid) {
synchronized (mStats) {
mStats.noteProcessCrashLocked(name, uid);
+
+ // TODO: remove this once we figure out properly where and how
+ // PROCESS_EVENT = 1112
+ // KEY_STATE = 1
+ // KEY_PACKAGE_NAME: 1002
+ // KEY_UID: 2
+ StatsLog.writeArray(1112, 1, 2, 1002, name, 2, uid);
}
}
@@ -320,9 +334,6 @@ public final class BatteryStatsService extends IBatteryStats.Stub
void noteUidProcessState(int uid, int state) {
synchronized (mStats) {
- // TODO: remove this once we figure out properly where and how
- StatsLog.write(StatsLog.PROCESS_STATE_CHANGED, uid, state);
-
mStats.noteUidProcessStateLocked(uid, state);
}
}
@@ -537,10 +548,12 @@ public final class BatteryStatsService extends IBatteryStats.Stub
enforceCallingPermission();
if (DBG) Slog.d(TAG, "begin noteScreenState");
synchronized (mStats) {
- // TODO: remove this once we figure out properly where and how
- StatsLog.write(StatsLog.SCREEN_STATE_CHANGED, state);
-
mStats.noteScreenStateLocked(state);
+ // TODO: remove this once we figure out properly where and how
+ // SCREEN_EVENT = 2
+ // KEY_STATE: 1
+ // State value: state. We can change this to our own def later.
+ StatsLog.writeArray(2, 1, state);
}
if (DBG) Slog.d(TAG, "end noteScreenState");
}
diff --git a/com/android/server/am/BroadcastFilter.java b/com/android/server/am/BroadcastFilter.java
index 7ff227f5..f96b06fa 100644
--- a/com/android/server/am/BroadcastFilter.java
+++ b/com/android/server/am/BroadcastFilter.java
@@ -19,9 +19,6 @@ package com.android.server.am;
import android.content.IntentFilter;
import android.util.PrintWriterPrinter;
import android.util.Printer;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.server.am.proto.BroadcastFilterProto;
import java.io.PrintWriter;
@@ -47,38 +44,27 @@ final class BroadcastFilter extends IntentFilter {
instantApp = _instantApp;
visibleToInstantApp = _visibleToInstantApp;
}
-
- public void writeToProto(ProtoOutputStream proto, long fieldId) {
- long token = proto.start(fieldId);
- super.writeToProto(proto, BroadcastFilterProto.INTENT_FILTER);
- if (requiredPermission != null) {
- proto.write(BroadcastFilterProto.REQUIRED_PERMISSION, requiredPermission);
- }
- proto.write(BroadcastFilterProto.HEX_HASH, Integer.toHexString(System.identityHashCode(this)));
- proto.write(BroadcastFilterProto.OWNING_USER_ID, owningUserId);
- proto.end(token);
- }
-
+
public void dump(PrintWriter pw, String prefix) {
dumpInReceiverList(pw, new PrintWriterPrinter(pw), prefix);
receiverList.dumpLocal(pw, prefix);
}
-
+
public void dumpBrief(PrintWriter pw, String prefix) {
dumpBroadcastFilterState(pw, prefix);
}
-
+
public void dumpInReceiverList(PrintWriter pw, Printer pr, String prefix) {
super.dump(pr, prefix);
dumpBroadcastFilterState(pw, prefix);
}
-
+
void dumpBroadcastFilterState(PrintWriter pw, String prefix) {
if (requiredPermission != null) {
pw.print(prefix); pw.print("requiredPermission="); pw.println(requiredPermission);
}
}
-
+
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("BroadcastFilter{");
diff --git a/com/android/server/am/BroadcastQueue.java b/com/android/server/am/BroadcastQueue.java
index c62cc38b..d8354549 100644
--- a/com/android/server/am/BroadcastQueue.java
+++ b/com/android/server/am/BroadcastQueue.java
@@ -51,12 +51,9 @@ import android.os.UserHandle;
import android.util.EventLog;
import android.util.Slog;
import android.util.TimeUtils;
-import android.util.proto.ProtoOutputStream;
import static com.android.server.am.ActivityManagerDebugConfig.*;
-import com.android.server.am.proto.BroadcastQueueProto;
-
/**
* BROADCASTS
*
@@ -1588,55 +1585,6 @@ public final class BroadcastQueue {
&& (mPendingBroadcast == null);
}
- void writeToProto(ProtoOutputStream proto, long fieldId) {
- long token = proto.start(fieldId);
- proto.write(BroadcastQueueProto.QUEUE_NAME, mQueueName);
- int N;
- N = mParallelBroadcasts.size();
- for (int i = N - 1; i >= 0; i--) {
- mParallelBroadcasts.get(i).writeToProto(proto, BroadcastQueueProto.PARALLEL_BROADCASTS);
- }
- N = mOrderedBroadcasts.size();
- for (int i = N - 1; i >= 0; i--) {
- mOrderedBroadcasts.get(i).writeToProto(proto, BroadcastQueueProto.ORDERED_BROADCASTS);
- }
- if (mPendingBroadcast != null) {
- mPendingBroadcast.writeToProto(proto, BroadcastQueueProto.PENDING_BROADCAST);
- }
-
- int lastIndex = mHistoryNext;
- int ringIndex = lastIndex;
- do {
- // increasing index = more recent entry, and we want to print the most
- // recent first and work backwards, so we roll through the ring backwards.
- ringIndex = ringAdvance(ringIndex, -1, MAX_BROADCAST_HISTORY);
- BroadcastRecord r = mBroadcastHistory[ringIndex];
- if (r != null) {
- r.writeToProto(proto, BroadcastQueueProto.HISTORICAL_BROADCASTS);
- }
- } while (ringIndex != lastIndex);
-
- lastIndex = ringIndex = mSummaryHistoryNext;
- do {
- ringIndex = ringAdvance(ringIndex, -1, MAX_BROADCAST_SUMMARY_HISTORY);
- Intent intent = mBroadcastSummaryHistory[ringIndex];
- if (intent == null) {
- continue;
- }
- long summaryToken = proto.start(BroadcastQueueProto.HISTORICAL_BROADCASTS_SUMMARY);
- intent.writeToProto(proto, BroadcastQueueProto.BroadcastSummary.INTENT,
- false, true, true, false);
- proto.write(BroadcastQueueProto.BroadcastSummary.ENQUEUE_CLOCK_TIME_MS,
- mSummaryHistoryEnqueueTime[ringIndex]);
- proto.write(BroadcastQueueProto.BroadcastSummary.DISPATCH_CLOCK_TIME_MS,
- mSummaryHistoryDispatchTime[ringIndex]);
- proto.write(BroadcastQueueProto.BroadcastSummary.FINISH_CLOCK_TIME_MS,
- mSummaryHistoryFinishTime[ringIndex]);
- proto.end(summaryToken);
- } while (ringIndex != lastIndex);
- proto.end(token);
- }
-
final boolean dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll, String dumpPackage, boolean needSep) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
diff --git a/com/android/server/am/BroadcastRecord.java b/com/android/server/am/BroadcastRecord.java
index 5b3b2a8e..6bc0744f 100644
--- a/com/android/server/am/BroadcastRecord.java
+++ b/com/android/server/am/BroadcastRecord.java
@@ -30,9 +30,6 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.util.PrintWriterPrinter;
import android.util.TimeUtils;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.server.am.proto.BroadcastRecordProto;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
@@ -334,17 +331,9 @@ final class BroadcastRecord extends Binder {
return didSomething;
}
- @Override
public String toString() {
return "BroadcastRecord{"
+ Integer.toHexString(System.identityHashCode(this))
+ " u" + userId + " " + intent.getAction() + "}";
}
-
- public void writeToProto(ProtoOutputStream proto, long fieldId) {
- long token = proto.start(fieldId);
- proto.write(BroadcastRecordProto.USER_ID, userId);
- proto.write(BroadcastRecordProto.INTENT_ACTION, intent.getAction());
- proto.end(token);
- }
}
diff --git a/com/android/server/am/KeyguardController.java b/com/android/server/am/KeyguardController.java
index c3fed171..5c48f90d 100644
--- a/com/android/server/am/KeyguardController.java
+++ b/com/android/server/am/KeyguardController.java
@@ -16,6 +16,7 @@
package com.android.server.am;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
@@ -46,6 +47,7 @@ import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.server.wm.WindowManagerService;
import java.io.PrintWriter;
+import java.util.ArrayList;
/**
* Controls Keyguard occluding, dismissing and transitions depending on what kind of activities are
@@ -236,9 +238,9 @@ class KeyguardController {
final ActivityRecord lastDismissingKeyguardActivity = mDismissingKeyguardActivity;
mOccluded = false;
mDismissingKeyguardActivity = null;
- final ActivityDisplay display = mStackSupervisor.getDefaultDisplay();
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
+ final ArrayList<ActivityStack> stacks = mStackSupervisor.getStacksOnDefaultDisplay();
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
// Only the focused stack top activity may control occluded state
if (mStackSupervisor.isFocusedStack(stack)) {
@@ -340,7 +342,7 @@ class KeyguardController {
// show on top of the lock screen. In this can we want to dismiss the docked
// stack since it will be complicated/risky to try to put the activity on top
// of the lock screen in the right fullscreen configuration.
- final ActivityStack stack = mStackSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack();
+ final ActivityStack stack = mStackSupervisor.getDefaultDisplay().getSplitScreenStack();
if (stack == null) {
return;
}
diff --git a/com/android/server/am/LaunchingTaskPositioner.java b/com/android/server/am/LaunchingTaskPositioner.java
index 0dc73e98..d6523418 100644
--- a/com/android/server/am/LaunchingTaskPositioner.java
+++ b/com/android/server/am/LaunchingTaskPositioner.java
@@ -24,8 +24,8 @@ import android.content.pm.ActivityInfo;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.Slog;
+import android.view.Display;
import android.view.Gravity;
-import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
@@ -64,11 +64,43 @@ class LaunchingTaskPositioner {
private static final int SHIFT_POLICY_HORIZONTAL_RIGHT = 2;
private static final int SHIFT_POLICY_HORIZONTAL_LEFT = 3;
+ private boolean mDefaultStartBoundsConfigurationSet = false;
private final Rect mAvailableRect = new Rect();
private final Rect mTmpProposal = new Rect();
private final Rect mTmpOriginal = new Rect();
- private final Point mDisplaySize = new Point();
+ private int mDefaultFreeformStartX;
+ private int mDefaultFreeformStartY;
+ private int mDefaultFreeformWidth;
+ private int mDefaultFreeformHeight;
+ private int mDefaultFreeformStepHorizontal;
+ private int mDefaultFreeformStepVertical;
+ private int mDisplayWidth;
+ private int mDisplayHeight;
+
+ void setDisplay(Display display) {
+ Point size = new Point();
+ display.getSize(size);
+ mDisplayWidth = size.x;
+ mDisplayHeight = size.y;
+ }
+
+ void configure(Rect stackBounds) {
+ if (stackBounds == null) {
+ mAvailableRect.set(0, 0, mDisplayWidth, mDisplayHeight);
+ } else {
+ mAvailableRect.set(stackBounds);
+ }
+ int width = mAvailableRect.width();
+ int height = mAvailableRect.height();
+ mDefaultFreeformStartX = mAvailableRect.left + width / MARGIN_SIZE_DENOMINATOR;
+ mDefaultFreeformStartY = mAvailableRect.top + height / MARGIN_SIZE_DENOMINATOR;
+ mDefaultFreeformWidth = width / WINDOW_SIZE_DENOMINATOR;
+ mDefaultFreeformHeight = height / WINDOW_SIZE_DENOMINATOR;
+ mDefaultFreeformStepHorizontal = Math.max(width / STEP_DENOMINATOR, MINIMAL_STEP);
+ mDefaultFreeformStepVertical = Math.max(height / STEP_DENOMINATOR, MINIMAL_STEP);
+ mDefaultStartBoundsConfigurationSet = true;
+ }
/**
* Tries to set task's bound in a way that it won't collide with any other task. By colliding
@@ -82,154 +114,104 @@ class LaunchingTaskPositioner {
*/
void updateDefaultBounds(TaskRecord task, ArrayList<TaskRecord> tasks,
@Nullable ActivityInfo.WindowLayout windowLayout) {
- updateAvailableRect(task, mAvailableRect);
-
+ if (!mDefaultStartBoundsConfigurationSet) {
+ return;
+ }
if (windowLayout == null) {
- positionCenter(task, tasks, mAvailableRect, getFreeformWidth(mAvailableRect),
- getFreeformHeight(mAvailableRect));
+ positionCenter(task, tasks, mDefaultFreeformWidth, mDefaultFreeformHeight);
return;
}
- int width = getFinalWidth(windowLayout, mAvailableRect);
- int height = getFinalHeight(windowLayout, mAvailableRect);
+ int width = getFinalWidth(windowLayout);
+ int height = getFinalHeight(windowLayout);
int verticalGravity = windowLayout.gravity & Gravity.VERTICAL_GRAVITY_MASK;
int horizontalGravity = windowLayout.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
if (verticalGravity == Gravity.TOP) {
if (horizontalGravity == Gravity.RIGHT) {
- positionTopRight(task, tasks, mAvailableRect, width, height);
+ positionTopRight(task, tasks, width, height);
} else {
- positionTopLeft(task, tasks, mAvailableRect, width, height);
+ positionTopLeft(task, tasks, width, height);
}
} else if (verticalGravity == Gravity.BOTTOM) {
if (horizontalGravity == Gravity.RIGHT) {
- positionBottomRight(task, tasks, mAvailableRect, width, height);
+ positionBottomRight(task, tasks, width, height);
} else {
- positionBottomLeft(task, tasks, mAvailableRect, width, height);
+ positionBottomLeft(task, tasks, width, height);
}
} else {
// Some fancy gravity setting that we don't support yet. We just put the activity in the
// center.
Slog.w(TAG, "Received unsupported gravity: " + windowLayout.gravity
+ ", positioning in the center instead.");
- positionCenter(task, tasks, mAvailableRect, width, height);
+ positionCenter(task, tasks, width, height);
}
}
- private void updateAvailableRect(TaskRecord task, Rect availableRect) {
- final Rect stackBounds = task.getStack().mBounds;
-
- if (stackBounds != null) {
- availableRect.set(stackBounds);
- } else {
- task.getStack().getDisplay().mDisplay.getSize(mDisplaySize);
- availableRect.set(0, 0, mDisplaySize.x, mDisplaySize.y);
- }
- }
-
- @VisibleForTesting
- static int getFreeformStartLeft(Rect bounds) {
- return bounds.left + bounds.width() / MARGIN_SIZE_DENOMINATOR;
- }
-
- @VisibleForTesting
- static int getFreeformStartTop(Rect bounds) {
- return bounds.top + bounds.height() / MARGIN_SIZE_DENOMINATOR;
- }
-
- @VisibleForTesting
- static int getFreeformWidth(Rect bounds) {
- return bounds.width() / WINDOW_SIZE_DENOMINATOR;
- }
-
- @VisibleForTesting
- static int getFreeformHeight(Rect bounds) {
- return bounds.height() / WINDOW_SIZE_DENOMINATOR;
- }
-
- @VisibleForTesting
- static int getHorizontalStep(Rect bounds) {
- return Math.max(bounds.width() / STEP_DENOMINATOR, MINIMAL_STEP);
- }
-
- @VisibleForTesting
- static int getVerticalStep(Rect bounds) {
- return Math.max(bounds.height() / STEP_DENOMINATOR, MINIMAL_STEP);
- }
-
-
-
- private int getFinalWidth(ActivityInfo.WindowLayout windowLayout, Rect availableRect) {
- int width = getFreeformWidth(availableRect);
+ private int getFinalWidth(ActivityInfo.WindowLayout windowLayout) {
+ int width = mDefaultFreeformWidth;
if (windowLayout.width > 0) {
width = windowLayout.width;
}
if (windowLayout.widthFraction > 0) {
- width = (int) (availableRect.width() * windowLayout.widthFraction);
+ width = (int) (mAvailableRect.width() * windowLayout.widthFraction);
}
return width;
}
- private int getFinalHeight(ActivityInfo.WindowLayout windowLayout, Rect availableRect) {
- int height = getFreeformHeight(availableRect);
+ private int getFinalHeight(ActivityInfo.WindowLayout windowLayout) {
+ int height = mDefaultFreeformHeight;
if (windowLayout.height > 0) {
height = windowLayout.height;
}
if (windowLayout.heightFraction > 0) {
- height = (int) (availableRect.height() * windowLayout.heightFraction);
+ height = (int) (mAvailableRect.height() * windowLayout.heightFraction);
}
return height;
}
- private void positionBottomLeft(TaskRecord task, ArrayList<TaskRecord> tasks,
- Rect availableRect, int width, int height) {
- mTmpProposal.set(availableRect.left, availableRect.bottom - height,
- availableRect.left + width, availableRect.bottom);
- position(task, tasks, availableRect, mTmpProposal, !ALLOW_RESTART,
- SHIFT_POLICY_HORIZONTAL_RIGHT);
+ private void positionBottomLeft(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
+ int height) {
+ mTmpProposal.set(mAvailableRect.left, mAvailableRect.bottom - height,
+ mAvailableRect.left + width, mAvailableRect.bottom);
+ position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_RIGHT);
}
- private void positionBottomRight(TaskRecord task, ArrayList<TaskRecord> tasks,
- Rect availableRect, int width, int height) {
- mTmpProposal.set(availableRect.right - width, availableRect.bottom - height,
- availableRect.right, availableRect.bottom);
- position(task, tasks, availableRect, mTmpProposal, !ALLOW_RESTART,
- SHIFT_POLICY_HORIZONTAL_LEFT);
+ private void positionBottomRight(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
+ int height) {
+ mTmpProposal.set(mAvailableRect.right - width, mAvailableRect.bottom - height,
+ mAvailableRect.right, mAvailableRect.bottom);
+ position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_LEFT);
}
- private void positionTopLeft(TaskRecord task, ArrayList<TaskRecord> tasks,
- Rect availableRect, int width, int height) {
- mTmpProposal.set(availableRect.left, availableRect.top,
- availableRect.left + width, availableRect.top + height);
- position(task, tasks, availableRect, mTmpProposal, !ALLOW_RESTART,
- SHIFT_POLICY_HORIZONTAL_RIGHT);
+ private void positionTopLeft(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
+ int height) {
+ mTmpProposal.set(mAvailableRect.left, mAvailableRect.top,
+ mAvailableRect.left + width, mAvailableRect.top + height);
+ position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_RIGHT);
}
- private void positionTopRight(TaskRecord task, ArrayList<TaskRecord> tasks,
- Rect availableRect, int width, int height) {
- mTmpProposal.set(availableRect.right - width, availableRect.top,
- availableRect.right, availableRect.top + height);
- position(task, tasks, availableRect, mTmpProposal, !ALLOW_RESTART,
- SHIFT_POLICY_HORIZONTAL_LEFT);
+ private void positionTopRight(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
+ int height) {
+ mTmpProposal.set(mAvailableRect.right - width, mAvailableRect.top,
+ mAvailableRect.right, mAvailableRect.top + height);
+ position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_LEFT);
}
- private void positionCenter(TaskRecord task, ArrayList<TaskRecord> tasks,
- Rect availableRect, int width, int height) {
- final int defaultFreeformLeft = getFreeformStartLeft(availableRect);
- final int defaultFreeformTop = getFreeformStartTop(availableRect);
- mTmpProposal.set(defaultFreeformLeft, defaultFreeformTop,
- defaultFreeformLeft + width, defaultFreeformTop + height);
- position(task, tasks, availableRect, mTmpProposal, ALLOW_RESTART,
- SHIFT_POLICY_DIAGONAL_DOWN);
+ private void positionCenter(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
+ int height) {
+ mTmpProposal.set(mDefaultFreeformStartX, mDefaultFreeformStartY,
+ mDefaultFreeformStartX + width, mDefaultFreeformStartY + height);
+ position(task, tasks, mTmpProposal, ALLOW_RESTART, SHIFT_POLICY_DIAGONAL_DOWN);
}
- private void position(TaskRecord task, ArrayList<TaskRecord> tasks, Rect availableRect,
- Rect proposal, boolean allowRestart, int shiftPolicy) {
+ private void position(TaskRecord task, ArrayList<TaskRecord> tasks, Rect proposal,
+ boolean allowRestart, int shiftPolicy) {
mTmpOriginal.set(proposal);
boolean restarted = false;
while (boundsConflict(proposal, tasks)) {
// Unfortunately there is already a task at that spot, so we need to look for some
// other place.
- shiftStartingPoint(proposal, availableRect, shiftPolicy);
- if (shiftedTooFar(proposal, availableRect, shiftPolicy)) {
+ shiftStartingPoint(proposal, shiftPolicy);
+ if (shiftedToFar(proposal, shiftPolicy)) {
// We don't want the task to go outside of the stack, because it won't look
// nice. Depending on the starting point we either restart, or immediately give up.
if (!allowRestart) {
@@ -238,13 +220,13 @@ class LaunchingTaskPositioner {
}
// We must have started not from the top. Let's restart from there because there
// might be some space there.
- proposal.set(availableRect.left, availableRect.top,
- availableRect.left + proposal.width(),
- availableRect.top + proposal.height());
+ proposal.set(mAvailableRect.left, mAvailableRect.top,
+ mAvailableRect.left + proposal.width(),
+ mAvailableRect.top + proposal.height());
restarted = true;
}
- if (restarted && (proposal.left > getFreeformStartLeft(availableRect)
- || proposal.top > getFreeformStartTop(availableRect))) {
+ if (restarted && (proposal.left > mDefaultFreeformStartX
+ || proposal.top > mDefaultFreeformStartY)) {
// If we restarted and crossed the initial position, let's not struggle anymore.
// The user already must have ton of tasks visible, we can just smack the new
// one in the center.
@@ -255,30 +237,27 @@ class LaunchingTaskPositioner {
task.updateOverrideConfiguration(proposal);
}
- private boolean shiftedTooFar(Rect start, Rect availableRect, int shiftPolicy) {
+ private boolean shiftedToFar(Rect start, int shiftPolicy) {
switch (shiftPolicy) {
case SHIFT_POLICY_HORIZONTAL_LEFT:
- return start.left < availableRect.left;
+ return start.left < mAvailableRect.left;
case SHIFT_POLICY_HORIZONTAL_RIGHT:
- return start.right > availableRect.right;
+ return start.right > mAvailableRect.right;
default: // SHIFT_POLICY_DIAGONAL_DOWN
- return start.right > availableRect.right || start.bottom > availableRect.bottom;
+ return start.right > mAvailableRect.right || start.bottom > mAvailableRect.bottom;
}
}
- private void shiftStartingPoint(Rect posposal, Rect availableRect, int shiftPolicy) {
- final int defaultFreeformStepHorizontal = getHorizontalStep(availableRect);
- final int defaultFreeformStepVertical = getVerticalStep(availableRect);
-
+ private void shiftStartingPoint(Rect posposal, int shiftPolicy) {
switch (shiftPolicy) {
case SHIFT_POLICY_HORIZONTAL_LEFT:
- posposal.offset(-defaultFreeformStepHorizontal, 0);
+ posposal.offset(-mDefaultFreeformStepHorizontal, 0);
break;
case SHIFT_POLICY_HORIZONTAL_RIGHT:
- posposal.offset(defaultFreeformStepHorizontal, 0);
+ posposal.offset(mDefaultFreeformStepHorizontal, 0);
break;
default: // SHIFT_POLICY_DIAGONAL_DOWN:
- posposal.offset(defaultFreeformStepHorizontal, defaultFreeformStepVertical);
+ posposal.offset(mDefaultFreeformStepHorizontal, mDefaultFreeformStepVertical);
break;
}
}
@@ -317,4 +296,8 @@ class LaunchingTaskPositioner {
return Math.abs(first.right - second.right) < BOUNDS_CONFLICT_MIN_DISTANCE
&& Math.abs(first.bottom - second.bottom) < BOUNDS_CONFLICT_MIN_DISTANCE;
}
+
+ void reset() {
+ mDefaultStartBoundsConfigurationSet = false;
+ }
}
diff --git a/com/android/server/am/LockTaskController.java b/com/android/server/am/LockTaskController.java
index 940f9051..72b5de88 100644
--- a/com/android/server/am/LockTaskController.java
+++ b/com/android/server/am/LockTaskController.java
@@ -19,6 +19,7 @@ package com.android.server.am;
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.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.StatusBarManager.DISABLE_BACK;
import static android.app.StatusBarManager.DISABLE_HOME;
import static android.app.StatusBarManager.DISABLE_MASK;
@@ -58,6 +59,7 @@ import android.provider.Settings;
import android.util.Slog;
import android.util.SparseArray;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.widget.LockPatternUtils;
@@ -431,7 +433,7 @@ public class LockTaskController {
mWindowManager.executeAppTransition();
} else if (lockTaskModeState != LOCK_TASK_MODE_NONE) {
mSupervisor.handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED,
- DEFAULT_DISPLAY, task.getStack(), true /* forceNonResizable */);
+ DEFAULT_DISPLAY, task.getStackId(), true /* forceNonResizable */);
}
}
@@ -492,7 +494,11 @@ public class LockTaskController {
}
for (int displayNdx = mSupervisor.getChildCount() - 1; displayNdx >= 0; --displayNdx) {
- mSupervisor.getChildAt(displayNdx).onLockTaskPackagesUpdated();
+ ArrayList<ActivityStack> stacks = mSupervisor.getChildAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ stack.onLockTaskPackagesUpdatedLocked();
+ }
}
final ActivityRecord r = mSupervisor.topRunningActivityLocked();
diff --git a/com/android/server/am/ProcessRecord.java b/com/android/server/am/ProcessRecord.java
index e8477231..0e318d9c 100644
--- a/com/android/server/am/ProcessRecord.java
+++ b/com/android/server/am/ProcessRecord.java
@@ -27,7 +27,6 @@ import android.util.Slog;
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.app.procstats.ProcessState;
import com.android.internal.os.BatteryStatsImpl;
-import com.android.server.am.proto.ProcessRecordProto;
import android.app.ActivityManager;
import android.app.Dialog;
@@ -45,7 +44,6 @@ import android.os.Trace;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.TimeUtils;
-import android.util.proto.ProtoOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -623,22 +621,6 @@ final class ProcessRecord {
}
}
- public void writeToProto(ProtoOutputStream proto, long fieldId) {
- long token = proto.start(fieldId);
- proto.write(ProcessRecordProto.PID, pid);
- proto.write(ProcessRecordProto.PROCESS_NAME, processName);
- if (info.uid < Process.FIRST_APPLICATION_UID) {
- proto.write(ProcessRecordProto.UID, uid);
- } else {
- proto.write(ProcessRecordProto.USER_ID, userId);
- proto.write(ProcessRecordProto.APP_ID, UserHandle.getAppId(info.uid));
- if (uid != info.uid) {
- proto.write(ProcessRecordProto.ISOLATED_APP_ID, UserHandle.getAppId(uid));
- }
- }
- proto.end(token);
- }
-
public String toShortString() {
if (shortStringName != null) {
return shortStringName;
diff --git a/com/android/server/am/ReceiverList.java b/com/android/server/am/ReceiverList.java
index a9890631..6ade7361 100644
--- a/com/android/server/am/ReceiverList.java
+++ b/com/android/server/am/ReceiverList.java
@@ -21,8 +21,6 @@ import android.os.Binder;
import android.os.IBinder;
import android.util.PrintWriterPrinter;
import android.util.Printer;
-import android.util.proto.ProtoOutputStream;
-import com.android.server.am.proto.ReceiverListProto;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -43,7 +41,7 @@ final class ReceiverList extends ArrayList<BroadcastFilter>
boolean linkedToDeath = false;
String stringName;
-
+
ReceiverList(ActivityManagerService _owner, ProcessRecord _app,
int _pid, int _uid, int _userId, IIntentReceiver _receiver) {
owner = _owner;
@@ -61,31 +59,12 @@ final class ReceiverList extends ArrayList<BroadcastFilter>
public int hashCode() {
return System.identityHashCode(this);
}
-
+
public void binderDied() {
linkedToDeath = false;
owner.unregisterReceiver(receiver);
}
-
- void writeToProto(ProtoOutputStream proto, long fieldId) {
- long token = proto.start(fieldId);
- app.writeToProto(proto, ReceiverListProto.APP);
- proto.write(ReceiverListProto.PID, pid);
- proto.write(ReceiverListProto.UID, uid);
- proto.write(ReceiverListProto.USER, userId);
- if (curBroadcast != null) {
- curBroadcast.writeToProto(proto, ReceiverListProto.CURRENT);
- }
- proto.write(ReceiverListProto.LINKED_TO_DEATH, linkedToDeath);
- final int N = size();
- for (int i=0; i<N; i++) {
- BroadcastFilter bf = get(i);
- bf.writeToProto(proto, ReceiverListProto.FILTERS);
- }
- proto.write(ReceiverListProto.HEX_HASH, Integer.toHexString(System.identityHashCode(this)));
- proto.end(token);
- }
-
+
void dumpLocal(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("app="); pw.print(app != null ? app.toShortString() : null);
pw.print(" pid="); pw.print(pid); pw.print(" uid="); pw.print(uid);
@@ -95,7 +74,7 @@ final class ReceiverList extends ArrayList<BroadcastFilter>
pw.print(" linkedToDeath="); pw.println(linkedToDeath);
}
}
-
+
void dump(PrintWriter pw, String prefix) {
Printer pr = new PrintWriterPrinter(pw);
dumpLocal(pw, prefix);
@@ -110,7 +89,7 @@ final class ReceiverList extends ArrayList<BroadcastFilter>
bf.dumpInReceiverList(pw, pr, p2);
}
}
-
+
public String toString() {
if (stringName != null) {
return stringName;
diff --git a/com/android/server/am/RecentTasks.java b/com/android/server/am/RecentTasks.java
index 78274bdc..365c5b1d 100644
--- a/com/android/server/am/RecentTasks.java
+++ b/com/android/server/am/RecentTasks.java
@@ -16,25 +16,15 @@
package com.android.server.am;
-import static android.app.ActivityManager.FLAG_AND_UNLOCKED;
-import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE;
-import static android.app.ActivityManager.RECENT_WITH_EXCLUDED;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
-
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS_TRIM_TASKS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RECENTS;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
import com.google.android.collect.Sets;
@@ -47,87 +37,43 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
-import android.content.pm.ParceledListSlice;
-import android.content.pm.UserInfo;
-import android.content.res.Resources;
import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.os.Bundle;
import android.os.Environment;
-import android.os.IBinder;
import android.os.RemoteException;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.util.ArraySet;
-import android.util.MutableBoolean;
-import android.util.MutableInt;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.am.ActivityStack.ActivityState;
-
import java.io.File;
-import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Set;
-import java.util.concurrent.TimeUnit;
/**
- * Class for managing the recent tasks list. The list is ordered by most recent (index 0) to the
- * least recent.
+ * Class for managing the recent tasks list.
*/
-class RecentTasks {
+class RecentTasks extends ArrayList<TaskRecord> {
private static final String TAG = TAG_WITH_CLASS_NAME ? "RecentTasks" : TAG_AM;
private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
- private static final boolean TRIMMED = true;
+ // Maximum number recent bitmaps to keep in memory.
+ private static final int MAX_RECENT_BITMAPS = 3;
private static final int DEFAULT_INITIAL_CAPACITY = 5;
// Whether or not to move all affiliated tasks to the front when one of the tasks is launched
private static final boolean MOVE_AFFILIATED_TASKS_TO_FRONT = false;
- // Comparator to sort by taskId
- private static final Comparator<TaskRecord> TASK_ID_COMPARATOR =
- (lhs, rhs) -> rhs.taskId - lhs.taskId;
-
- // Placeholder variables to keep track of activities/apps that are no longer avialble while
- // iterating through the recents list
- private static final ActivityInfo NO_ACTIVITY_INFO_TOKEN = new ActivityInfo();
- private static final ApplicationInfo NO_APPLICATION_INFO_TOKEN = new ApplicationInfo();
-
- /**
- * Callbacks made when manipulating the list.
- */
- interface Callbacks {
- /**
- * Called when a task is added to the recent tasks list.
- */
- void onRecentTaskAdded(TaskRecord task);
-
- /**
- * Called when a task is removed from the recent tasks list.
- */
- void onRecentTaskRemoved(TaskRecord task, boolean wasTrimmed);
- }
-
/**
* Save recent tasks information across reboots.
*/
private final TaskPersister mTaskPersister;
private final ActivityManagerService mService;
- private final UserController mUserController;
-
- /**
- * Mapping of user id -> whether recent tasks have been loaded for that user.
- */
private final SparseBooleanArray mUsersWithRecentsLoaded = new SparseBooleanArray(
DEFAULT_INITIAL_CAPACITY);
@@ -135,106 +81,21 @@ class RecentTasks {
* Stores for each user task ids that are taken by tasks residing in persistent storage. These
* tasks may or may not currently be in memory.
*/
- private final SparseArray<SparseBooleanArray> mPersistedTaskIds = new SparseArray<>(
+ final SparseArray<SparseBooleanArray> mPersistedTaskIds = new SparseArray<>(
DEFAULT_INITIAL_CAPACITY);
- // List of all active recent tasks
- private final ArrayList<TaskRecord> mTasks = new ArrayList<>();
- private final ArrayList<Callbacks> mCallbacks = new ArrayList<>();
-
- // These values are generally loaded from resources, but can be set dynamically in the tests
- private boolean mHasVisibleRecentTasks;
- private int mGlobalMaxNumTasks;
- private int mMinNumVisibleTasks;
- private int mMaxNumVisibleTasks;
- private long mActiveTasksSessionDurationMs;
-
// Mainly to avoid object recreation on multiple calls.
- private final ArrayList<TaskRecord> mTmpRecents = new ArrayList<>();
+ private final ArrayList<TaskRecord> mTmpRecents = new ArrayList<TaskRecord>();
private final HashMap<ComponentName, ActivityInfo> mTmpAvailActCache = new HashMap<>();
private final HashMap<String, ApplicationInfo> mTmpAvailAppCache = new HashMap<>();
- private final SparseBooleanArray mTmpQuietProfileUserIds = new SparseBooleanArray();
+ private final ActivityInfo mTmpActivityInfo = new ActivityInfo();
+ private final ApplicationInfo mTmpAppInfo = new ApplicationInfo();
- @VisibleForTesting
- RecentTasks(ActivityManagerService service, TaskPersister taskPersister,
- UserController userController) {
+ RecentTasks(ActivityManagerService service, ActivityStackSupervisor mStackSupervisor) {
+ File systemDir = Environment.getDataSystemDirectory();
mService = service;
- mUserController = userController;
- mTaskPersister = taskPersister;
- mGlobalMaxNumTasks = ActivityManager.getMaxRecentTasksStatic();
- mHasVisibleRecentTasks = true;
- }
-
- RecentTasks(ActivityManagerService service, ActivityStackSupervisor stackSupervisor) {
- final File systemDir = Environment.getDataSystemDirectory();
- final Resources res = service.mContext.getResources();
- mService = service;
- mUserController = service.mUserController;
- mTaskPersister = new TaskPersister(systemDir, stackSupervisor, service, this);
- mGlobalMaxNumTasks = ActivityManager.getMaxRecentTasksStatic();
- mHasVisibleRecentTasks = res.getBoolean(com.android.internal.R.bool.config_hasRecents);
- loadParametersFromResources(service.mContext.getResources());
- }
-
- @VisibleForTesting
- void setParameters(int minNumVisibleTasks, int maxNumVisibleTasks,
- long activeSessionDurationMs) {
- mMinNumVisibleTasks = minNumVisibleTasks;
- mMaxNumVisibleTasks = maxNumVisibleTasks;
- mActiveTasksSessionDurationMs = activeSessionDurationMs;
- }
-
- @VisibleForTesting
- void setGlobalMaxNumTasks(int globalMaxNumTasks) {
- mGlobalMaxNumTasks = globalMaxNumTasks;
- }
-
- /**
- * Loads the parameters from the system resources.
- */
- @VisibleForTesting
- void loadParametersFromResources(Resources res) {
- if (ActivityManager.isLowRamDeviceStatic()) {
- mMinNumVisibleTasks = res.getInteger(
- com.android.internal.R.integer.config_minNumVisibleRecentTasks_lowRam);
- mMaxNumVisibleTasks = res.getInteger(
- com.android.internal.R.integer.config_maxNumVisibleRecentTasks_lowRam);
- } else if (SystemProperties.getBoolean("ro.recents.grid", false)) {
- mMinNumVisibleTasks = res.getInteger(
- com.android.internal.R.integer.config_minNumVisibleRecentTasks_grid);
- mMaxNumVisibleTasks = res.getInteger(
- com.android.internal.R.integer.config_maxNumVisibleRecentTasks_grid);
- } else {
- mMinNumVisibleTasks = res.getInteger(
- com.android.internal.R.integer.config_minNumVisibleRecentTasks);
- mMaxNumVisibleTasks = res.getInteger(
- com.android.internal.R.integer.config_maxNumVisibleRecentTasks);
- }
- final int sessionDurationHrs = res.getInteger(
- com.android.internal.R.integer.config_activeTaskDurationHours);
- mActiveTasksSessionDurationMs = (sessionDurationHrs > 0)
- ? TimeUnit.HOURS.toMillis(sessionDurationHrs)
- : -1;
- }
-
- void registerCallback(Callbacks callback) {
- mCallbacks.add(callback);
- }
-
- void unregisterCallback(Callbacks callback) {
- mCallbacks.remove(callback);
- }
-
- private void notifyTaskAdded(TaskRecord task) {
- for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).onRecentTaskAdded(task);
- }
- }
-
- private void notifyTaskRemoved(TaskRecord task, boolean wasTrimmed) {
- for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).onRecentTaskRemoved(task, wasTrimmed);
- }
+ mTaskPersister = new TaskPersister(systemDir, mStackSupervisor, service, this);
+ mStackSupervisor.setRecentTasks(this);
}
/**
@@ -245,7 +106,6 @@ class RecentTasks {
*/
void loadUserRecentsLocked(int userId) {
if (mUsersWithRecentsLoaded.get(userId)) {
- // User already loaded, return early
return;
}
@@ -254,14 +114,14 @@ class RecentTasks {
// Check if any tasks are added before recents is loaded
final SparseBooleanArray preaddedTasks = new SparseBooleanArray();
- for (final TaskRecord task : mTasks) {
+ for (final TaskRecord task : this) {
if (task.userId == userId && shouldPersistTaskLocked(task)) {
preaddedTasks.put(task.taskId, true);
}
}
Slog.i(TAG, "Loading recents for user " + userId + " into memory.");
- mTasks.addAll(mTaskPersister.restoreTasksForUserLocked(userId, preaddedTasks));
+ addAll(mTaskPersister.restoreTasksForUserLocked(userId, preaddedTasks));
cleanupLocked(userId);
mUsersWithRecentsLoaded.put(userId, true);
@@ -280,25 +140,11 @@ class RecentTasks {
}
}
- /**
- * @return whether the {@param taskId} is currently in use for the given user.
- */
- boolean containsTaskId(int taskId, int userId) {
+ boolean taskIdTakenForUserLocked(int taskId, int userId) {
loadPersistedTaskIdsForUserLocked(userId);
return mPersistedTaskIds.get(userId).get(taskId);
}
- /**
- * @return all the task ids for the user with the given {@param userId}.
- */
- SparseBooleanArray getTaskIdsForUser(int userId) {
- loadPersistedTaskIdsForUserLocked(userId);
- return mPersistedTaskIds.get(userId);
- }
-
- /**
- * Kicks off the task persister to write any pending tasks to disk.
- */
void notifyTaskPersisterLocked(TaskRecord task, boolean flush) {
final ActivityStack stack = task != null ? task.getStack() : null;
if (stack != null && stack.isHomeOrRecentsStack()) {
@@ -318,8 +164,8 @@ class RecentTasks {
mPersistedTaskIds.valueAt(i).clear();
}
}
- for (int i = mTasks.size() - 1; i >= 0; i--) {
- final TaskRecord task = mTasks.get(i);
+ for (int i = size() - 1; i >= 0; i--) {
+ final TaskRecord task = get(i);
if (shouldPersistTaskLocked(task)) {
// Set of persisted taskIds for task.userId should not be null here
// TODO Investigate why it can happen. For now initialize with an empty set
@@ -334,12 +180,12 @@ class RecentTasks {
}
private static boolean shouldPersistTaskLocked(TaskRecord task) {
- final ActivityStack stack = task.getStack();
+ final ActivityStack<?> stack = task.getStack();
return task.isPersistable && (stack == null || !stack.isHomeOrRecentsStack());
}
void onSystemReadyLocked() {
- mTasks.clear();
+ clear();
mTaskPersister.startPersisting();
}
@@ -379,6 +225,14 @@ class RecentTasks {
return usersWithRecentsLoaded;
}
+ private void unloadUserRecentsLocked(int userId) {
+ if (mUsersWithRecentsLoaded.get(userId)) {
+ Slog.i(TAG, "Unloading recents for user " + userId + " from memory.");
+ mUsersWithRecentsLoaded.delete(userId);
+ removeTasksForUserLocked(userId);
+ }
+ }
+
/**
* Removes recent tasks and any other state kept in memory for the passed in user. Does not
* touch the information present on persistent storage.
@@ -386,36 +240,44 @@ class RecentTasks {
* @param userId the id of the user
*/
void unloadUserDataFromMemoryLocked(int userId) {
- if (mUsersWithRecentsLoaded.get(userId)) {
- Slog.i(TAG, "Unloading recents for user " + userId + " from memory.");
- mUsersWithRecentsLoaded.delete(userId);
- removeTasksForUserLocked(userId);
- }
+ unloadUserRecentsLocked(userId);
mPersistedTaskIds.delete(userId);
mTaskPersister.unloadUserDataFromMemory(userId);
}
+ TaskRecord taskForIdLocked(int id) {
+ final int recentsCount = size();
+ for (int i = 0; i < recentsCount; i++) {
+ TaskRecord tr = get(i);
+ if (tr.taskId == id) {
+ return tr;
+ }
+ }
+ return null;
+ }
+
/** Remove recent tasks for a user. */
- private void removeTasksForUserLocked(int userId) {
+ void removeTasksForUserLocked(int userId) {
if(userId <= 0) {
Slog.i(TAG, "Can't remove recent task on user " + userId);
return;
}
- for (int i = mTasks.size() - 1; i >= 0; --i) {
- TaskRecord tr = mTasks.get(i);
+ for (int i = size() - 1; i >= 0; --i) {
+ TaskRecord tr = get(i);
if (tr.userId == userId) {
if(DEBUG_TASKS) Slog.i(TAG_TASKS,
"remove RecentTask " + tr + " when finishing user" + userId);
- remove(mTasks.get(i));
+ remove(i);
+ tr.removedFromRecents();
}
}
}
void onPackagesSuspendedChanged(String[] packages, boolean suspended, int userId) {
final Set<String> packageNames = Sets.newHashSet(packages);
- for (int i = mTasks.size() - 1; i >= 0; --i) {
- final TaskRecord tr = mTasks.get(i);
+ for (int i = size() - 1; i >= 0; --i) {
+ final TaskRecord tr = get(i);
if (tr.realActivity != null
&& packageNames.contains(tr.realActivity.getPackageName())
&& tr.userId == userId
@@ -424,36 +286,7 @@ class RecentTasks {
notifyTaskPersisterLocked(tr, false);
}
}
- }
-
- void removeTasksByPackageName(String packageName, int userId) {
- for (int i = mTasks.size() - 1; i >= 0; --i) {
- final TaskRecord tr = mTasks.get(i);
- final String taskPackageName =
- tr.getBaseIntent().getComponent().getPackageName();
- if (tr.userId != userId) return;
- if (!taskPackageName.equals(packageName)) return;
-
- mService.mStackSupervisor.removeTaskByIdLocked(tr.taskId, true, REMOVE_FROM_RECENTS);
- }
- }
-
- void cleanupDisabledPackageTasksLocked(String packageName, Set<String> filterByClasses,
- int userId) {
- for (int i = mTasks.size() - 1; i >= 0; --i) {
- final TaskRecord tr = mTasks.get(i);
- if (userId != UserHandle.USER_ALL && tr.userId != userId) {
- continue;
- }
- ComponentName cn = tr.intent.getComponent();
- final boolean sameComponent = cn != null && cn.getPackageName().equals(packageName)
- && (filterByClasses == null || filterByClasses.contains(cn.getClassName()));
- if (sameComponent) {
- mService.mStackSupervisor.removeTaskByIdLocked(tr.taskId, false,
- REMOVE_FROM_RECENTS);
- }
- }
}
/**
@@ -462,28 +295,24 @@ class RecentTasks {
* of affiliations.
*/
void cleanupLocked(int userId) {
- int recentsCount = mTasks.size();
+ int recentsCount = size();
if (recentsCount == 0) {
// Happens when called from the packagemanager broadcast before boot,
// or just any empty list.
return;
}
- // Clear the temp lists
- mTmpAvailActCache.clear();
- mTmpAvailAppCache.clear();
-
final IPackageManager pm = AppGlobals.getPackageManager();
for (int i = recentsCount - 1; i >= 0; i--) {
- final TaskRecord task = mTasks.get(i);
+ final TaskRecord task = get(i);
if (userId != UserHandle.USER_ALL && task.userId != userId) {
// Only look at tasks for the user ID of interest.
continue;
}
if (task.autoRemoveRecents && task.getTopActivity() == null) {
// This situation is broken, and we should just get rid of it now.
- mTasks.remove(i);
- notifyTaskRemoved(task, !TRIMMED);
+ remove(i);
+ task.removedFromRecents();
Slog.w(TAG, "Removing auto-remove without activity: " + task);
continue;
}
@@ -502,11 +331,11 @@ class RecentTasks {
continue;
}
if (ai == null) {
- ai = NO_ACTIVITY_INFO_TOKEN;
+ ai = mTmpActivityInfo;
}
mTmpAvailActCache.put(task.realActivity, ai);
}
- if (ai == NO_ACTIVITY_INFO_TOKEN) {
+ if (ai == mTmpActivityInfo) {
// This could be either because the activity no longer exists, or the
// app is temporarily gone. For the former we want to remove the recents
// entry; for the latter we want to mark it as unavailable.
@@ -521,15 +350,15 @@ class RecentTasks {
continue;
}
if (app == null) {
- app = NO_APPLICATION_INFO_TOKEN;
+ app = mTmpAppInfo;
}
mTmpAvailAppCache.put(task.realActivity.getPackageName(), app);
}
- if (app == NO_APPLICATION_INFO_TOKEN
+ if (app == mTmpAppInfo
|| (app.flags & ApplicationInfo.FLAG_INSTALLED) == 0) {
// Doesn't exist any more! Good-bye.
- mTasks.remove(i);
- notifyTaskRemoved(task, !TRIMMED);
+ remove(i);
+ task.removedFromRecents();
Slog.w(TAG, "Removing no longer valid recent: " + task);
continue;
} else {
@@ -561,197 +390,121 @@ class RecentTasks {
// Verify the affiliate chain for each task.
int i = 0;
- recentsCount = mTasks.size();
+ recentsCount = size();
while (i < recentsCount) {
i = processNextAffiliateChainLocked(i);
}
// recent tasks are now in sorted, affiliated order.
}
- /**
- * @return whether the given {@param task} can be added to the list without causing another
- * task to be trimmed as a result of that add.
- */
- private boolean canAddTaskWithoutTrim(TaskRecord task) {
- return findTrimIndexForAddTask(task) == -1;
- }
-
- /**
- * Returns the list of {@link ActivityManager.AppTask}s.
- */
- ArrayList<IBinder> getAppTasksList(int callingUid, String callingPackage) {
- final ArrayList<IBinder> list = new ArrayList<>();
- final int size = mTasks.size();
- for (int i = 0; i < size; i++) {
- final TaskRecord tr = mTasks.get(i);
- // Skip tasks that do not match the caller. We don't need to verify
- // callingPackage, because we are also limiting to callingUid and know
- // that will limit to the correct security sandbox.
- if (tr.effectiveUid != callingUid) {
- continue;
- }
- Intent intent = tr.getBaseIntent();
- if (intent == null || !callingPackage.equals(intent.getComponent().getPackageName())) {
- continue;
- }
- ActivityManager.RecentTaskInfo taskInfo = createRecentTaskInfo(tr);
- AppTaskImpl taskImpl = new AppTaskImpl(mService, taskInfo.persistentId, callingUid);
- list.add(taskImpl.asBinder());
- }
- return list;
- }
-
- /**
- * @return the list of recent tasks for presentation.
- */
- ParceledListSlice<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum, int flags,
- boolean getTasksAllowed, boolean getDetailedTasks, int userId, int callingUid) {
- final boolean withExcluded = (flags & RECENT_WITH_EXCLUDED) != 0;
-
- if (!mService.isUserRunning(userId, FLAG_AND_UNLOCKED)) {
- Slog.i(TAG, "user " + userId + " is still locked. Cannot load recents");
- return ParceledListSlice.emptyList();
+ private final boolean moveAffiliatedTasksToFront(TaskRecord task, int taskIndex) {
+ int recentsCount = size();
+ TaskRecord top = task;
+ int topIndex = taskIndex;
+ while (top.mNextAffiliate != null && topIndex > 0) {
+ top = top.mNextAffiliate;
+ topIndex--;
}
- loadUserRecentsLocked(userId);
-
- final Set<Integer> includedUsers = mUserController.getProfileIds(userId);
- includedUsers.add(Integer.valueOf(userId));
-
- final ArrayList<ActivityManager.RecentTaskInfo> res = new ArrayList<>();
- final int size = mTasks.size();
- int numVisibleTasks = 0;
- for (int i = 0; i < size; i++) {
- final TaskRecord tr = mTasks.get(i);
-
- if (isVisibleRecentTask(tr)) {
- numVisibleTasks++;
- if (isInVisibleRange(tr, numVisibleTasks)) {
- // Fall through
- } else {
- // Not in visible range
- continue;
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: adding affilliates starting at "
+ + topIndex + " from intial " + taskIndex);
+ // Find the end of the chain, doing a sanity check along the way.
+ boolean sane = top.mAffiliatedTaskId == task.mAffiliatedTaskId;
+ int endIndex = topIndex;
+ TaskRecord prev = top;
+ while (endIndex < recentsCount) {
+ TaskRecord cur = get(endIndex);
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: looking at next chain @"
+ + endIndex + " " + cur);
+ if (cur == top) {
+ // Verify start of the chain.
+ if (cur.mNextAffiliate != null || cur.mNextAffiliateTaskId != INVALID_TASK_ID) {
+ Slog.wtf(TAG, "Bad chain @" + endIndex
+ + ": first task has next affiliate: " + prev);
+ sane = false;
+ break;
}
} else {
- // Not visible
- continue;
- }
-
- // Skip remaining tasks once we reach the requested size
- if (res.size() >= maxNum) {
- continue;
- }
-
- // Only add calling user or related users recent tasks
- if (!includedUsers.contains(Integer.valueOf(tr.userId))) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, not user: " + tr);
- continue;
- }
-
- if (tr.realActivitySuspended) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, activity suspended: " + tr);
- continue;
- }
-
- // Return the entry if desired by the caller. We always return
- // the first entry, because callers always expect this to be the
- // foreground app. We may filter others if the caller has
- // not supplied RECENT_WITH_EXCLUDED and there is some reason
- // we should exclude the entry.
-
- if (i == 0
- || withExcluded
- || (tr.intent == null)
- || ((tr.intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
- == 0)) {
- if (!getTasksAllowed) {
- // If the caller doesn't have the GET_TASKS permission, then only
- // allow them to see a small subset of tasks -- their own and home.
- if (!tr.isActivityTypeHome() && tr.effectiveUid != callingUid) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, not allowed: " + tr);
- continue;
- }
- }
- if (tr.autoRemoveRecents && tr.getTopActivity() == null) {
- // Don't include auto remove tasks that are finished or finishing.
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "Skipping, auto-remove without activity: " + tr);
- continue;
- }
- if ((flags & RECENT_IGNORE_UNAVAILABLE) != 0 && !tr.isAvailable) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "Skipping, unavail real act: " + tr);
- continue;
+ // Verify middle of the chain's next points back to the one before.
+ if (cur.mNextAffiliate != prev
+ || cur.mNextAffiliateTaskId != prev.taskId) {
+ Slog.wtf(TAG, "Bad chain @" + endIndex
+ + ": middle task " + cur + " @" + endIndex
+ + " has bad next affiliate "
+ + cur.mNextAffiliate + " id " + cur.mNextAffiliateTaskId
+ + ", expected " + prev);
+ sane = false;
+ break;
}
-
- if (!tr.mUserSetupComplete) {
- // Don't include task launched while user is not done setting-up.
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "Skipping, user setup not complete: " + tr);
- continue;
+ }
+ if (cur.mPrevAffiliateTaskId == INVALID_TASK_ID) {
+ // Chain ends here.
+ if (cur.mPrevAffiliate != null) {
+ Slog.wtf(TAG, "Bad chain @" + endIndex
+ + ": last task " + cur + " has previous affiliate "
+ + cur.mPrevAffiliate);
+ sane = false;
}
-
- ActivityManager.RecentTaskInfo rti = RecentTasks.createRecentTaskInfo(tr);
- if (!getDetailedTasks) {
- rti.baseIntent.replaceExtras((Bundle)null);
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: end of chain @" + endIndex);
+ break;
+ } else {
+ // Verify middle of the chain's prev points to a valid item.
+ if (cur.mPrevAffiliate == null) {
+ Slog.wtf(TAG, "Bad chain @" + endIndex
+ + ": task " + cur + " has previous affiliate "
+ + cur.mPrevAffiliate + " but should be id "
+ + cur.mPrevAffiliate);
+ sane = false;
+ break;
}
-
- res.add(rti);
+ }
+ if (cur.mAffiliatedTaskId != task.mAffiliatedTaskId) {
+ Slog.wtf(TAG, "Bad chain @" + endIndex
+ + ": task " + cur + " has affiliated id "
+ + cur.mAffiliatedTaskId + " but should be "
+ + task.mAffiliatedTaskId);
+ sane = false;
+ break;
+ }
+ prev = cur;
+ endIndex++;
+ if (endIndex >= recentsCount) {
+ Slog.wtf(TAG, "Bad chain ran off index " + endIndex
+ + ": last task " + prev);
+ sane = false;
+ break;
}
}
- return new ParceledListSlice<>(res);
- }
-
- /**
- * @return the list of persistable task ids.
- */
- void getPersistableTaskIds(ArraySet<Integer> persistentTaskIds) {
- final int size = mTasks.size();
- for (int i = 0; i < size; i++) {
- final TaskRecord task = mTasks.get(i);
- if (TaskPersister.DEBUG) Slog.d(TAG, "LazyTaskWriter: task=" + task
- + " persistable=" + task.isPersistable);
- final ActivityStack stack = task.getStack();
- if ((task.isPersistable || task.inRecents)
- && (stack == null || !stack.isHomeOrRecentsStack())) {
- if (TaskPersister.DEBUG) Slog.d(TAG, "adding to persistentTaskIds task=" + task);
- persistentTaskIds.add(task.taskId);
- } else {
- if (TaskPersister.DEBUG) Slog.d(TAG, "omitting from persistentTaskIds task="
- + task);
+ if (sane) {
+ if (endIndex < taskIndex) {
+ Slog.wtf(TAG, "Bad chain @" + endIndex
+ + ": did not extend to task " + task + " @" + taskIndex);
+ sane = false;
}
}
- }
-
- @VisibleForTesting
- ArrayList<TaskRecord> getRawTasks() {
- return mTasks;
- }
-
- /**
- * @return the task in the task list with the given {@param id} if one exists.
- */
- TaskRecord getTask(int id) {
- final int recentsCount = mTasks.size();
- for (int i = 0; i < recentsCount; i++) {
- TaskRecord tr = mTasks.get(i);
- if (tr.taskId == id) {
- return tr;
+ if (sane) {
+ // All looks good, we can just move all of the affiliated tasks
+ // to the top.
+ for (int i=topIndex; i<=endIndex; i++) {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: moving affiliated " + task
+ + " from " + i + " to " + (i-topIndex));
+ TaskRecord cur = remove(i);
+ add(i - topIndex, cur);
}
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: done moving tasks " + topIndex
+ + " to " + endIndex);
+ return true;
}
- return null;
- }
- /**
- * Add a new task to the recent tasks list.
- */
- void add(TaskRecord task) {
- if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "add: task=" + task);
+ // Whoops, couldn't do it.
+ return false;
+ }
+ final void addLocked(TaskRecord task) {
final boolean isAffiliated = task.mAffiliatedTaskId != task.taskId
|| task.mNextAffiliateTaskId != INVALID_TASK_ID
|| task.mPrevAffiliateTaskId != INVALID_TASK_ID;
- int recentsCount = mTasks.size();
+ int recentsCount = size();
// Quick case: never add voice sessions.
// TODO: VI what about if it's just an activity?
// Probably nothing to do here
@@ -761,15 +514,15 @@ class RecentTasks {
return;
}
// Another quick case: check if the top-most recent task is the same.
- if (!isAffiliated && recentsCount > 0 && mTasks.get(0) == task) {
+ if (!isAffiliated && recentsCount > 0 && get(0) == task) {
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: already at top: " + task);
return;
}
// Another quick case: check if this is part of a set of affiliated
// tasks that are at the top.
if (isAffiliated && recentsCount > 0 && task.inRecents
- && task.mAffiliatedTaskId == mTasks.get(0).mAffiliatedTaskId) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: affiliated " + mTasks.get(0)
+ && task.mAffiliatedTaskId == get(0).mAffiliatedTaskId) {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: affiliated " + get(0)
+ " at top when adding " + task);
return;
}
@@ -779,12 +532,12 @@ class RecentTasks {
// Slightly less quick case: the task is already in recents, so all we need
// to do is move it.
if (task.inRecents) {
- int taskIndex = mTasks.indexOf(task);
+ int taskIndex = indexOf(task);
if (taskIndex >= 0) {
- if (!isAffiliated || !MOVE_AFFILIATED_TASKS_TO_FRONT) {
+ if (!isAffiliated || MOVE_AFFILIATED_TASKS_TO_FRONT) {
// Simple case: this is not an affiliated task, so we just move it to the front.
- mTasks.remove(taskIndex);
- mTasks.add(0, task);
+ remove(taskIndex);
+ add(0, task);
notifyTaskPersisterLocked(task, false);
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: moving to top " + task
+ " from " + taskIndex);
@@ -807,14 +560,20 @@ class RecentTasks {
}
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: trimming tasks for " + task);
- trimForAddTask(task);
+ trimForTaskLocked(task, true);
+ recentsCount = size();
+ final int maxRecents = ActivityManager.getMaxRecentTasksStatic();
+ while (recentsCount >= maxRecents) {
+ final TaskRecord tr = remove(recentsCount - 1);
+ tr.removedFromRecents();
+ recentsCount--;
+ }
task.inRecents = true;
if (!isAffiliated || needAffiliationFix) {
// If this is a simple non-affiliated task, or we had some failure trying to
// handle it as part of an affilated task, then just place it at the top.
- mTasks.add(0, task);
- notifyTaskAdded(task);
+ add(0, task);
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: adding " + task);
} else if (isAffiliated) {
// If this is a new affiliated task, then move all of the affiliated tasks
@@ -824,7 +583,7 @@ class RecentTasks {
other = task.mPrevAffiliate;
}
if (other != null) {
- int otherIndex = mTasks.indexOf(other);
+ int otherIndex = indexOf(other);
if (otherIndex >= 0) {
// Insert new task at appropriate location.
int taskIndex;
@@ -839,8 +598,7 @@ class RecentTasks {
}
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
"addRecent: new affiliated task added at " + taskIndex + ": " + task);
- mTasks.add(taskIndex, task);
- notifyTaskAdded(task);
+ add(taskIndex, task);
// Now move everything to the front.
if (moveAffiliatedTasksToFront(task, taskIndex)) {
@@ -867,235 +625,21 @@ class RecentTasks {
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: regrouping affiliations");
cleanupLocked(task.userId);
}
-
- // Trim the set of tasks to the active set
- trimInactiveRecentTasks();
- }
-
- /**
- * Add the task to the bottom if possible.
- */
- boolean addToBottom(TaskRecord task) {
- if (!canAddTaskWithoutTrim(task)) {
- // Adding this task would cause the task to be removed (since it's appended at
- // the bottom and would be trimmed) so just return now
- return false;
- }
-
- add(task);
- return true;
- }
-
- /**
- * Remove a task from the recent tasks list.
- */
- void remove(TaskRecord task) {
- mTasks.remove(task);
- notifyTaskRemoved(task, !TRIMMED);
- }
-
- /**
- * Trims the recents task list to the global max number of recents.
- */
- private void trimInactiveRecentTasks() {
- int recentsCount = mTasks.size();
-
- // Remove from the end of the list until we reach the max number of recents
- while (recentsCount > mGlobalMaxNumTasks) {
- final TaskRecord tr = mTasks.remove(recentsCount - 1);
- notifyTaskRemoved(tr, TRIMMED);
- recentsCount--;
- if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "Trimming over max-recents task=" + tr
- + " max=" + mGlobalMaxNumTasks);
- }
-
- // Remove any tasks that belong to currently quiet profiles
- final int[] profileUserIds = mUserController.getCurrentProfileIds();
- mTmpQuietProfileUserIds.clear();
- for (int userId : profileUserIds) {
- final UserInfo userInfo = mUserController.getUserInfo(userId);
- if (userInfo.isManagedProfile() && userInfo.isQuietModeEnabled()) {
- mTmpQuietProfileUserIds.put(userId, true);
- }
- if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "User: " + userInfo
- + " quiet=" + mTmpQuietProfileUserIds.get(userId));
- }
-
- // Remove any inactive tasks, calculate the latest set of visible tasks
- int numVisibleTasks = 0;
- for (int i = 0; i < mTasks.size();) {
- final TaskRecord task = mTasks.get(i);
-
- if (isActiveRecentTask(task, mTmpQuietProfileUserIds)) {
- if (!mHasVisibleRecentTasks) {
- // Keep all active tasks if visible recent tasks is not supported
- i++;
- continue;
- }
-
- if (!isVisibleRecentTask(task)) {
- // Keep all active-but-invisible tasks
- i++;
- continue;
- } else {
- numVisibleTasks++;
- if (isInVisibleRange(task, numVisibleTasks)) {
- // Keep visible tasks in range
- i++;
- continue;
- } else {
- // Fall through to trim visible tasks that are no longer in range
- if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG,
- "Trimming out-of-range visible task=" + task);
- }
- }
- } else {
- // Fall through to trim inactive tasks
- if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "Trimming inactive task=" + task);
- }
-
- // Task is no longer active, trim it from the list
- mTasks.remove(task);
- notifyTaskRemoved(task, TRIMMED);
- notifyTaskPersisterLocked(task, false /* flush */);
- }
- }
-
- /**
- * @return whether the given task should be considered active.
- */
- private boolean isActiveRecentTask(TaskRecord task, SparseBooleanArray quietProfileUserIds) {
- if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "isActiveRecentTask: task=" + task
- + " globalMax=" + mGlobalMaxNumTasks);
-
- if (quietProfileUserIds.get(task.userId)) {
- // Quiet profile user's tasks are never active
- if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "\tisQuietProfileTask=true");
- return false;
- }
-
- if (task.mAffiliatedTaskId != INVALID_TASK_ID && task.mAffiliatedTaskId != task.taskId) {
- // Keep the task active if its affiliated task is also active
- final TaskRecord affiliatedTask = getTask(task.mAffiliatedTaskId);
- if (affiliatedTask != null) {
- if (!isActiveRecentTask(affiliatedTask, quietProfileUserIds)) {
- if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG,
- "\taffiliatedWithTask=" + affiliatedTask + " is not active");
- return false;
- }
- }
- }
-
- // All other tasks are considered active
- return true;
- }
-
- /**
- * @return whether the given active task should be presented to the user through SystemUI.
- */
- private boolean isVisibleRecentTask(TaskRecord task) {
- if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "isVisibleRecentTask: task=" + task
- + " minVis=" + mMinNumVisibleTasks + " maxVis=" + mMaxNumVisibleTasks
- + " sessionDuration=" + mActiveTasksSessionDurationMs
- + " inactiveDuration=" + task.getInactiveDuration()
- + " activityType=" + task.getActivityType()
- + " windowingMode=" + task.getWindowingMode());
-
- // Ignore certain activity types completely
- switch (task.getActivityType()) {
- case ACTIVITY_TYPE_HOME:
- case ACTIVITY_TYPE_RECENTS:
- return false;
- }
-
- // Ignore certain windowing modes
- switch (task.getWindowingMode()) {
- case WINDOWING_MODE_PINNED:
- return false;
- case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
- if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "\ttop=" + task.getStack().topTask());
- final ActivityStack stack = task.getStack();
- if (stack != null && stack.topTask() == task) {
- // Only the non-top task of the primary split screen mode is visible
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * @return whether the given visible task is within the policy range.
- */
- private boolean isInVisibleRange(TaskRecord task, int numVisibleTasks) {
- // Keep the last most task even if it is excluded from recents
- final boolean isExcludeFromRecents =
- (task.getBaseIntent().getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
- == Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
- if (isExcludeFromRecents) {
- if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "\texcludeFromRecents=true");
- return numVisibleTasks == 1;
- }
-
- if (mMinNumVisibleTasks >= 0 && numVisibleTasks <= mMinNumVisibleTasks) {
- // Always keep up to the min number of recent tasks, after that fall through to the
- // checks below
- return true;
- }
-
- if (mMaxNumVisibleTasks >= 0) {
- // Always keep up to the max number of recent tasks, but return false afterwards
- return numVisibleTasks <= mMaxNumVisibleTasks;
- }
-
- if (mActiveTasksSessionDurationMs > 0) {
- // Keep the task if the inactive time is within the session window, this check must come
- // after the checks for the min/max visible task range
- if (task.getInactiveDuration() <= mActiveTasksSessionDurationMs) {
- return true;
- }
- }
-
- return false;
}
/**
* If needed, remove oldest existing entries in recents that are for the same kind
* of task as the given one.
*/
- private void trimForAddTask(TaskRecord task) {
- final int removeIndex = findTrimIndexForAddTask(task);
- if (removeIndex == -1) {
- // Nothing to trim
- return;
- }
-
- // There is a similar task that will be removed for the addition of {@param task}, but it
- // can be the same task, and if so, the task will be re-added in add(), so skip the
- // callbacks here.
- final TaskRecord removedTask = mTasks.remove(removeIndex);
- if (removedTask != task) {
- notifyTaskRemoved(removedTask, TRIMMED);
- if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "Trimming task=" + removedTask
- + " for addition of task=" + task);
- }
- notifyTaskPersisterLocked(removedTask, false /* flush */);
- }
-
- /**
- * Find the task that would be removed if the given {@param task} is added to the recent tasks
- * list (if any).
- */
- private int findTrimIndexForAddTask(TaskRecord task) {
- int recentsCount = mTasks.size();
+ int trimForTaskLocked(TaskRecord task, boolean doTrim) {
+ int recentsCount = size();
final Intent intent = task.intent;
final boolean document = intent != null && intent.isDocument();
int maxRecents = task.maxRecents - 1;
final ActivityStack stack = task.getStack();
for (int i = 0; i < recentsCount; i++) {
- final TaskRecord tr = mTasks.get(i);
+ final TaskRecord tr = get(i);
final ActivityStack trStack = tr.getStack();
-
if (task != tr) {
if (stack != null && trStack != null && stack != trStack) {
continue;
@@ -1106,7 +650,7 @@ class RecentTasks {
final Intent trIntent = tr.intent;
final boolean sameAffinity =
task.affinity != null && task.affinity.equals(tr.affinity);
- final boolean sameIntent = intent != null && intent.filterEquals(trIntent);
+ final boolean sameIntentFilter = intent != null && intent.filterEquals(trIntent);
boolean multiTasksAllowed = false;
final int flags = intent.getFlags();
if ((flags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NEW_DOCUMENT)) != 0
@@ -1115,7 +659,7 @@ class RecentTasks {
}
final boolean trIsDocument = trIntent != null && trIntent.isDocument();
final boolean bothDocuments = document && trIsDocument;
- if (!sameAffinity && !sameIntent && !bothDocuments) {
+ if (!sameAffinity && !sameIntentFilter && !bothDocuments) {
continue;
}
@@ -1124,17 +668,17 @@ class RecentTasks {
final boolean sameActivity = task.realActivity != null
&& tr.realActivity != null
&& task.realActivity.equals(tr.realActivity);
+ // If the document is open in another app or is not the same
+ // document, we don't need to trim it.
if (!sameActivity) {
- // If the document is open in another app or is not the same document, we
- // don't need to trim it.
continue;
+ // Otherwise only trim if we are over our max recents for this task
} else if (maxRecents > 0) {
- // Otherwise only trim if we are over our max recents for this task
--maxRecents;
- if (!sameIntent || multiTasksAllowed) {
+ if (!doTrim || !sameIntentFilter || multiTasksAllowed) {
// We don't want to trim if we are not over the max allowed entries and
- // the tasks are not of the same intent filter, or multiple entries for
- // the task is allowed.
+ // the caller doesn't want us to trim, the tasks are not of the same
+ // intent filter, or multiple entries fot the task is allowed.
continue;
}
}
@@ -1145,14 +689,44 @@ class RecentTasks {
continue;
}
}
- return i;
+
+ if (!doTrim) {
+ // If the caller is not actually asking for a trim, just tell them we reached
+ // a point where the trim would happen.
+ return i;
+ }
+
+ // Either task and tr are the same or, their affinities match or their intents match
+ // and neither of them is a document, or they are documents using the same activity
+ // and their maxRecents has been reached.
+ remove(i);
+ if (task != tr) {
+ tr.removedFromRecents();
+ }
+ i--;
+ recentsCount--;
+ if (task.intent == null) {
+ // If the new recent task we are adding is not fully
+ // specified, then replace it with the existing recent task.
+ task = tr;
+ }
+ notifyTaskPersisterLocked(tr, false);
}
+
return -1;
}
+ // Sort by taskId
+ private static Comparator<TaskRecord> sTaskRecordComparator = new Comparator<TaskRecord>() {
+ @Override
+ public int compare(TaskRecord lhs, TaskRecord rhs) {
+ return rhs.taskId - lhs.taskId;
+ }
+ };
+
// Extract the affiliates of the chain containing recent at index start.
private int processNextAffiliateChainLocked(int start) {
- final TaskRecord startTask = mTasks.get(start);
+ final TaskRecord startTask = get(start);
final int affiliateId = startTask.mAffiliatedTaskId;
// Quick identification of isolated tasks. I.e. those not launched behind.
@@ -1167,17 +741,17 @@ class RecentTasks {
// Remove all tasks that are affiliated to affiliateId and put them in mTmpRecents.
mTmpRecents.clear();
- for (int i = mTasks.size() - 1; i >= start; --i) {
- final TaskRecord task = mTasks.get(i);
+ for (int i = size() - 1; i >= start; --i) {
+ final TaskRecord task = get(i);
if (task.mAffiliatedTaskId == affiliateId) {
- mTasks.remove(i);
+ remove(i);
mTmpRecents.add(task);
}
}
// Sort them all by taskId. That is the order they were create in and that order will
// always be correct.
- Collections.sort(mTmpRecents, TASK_ID_COMPARATOR);
+ Collections.sort(mTmpRecents, sTaskRecordComparator);
// Go through and fix up the linked list.
// The first one is the end of the chain and has no next.
@@ -1215,197 +789,11 @@ class RecentTasks {
notifyTaskPersisterLocked(last, false);
}
- // Insert the group back into mTmpTasks at start.
- mTasks.addAll(start, mTmpRecents);
+ // Insert the group back into mRecentTasks at start.
+ addAll(start, mTmpRecents);
mTmpRecents.clear();
// Let the caller know where we left off.
return start + tmpSize;
}
-
- private boolean moveAffiliatedTasksToFront(TaskRecord task, int taskIndex) {
- int recentsCount = mTasks.size();
- TaskRecord top = task;
- int topIndex = taskIndex;
- while (top.mNextAffiliate != null && topIndex > 0) {
- top = top.mNextAffiliate;
- topIndex--;
- }
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: adding affilliates starting at "
- + topIndex + " from intial " + taskIndex);
- // Find the end of the chain, doing a sanity check along the way.
- boolean sane = top.mAffiliatedTaskId == task.mAffiliatedTaskId;
- int endIndex = topIndex;
- TaskRecord prev = top;
- while (endIndex < recentsCount) {
- TaskRecord cur = mTasks.get(endIndex);
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: looking at next chain @"
- + endIndex + " " + cur);
- if (cur == top) {
- // Verify start of the chain.
- if (cur.mNextAffiliate != null || cur.mNextAffiliateTaskId != INVALID_TASK_ID) {
- Slog.wtf(TAG, "Bad chain @" + endIndex
- + ": first task has next affiliate: " + prev);
- sane = false;
- break;
- }
- } else {
- // Verify middle of the chain's next points back to the one before.
- if (cur.mNextAffiliate != prev
- || cur.mNextAffiliateTaskId != prev.taskId) {
- Slog.wtf(TAG, "Bad chain @" + endIndex
- + ": middle task " + cur + " @" + endIndex
- + " has bad next affiliate "
- + cur.mNextAffiliate + " id " + cur.mNextAffiliateTaskId
- + ", expected " + prev);
- sane = false;
- break;
- }
- }
- if (cur.mPrevAffiliateTaskId == INVALID_TASK_ID) {
- // Chain ends here.
- if (cur.mPrevAffiliate != null) {
- Slog.wtf(TAG, "Bad chain @" + endIndex
- + ": last task " + cur + " has previous affiliate "
- + cur.mPrevAffiliate);
- sane = false;
- }
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: end of chain @" + endIndex);
- break;
- } else {
- // Verify middle of the chain's prev points to a valid item.
- if (cur.mPrevAffiliate == null) {
- Slog.wtf(TAG, "Bad chain @" + endIndex
- + ": task " + cur + " has previous affiliate "
- + cur.mPrevAffiliate + " but should be id "
- + cur.mPrevAffiliate);
- sane = false;
- break;
- }
- }
- if (cur.mAffiliatedTaskId != task.mAffiliatedTaskId) {
- Slog.wtf(TAG, "Bad chain @" + endIndex
- + ": task " + cur + " has affiliated id "
- + cur.mAffiliatedTaskId + " but should be "
- + task.mAffiliatedTaskId);
- sane = false;
- break;
- }
- prev = cur;
- endIndex++;
- if (endIndex >= recentsCount) {
- Slog.wtf(TAG, "Bad chain ran off index " + endIndex
- + ": last task " + prev);
- sane = false;
- break;
- }
- }
- if (sane) {
- if (endIndex < taskIndex) {
- Slog.wtf(TAG, "Bad chain @" + endIndex
- + ": did not extend to task " + task + " @" + taskIndex);
- sane = false;
- }
- }
- if (sane) {
- // All looks good, we can just move all of the affiliated tasks
- // to the top.
- for (int i=topIndex; i<=endIndex; i++) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: moving affiliated " + task
- + " from " + i + " to " + (i-topIndex));
- TaskRecord cur = mTasks.remove(i);
- mTasks.add(i - topIndex, cur);
- }
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: done moving tasks " + topIndex
- + " to " + endIndex);
- return true;
- }
-
- // Whoops, couldn't do it.
- return false;
- }
-
- void dump(PrintWriter pw, boolean dumpAll, String dumpPackage) {
- pw.println("ACTIVITY MANAGER RECENT TASKS (dumpsys activity recents)");
- if (mTasks.isEmpty()) {
- return;
- }
-
- final MutableBoolean printedAnything = new MutableBoolean(false);
- final MutableBoolean printedHeader = new MutableBoolean(false);
- final int size = mTasks.size();
- for (int i = 0; i < size; i++) {
- final TaskRecord tr = mTasks.get(i);
- if (dumpPackage != null && (tr.realActivity == null ||
- !dumpPackage.equals(tr.realActivity.getPackageName()))) {
- continue;
- }
-
- if (!printedHeader.value) {
- pw.println(" Recent tasks:");
- printedHeader.value = true;
- printedAnything.value = true;
- }
- pw.print(" * Recent #"); pw.print(i); pw.print(": ");
- pw.println(tr);
- if (dumpAll) {
- tr.dump(pw, " ");
- }
- }
-
- if (!printedAnything.value) {
- pw.println(" (nothing)");
- }
- }
-
- /**
- * Creates a new RecentTaskInfo from a TaskRecord.
- */
- static ActivityManager.RecentTaskInfo createRecentTaskInfo(TaskRecord tr) {
- // Update the task description to reflect any changes in the task stack
- tr.updateTaskDescription();
-
- // Compose the recent task info
- ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
- rti.id = tr.getTopActivity() == null ? INVALID_TASK_ID : tr.taskId;
- rti.persistentId = tr.taskId;
- rti.baseIntent = new Intent(tr.getBaseIntent());
- rti.origActivity = tr.origActivity;
- rti.realActivity = tr.realActivity;
- rti.description = tr.lastDescription;
- rti.stackId = tr.getStackId();
- rti.userId = tr.userId;
- rti.taskDescription = new ActivityManager.TaskDescription(tr.lastTaskDescription);
- rti.lastActiveTime = tr.lastActiveTime;
- rti.affiliatedTaskId = tr.mAffiliatedTaskId;
- rti.affiliatedTaskColor = tr.mAffiliatedTaskColor;
- rti.numActivities = 0;
- if (tr.mBounds != null) {
- rti.bounds = new Rect(tr.mBounds);
- }
- rti.supportsSplitScreenMultiWindow = tr.supportsSplitScreenWindowingMode();
- rti.resizeMode = tr.mResizeMode;
- rti.configuration.setTo(tr.getConfiguration());
-
- ActivityRecord base = null;
- ActivityRecord top = null;
- ActivityRecord tmp;
-
- for (int i = tr.mActivities.size() - 1; i >= 0; --i) {
- tmp = tr.mActivities.get(i);
- if (tmp.finishing) {
- continue;
- }
- base = tmp;
- if (top == null || (top.state == ActivityState.INITIALIZING)) {
- top = base;
- }
- rti.numActivities++;
- }
-
- rti.baseActivity = (base != null) ? base.intent.getComponent() : null;
- rti.topActivity = (top != null) ? top.intent.getComponent() : null;
-
- return rti;
- }
}
diff --git a/com/android/server/am/ServiceRecord.java b/com/android/server/am/ServiceRecord.java
index 16995e50..ac85e6b1 100644
--- a/com/android/server/am/ServiceRecord.java
+++ b/com/android/server/am/ServiceRecord.java
@@ -33,7 +33,6 @@ import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.net.Uri;
import android.os.Binder;
-import android.os.Build;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -518,27 +517,14 @@ final class ServiceRecord extends Binder {
} catch (PackageManager.NameNotFoundException e) {
}
}
- if (nm.getNotificationChannel(localPackageName, appUid,
+ if (localForegroundNoti.getSmallIcon() == null
+ || nm.getNotificationChannel(localPackageName, appUid,
localForegroundNoti.getChannelId()) == null) {
- int targetSdkVersion = Build.VERSION_CODES.O_MR1;
- try {
- final ApplicationInfo applicationInfo =
- ams.mContext.getPackageManager().getApplicationInfoAsUser(
- appInfo.packageName, 0, userId);
- targetSdkVersion = applicationInfo.targetSdkVersion;
- } catch (PackageManager.NameNotFoundException e) {
- }
- if (targetSdkVersion >= Build.VERSION_CODES.O_MR1) {
- throw new RuntimeException(
- "invalid channel for service notification: "
- + foregroundNoti);
- }
- }
- if (localForegroundNoti.getSmallIcon() == null) {
// Notifications whose icon is 0 are defined to not show
// a notification, silently ignoring it. We don't want to
// just ignore it, we want to prevent the service from
// being foreground.
+ // Also every notification needs a channel.
throw new RuntimeException("invalid service notification: "
+ foregroundNoti);
}
diff --git a/com/android/server/am/TaskPersister.java b/com/android/server/am/TaskPersister.java
index 2689d6a4..61994b55 100644
--- a/com/android/server/am/TaskPersister.java
+++ b/com/android/server/am/TaskPersister.java
@@ -567,7 +567,7 @@ public class TaskPersister {
SparseArray<SparseBooleanArray> changedTaskIdsPerUser = new SparseArray<>();
synchronized (mService) {
for (int userId : mRecentTasks.usersWithRecentsLoadedLocked()) {
- SparseBooleanArray taskIdsToSave = mRecentTasks.getTaskIdsForUser(userId);
+ SparseBooleanArray taskIdsToSave = mRecentTasks.mPersistedTaskIds.get(userId);
SparseBooleanArray persistedIdsInFile = mTaskIdsInFile.get(userId);
if (persistedIdsInFile != null && persistedIdsInFile.equals(taskIdsToSave)) {
continue;
@@ -640,7 +640,7 @@ public class TaskPersister {
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- ArraySet<Integer> persistentTaskIds = new ArraySet<>();
+ ArraySet<Integer> persistentTaskIds = new ArraySet<Integer>();
while (true) {
// We can't lock mService while holding TaskPersister.this, but we don't want to
// call removeObsoleteFiles every time through the loop, only the last time before
@@ -654,7 +654,20 @@ public class TaskPersister {
persistentTaskIds.clear();
synchronized (mService) {
if (DEBUG) Slog.d(TAG, "mRecents=" + mRecentTasks);
- mRecentTasks.getPersistableTaskIds(persistentTaskIds);
+ for (int taskNdx = mRecentTasks.size() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = mRecentTasks.get(taskNdx);
+ if (DEBUG) Slog.d(TAG, "LazyTaskWriter: task=" + task +
+ " persistable=" + task.isPersistable);
+ final ActivityStack stack = task.getStack();
+ if ((task.isPersistable || task.inRecents)
+ && (stack == null || !stack.isHomeOrRecentsStack())) {
+ if (DEBUG) Slog.d(TAG, "adding to persistentTaskIds task=" + task);
+ persistentTaskIds.add(task.taskId);
+ } else {
+ if (DEBUG) Slog.d(TAG,
+ "omitting from persistentTaskIds task=" + task);
+ }
+ }
mService.mWindowManager.removeObsoleteTaskFiles(persistentTaskIds,
mRecentTasks.usersWithRecentsLoadedLocked());
}
diff --git a/com/android/server/am/TaskRecord.java b/com/android/server/am/TaskRecord.java
index a1b45a1e..0d8df796 100644
--- a/com/android/server/am/TaskRecord.java
+++ b/com/android/server/am/TaskRecord.java
@@ -18,7 +18,10 @@ package com.android.server.am;
import static android.app.ActivityManager.RESIZE_MODE_FORCED;
import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
@@ -28,7 +31,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
@@ -43,6 +45,7 @@ import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
+import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -83,6 +86,7 @@ import android.annotation.IntDef;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
+import android.app.ActivityManager.StackId;
import android.app.ActivityManager.TaskDescription;
import android.app.ActivityManager.TaskSnapshot;
import android.app.ActivityOptions;
@@ -98,7 +102,6 @@ import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Debug;
import android.os.RemoteException;
-import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings;
@@ -152,6 +155,8 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
private static final String ATTR_EFFECTIVE_UID = "effective_uid";
@Deprecated
private static final String ATTR_TASKTYPE = "task_type";
+ private static final String ATTR_FIRSTACTIVETIME = "first_active_time";
+ private static final String ATTR_LASTACTIVETIME = "last_active_time";
private static final String ATTR_LASTDESCRIPTION = "last_description";
private static final String ATTR_LASTTIMEMOVED = "last_time_moved";
private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity";
@@ -163,6 +168,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
private static final String ATTR_CALLING_PACKAGE = "calling_package";
private static final String ATTR_SUPPORTS_PICTURE_IN_PICTURE = "supports_picture_in_picture";
private static final String ATTR_RESIZE_MODE = "resize_mode";
+ private static final String ATTR_PRIVILEGED = "privileged";
private static final String ATTR_NON_FULLSCREEN_BOUNDS = "non_fullscreen_bounds";
private static final String ATTR_MIN_WIDTH = "min_width";
private static final String ATTR_MIN_HEIGHT = "min_height";
@@ -206,10 +212,9 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
ComponentName realActivity; // The actual activity component that started the task.
boolean realActivitySuspended; // True if the actual activity component that started the
// task is suspended.
+ long firstActiveTime; // First time this task was active.
+ long lastActiveTime; // Last time this task was active, including sleep.
boolean inRecents; // Actually in the recents list?
- long lastActiveTime; // Last time this task was active in the current device session,
- // including sleep. This time is initialized to the elapsed time when
- // restored from disk.
boolean isAvailable; // Is the activity available to be launched?
boolean rootWasReset; // True if the intent at the root of the task had
// the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
@@ -232,6 +237,10 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
// of the root activity.
boolean mTemporarilyUnresizable; // Separate flag from mResizeMode used to suppress resize
// changes on a temporary basis.
+ private int mLockTaskMode; // Which tasklock mode to launch this task in. One of
+ // ActivityManager.LOCK_TASK_LAUNCH_MODE_*
+ private boolean mPrivileged; // The root activity application of this task holds
+ // privileged permissions.
/** Can't be put in lockTask mode. */
final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
@@ -330,7 +339,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
TaskPersister.IMAGE_EXTENSION;
userId = UserHandle.getUserId(info.applicationInfo.uid);
taskId = _taskId;
- lastActiveTime = SystemClock.elapsedRealtime();
mAffiliatedTaskId = _taskId;
voiceSession = _voiceSession;
voiceInteractor = _voiceInteractor;
@@ -351,7 +359,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
TaskPersister.IMAGE_EXTENSION;
userId = UserHandle.getUserId(info.applicationInfo.uid);
taskId = _taskId;
- lastActiveTime = SystemClock.elapsedRealtime();
mAffiliatedTaskId = _taskId;
voiceSession = null;
voiceInteractor = null;
@@ -378,11 +385,12 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId,
int _effectiveUid, String _lastDescription, ArrayList<ActivityRecord> activities,
- long lastTimeMoved, boolean neverRelinquishIdentity,
- TaskDescription _lastTaskDescription, int taskAffiliation, int prevTaskId,
- int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
- int resizeMode, boolean supportsPictureInPicture, boolean _realActivitySuspended,
- boolean userSetupComplete, int minWidth, int minHeight) {
+ long _firstActiveTime, long _lastActiveTime, long lastTimeMoved,
+ boolean neverRelinquishIdentity, TaskDescription _lastTaskDescription,
+ int taskAffiliation, int prevTaskId, int nextTaskId, int taskAffiliationColor,
+ int callingUid, String callingPackage, int resizeMode, boolean supportsPictureInPicture,
+ boolean privileged, boolean _realActivitySuspended, boolean userSetupComplete,
+ int minWidth, int minHeight) {
mService = service;
mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX +
TaskPersister.IMAGE_EXTENSION;
@@ -404,7 +412,8 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
userId = _userId;
mUserSetupComplete = userSetupComplete;
effectiveUid = _effectiveUid;
- lastActiveTime = SystemClock.elapsedRealtime();
+ firstActiveTime = _firstActiveTime;
+ lastActiveTime = _lastActiveTime;
lastDescription = _lastDescription;
mActivities = activities;
mLastTimeMoved = lastTimeMoved;
@@ -418,6 +427,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
mCallingPackage = callingPackage;
mResizeMode = resizeMode;
mSupportsPictureInPicture = supportsPictureInPicture;
+ mPrivileged = privileged;
mMinWidth = minWidth;
mMinHeight = minHeight;
mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
@@ -510,7 +520,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
// All we can do for now is update the bounds so it can be used when the task is
// added to window manager.
updateOverrideConfiguration(bounds);
- if (!inFreeformWindowingMode()) {
+ if (getStackId() != FREEFORM_WORKSPACE_STACK_ID) {
// re-restore the task so it can have the proper stack association.
mService.mStackSupervisor.restoreRecentTaskLocked(this, null);
}
@@ -606,7 +616,8 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
* @return whether the task was reparented
*/
// TODO: Inspect all call sites and change to just changing windowing mode of the stack vs.
- // re-parenting the task. Can only be done when we are no longer using static stack Ids.
+ // re-parenting the task. Can only be done when we are no longer using static stack Ids like
+ /** {@link ActivityManager.StackId#FULLSCREEN_WORKSPACE_STACK_ID} */
boolean reparent(ActivityStack preferredStack, int position,
@ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
boolean schedulePictureInPictureModeChange, String reason) {
@@ -619,12 +630,12 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
return false;
}
- final int toStackWindowingMode = toStack.getWindowingMode();
+ final int sourceStackId = getStackId();
+ final int stackId = toStack.getStackId();
final ActivityRecord topActivity = getTopActivity();
- final boolean mightReplaceWindow =
- replaceWindowsOnTaskMove(getWindowingMode(), toStackWindowingMode)
- && topActivity != null;
+ final boolean mightReplaceWindow = StackId.replaceWindowsOnTaskMove(sourceStackId, stackId)
+ && topActivity != null;
if (mightReplaceWindow) {
// We are about to relaunch the activity because its configuration changed due to
// being maximized, i.e. size change. The activity will first remove the old window
@@ -649,7 +660,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
// In some cases the focused stack isn't the front stack. E.g. pinned stack.
// Whenever we are moving the top activity from the front stack we want to make sure to
// move the stack to the front.
- final boolean wasFront = r != null && sourceStack.isTopStackOnDisplay()
+ final boolean wasFront = r != null && supervisor.isFrontStackOnDisplay(sourceStack)
&& (sourceStack.topRunningActivityLocked() == r);
// Adjust the position for the new parent stack as needed.
@@ -696,10 +707,10 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
toStack.prepareFreezingTaskBounds();
// Make sure the task has the appropriate bounds/size for the stack it is in.
+ final int toStackWindowingMode = toStack.getWindowingMode();
final boolean toStackSplitScreenPrimary =
toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
- if ((toStackWindowingMode == WINDOWING_MODE_FULLSCREEN
- || toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)
+ if (stackId == FULLSCREEN_WORKSPACE_STACK_ID
&& !Objects.equals(mBounds, toStack.mBounds)) {
kept = resize(toStack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow,
deferResume);
@@ -738,9 +749,9 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
}
// TODO: Handle incorrect request to move before the actual move, not after.
- final boolean inSplitScreenMode = supervisor.getDefaultDisplay().hasSplitScreenPrimaryStack();
+ final boolean inSplitScreenMode = supervisor.getDefaultDisplay().hasSplitScreenStack();
supervisor.handleNonResizableTaskIfNeeded(this, preferredStack.getWindowingMode(),
- DEFAULT_DISPLAY, toStack);
+ DEFAULT_DISPLAY, stackId);
boolean successful = (preferredStack == toStack);
if (successful && toStack.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
@@ -750,18 +761,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
return successful;
}
- /**
- * Returns true if the windows of tasks being moved to the target stack from the source
- * stack should be replaced, meaning that window manager will keep the old window around
- * until the new is ready.
- * @hide
- */
- private static boolean replaceWindowsOnTaskMove(
- int sourceWindowingMode, int targetWindowingMode) {
- return sourceWindowingMode == WINDOWING_MODE_FREEFORM
- || targetWindowingMode == WINDOWING_MODE_FREEFORM;
- }
-
void cancelWindowTransition() {
mWindowContainerController.cancelWindowTransition();
}
@@ -781,11 +780,14 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
}
void touchActiveTime() {
- lastActiveTime = SystemClock.elapsedRealtime();
+ lastActiveTime = System.currentTimeMillis();
+ if (firstActiveTime == 0) {
+ firstActiveTime = lastActiveTime;
+ }
}
long getInactiveDuration() {
- return SystemClock.elapsedRealtime() - lastActiveTime;
+ return System.currentTimeMillis() - lastActiveTime;
}
/** Sets the original intent, and the calling uid and package. */
@@ -793,7 +795,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
mCallingUid = r.launchedFromUid;
mCallingPackage = r.launchedFromPackage;
setIntent(r.intent, r.info);
- setLockTaskAuth(r);
}
/** Sets the original intent, _without_ updating the calling uid or package. */
@@ -877,6 +878,14 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
}
mResizeMode = info.resizeMode;
mSupportsPictureInPicture = info.supportsPictureInPicture();
+ mPrivileged = (info.applicationInfo.privateFlags & PRIVATE_FLAG_PRIVILEGED) != 0;
+ mLockTaskMode = info.lockTaskLaunchMode;
+ if (!mPrivileged && (mLockTaskMode == LOCK_TASK_LAUNCH_MODE_ALWAYS
+ || mLockTaskMode == LOCK_TASK_LAUNCH_MODE_NEVER)) {
+ // Non-priv apps are not allowed to use always or never, fall back to default
+ mLockTaskMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
+ }
+ setLockTaskAuth();
}
/** Sets the original minimal width and height. */
@@ -1254,7 +1263,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
mService.notifyTaskPersisterLocked(this, false);
}
- if (inPinnedWindowingMode()) {
+ if (getStackId() == PINNED_STACK_ID) {
// We normally notify listeners of task stack changes on pause, however pinned stack
// activities are normally in the paused state so no notification will be sent there
// before the activity is removed. We send it here so instead.
@@ -1413,17 +1422,8 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
}
void setLockTaskAuth() {
- setLockTaskAuth(getRootActivity());
- }
-
- private void setLockTaskAuth(@Nullable ActivityRecord r) {
- if (r == null) {
- mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
- return;
- }
-
final String pkg = (realActivity != null) ? realActivity.getPackageName() : null;
- switch (r.lockTaskLaunchMode) {
+ switch (mLockTaskMode) {
case LOCK_TASK_LAUNCH_MODE_DEFAULT:
mLockTaskAuth = mService.mLockTaskController.isPackageWhitelisted(userId, pkg)
? LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE;
@@ -1493,7 +1493,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
* @return True if the requested bounds are okay for a resizing request.
*/
private boolean canResizeToBounds(Rect bounds) {
- if (bounds == null || !inFreeformWindowingMode()) {
+ if (bounds == null || getStackId() != FREEFORM_WORKSPACE_STACK_ID) {
// Note: If not on the freeform workspace, we ignore the bounds.
return true;
}
@@ -1559,7 +1559,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
// values in the TaskRecord.
String label = null;
String iconFilename = null;
- int iconResource = -1;
int colorPrimary = 0;
int colorBackground = 0;
int statusBarColor = 0;
@@ -1571,9 +1570,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
if (label == null) {
label = r.taskDescription.getLabel();
}
- if (iconResource == -1) {
- iconResource = r.taskDescription.getIconResource();
- }
if (iconFilename == null) {
iconFilename = r.taskDescription.getIconFilename();
}
@@ -1588,8 +1584,8 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
}
topActivity = false;
}
- lastTaskDescription = new TaskDescription(label, null, iconResource, iconFilename,
- colorPrimary, colorBackground, statusBarColor, navigationBarColor);
+ lastTaskDescription = new TaskDescription(label, null, iconFilename, colorPrimary,
+ colorBackground, statusBarColor, navigationBarColor);
if (mWindowContainerController != null) {
mWindowContainerController.setTaskDescription(lastTaskDescription);
}
@@ -1651,6 +1647,8 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
out.attribute(null, ATTR_USERID, String.valueOf(userId));
out.attribute(null, ATTR_USER_SETUP_COMPLETE, String.valueOf(mUserSetupComplete));
out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid));
+ out.attribute(null, ATTR_FIRSTACTIVETIME, String.valueOf(firstActiveTime));
+ out.attribute(null, ATTR_LASTACTIVETIME, String.valueOf(lastActiveTime));
out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved));
out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity));
if (lastDescription != null) {
@@ -1668,6 +1666,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
out.attribute(null, ATTR_RESIZE_MODE, String.valueOf(mResizeMode));
out.attribute(null, ATTR_SUPPORTS_PICTURE_IN_PICTURE,
String.valueOf(mSupportsPictureInPicture));
+ out.attribute(null, ATTR_PRIVILEGED, String.valueOf(mPrivileged));
if (mLastNonFullscreenBounds != null) {
out.attribute(
null, ATTR_NON_FULLSCREEN_BOUNDS, mLastNonFullscreenBounds.flattenToString());
@@ -1722,6 +1721,8 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
boolean userSetupComplete = true;
int effectiveUid = -1;
String lastDescription = null;
+ long firstActiveTime = -1;
+ long lastActiveTime = -1;
long lastTimeOnTop = 0;
boolean neverRelinquishIdentity = true;
int taskId = INVALID_TASK_ID;
@@ -1735,6 +1736,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
String callingPackage = "";
int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
boolean supportsPictureInPicture = false;
+ boolean privileged = false;
Rect bounds = null;
int minWidth = INVALID_MIN_SIZE;
int minHeight = INVALID_MIN_SIZE;
@@ -1772,6 +1774,10 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
effectiveUid = Integer.parseInt(attrValue);
} else if (ATTR_TASKTYPE.equals(attrName)) {
taskType = Integer.parseInt(attrValue);
+ } else if (ATTR_FIRSTACTIVETIME.equals(attrName)) {
+ firstActiveTime = Long.parseLong(attrValue);
+ } else if (ATTR_LASTACTIVETIME.equals(attrName)) {
+ lastActiveTime = Long.parseLong(attrValue);
} else if (ATTR_LASTDESCRIPTION.equals(attrName)) {
lastDescription = attrValue;
} else if (ATTR_LASTTIMEMOVED.equals(attrName)) {
@@ -1796,6 +1802,8 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
resizeMode = Integer.parseInt(attrValue);
} else if (ATTR_SUPPORTS_PICTURE_IN_PICTURE.equals(attrName)) {
supportsPictureInPicture = Boolean.parseBoolean(attrValue);
+ } else if (ATTR_PRIVILEGED.equals(attrName)) {
+ privileged = Boolean.parseBoolean(attrValue);
} else if (ATTR_NON_FULLSCREEN_BOUNDS.equals(attrName)) {
bounds = Rect.unflattenFromString(attrValue);
} else if (ATTR_MIN_WIDTH.equals(attrName)) {
@@ -1880,10 +1888,10 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
final TaskRecord task = new TaskRecord(stackSupervisor.mService, taskId, intent,
affinityIntent, affinity, rootAffinity, realActivity, origActivity, rootHasReset,
autoRemoveRecents, askedCompatMode, userId, effectiveUid, lastDescription,
- activities, lastTimeOnTop, neverRelinquishIdentity, taskDescription,
- taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor, callingUid,
- callingPackage, resizeMode, supportsPictureInPicture, realActivitySuspended,
- userSetupComplete, minWidth, minHeight);
+ activities, firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity,
+ taskDescription, taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor,
+ callingUid, callingPackage, resizeMode, supportsPictureInPicture, privileged,
+ realActivitySuspended, userSetupComplete, minWidth, minHeight);
task.updateOverrideConfiguration(bounds);
for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
@@ -1903,7 +1911,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
// If the task has no requested minimal size, we'd like to enforce a minimal size
// so that the user can not render the task too small to manipulate. We don't need
// to do this for the pinned stack as the bounds are controlled by the system.
- if (!inPinnedWindowingMode()) {
+ if (getStackId() != PINNED_STACK_ID) {
if (minWidth == INVALID_MIN_SIZE) {
minWidth = mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
}
@@ -2077,7 +2085,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
return;
}
- if (inStack.inFreeformWindowingMode()) {
+ if (inStack.mStackId == FREEFORM_WORKSPACE_STACK_ID) {
if (!isResizeable()) {
throw new IllegalArgumentException("Can not position non-resizeable task="
+ this + " in stack=" + inStack);
@@ -2212,6 +2220,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
pw.print(" mSupportsPictureInPicture=" + mSupportsPictureInPicture);
pw.print(" isResizeable=" + isResizeable());
+ pw.print(" firstActiveTime=" + firstActiveTime);
pw.print(" lastActiveTime=" + lastActiveTime);
pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
}
diff --git a/com/android/server/appwidget/AppWidgetServiceImpl.java b/com/android/server/appwidget/AppWidgetServiceImpl.java
index 51afada2..a6aaaa67 100644
--- a/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -71,6 +71,7 @@ import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.storage.StorageManager;
import android.service.appwidget.AppWidgetServiceDumpProto;
import android.service.appwidget.WidgetProto;
import android.text.TextUtils;
@@ -158,9 +159,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
// Bump if the stored widgets need to be upgraded.
private static final int CURRENT_VERSION = 1;
- // Every widget update request is associated which an increasing sequence number. This is
- // used to verify which request has successfully been received by the host.
- private static final AtomicLong UPDATE_COUNTER = new AtomicLong();
+ private static final AtomicLong REQUEST_COUNTER = new AtomicLong();
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
@@ -815,9 +814,9 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
Host host = lookupOrAddHostLocked(id);
host.callbacks = callbacks;
- long updateSequenceNo = UPDATE_COUNTER.incrementAndGet();
int N = appWidgetIds.length;
ArrayList<PendingHostUpdate> outUpdates = new ArrayList<>(N);
+
LongSparseArray<PendingHostUpdate> updatesMap = new LongSparseArray<>();
for (int i = 0; i < N; i++) {
if (host.getPendingUpdatesForId(appWidgetIds[i], updatesMap)) {
@@ -829,8 +828,6 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
}
}
}
- // Reset the update counter once all the updates have been calculated
- host.lastWidgetUpdateSequenceNo = updateSequenceNo;
return new ParceledListSlice<>(outUpdates);
}
}
@@ -1917,9 +1914,9 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
// method with a wrong id. In that case, ignore the call.
return;
}
- long requestId = UPDATE_COUNTER.incrementAndGet();
+ long requestId = REQUEST_COUNTER.incrementAndGet();
if (widget != null) {
- widget.updateSequenceNos.put(viewId, requestId);
+ widget.updateRequestIds.put(viewId, requestId);
}
if (widget == null || widget.host == null || widget.host.zombie
|| widget.host.callbacks == null || widget.provider == null
@@ -1944,7 +1941,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
int appWidgetId, int viewId, long requestId) {
try {
callbacks.viewDataChanged(appWidgetId, viewId);
- host.lastWidgetUpdateSequenceNo = requestId;
+ host.lastWidgetUpdateRequestId = requestId;
} catch (RemoteException re) {
// It failed; remove the callback. No need to prune because
// we know that this host is still referenced by this instance.
@@ -1991,9 +1988,9 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
}
private void scheduleNotifyUpdateAppWidgetLocked(Widget widget, RemoteViews updateViews) {
- long requestId = UPDATE_COUNTER.incrementAndGet();
+ long requestId = REQUEST_COUNTER.incrementAndGet();
if (widget != null) {
- widget.updateSequenceNos.put(ID_VIEWS_UPDATE, requestId);
+ widget.updateRequestIds.put(ID_VIEWS_UPDATE, requestId);
}
if (widget == null || widget.provider == null || widget.provider.zombie
|| widget.host.callbacks == null || widget.host.zombie) {
@@ -2016,7 +2013,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
int appWidgetId, RemoteViews views, long requestId) {
try {
callbacks.updateAppWidget(appWidgetId, views);
- host.lastWidgetUpdateSequenceNo = requestId;
+ host.lastWidgetUpdateRequestId = requestId;
} catch (RemoteException re) {
synchronized (mLock) {
Slog.e(TAG, "Widget host dead: " + host.id, re);
@@ -2026,11 +2023,11 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
}
private void scheduleNotifyProviderChangedLocked(Widget widget) {
- long requestId = UPDATE_COUNTER.incrementAndGet();
+ long requestId = REQUEST_COUNTER.incrementAndGet();
if (widget != null) {
// When the provider changes, reset everything else.
- widget.updateSequenceNos.clear();
- widget.updateSequenceNos.append(ID_PROVIDER_CHANGED, requestId);
+ widget.updateRequestIds.clear();
+ widget.updateRequestIds.append(ID_PROVIDER_CHANGED, requestId);
}
if (widget == null || widget.provider == null || widget.provider.zombie
|| widget.host.callbacks == null || widget.host.zombie) {
@@ -2053,7 +2050,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
int appWidgetId, AppWidgetProviderInfo info, long requestId) {
try {
callbacks.providerChanged(appWidgetId, info);
- host.lastWidgetUpdateSequenceNo = requestId;
+ host.lastWidgetUpdateRequestId = requestId;
} catch (RemoteException re) {
synchronized (mLock){
Slog.e(TAG, "Widget host dead: " + host.id, re);
@@ -3890,11 +3887,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
int tag = TAG_UNDEFINED; // for use while saving state (the index)
- // Sequence no for the last update successfully sent. This is updated whenever a
- // widget update is successfully sent to the host callbacks. As all new/undelivered updates
- // will have sequenceNo greater than this, all those updates will be sent when the host
- // callbacks are attached again.
- long lastWidgetUpdateSequenceNo;
+ long lastWidgetUpdateRequestId; // request id for the last update successfully sent
public int getUserId() {
return UserHandle.getUserId(id.uid);
@@ -3921,18 +3914,18 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
*/
public boolean getPendingUpdatesForId(int appWidgetId,
LongSparseArray<PendingHostUpdate> outUpdates) {
- long updateSequenceNo = lastWidgetUpdateSequenceNo;
+ long updateRequestId = lastWidgetUpdateRequestId;
int N = widgets.size();
for (int i = 0; i < N; i++) {
Widget widget = widgets.get(i);
if (widget.appWidgetId == appWidgetId) {
outUpdates.clear();
- for (int j = widget.updateSequenceNos.size() - 1; j >= 0; j--) {
- long requestId = widget.updateSequenceNos.valueAt(j);
- if (requestId <= updateSequenceNo) {
+ for (int j = widget.updateRequestIds.size() - 1; j >= 0; j--) {
+ long requestId = widget.updateRequestIds.valueAt(j);
+ if (requestId <= updateRequestId) {
continue;
}
- int id = widget.updateSequenceNos.keyAt(j);
+ int id = widget.updateRequestIds.keyAt(j);
final PendingHostUpdate update;
switch (id) {
case ID_PROVIDER_CHANGED:
@@ -4028,8 +4021,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
RemoteViews maskedViews;
Bundle options;
Host host;
- // Map of request type to updateSequenceNo.
- SparseLongArray updateSequenceNos = new SparseLongArray(2);
+ // Request ids for various operations
+ SparseLongArray updateRequestIds = new SparseLongArray(2);
@Override
public String toString() {
diff --git a/com/android/server/audio/PlaybackActivityMonitor.java b/com/android/server/audio/PlaybackActivityMonitor.java
index 49431733..6506cf7f 100644
--- a/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/com/android/server/audio/PlaybackActivityMonitor.java
@@ -184,15 +184,11 @@ public final class PlaybackActivityMonitor
}
}
- private static final int FLAGS_FOR_SILENCE_OVERRIDE =
- AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY |
- AudioAttributes.FLAG_BYPASS_MUTE;
-
private void checkVolumeForPrivilegedAlarm(AudioPlaybackConfiguration apc, int event) {
if (event == AudioPlaybackConfiguration.PLAYER_STATE_STARTED ||
apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) {
- if ((apc.getAudioAttributes().getAllFlags() & FLAGS_FOR_SILENCE_OVERRIDE)
- == FLAGS_FOR_SILENCE_OVERRIDE &&
+ if ((apc.getAudioAttributes().getAllFlags() &
+ AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0 &&
apc.getAudioAttributes().getUsage() == AudioAttributes.USAGE_ALARM &&
mContext.checkPermission(android.Manifest.permission.MODIFY_PHONE_STATE,
apc.getClientPid(), apc.getClientUid()) ==
diff --git a/com/android/server/autofill/AutofillManagerServiceImpl.java b/com/android/server/autofill/AutofillManagerServiceImpl.java
index 880f236c..862070ad 100644
--- a/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -216,12 +216,9 @@ final class AutofillManagerServiceImpl {
serviceComponent = ComponentName.unflattenFromString(componentName);
serviceInfo = AppGlobals.getPackageManager().getServiceInfo(serviceComponent,
0, mUserId);
- if (serviceInfo == null) {
- Slog.e(TAG, "Bad AutofillService name: " + componentName);
- }
} catch (RuntimeException | RemoteException e) {
- Slog.e(TAG, "Error getting service info for '" + componentName + "': " + e);
- serviceInfo = null;
+ Slog.e(TAG, "Bad autofill service name " + componentName + ": " + e);
+ return;
}
}
try {
@@ -231,24 +228,21 @@ final class AutofillManagerServiceImpl {
if (sDebug) Slog.d(TAG, "Set component for user " + mUserId + " as " + mInfo);
} else {
mInfo = null;
- if (sDebug) {
- Slog.d(TAG, "Reset component for user " + mUserId + " (" + componentName + ")");
- }
+ if (sDebug) Slog.d(TAG, "Reset component for user " + mUserId);
}
- } catch (Exception e) {
- Slog.e(TAG, "Bad AutofillServiceInfo for '" + componentName + "': " + e);
- mInfo = null;
- }
- final boolean isEnabled = isEnabled();
- if (wasEnabled != isEnabled) {
- if (!isEnabled) {
- final int sessionCount = mSessions.size();
- for (int i = sessionCount - 1; i >= 0; i--) {
- final Session session = mSessions.valueAt(i);
- session.removeSelfLocked();
+ final boolean isEnabled = isEnabled();
+ if (wasEnabled != isEnabled) {
+ if (!isEnabled) {
+ final int sessionCount = mSessions.size();
+ for (int i = sessionCount - 1; i >= 0; i--) {
+ final Session session = mSessions.valueAt(i);
+ session.removeSelfLocked();
+ }
}
+ sendStateToClients(false);
}
- sendStateToClients(false);
+ } catch (Exception e) {
+ Slog.e(TAG, "Bad AutofillService '" + componentName + "': " + e);
}
}
diff --git a/com/android/server/autofill/Session.java b/com/android/server/autofill/Session.java
index 3c12d670..ed00ffed 100644
--- a/com/android/server/autofill/Session.java
+++ b/com/android/server/autofill/Session.java
@@ -495,7 +495,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
notifyUnavailableToClient(false);
}
synchronized (mLock) {
- processResponseLocked(response, null, requestFlags);
+ processResponseLocked(response, requestFlags);
}
final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_REQUEST, servicePackageName)
@@ -762,21 +762,13 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
final Parcelable result = data.getParcelable(AutofillManager.EXTRA_AUTHENTICATION_RESULT);
- final Bundle newClientState = data.getBundle(AutofillManager.EXTRA_CLIENT_STATE);
- if (sDebug) {
- Slog.d(TAG, "setAuthenticationResultLocked(): result=" + result
- + ", clientState=" + newClientState);
- }
+ if (sDebug) Slog.d(TAG, "setAuthenticationResultLocked(): result=" + result);
if (result instanceof FillResponse) {
writeLog(MetricsEvent.AUTOFILL_AUTHENTICATED);
- replaceResponseLocked(authenticatedResponse, (FillResponse) result, newClientState);
+ replaceResponseLocked(authenticatedResponse, (FillResponse) result);
} else if (result instanceof Dataset) {
if (datasetIdx != AutofillManager.AUTHENTICATION_ID_DATASET_ID_UNDEFINED) {
writeLog(MetricsEvent.AUTOFILL_DATASET_AUTHENTICATED);
- if (newClientState != null) {
- if (sDebug) Slog.d(TAG, "Updating client state from auth dataset");
- mClientState = newClientState;
- }
final Dataset dataset = (Dataset) result;
authenticatedResponse.getDatasets().set(datasetIdx, dataset);
autoFill(requestId, datasetIdx, dataset, false);
@@ -1499,14 +1491,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
ArraySet<AutofillId> trackedViews = null;
boolean saveOnAllViewsInvisible = false;
- boolean saveOnFinish = true;
final SaveInfo saveInfo = response.getSaveInfo();
- final AutofillId saveTriggerId;
if (saveInfo != null) {
- saveTriggerId = saveInfo.getTriggerId();
- if (saveTriggerId != null) {
- writeLog(MetricsEvent.AUTOFILL_EXPLICIT_SAVE_TRIGGER_DEFINITION);
- }
saveOnAllViewsInvisible =
(saveInfo.getFlags() & SaveInfo.FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE) != 0;
@@ -1523,12 +1509,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
Collections.addAll(trackedViews, saveInfo.getOptionalIds());
}
}
- if ((saveInfo.getFlags() & SaveInfo.FLAG_DONT_SAVE_ON_FINISH) != 0) {
- saveOnFinish = false;
- }
-
- } else {
- saveTriggerId = null;
}
// Must also track that are part of datasets, otherwise the FillUI won't be hidden when
@@ -1553,18 +1533,17 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
try {
if (sVerbose) {
- Slog.v(TAG, "updateTrackedIdsLocked(): " + trackedViews + " => " + fillableIds
- + " (triggering on " + saveTriggerId + ")");
+ Slog.v(TAG, "updateTrackedIdsLocked(): " + trackedViews + " => " + fillableIds);
}
mClient.setTrackedViews(id, toArray(trackedViews), saveOnAllViewsInvisible,
- saveOnFinish, toArray(fillableIds), saveTriggerId);
+ toArray(fillableIds));
} catch (RemoteException e) {
Slog.w(TAG, "Cannot set tracked ids", e);
}
}
private void replaceResponseLocked(@NonNull FillResponse oldResponse,
- @NonNull FillResponse newResponse, @Nullable Bundle newClientState) {
+ @NonNull FillResponse newResponse) {
// Disassociate view states with the old response
setViewStatesLocked(oldResponse, ViewState.STATE_INITIAL, true);
// Move over the id
@@ -1572,7 +1551,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
// Replace the old response
mResponses.put(newResponse.getRequestId(), newResponse);
// Now process the new response
- processResponseLocked(newResponse, newClientState, 0);
+ processResponseLocked(newResponse, 0);
}
private void processNullResponseLocked(int flags) {
@@ -1586,8 +1565,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
removeSelf();
}
- private void processResponseLocked(@NonNull FillResponse newResponse,
- @Nullable Bundle newClientState, int flags) {
+ private void processResponseLocked(@NonNull FillResponse newResponse, int flags) {
// Make sure we are hiding the UI which will be shown
// only if handling the current response requires it.
mUi.hideAll(this);
@@ -1595,15 +1573,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
final int requestId = newResponse.getRequestId();
if (sVerbose) {
Slog.v(TAG, "processResponseLocked(): mCurrentViewId=" + mCurrentViewId
- + ",flags=" + flags + ", reqId=" + requestId + ", resp=" + newResponse
- + ",newClientState=" + newClientState);
+ + ",flags=" + flags + ", reqId=" + requestId + ", resp=" + newResponse);
}
if (mResponses == null) {
mResponses = new SparseArray<>(4);
}
mResponses.put(requestId, newResponse);
- mClientState = newClientState != null ? newClientState : newResponse.getClientState();
+ mClientState = newResponse.getClientState();
setViewStatesLocked(newResponse, ViewState.STATE_FILLABLE, false);
updateTrackedIdsLocked();
diff --git a/com/android/server/backup/BackupManagerService.java b/com/android/server/backup/BackupManagerService.java
index f9213aab..eabe21fe 100644
--- a/com/android/server/backup/BackupManagerService.java
+++ b/com/android/server/backup/BackupManagerService.java
@@ -319,6 +319,7 @@ public class BackupManagerService implements BackupManagerServiceInterface {
boolean mProvisioned;
boolean mAutoRestore;
PowerManager.WakeLock mWakelock;
+ HandlerThread mHandlerThread;
BackupHandler mBackupHandler;
PendingIntent mRunBackupIntent, mRunInitIntent;
BroadcastReceiver mRunBackupReceiver, mRunInitReceiver;
@@ -408,37 +409,43 @@ public class BackupManagerService implements BackupManagerServiceInterface {
// Called through the trampoline from onUnlockUser(), then we buck the work
// off to the background thread to keep the unlock time down.
public void unlockSystemUser() {
- // Migrate legacy setting
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup migrate");
- if (!backupSettingMigrated(UserHandle.USER_SYSTEM)) {
- if (DEBUG) {
- Slog.i(TAG, "Backup enable apparently not migrated");
- }
- final ContentResolver r = sInstance.mContext.getContentResolver();
- final int enableState = Settings.Secure.getIntForUser(r,
- Settings.Secure.BACKUP_ENABLED, -1, UserHandle.USER_SYSTEM);
- if (enableState >= 0) {
+ mBackupHandler.post(() -> {
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup init");
+ sInstance.initialize(UserHandle.USER_SYSTEM);
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+
+ // Migrate legacy setting
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup migrate");
+ if (!backupSettingMigrated(UserHandle.USER_SYSTEM)) {
if (DEBUG) {
- Slog.i(TAG, "Migrating enable state " + (enableState != 0));
+ Slog.i(TAG, "Backup enable apparently not migrated");
}
- writeBackupEnableState(enableState != 0, UserHandle.USER_SYSTEM);
- Settings.Secure.putStringForUser(r,
- Settings.Secure.BACKUP_ENABLED, null, UserHandle.USER_SYSTEM);
- } else {
- if (DEBUG) {
- Slog.i(TAG, "Backup not yet configured; retaining null enable state");
+ final ContentResolver r = sInstance.mContext.getContentResolver();
+ final int enableState = Settings.Secure.getIntForUser(r,
+ Settings.Secure.BACKUP_ENABLED, -1, UserHandle.USER_SYSTEM);
+ if (enableState >= 0) {
+ if (DEBUG) {
+ Slog.i(TAG, "Migrating enable state " + (enableState != 0));
+ }
+ writeBackupEnableState(enableState != 0, UserHandle.USER_SYSTEM);
+ Settings.Secure.putStringForUser(r,
+ Settings.Secure.BACKUP_ENABLED, null, UserHandle.USER_SYSTEM);
+ } else {
+ if (DEBUG) {
+ Slog.i(TAG, "Backup not yet configured; retaining null enable state");
+ }
}
}
- }
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup enable");
- try {
- sInstance.setBackupEnabled(readBackupEnableState(UserHandle.USER_SYSTEM));
- } catch (RemoteException e) {
- // can't happen; it's a local object
- }
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup enable");
+ try {
+ sInstance.setBackupEnabled(readBackupEnableState(UserHandle.USER_SYSTEM));
+ } catch (RemoteException e) {
+ // can't happen; it's a local object
+ }
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ });
}
class ProvisionedObserver extends ContentObserver {
@@ -1213,7 +1220,7 @@ public class BackupManagerService implements BackupManagerServiceInterface {
// ----- Main service implementation -----
- public BackupManagerService(Context context, Trampoline parent, HandlerThread backupThread) {
+ public BackupManagerService(Context context, Trampoline parent) {
mContext = context;
mPackageManager = context.getPackageManager();
mPackageManagerBinder = AppGlobals.getPackageManager();
@@ -1226,7 +1233,9 @@ public class BackupManagerService implements BackupManagerServiceInterface {
mBackupManagerBinder = Trampoline.asInterface(parent.asBinder());
// spin up the backup/restore handler thread
- mBackupHandler = new BackupHandler(backupThread.getLooper());
+ mHandlerThread = new HandlerThread("backup", Process.THREAD_PRIORITY_BACKGROUND);
+ mHandlerThread.start();
+ mBackupHandler = new BackupHandler(mHandlerThread.getLooper());
// Set up our bookkeeping
final ContentResolver resolver = context.getContentResolver();
@@ -1351,7 +1360,7 @@ public class BackupManagerService implements BackupManagerServiceInterface {
if (DEBUG) Slog.v(TAG, "Starting with transport " + currentTransport);
mTransportManager = new TransportManager(context, transportWhitelist, currentTransport,
- mTransportBoundListener, backupThread.getLooper());
+ mTransportBoundListener, mHandlerThread.getLooper());
mTransportManager.registerAllTransports();
// Now that we know about valid backup participants, parse any
diff --git a/com/android/server/backup/RefactoredBackupManagerService.java b/com/android/server/backup/RefactoredBackupManagerService.java
index 20f23690..f2980659 100644
--- a/com/android/server/backup/RefactoredBackupManagerService.java
+++ b/com/android/server/backup/RefactoredBackupManagerService.java
@@ -237,6 +237,7 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
private boolean mProvisioned;
private boolean mAutoRestore;
private PowerManager.WakeLock mWakelock;
+ private HandlerThread mHandlerThread;
private BackupHandler mBackupHandler;
private PendingIntent mRunBackupIntent;
private PendingIntent mRunInitIntent;
@@ -555,37 +556,43 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
// Called through the trampoline from onUnlockUser(), then we buck the work
// off to the background thread to keep the unlock time down.
public void unlockSystemUser() {
- // Migrate legacy setting
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup migrate");
- if (!backupSettingMigrated(UserHandle.USER_SYSTEM)) {
- if (DEBUG) {
- Slog.i(TAG, "Backup enable apparently not migrated");
- }
- final ContentResolver r = sInstance.mContext.getContentResolver();
- final int enableState = Settings.Secure.getIntForUser(r,
- Settings.Secure.BACKUP_ENABLED, -1, UserHandle.USER_SYSTEM);
- if (enableState >= 0) {
+ mBackupHandler.post(() -> {
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup init");
+ sInstance.initialize(UserHandle.USER_SYSTEM);
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+
+ // Migrate legacy setting
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup migrate");
+ if (!backupSettingMigrated(UserHandle.USER_SYSTEM)) {
if (DEBUG) {
- Slog.i(TAG, "Migrating enable state " + (enableState != 0));
+ Slog.i(TAG, "Backup enable apparently not migrated");
}
- writeBackupEnableState(enableState != 0, UserHandle.USER_SYSTEM);
- Settings.Secure.putStringForUser(r,
- Settings.Secure.BACKUP_ENABLED, null, UserHandle.USER_SYSTEM);
- } else {
- if (DEBUG) {
- Slog.i(TAG, "Backup not yet configured; retaining null enable state");
+ final ContentResolver r = sInstance.mContext.getContentResolver();
+ final int enableState = Settings.Secure.getIntForUser(r,
+ Settings.Secure.BACKUP_ENABLED, -1, UserHandle.USER_SYSTEM);
+ if (enableState >= 0) {
+ if (DEBUG) {
+ Slog.i(TAG, "Migrating enable state " + (enableState != 0));
+ }
+ writeBackupEnableState(enableState != 0, UserHandle.USER_SYSTEM);
+ Settings.Secure.putStringForUser(r,
+ Settings.Secure.BACKUP_ENABLED, null, UserHandle.USER_SYSTEM);
+ } else {
+ if (DEBUG) {
+ Slog.i(TAG, "Backup not yet configured; retaining null enable state");
+ }
}
}
- }
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup enable");
- try {
- sInstance.setBackupEnabled(readBackupEnableState(UserHandle.USER_SYSTEM));
- } catch (RemoteException e) {
- // can't happen; it's a local object
- }
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup enable");
+ try {
+ sInstance.setBackupEnabled(readBackupEnableState(UserHandle.USER_SYSTEM));
+ } catch (RemoteException e) {
+ // can't happen; it's a local object
+ }
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ });
}
// Bookkeeping of in-flight operations for timeout etc. purposes. The operation
@@ -722,8 +729,7 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
// ----- Main service implementation -----
- public RefactoredBackupManagerService(Context context, Trampoline parent,
- HandlerThread backupThread) {
+ public RefactoredBackupManagerService(Context context, Trampoline parent) {
mContext = context;
mPackageManager = context.getPackageManager();
mPackageManagerBinder = AppGlobals.getPackageManager();
@@ -736,7 +742,9 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
mBackupManagerBinder = Trampoline.asInterface(parent.asBinder());
// spin up the backup/restore handler thread
- mBackupHandler = new BackupHandler(this, backupThread.getLooper());
+ mHandlerThread = new HandlerThread("backup", Process.THREAD_PRIORITY_BACKGROUND);
+ mHandlerThread.start();
+ mBackupHandler = new BackupHandler(this, mHandlerThread.getLooper());
// Set up our bookkeeping
final ContentResolver resolver = context.getContentResolver();
@@ -816,7 +824,7 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
if (DEBUG) Slog.v(TAG, "Starting with transport " + currentTransport);
mTransportManager = new TransportManager(context, transportWhitelist, currentTransport,
- mTransportBoundListener, backupThread.getLooper());
+ mTransportBoundListener, mHandlerThread.getLooper());
mTransportManager.registerAllTransports();
// Now that we know about valid backup participants, parse any
diff --git a/com/android/server/backup/Trampoline.java b/com/android/server/backup/Trampoline.java
index 9847edf8..9739e380 100644
--- a/com/android/server/backup/Trampoline.java
+++ b/com/android/server/backup/Trampoline.java
@@ -28,15 +28,11 @@ import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Environment;
-import android.os.Handler;
-import android.os.HandlerThread;
import android.os.IBinder;
-import android.os.Looper;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemProperties;
-import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Slog;
@@ -79,8 +75,6 @@ public class Trampoline extends IBackupManager.Stub {
final boolean mGlobalDisable;
volatile BackupManagerServiceInterface mService;
- private HandlerThread mHandlerThread;
-
public Trampoline(Context context) {
mContext = context;
mGlobalDisable = isBackupDisabled();
@@ -117,11 +111,11 @@ public class Trampoline extends IBackupManager.Stub {
}
protected BackupManagerServiceInterface createRefactoredBackupManagerService() {
- return new RefactoredBackupManagerService(mContext, this, mHandlerThread);
+ return new RefactoredBackupManagerService(mContext, this);
}
protected BackupManagerServiceInterface createBackupManagerService() {
- return new BackupManagerService(mContext, this, mHandlerThread);
+ return new BackupManagerService(mContext, this);
}
// internal control API
@@ -146,21 +140,10 @@ public class Trampoline extends IBackupManager.Stub {
}
void unlockSystemUser() {
- mHandlerThread = new HandlerThread("backup", Process.THREAD_PRIORITY_BACKGROUND);
- mHandlerThread.start();
-
- Handler h = new Handler(mHandlerThread.getLooper());
- h.post(() -> {
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup init");
- initialize(UserHandle.USER_SYSTEM);
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
-
- BackupManagerServiceInterface svc = mService;
- Slog.i(TAG, "Unlocking system user; mService=" + mService);
- if (svc != null) {
- svc.unlockSystemUser();
- }
- });
+ BackupManagerServiceInterface svc = mService;
+ if (svc != null) {
+ svc.unlockSystemUser();
+ }
}
public void setBackupServiceActive(final int userHandle, boolean makeActive) {
diff --git a/com/android/server/clipboard/ClipboardService.java b/com/android/server/clipboard/ClipboardService.java
index 0c9d70a9..e6228d46 100644
--- a/com/android/server/clipboard/ClipboardService.java
+++ b/com/android/server/clipboard/ClipboardService.java
@@ -435,12 +435,11 @@ public class ClipboardService extends SystemService {
}
private boolean isDeviceLocked() {
- int callingUserId = UserHandle.getCallingUserId();
final long token = Binder.clearCallingIdentity();
try {
final KeyguardManager keyguardManager = getContext().getSystemService(
KeyguardManager.class);
- return keyguardManager != null && keyguardManager.isDeviceLocked(callingUserId);
+ return keyguardManager != null && keyguardManager.isDeviceLocked();
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/com/android/server/connectivity/Tethering.java b/com/android/server/connectivity/Tethering.java
index d7cd81ff..5583e86c 100644
--- a/com/android/server/connectivity/Tethering.java
+++ b/com/android/server/connectivity/Tethering.java
@@ -1371,7 +1371,6 @@ public class Tethering extends BaseNetworkObserver {
sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
}
}
- mUpstreamNetworkMonitor.setCurrentUpstream((ns != null) ? ns.network : null);
setUpstreamNetwork(ns);
}
diff --git a/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
index b35ed751..c5f75280 100644
--- a/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
+++ b/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
@@ -95,10 +95,7 @@ public class UpstreamNetworkMonitor {
private NetworkCallback mDefaultNetworkCallback;
private NetworkCallback mMobileNetworkCallback;
private boolean mDunRequired;
- // The current system default network (not really used yet).
- private Network mDefaultInternetNetwork;
- // The current upstream network used for tethering.
- private Network mTetheringUpstreamNetwork;
+ private Network mCurrentDefault;
public UpstreamNetworkMonitor(Context ctx, StateMachine tgt, SharedLog log, int what) {
mContext = ctx;
@@ -133,12 +130,10 @@ public class UpstreamNetworkMonitor {
releaseCallback(mDefaultNetworkCallback);
mDefaultNetworkCallback = null;
- mDefaultInternetNetwork = null;
releaseCallback(mListenAllCallback);
mListenAllCallback = null;
- mTetheringUpstreamNetwork = null;
mNetworkMap.clear();
}
@@ -212,7 +207,7 @@ public class UpstreamNetworkMonitor {
break;
default:
/* If we've found an active upstream connection that's not DUN/HIPRI
- * we should stop any outstanding DUN/HIPRI requests.
+ * we should stop any outstanding DUN/HIPRI start requests.
*
* If we found NONE we don't want to do this as we want any previous
* requests to keep trying to bring up something we can use.
@@ -224,10 +219,6 @@ public class UpstreamNetworkMonitor {
return typeStatePair.ns;
}
- public void setCurrentUpstream(Network upstream) {
- mTetheringUpstreamNetwork = upstream;
- }
-
public Set<IpPrefix> getLocalPrefixes() {
return (Set<IpPrefix>) mLocalPrefixes.clone();
}
@@ -259,7 +250,7 @@ public class UpstreamNetworkMonitor {
// These request*() calls can be deleted post oag/339444.
return;
}
- mDefaultInternetNetwork = network;
+ mCurrentDefault = network;
break;
case CALLBACK_MOBILE_REQUEST:
@@ -311,13 +302,6 @@ public class UpstreamNetworkMonitor {
network, newNc));
}
- // Log changes in upstream network signal strength, if available.
- if (network.equals(mTetheringUpstreamNetwork) && newNc.hasSignalStrength()) {
- final int newSignal = newNc.getSignalStrength();
- final String prevSignal = getSignalStrength(prev.networkCapabilities);
- mLog.logf("upstream network signal strength: %s -> %s", prevSignal, newSignal);
- }
-
mNetworkMap.put(network, new NetworkState(
null, prev.linkProperties, newNc, network, null, null));
// TODO: If sufficient information is available to select a more
@@ -346,21 +330,9 @@ public class UpstreamNetworkMonitor {
notifyTarget(EVENT_ON_LINKPROPERTIES, network);
}
- private void handleSuspended(int callbackType, Network network) {
- if (callbackType != CALLBACK_LISTEN_ALL) return;
- if (!network.equals(mTetheringUpstreamNetwork)) return;
- mLog.log("SUSPENDED current upstream: " + network);
- }
-
- private void handleResumed(int callbackType, Network network) {
- if (callbackType != CALLBACK_LISTEN_ALL) return;
- if (!network.equals(mTetheringUpstreamNetwork)) return;
- mLog.log("RESUMED current upstream: " + network);
- }
-
private void handleLost(int callbackType, Network network) {
if (callbackType == CALLBACK_TRACK_DEFAULT) {
- mDefaultInternetNetwork = null;
+ mCurrentDefault = null;
// Receiving onLost() for a default network does not necessarily
// mean the network is gone. We wait for a separate notification
// on either the LISTEN_ALL or MOBILE_REQUEST callbacks before
@@ -429,15 +401,8 @@ public class UpstreamNetworkMonitor {
recomputeLocalPrefixes();
}
- @Override
- public void onNetworkSuspended(Network network) {
- handleSuspended(mCallbackType, network);
- }
-
- @Override
- public void onNetworkResumed(Network network) {
- handleResumed(mCallbackType, network);
- }
+ // TODO: Handle onNetworkSuspended();
+ // TODO: Handle onNetworkResumed();
@Override
public void onLost(Network network) {
@@ -502,9 +467,4 @@ public class UpstreamNetworkMonitor {
return prefixSet;
}
-
- private static String getSignalStrength(NetworkCapabilities nc) {
- if (nc == null || !nc.hasSignalStrength()) return "unknown";
- return Integer.toString(nc.getSignalStrength());
- }
}
diff --git a/com/android/server/display/AutomaticBrightnessController.java b/com/android/server/display/AutomaticBrightnessController.java
index 9a6e6094..9aabdab7 100644
--- a/com/android/server/display/AutomaticBrightnessController.java
+++ b/com/android/server/display/AutomaticBrightnessController.java
@@ -29,7 +29,6 @@ import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.SystemClock;
-import android.os.Trace;
import android.text.format.DateUtils;
import android.util.EventLog;
import android.util.MathUtils;
@@ -305,7 +304,6 @@ class AutomaticBrightnessController {
}
private void handleLightSensorEvent(long time, float lux) {
- Trace.traceCounter(Trace.TRACE_TAG_POWER, "ALS", (int) lux);
mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX);
if (mAmbientLightRingBuffer.size() == 0) {
diff --git a/com/android/server/display/DisplayPowerController.java b/com/android/server/display/DisplayPowerController.java
index f930b523..f8e58362 100644
--- a/com/android/server/display/DisplayPowerController.java
+++ b/com/android/server/display/DisplayPowerController.java
@@ -683,8 +683,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Configure auto-brightness.
boolean autoBrightnessEnabled = false;
if (mAutomaticBrightnessController != null) {
- final boolean autoBrightnessEnabledInDoze =
- mAllowAutoBrightnessWhileDozingConfig && Display.isDozeState(state);
+ final boolean autoBrightnessEnabledInDoze = mAllowAutoBrightnessWhileDozingConfig
+ && (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND);
autoBrightnessEnabled = mPowerRequest.useAutoBrightness
&& (state == Display.STATE_ON || autoBrightnessEnabledInDoze)
&& brightness < 0;
@@ -726,7 +726,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
// Use default brightness when dozing unless overridden.
- if (brightness < 0 && Display.isDozeState(state)) {
+ if (brightness < 0 && (state == Display.STATE_DOZE
+ || state == Display.STATE_DOZE_SUSPEND)) {
brightness = mScreenBrightnessDozeConfig;
}
@@ -776,6 +777,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Skip the animation when the screen is off or suspended or transition to/from VR.
if (!mPendingScreenOff) {
if (mSkipScreenOnBrightnessRamp) {
+
if (state == Display.STATE_ON) {
if (mSkipRampState == RAMP_STATE_SKIP_NONE && mDozing) {
mInitialAutoBrightness = brightness;
@@ -792,25 +794,15 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
}
- final boolean wasOrWillBeInVr =
- (state == Display.STATE_VR || oldState == Display.STATE_VR);
- final boolean initialRampSkip =
- state == Display.STATE_ON && mSkipRampState != RAMP_STATE_SKIP_NONE;
- // While dozing, sometimes the brightness is split into buckets. Rather than animating
- // through the buckets, which is unlikely to be smooth in the first place, just jump
- // right to the suggested brightness.
- final boolean hasBrightnessBuckets =
- Display.isDozeState(state) && mBrightnessBucketsInDozeConfig;
- // If the color fade is totally covering the screen then we can change the backlight
- // level without it being a noticeable jump since any actual content isn't yet visible.
- final boolean isDisplayContentVisible =
- mColorFadeEnabled && mPowerState.getColorFadeLevel() == 1.0f;
- if (initialRampSkip || hasBrightnessBuckets
- || wasOrWillBeInVr || !isDisplayContentVisible) {
- animateScreenBrightness(brightness, 0);
- } else {
+ boolean wasOrWillBeInVr = (state == Display.STATE_VR || oldState == Display.STATE_VR);
+ if ((state == Display.STATE_ON
+ && mSkipRampState == RAMP_STATE_SKIP_NONE
+ || state == Display.STATE_DOZE && !mBrightnessBucketsInDozeConfig)
+ && !wasOrWillBeInVr) {
animateScreenBrightness(brightness,
slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);
+ } else {
+ animateScreenBrightness(brightness, 0);
}
}
@@ -933,7 +925,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
if (!reportOnly) {
- Trace.traceCounter(Trace.TRACE_TAG_POWER, "ScreenState", state);
mPowerState.setScreenState(state);
// Tell battery stats about the transition.
try {
diff --git a/com/android/server/job/controllers/TimeController.java b/com/android/server/job/controllers/TimeController.java
index ee4c606f..d90699a6 100644
--- a/com/android/server/job/controllers/TimeController.java
+++ b/com/android/server/job/controllers/TimeController.java
@@ -110,7 +110,7 @@ public final class TimeController extends StateController {
maybeUpdateAlarmsLocked(
job.hasTimingDelayConstraint() ? job.getEarliestRunTime() : Long.MAX_VALUE,
job.hasDeadlineConstraint() ? job.getLatestRunTimeElapsed() : Long.MAX_VALUE,
- new WorkSource(job.getSourceUid(), job.getSourcePackageName()));
+ job.getSourceUid());
}
}
@@ -156,7 +156,6 @@ public final class TimeController extends StateController {
synchronized (mLock) {
long nextExpiryTime = Long.MAX_VALUE;
int nextExpiryUid = 0;
- String nextExpiryPackageName = null;
final long nowElapsedMillis = SystemClock.elapsedRealtime();
Iterator<JobStatus> it = mTrackedJobs.iterator();
@@ -172,13 +171,10 @@ public final class TimeController extends StateController {
} else { // Sorted by expiry time, so take the next one and stop.
nextExpiryTime = job.getLatestRunTimeElapsed();
nextExpiryUid = job.getSourceUid();
- nextExpiryPackageName = job.getSourcePackageName();
break;
}
}
- setDeadlineExpiredAlarmLocked(nextExpiryTime, nextExpiryPackageName != null
- ? new WorkSource(nextExpiryUid, nextExpiryPackageName)
- : new WorkSource(nextExpiryUid));
+ setDeadlineExpiredAlarmLocked(nextExpiryTime, nextExpiryUid);
}
}
@@ -204,7 +200,6 @@ public final class TimeController extends StateController {
final long nowElapsedMillis = SystemClock.elapsedRealtime();
long nextDelayTime = Long.MAX_VALUE;
int nextDelayUid = 0;
- String nextDelayPackageName = null;
boolean ready = false;
Iterator<JobStatus> it = mTrackedJobs.iterator();
while (it.hasNext()) {
@@ -226,16 +221,13 @@ public final class TimeController extends StateController {
if (nextDelayTime > jobDelayTime) {
nextDelayTime = jobDelayTime;
nextDelayUid = job.getSourceUid();
- nextDelayPackageName = job.getSourcePackageName();
}
}
}
if (ready) {
mStateChangedListener.onControllerStateChanged();
}
- setDelayExpiredAlarmLocked(nextDelayTime, nextDelayPackageName != null
- ? new WorkSource(nextDelayUid, nextDelayPackageName)
- : new WorkSource(nextDelayUid));
+ setDelayExpiredAlarmLocked(nextDelayTime, nextDelayUid);
}
}
@@ -249,12 +241,12 @@ public final class TimeController extends StateController {
}
private void maybeUpdateAlarmsLocked(long delayExpiredElapsed, long deadlineExpiredElapsed,
- WorkSource ws) {
+ int uid) {
if (delayExpiredElapsed < mNextDelayExpiredElapsedMillis) {
- setDelayExpiredAlarmLocked(delayExpiredElapsed, ws);
+ setDelayExpiredAlarmLocked(delayExpiredElapsed, uid);
}
if (deadlineExpiredElapsed < mNextJobExpiredElapsedMillis) {
- setDeadlineExpiredAlarmLocked(deadlineExpiredElapsed, ws);
+ setDeadlineExpiredAlarmLocked(deadlineExpiredElapsed, uid);
}
}
@@ -263,11 +255,11 @@ public final class TimeController extends StateController {
* delay will expire.
* This alarm <b>will</b> wake up the phone.
*/
- private void setDelayExpiredAlarmLocked(long alarmTimeElapsedMillis, WorkSource ws) {
+ private void setDelayExpiredAlarmLocked(long alarmTimeElapsedMillis, int uid) {
alarmTimeElapsedMillis = maybeAdjustAlarmTime(alarmTimeElapsedMillis);
mNextDelayExpiredElapsedMillis = alarmTimeElapsedMillis;
updateAlarmWithListenerLocked(DELAY_TAG, mNextDelayExpiredListener,
- mNextDelayExpiredElapsedMillis, ws);
+ mNextDelayExpiredElapsedMillis, uid);
}
/**
@@ -275,11 +267,11 @@ public final class TimeController extends StateController {
* deadline will expire.
* This alarm <b>will</b> wake up the phone.
*/
- private void setDeadlineExpiredAlarmLocked(long alarmTimeElapsedMillis, WorkSource ws) {
+ private void setDeadlineExpiredAlarmLocked(long alarmTimeElapsedMillis, int uid) {
alarmTimeElapsedMillis = maybeAdjustAlarmTime(alarmTimeElapsedMillis);
mNextJobExpiredElapsedMillis = alarmTimeElapsedMillis;
updateAlarmWithListenerLocked(DEADLINE_TAG, mDeadlineExpiredListener,
- mNextJobExpiredElapsedMillis, ws);
+ mNextJobExpiredElapsedMillis, uid);
}
private long maybeAdjustAlarmTime(long proposedAlarmTimeElapsedMillis) {
@@ -291,7 +283,7 @@ public final class TimeController extends StateController {
}
private void updateAlarmWithListenerLocked(String tag, OnAlarmListener listener,
- long alarmTimeElapsed, WorkSource ws) {
+ long alarmTimeElapsed, int uid) {
ensureAlarmServiceLocked();
if (alarmTimeElapsed == Long.MAX_VALUE) {
mAlarmService.cancel(listener);
@@ -300,7 +292,7 @@ public final class TimeController extends StateController {
Slog.d(TAG, "Setting " + tag + " for: " + alarmTimeElapsed);
}
mAlarmService.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTimeElapsed,
- AlarmManager.WINDOW_HEURISTIC, 0, tag, listener, null, ws);
+ AlarmManager.WINDOW_HEURISTIC, 0, tag, listener, null, new WorkSource(uid));
}
}
diff --git a/com/android/server/location/GnssLocationProvider.java b/com/android/server/location/GnssLocationProvider.java
index e41c17df..0aa6a90e 100644
--- a/com/android/server/location/GnssLocationProvider.java
+++ b/com/android/server/location/GnssLocationProvider.java
@@ -417,11 +417,7 @@ public class GnssLocationProvider implements LocationProviderInterface {
// stops output right at 600m/s, depriving this of the information of a device that reaches
// greater than 600m/s, and higher than the speed of sound to avoid impacting most use cases.
private static final float ITAR_SPEED_LIMIT_METERS_PER_SECOND = 400.0F;
-
- // TODO: improve comment
- // Volatile to ensure that potentially near-concurrent outputs from HAL
- // react to this value change promptly
- private volatile boolean mItarSpeedLimitExceeded = false;
+ private boolean mItarSpeedLimitExceeded = false;
// GNSS Metrics
private GnssMetrics mGnssMetrics;
diff --git a/com/android/server/media/MediaSessionRecord.java b/com/android/server/media/MediaSessionRecord.java
index 664d2f97..0b11479a 100644
--- a/com/android/server/media/MediaSessionRecord.java
+++ b/com/android/server/media/MediaSessionRecord.java
@@ -784,14 +784,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
mService.enforcePhoneStatePermission(pid, uid);
}
mFlags = flags;
- if ((flags & MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0) {
- final long token = Binder.clearCallingIdentity();
- try {
- mService.setGlobalPrioritySession(MediaSessionRecord.this);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
mHandler.post(MessageHandler.MSG_UPDATE_SESSION_STATE);
}
diff --git a/com/android/server/media/MediaSessionService.java b/com/android/server/media/MediaSessionService.java
index aa652445..b9a2d184 100644
--- a/com/android/server/media/MediaSessionService.java
+++ b/com/android/server/media/MediaSessionService.java
@@ -178,6 +178,17 @@ public class MediaSessionService extends SystemService implements Monitor {
return;
}
if ((record.getFlags() & MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0) {
+ if (mGlobalPrioritySession != record) {
+ Log.d(TAG, "Global priority session is changed from " + mGlobalPrioritySession
+ + " to " + record);
+ mGlobalPrioritySession = record;
+ if (user != null && user.mPriorityStack.contains(record)) {
+ // Handle the global priority session separately.
+ // Otherwise, it will be the media button session even after it becomes
+ // inactive because it has been the lastly played media app.
+ user.mPriorityStack.removeSession(record);
+ }
+ }
if (DEBUG_KEY_EVENT) {
Log.d(TAG, "Global priority session is updated, active=" + record.isActive());
}
@@ -193,27 +204,10 @@ public class MediaSessionService extends SystemService implements Monitor {
}
}
- public void setGlobalPrioritySession(MediaSessionRecord record) {
- synchronized (mLock) {
- FullUserRecord user = getFullUserRecordLocked(record.getUserId());
- if (mGlobalPrioritySession != record) {
- Log.d(TAG, "Global priority session is changed from " + mGlobalPrioritySession
- + " to " + record);
- mGlobalPrioritySession = record;
- if (user != null && user.mPriorityStack.contains(record)) {
- // Handle the global priority session separately.
- // Otherwise, it can be the media button session regardless of the active state
- // because it or other system components might have been the lastly played media
- // app.
- user.mPriorityStack.removeSession(record);
- }
- }
- }
- }
-
private List<MediaSessionRecord> getActiveSessionsLocked(int userId) {
- List<MediaSessionRecord> records = new ArrayList<>();
+ List<MediaSessionRecord> records;
if (userId == UserHandle.USER_ALL) {
+ records = new ArrayList<>();
int size = mUserRecords.size();
for (int i = 0; i < size; i++) {
records.addAll(mUserRecords.valueAt(i).mPriorityStack.getActiveSessions(userId));
@@ -222,9 +216,9 @@ public class MediaSessionService extends SystemService implements Monitor {
FullUserRecord user = getFullUserRecordLocked(userId);
if (user == null) {
Log.w(TAG, "getSessions failed. Unknown user " + userId);
- return records;
+ return new ArrayList<>();
}
- records.addAll(user.mPriorityStack.getActiveSessions(userId));
+ records = user.mPriorityStack.getActiveSessions(userId);
}
// Return global priority session at the first whenever it's asked.
diff --git a/com/android/server/notification/NotificationManagerService.java b/com/android/server/notification/NotificationManagerService.java
index 238d87b7..14cd0555 100644
--- a/com/android/server/notification/NotificationManagerService.java
+++ b/com/android/server/notification/NotificationManagerService.java
@@ -133,6 +133,7 @@ import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationRankingUpdate;
import android.service.notification.NotificationRecordProto;
import android.service.notification.NotificationServiceDumpProto;
+import android.service.notification.NotificationServiceProto;
import android.service.notification.NotificationStats;
import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification;
@@ -281,7 +282,6 @@ public class NotificationManagerService extends SystemService {
private WindowManagerInternal mWindowManagerInternal;
private AlarmManager mAlarmManager;
private ICompanionDeviceManager mCompanionManager;
- private AccessibilityManager mAccessibilityManager;
final IBinder mForegroundToken = new Binder();
private WorkerHandler mHandler;
@@ -1221,12 +1221,6 @@ public class NotificationManagerService extends SystemService {
mUsageStats = us;
}
- @VisibleForTesting
- void setAccessibilityManager(AccessibilityManager am) {
- mAccessibilityManager = am;
- }
-
-
// TODO: All tests should use this init instead of the one-off setters above.
@VisibleForTesting
void init(Looper looper, IPackageManager packageManager,
@@ -1241,8 +1235,6 @@ public class NotificationManagerService extends SystemService {
Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE,
DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE);
- mAccessibilityManager =
- (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
mAm = ActivityManager.getService();
mPackageManager = packageManager;
mPackageManagerClient = packageManagerClient;
@@ -3262,7 +3254,7 @@ public class NotificationManagerService extends SystemService {
final NotificationRecord nr = mNotificationList.get(i);
if (filter.filtered && !filter.matches(nr.sbn)) continue;
nr.dump(proto, filter.redact);
- proto.write(NotificationRecordProto.STATE, NotificationRecordProto.POSTED);
+ proto.write(NotificationRecordProto.STATE, NotificationServiceProto.POSTED);
}
}
N = mEnqueuedNotifications.size();
@@ -3271,7 +3263,7 @@ public class NotificationManagerService extends SystemService {
final NotificationRecord nr = mEnqueuedNotifications.get(i);
if (filter.filtered && !filter.matches(nr.sbn)) continue;
nr.dump(proto, filter.redact);
- proto.write(NotificationRecordProto.STATE, NotificationRecordProto.ENQUEUED);
+ proto.write(NotificationRecordProto.STATE, NotificationServiceProto.ENQUEUED);
}
}
List<NotificationRecord> snoozed = mSnoozeHelper.getSnoozed();
@@ -3281,7 +3273,7 @@ public class NotificationManagerService extends SystemService {
final NotificationRecord nr = snoozed.get(i);
if (filter.filtered && !filter.matches(nr.sbn)) continue;
nr.dump(proto, filter.redact);
- proto.write(NotificationRecordProto.STATE, NotificationRecordProto.SNOOZED);
+ proto.write(NotificationRecordProto.STATE, NotificationServiceProto.SNOOZED);
}
}
proto.end(records);
@@ -4125,16 +4117,13 @@ public class NotificationManagerService extends SystemService {
// These are set inside the conditional if the notification is allowed to make noise.
boolean hasValidVibrate = false;
boolean hasValidSound = false;
- boolean sentAccessibilityEvent = false;
- // If the notification will appear in the status bar, it should send an accessibility
- // event
- if (!record.isUpdate && record.getImportance() > IMPORTANCE_MIN) {
- sendAccessibilityEvent(notification, record.sbn.getPackageName());
- sentAccessibilityEvent = true;
- }
if (aboveThreshold && isNotificationForCurrentUser(record)) {
-
+ // If the notification will appear in the status bar, it should send an accessibility
+ // event
+ if (!record.isUpdate && record.getImportance() > IMPORTANCE_MIN) {
+ sendAccessibilityEvent(notification, record.sbn.getPackageName());
+ }
if (mSystemReady && mAudioManager != null) {
Uri soundUri = record.getSound();
hasValidSound = soundUri != null && !Uri.EMPTY.equals(soundUri);
@@ -4152,10 +4141,6 @@ public class NotificationManagerService extends SystemService {
boolean hasAudibleAlert = hasValidSound || hasValidVibrate;
if (hasAudibleAlert && !shouldMuteNotificationLocked(record)) {
- if (!sentAccessibilityEvent) {
- sendAccessibilityEvent(notification, record.sbn.getPackageName());
- sentAccessibilityEvent = true;
- }
if (DBG) Slog.v(TAG, "Interrupting!");
if (hasValidSound) {
mSoundNotificationKey = key;
@@ -4676,7 +4661,8 @@ public class NotificationManagerService extends SystemService {
}
void sendAccessibilityEvent(Notification notification, CharSequence packageName) {
- if (!mAccessibilityManager.isEnabled()) {
+ AccessibilityManager manager = AccessibilityManager.getInstance(getContext());
+ if (!manager.isEnabled()) {
return;
}
@@ -4690,7 +4676,7 @@ public class NotificationManagerService extends SystemService {
event.getText().add(tickerText);
}
- mAccessibilityManager.sendAccessibilityEvent(event);
+ manager.sendAccessibilityEvent(event);
}
/**
diff --git a/com/android/server/notification/ZenModeFiltering.java b/com/android/server/notification/ZenModeFiltering.java
index abf29006..a7a2743d 100644
--- a/com/android/server/notification/ZenModeFiltering.java
+++ b/com/android/server/notification/ZenModeFiltering.java
@@ -117,19 +117,15 @@ public class ZenModeFiltering {
ZenLog.traceIntercepted(record, "alarmsOnly");
return true;
case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
+ if (isAlarm(record)) {
+ // Alarms are always priority
+ return false;
+ }
// allow user-prioritized packages through in priority mode
if (record.getPackagePriority() == Notification.PRIORITY_MAX) {
ZenLog.traceNotIntercepted(record, "priorityApp");
return false;
}
-
- if (isAlarm(record)) {
- if (!config.allowAlarms) {
- ZenLog.traceIntercepted(record, "!allowAlarms");
- return true;
- }
- return false;
- }
if (isCall(record)) {
if (config.allowRepeatCallers
&& REPEAT_CALLERS.isRepeat(mContext, extras(record))) {
@@ -163,15 +159,6 @@ public class ZenModeFiltering {
}
return false;
}
- AudioAttributes aa = record.getAudioAttributes();
- if (aa != null && AudioAttributes.SUPPRESSIBLE_USAGES.get(aa.getUsage()) ==
- AudioAttributes.SUPPRESSIBLE_MEDIA_SYSTEM_OTHER) {
- if (!config.allowMediaSystemOther) {
- ZenLog.traceIntercepted(record, "!allowMediaSystemOther");
- return true;
- }
- return false;
- }
ZenLog.traceIntercepted(record, "!priority");
return true;
default:
diff --git a/com/android/server/notification/ZenModeHelper.java b/com/android/server/notification/ZenModeHelper.java
index 710684f4..9fcc67df 100644
--- a/com/android/server/notification/ZenModeHelper.java
+++ b/com/android/server/notification/ZenModeHelper.java
@@ -59,7 +59,6 @@ import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import com.android.internal.R;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.server.LocalServices;
@@ -88,7 +87,7 @@ public class ZenModeHelper {
private final Context mContext;
private final H mHandler;
private final SettingsObserver mSettingsObserver;
- @VisibleForTesting protected final AppOpsManager mAppOps;
+ private final AppOpsManager mAppOps;
protected ZenModeConfig mDefaultConfig;
private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
private final ZenModeFiltering mFiltering;
@@ -103,9 +102,9 @@ public class ZenModeHelper {
private final String SCHEDULED_DEFAULT_RULE_1 = "SCHEDULED_DEFAULT_RULE_1";
private final String SCHEDULED_DEFAULT_RULE_2 = "SCHEDULED_DEFAULT_RULE_2";
- @VisibleForTesting protected int mZenMode;
+ private int mZenMode;
private int mUser = UserHandle.USER_SYSTEM;
- @VisibleForTesting protected ZenModeConfig mConfig;
+ protected ZenModeConfig mConfig;
private AudioManagerInternal mAudioManager;
protected PackageManager mPm;
private long mSuppressedEffects;
@@ -596,9 +595,8 @@ public class ZenModeHelper {
pw.println(config);
return;
}
- pw.printf("allow(alarms=%b,media=%bcalls=%b,callsFrom=%s,repeatCallers=%b,messages=%b,messagesFrom=%s,"
+ pw.printf("allow(calls=%b,callsFrom=%s,repeatCallers=%b,messages=%b,messagesFrom=%s,"
+ "events=%b,reminders=%b,whenScreenOff=%b,whenScreenOn=%b)\n",
- config.allowAlarms, config.allowMediaSystemOther,
config.allowCalls, ZenModeConfig.sourceToString(config.allowCallsFrom),
config.allowRepeatCallers, config.allowMessages,
ZenModeConfig.sourceToString(config.allowMessagesFrom),
@@ -815,8 +813,7 @@ public class ZenModeHelper {
}
}
- @VisibleForTesting
- protected void applyRestrictions() {
+ private void applyRestrictions() {
final boolean zen = mZenMode != Global.ZEN_MODE_OFF;
// notification restrictions
@@ -825,10 +822,6 @@ public class ZenModeHelper {
// call restrictions
final boolean muteCalls = zen && !mConfig.allowCalls && !mConfig.allowRepeatCallers
|| (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0;
- // alarm restrictions
- final boolean muteAlarms = zen && !mConfig.allowAlarms;
- // alarm restrictions
- final boolean muteMediaAndSystemSounds = zen && !mConfig.allowMediaSystemOther;
// total silence restrictions
final boolean muteEverything = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
@@ -840,18 +833,13 @@ public class ZenModeHelper {
applyRestrictions(muteNotifications || muteEverything, usage);
} else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL) {
applyRestrictions(muteCalls || muteEverything, usage);
- } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_ALARM) {
- applyRestrictions(muteAlarms || muteEverything, usage);
- } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_MEDIA_SYSTEM_OTHER) {
- applyRestrictions(muteMediaAndSystemSounds || muteEverything, usage);
} else {
applyRestrictions(muteEverything, usage);
}
}
}
- @VisibleForTesting
- protected void applyRestrictions(boolean mute, int usage) {
+ private void applyRestrictions(boolean mute, int usage) {
final String[] exceptionPackages = null; // none (for now)
mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, usage,
mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
diff --git a/com/android/server/pm/LauncherAppsService.java b/com/android/server/pm/LauncherAppsService.java
index b06b5838..4a5ce120 100644
--- a/com/android/server/pm/LauncherAppsService.java
+++ b/com/android/server/pm/LauncherAppsService.java
@@ -30,10 +30,12 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ILauncherApps;
import android.content.pm.IOnAppsChangedListener;
+import android.content.pm.IPackageManager;
import android.content.pm.LauncherApps.ShortcutQuery;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.pm.ShortcutInfo;
@@ -62,6 +64,7 @@ import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -86,14 +89,10 @@ public class LauncherAppsService extends SystemService {
static class BroadcastCookie {
public final UserHandle user;
public final String packageName;
- public final int callingUid;
- public final int callingPid;
- BroadcastCookie(UserHandle userHandle, String packageName, int callingPid, int callingUid) {
+ BroadcastCookie(UserHandle userHandle, String packageName) {
this.user = userHandle;
this.packageName = packageName;
- this.callingUid = callingUid;
- this.callingPid = callingPid;
}
}
@@ -128,11 +127,6 @@ public class LauncherAppsService extends SystemService {
return getCallingUid();
}
- @VisibleForTesting
- int injectBinderCallingPid() {
- return getCallingPid();
- }
-
final int injectCallingUserId() {
return UserHandle.getUserId(injectBinderCallingUid());
}
@@ -172,7 +166,7 @@ public class LauncherAppsService extends SystemService {
}
mListeners.unregister(listener);
mListeners.register(listener, new BroadcastCookie(UserHandle.of(getCallingUserId()),
- callingPackage, injectBinderCallingPid(), injectBinderCallingUid()));
+ callingPackage));
}
}
@@ -444,7 +438,7 @@ public class LauncherAppsService extends SystemService {
private void ensureShortcutPermission(@NonNull String callingPackage) {
verifyCallingPackage(callingPackage);
if (!mShortcutServiceInternal.hasShortcutHostPermission(getCallingUserId(),
- callingPackage, injectBinderCallingPid(), injectBinderCallingUid())) {
+ callingPackage)) {
throw new SecurityException("Caller can't access shortcut information");
}
}
@@ -467,8 +461,7 @@ public class LauncherAppsService extends SystemService {
return new ParceledListSlice<>((List<ShortcutInfo>)
mShortcutServiceInternal.getShortcuts(getCallingUserId(),
callingPackage, changedSince, packageName, shortcutIds,
- componentName, flags, targetUser.getIdentifier(),
- injectBinderCallingPid(), injectBinderCallingUid()));
+ componentName, flags, targetUser.getIdentifier()));
}
@Override
@@ -521,7 +514,7 @@ public class LauncherAppsService extends SystemService {
public boolean hasShortcutHostPermission(String callingPackage) {
verifyCallingPackage(callingPackage);
return mShortcutServiceInternal.hasShortcutHostPermission(getCallingUserId(),
- callingPackage, injectBinderCallingPid(), injectBinderCallingUid());
+ callingPackage);
}
@Override
@@ -543,8 +536,7 @@ public class LauncherAppsService extends SystemService {
}
final Intent[] intents = mShortcutServiceInternal.createShortcutIntents(
- getCallingUserId(), callingPackage, packageName, shortcutId, targetUserId,
- injectBinderCallingPid(), injectBinderCallingUid());
+ getCallingUserId(), callingPackage, packageName, shortcutId, targetUserId);
if (intents == null || intents.length == 0) {
return false;
}
@@ -909,8 +901,7 @@ public class LauncherAppsService extends SystemService {
// Make sure the caller has the permission.
if (!mShortcutServiceInternal.hasShortcutHostPermission(
- launcherUserId, cookie.packageName,
- cookie.callingPid, cookie.callingUid)) {
+ launcherUserId, cookie.packageName)) {
continue;
}
// Each launcher has a different set of pinned shortcuts, so we need to do a
@@ -923,8 +914,8 @@ public class LauncherAppsService extends SystemService {
/* changedSince= */ 0, packageName, /* shortcutIds=*/ null,
/* component= */ null,
ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY
- | ShortcutQuery.FLAG_MATCH_ALL_KINDS_WITH_ALL_PINNED
- , userId, cookie.callingPid, cookie.callingUid);
+ | ShortcutQuery.FLAG_GET_ALL_KINDS
+ , userId);
try {
listener.onShortcutChanged(user, packageName,
new ParceledListSlice<>(list));
diff --git a/com/android/server/pm/PackageDexOptimizer.java b/com/android/server/pm/PackageDexOptimizer.java
index cf0ffbb1..8ebeeae2 100644
--- a/com/android/server/pm/PackageDexOptimizer.java
+++ b/com/android/server/pm/PackageDexOptimizer.java
@@ -236,10 +236,9 @@ public class PackageDexOptimizer {
*/
@GuardedBy("mInstallLock")
private int dexOptPath(PackageParser.Package pkg, String path, String isa,
- String compilerFilter, boolean profileUpdated, String classLoaderContext,
+ String compilerFilter, boolean profileUpdated, String sharedLibrariesPath,
int dexoptFlags, int uid, CompilerStats.PackageStats packageStats, boolean downgrade) {
- int dexoptNeeded = getDexoptNeeded(path, isa, compilerFilter, classLoaderContext,
- profileUpdated, downgrade);
+ int dexoptNeeded = getDexoptNeeded(path, isa, compilerFilter, profileUpdated, downgrade);
if (Math.abs(dexoptNeeded) == DexFile.NO_DEXOPT_NEEDED) {
return DEX_OPT_SKIPPED;
}
@@ -252,8 +251,8 @@ public class PackageDexOptimizer {
Log.i(TAG, "Running dexopt (dexoptNeeded=" + dexoptNeeded + ") on: " + path
+ " pkg=" + pkg.applicationInfo.packageName + " isa=" + isa
+ " dexoptFlags=" + printDexoptFlags(dexoptFlags)
- + " targetFilter=" + compilerFilter + " oatDir=" + oatDir
- + " classLoaderContext=" + classLoaderContext);
+ + " target-filter=" + compilerFilter + " oatDir=" + oatDir
+ + " sharedLibraries=" + sharedLibrariesPath);
try {
long startTime = System.currentTimeMillis();
@@ -262,7 +261,7 @@ public class PackageDexOptimizer {
// installd only uses downgrade flag for secondary dex files and ignores it for
// primary dex files.
mInstaller.dexopt(path, uid, pkg.packageName, isa, dexoptNeeded, oatDir, dexoptFlags,
- compilerFilter, pkg.volumeUuid, classLoaderContext, pkg.applicationInfo.seInfo,
+ compilerFilter, pkg.volumeUuid, sharedLibrariesPath, pkg.applicationInfo.seInfo,
false /* downgrade*/);
if (packageStats != null) {
@@ -509,11 +508,11 @@ public class PackageDexOptimizer {
* configuration (isa, compiler filter, profile).
*/
private int getDexoptNeeded(String path, String isa, String compilerFilter,
- String classLoaderContext, boolean newProfile, boolean downgrade) {
+ boolean newProfile, boolean downgrade) {
int dexoptNeeded;
try {
- dexoptNeeded = DexFile.getDexOptNeeded(path, isa, compilerFilter, classLoaderContext,
- newProfile, downgrade);
+ dexoptNeeded = DexFile.getDexOptNeeded(path, isa, compilerFilter, newProfile,
+ downgrade);
} catch (IOException ioe) {
Slog.w(TAG, "IOException reading apk: " + path, ioe);
return DEX_OPT_FAILED;
diff --git a/com/android/server/pm/PackageInstallerSession.java b/com/android/server/pm/PackageInstallerSession.java
index 496ebc23..d62f0934 100644
--- a/com/android/server/pm/PackageInstallerSession.java
+++ b/com/android/server/pm/PackageInstallerSession.java
@@ -1127,8 +1127,15 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mResolvedInstructionSets.add(archSubDir.getName());
List<File> oatFiles = Arrays.asList(archSubDir.listFiles());
- if (!oatFiles.isEmpty()) {
- mResolvedInheritedFiles.addAll(oatFiles);
+
+ // Only add compiled files associated with the base.
+ // Once b/62269291 is resolved, we can add all compiled files again.
+ for (File oatFile : oatFiles) {
+ if (oatFile.getName().equals("base.art")
+ || oatFile.getName().equals("base.odex")
+ || oatFile.getName().equals("base.vdex")) {
+ mResolvedInheritedFiles.add(oatFile);
+ }
}
}
}
diff --git a/com/android/server/pm/PackageManagerService.java b/com/android/server/pm/PackageManagerService.java
index 275db1fa..7d1a6470 100644
--- a/com/android/server/pm/PackageManagerService.java
+++ b/com/android/server/pm/PackageManagerService.java
@@ -398,7 +398,7 @@ public class PackageManagerService extends IPackageManager.Stub
static final boolean DEBUG_DOMAIN_VERIFICATION = false;
private static final boolean DEBUG_BACKUP = false;
private static final boolean DEBUG_INSTALL = false;
- public static final boolean DEBUG_REMOVE = false;
+ private static final boolean DEBUG_REMOVE = false;
private static final boolean DEBUG_BROADCASTS = false;
private static final boolean DEBUG_SHOW_INFO = false;
private static final boolean DEBUG_PACKAGE_INFO = false;
@@ -406,7 +406,7 @@ public class PackageManagerService extends IPackageManager.Stub
public static final boolean DEBUG_PACKAGE_SCANNING = false;
private static final boolean DEBUG_VERIFY = false;
private static final boolean DEBUG_FILTERS = false;
- public static final boolean DEBUG_PERMISSIONS = false;
+ private static final boolean DEBUG_PERMISSIONS = false;
private static final boolean DEBUG_SHARED_LIBRARIES = false;
private static final boolean DEBUG_COMPRESSION = Build.IS_DEBUGGABLE;
@@ -954,6 +954,9 @@ public class PackageManagerService extends IPackageManager.Stub
final SparseArray<PackageVerificationState> mPendingVerification
= new SparseArray<PackageVerificationState>();
+ /** Set of packages associated with each app op permission. */
+ final ArrayMap<String, ArraySet<String>> mAppOpPermissionPackages = new ArrayMap<>();
+
final PackageInstallerService mInstallerService;
private final PackageDexOptimizer mPackageDexOptimizer;
@@ -2878,7 +2881,7 @@ public class PackageManagerService extends IPackageManager.Stub
+ mSdkVersion + "; regranting permissions for internal storage");
updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL;
}
- updatePermissionsLocked(null, null, StorageManager.UUID_PRIVATE_INTERNAL, updateFlags);
+ updatePermissionsLPw(null, null, StorageManager.UUID_PRIVATE_INTERNAL, updateFlags);
ver.sdkVersion = mSdkVersion;
// If this is the first boot or an update from pre-M, and it is a normal
@@ -3261,6 +3264,23 @@ public class PackageManagerService extends IPackageManager.Stub
return null;
}
+ // If we have a profile for a compressed APK, copy it to the reference location.
+ // Since the package is the stub one, remove the stub suffix to get the normal package and
+ // APK name.
+ File profileFile = new File(getPrebuildProfilePath(pkg).replace(STUB_SUFFIX, ""));
+ if (profileFile.exists()) {
+ try {
+ // We could also do this lazily before calling dexopt in
+ // PackageDexOptimizer to prevent this happening on first boot. The issue
+ // is that we don't have a good way to say "do this only once".
+ if (!mInstaller.copySystemProfile(profileFile.getAbsolutePath(),
+ pkg.applicationInfo.uid, pkg.packageName)) {
+ Log.e(TAG, "decompressPackage failed to copy system profile!");
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath() + " ", e);
+ }
+ }
return dstCodePath;
}
@@ -3348,9 +3368,7 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public boolean isUpgrade() {
// allow instant applications
- // The system property allows testing ota flow when upgraded to the same image.
- return mIsUpgrade || SystemProperties.getBoolean(
- "persist.pm.mock-upgrade", false /* default */);
+ return mIsUpgrade;
}
private @Nullable String getRequiredButNotReallyRequiredVerifierLPr() {
@@ -5164,7 +5182,7 @@ public class PackageManagerService extends IPackageManager.Stub
final PermissionsState permissionsState = settingBase.getPermissionsState();
if (permissionsState.hasPermission(permName, userId)) {
if (isUidInstantApp) {
- if (mSettings.mPermissions.isPermissionInstant(permName)) {
+ if (mPermissionManager.isPermissionInstant(permName)) {
return PackageManager.PERMISSION_GRANTED;
}
} else {
@@ -5233,8 +5251,8 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
- private boolean addDynamicPermission(PermissionInfo info, final boolean async) {
- return mPermissionManager.addDynamicPermission(
+ boolean addPermission(PermissionInfo info, final boolean async) {
+ return mPermissionManager.addPermission(
info, async, getCallingUid(), new PermissionCallback() {
@Override
public void onPermissionChanged() {
@@ -5250,20 +5268,20 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public boolean addPermission(PermissionInfo info) {
synchronized (mPackages) {
- return addDynamicPermission(info, false);
+ return addPermission(info, false);
}
}
@Override
public boolean addPermissionAsync(PermissionInfo info) {
synchronized (mPackages) {
- return addDynamicPermission(info, true);
+ return addPermission(info, true);
}
}
@Override
public void removePermission(String permName) {
- mPermissionManager.removeDynamicPermission(permName, getCallingUid(), mPermissionCallback);
+ mPermissionManager.removePermission(permName, getCallingUid(), mPermissionCallback);
}
@Override
@@ -5924,8 +5942,17 @@ public class PackageManagerService extends IPackageManager.Stub
}
@Override
- public String[] getAppOpPermissionPackages(String permName) {
- return mPermissionManager.getAppOpPermissionPackages(permName);
+ public String[] getAppOpPermissionPackages(String permissionName) {
+ if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+ return null;
+ }
+ synchronized (mPackages) {
+ ArraySet<String> pkgs = mAppOpPermissionPackages.get(permissionName);
+ if (pkgs == null) {
+ return null;
+ }
+ return pkgs.toArray(new String[pkgs.size()]);
+ }
}
@Override
@@ -9097,30 +9124,10 @@ public class PackageManagerService extends IPackageManager.Stub
// package and APK names.
String systemProfilePath =
getPrebuildProfilePath(disabledPs.pkg).replace(STUB_SUFFIX, "");
- profileFile = new File(systemProfilePath);
- // If we have a profile for a compressed APK, copy it to the reference
- // location.
- // Note that copying the profile here will cause it to override the
- // reference profile every OTA even though the existing reference profile
- // may have more data. We can't copy during decompression since the
- // directories are not set up at that point.
- if (profileFile.exists()) {
- try {
- // We could also do this lazily before calling dexopt in
- // PackageDexOptimizer to prevent this happening on first boot. The
- // issue is that we don't have a good way to say "do this only
- // once".
- if (!mInstaller.copySystemProfile(profileFile.getAbsolutePath(),
- pkg.applicationInfo.uid, pkg.packageName)) {
- Log.e(TAG, "Failed to copy system profile for stub package!");
- } else {
- useProfileForDexopt = true;
- }
- } catch (Exception e) {
- Log.e(TAG, "Failed to copy profile " +
- profileFile.getAbsolutePath() + " ", e);
- }
- }
+ File systemProfile = new File(systemProfilePath);
+ // Use the profile for compilation if there exists one for the same package
+ // in the system partition.
+ useProfileForDexopt = systemProfile.exists();
}
}
}
@@ -10339,7 +10346,7 @@ public class PackageManagerService extends IPackageManager.Stub
Slog.i(TAG, "Adopting permissions from " + origName + " to "
+ pkg.packageName);
// SIDE EFFECTS; updates permissions system state; move elsewhere
- mSettings.mPermissions.transferPermissions(origName, pkg.packageName);
+ mSettings.transferPermissionsLPw(origName, pkg.packageName);
}
}
}
@@ -11187,13 +11194,54 @@ public class PackageManagerService extends IPackageManager.Stub
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permission Groups: " + r);
}
+ N = pkg.permissions.size();
+ r = null;
+ for (i=0; i<N; i++) {
+ PackageParser.Permission p = pkg.permissions.get(i);
- // Dont allow ephemeral apps to define new permissions.
- if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
- Slog.w(TAG, "Permissions from package " + pkg.packageName
- + " ignored: instant apps cannot define new permissions.");
- } else {
- mPermissionManager.addAllPermissions(pkg, chatty);
+ // Dont allow ephemeral apps to define new permissions.
+ if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
+ Slog.w(TAG, "Permission " + p.info.name + " from package "
+ + p.info.packageName
+ + " ignored: instant apps cannot define new permissions.");
+ continue;
+ }
+
+ // Assume by default that we did not install this permission into the system.
+ p.info.flags &= ~PermissionInfo.FLAG_INSTALLED;
+
+ // Now that permission groups have a special meaning, we ignore permission
+ // groups for legacy apps to prevent unexpected behavior. In particular,
+ // permissions for one app being granted to someone just because they happen
+ // to be in a group defined by another app (before this had no implications).
+ if (pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
+ p.group = mPermissionGroups.get(p.info.group);
+ // Warn for a permission in an unknown group.
+ if (DEBUG_PERMISSIONS && p.info.group != null && p.group == null) {
+ Slog.i(TAG, "Permission " + p.info.name + " from package "
+ + p.info.packageName + " in an unknown group " + p.info.group);
+ }
+ }
+
+ // TODO Move to PermissionManager once mPermissionTrees moves there.
+// p.tree ? mSettings.mPermissionTrees
+// : mSettings.mPermissions;
+// final BasePermission bp = BasePermission.createOrUpdate(
+// permissionMap.get(p.info.name), p, pkg, mSettings.mPermissionTrees, chatty);
+// permissionMap.put(p.info.name, bp);
+ if (p.tree) {
+ final ArrayMap<String, BasePermission> permissionMap =
+ mSettings.mPermissionTrees;
+ final BasePermission bp = BasePermission.createOrUpdate(
+ permissionMap.get(p.info.name), p, pkg, mSettings.mPermissionTrees,
+ chatty);
+ permissionMap.put(p.info.name, bp);
+ } else {
+ final BasePermission bp = BasePermission.createOrUpdate(
+ (BasePermission) mPermissionManager.getPermissionTEMP(p.info.name),
+ p, pkg, mSettings.mPermissionTrees, chatty);
+ mPermissionManager.putPermissionTEMP(p.info.name, bp);
+ }
}
N = pkg.instrumentation.size();
@@ -11919,7 +11967,53 @@ public class PackageManagerService extends IPackageManager.Stub
if (DEBUG_REMOVE) Log.d(TAG, " Activities: " + r);
}
- mPermissionManager.removeAllPermissions(pkg, chatty);
+ N = pkg.permissions.size();
+ r = null;
+ for (i=0; i<N; i++) {
+ PackageParser.Permission p = pkg.permissions.get(i);
+ BasePermission bp = (BasePermission) mPermissionManager.getPermissionTEMP(p.info.name);
+ if (bp == null) {
+ bp = mSettings.mPermissionTrees.get(p.info.name);
+ }
+ if (bp != null && bp.isPermission(p)) {
+ bp.setPermission(null);
+ if (DEBUG_REMOVE && chatty) {
+ if (r == null) {
+ r = new StringBuilder(256);
+ } else {
+ r.append(' ');
+ }
+ r.append(p.info.name);
+ }
+ }
+ if ((p.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) != 0) {
+ ArraySet<String> appOpPkgs = mAppOpPermissionPackages.get(p.info.name);
+ if (appOpPkgs != null) {
+ appOpPkgs.remove(pkg.packageName);
+ }
+ }
+ }
+ if (r != null) {
+ if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
+ }
+
+ N = pkg.requestedPermissions.size();
+ r = null;
+ for (i=0; i<N; i++) {
+ String perm = pkg.requestedPermissions.get(i);
+ if (mPermissionManager.isPermissionAppOp(perm)) {
+ ArraySet<String> appOpPkgs = mAppOpPermissionPackages.get(perm);
+ if (appOpPkgs != null) {
+ appOpPkgs.remove(pkg.packageName);
+ if (appOpPkgs.isEmpty()) {
+ mAppOpPermissionPackages.remove(perm);
+ }
+ }
+ }
+ }
+ if (r != null) {
+ if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
+ }
N = pkg.instrumentation.size();
r = null;
@@ -11980,9 +12074,18 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
- public static final int UPDATE_PERMISSIONS_ALL = 1<<0;
- public static final int UPDATE_PERMISSIONS_REPLACE_PKG = 1<<1;
- public static final int UPDATE_PERMISSIONS_REPLACE_ALL = 1<<2;
+ private static boolean hasPermission(PackageParser.Package pkgInfo, String perm) {
+ for (int i=pkgInfo.permissions.size()-1; i>=0; i--) {
+ if (pkgInfo.permissions.get(i).info.name.equals(perm)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static final int UPDATE_PERMISSIONS_ALL = 1<<0;
+ static final int UPDATE_PERMISSIONS_REPLACE_PKG = 1<<1;
+ static final int UPDATE_PERMISSIONS_REPLACE_ALL = 1<<2;
private void updatePermissionsLPw(PackageParser.Package pkg, int flags) {
// Update the parent permissions
@@ -11998,10 +12101,10 @@ public class PackageManagerService extends IPackageManager.Stub
private void updatePermissionsLPw(String changingPkg, PackageParser.Package pkgInfo,
int flags) {
final String volumeUuid = (pkgInfo != null) ? getVolumeUuidForPackage(pkgInfo) : null;
- updatePermissionsLocked(changingPkg, pkgInfo, volumeUuid, flags);
+ updatePermissionsLPw(changingPkg, pkgInfo, volumeUuid, flags);
}
- private void updatePermissionsLocked(String changingPkg,
+ private void updatePermissionsLPw(String changingPkg,
PackageParser.Package pkgInfo, String replaceVolumeUuid, int flags) {
// TODO: Most of the methods exposing BasePermission internals [source package name,
// etc..] shouldn't be needed. Instead, when we've parsed a permission that doesn't
@@ -12013,11 +12116,55 @@ public class PackageManagerService extends IPackageManager.Stub
// normal permissions. Today, we need two separate loops because these BasePermission
// objects are stored separately.
// Make sure there are no dangling permission trees.
- flags = mPermissionManager.updatePermissionTrees(changingPkg, pkgInfo, flags);
+ Iterator<BasePermission> it = mSettings.mPermissionTrees.values().iterator();
+ while (it.hasNext()) {
+ final BasePermission bp = it.next();
+ if (bp.getSourcePackageSetting() == null) {
+ // We may not yet have parsed the package, so just see if
+ // we still know about its settings.
+ bp.setSourcePackageSetting(mSettings.mPackages.get(bp.getSourcePackageName()));
+ }
+ if (bp.getSourcePackageSetting() == null) {
+ Slog.w(TAG, "Removing dangling permission tree: " + bp.getName()
+ + " from package " + bp.getSourcePackageName());
+ it.remove();
+ } else if (changingPkg != null && changingPkg.equals(bp.getSourcePackageName())) {
+ if (pkgInfo == null || !hasPermission(pkgInfo, bp.getName())) {
+ Slog.i(TAG, "Removing old permission tree: " + bp.getName()
+ + " from package " + bp.getSourcePackageName());
+ flags |= UPDATE_PERMISSIONS_ALL;
+ it.remove();
+ }
+ }
+ }
// Make sure all dynamic permissions have been assigned to a package,
// and make sure there are no dangling permissions.
- flags = mPermissionManager.updatePermissions(changingPkg, pkgInfo, flags);
+ final Iterator<BasePermission> permissionIter =
+ mPermissionManager.getPermissionIteratorTEMP();
+ while (permissionIter.hasNext()) {
+ final BasePermission bp = permissionIter.next();
+ if (bp.isDynamic()) {
+ bp.updateDynamicPermission(mSettings.mPermissionTrees);
+ }
+ if (bp.getSourcePackageSetting() == null) {
+ // We may not yet have parsed the package, so just see if
+ // we still know about its settings.
+ bp.setSourcePackageSetting(mSettings.mPackages.get(bp.getSourcePackageName()));
+ }
+ if (bp.getSourcePackageSetting() == null) {
+ Slog.w(TAG, "Removing dangling permission: " + bp.getName()
+ + " from package " + bp.getSourcePackageName());
+ permissionIter.remove();
+ } else if (changingPkg != null && changingPkg.equals(bp.getSourcePackageName())) {
+ if (pkgInfo == null || !hasPermission(pkgInfo, bp.getName())) {
+ Slog.i(TAG, "Removing old permission: " + bp.getName()
+ + " from package " + bp.getSourcePackageName());
+ flags |= UPDATE_PERMISSIONS_ALL;
+ permissionIter.remove();
+ }
+ }
+ }
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "grantPermissions");
// Now update the permissions for all packages, in particular
@@ -12139,7 +12286,12 @@ public class PackageManagerService extends IPackageManager.Stub
// Keep track of app op permissions.
if (bp.isAppOp()) {
- mSettings.addAppOpPackage(perm, pkg.packageName);
+ ArraySet<String> pkgs = mAppOpPermissionPackages.get(perm);
+ if (pkgs == null) {
+ pkgs = new ArraySet<>();
+ mAppOpPermissionPackages.put(perm, pkgs);
+ }
+ pkgs.add(pkg.packageName);
}
if (bp.isNormal()) {
@@ -21086,7 +21238,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
// permissions, ensure permissions are updated. Beware of dragons if you
// try optimizing this.
synchronized (mPackages) {
- updatePermissionsLocked(null, null, StorageManager.UUID_PRIVATE_INTERNAL,
+ updatePermissionsLPw(null, null, StorageManager.UUID_PRIVATE_INTERNAL,
UPDATE_PERMISSIONS_ALL);
}
@@ -21137,8 +21289,9 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
reconcileApps(StorageManager.UUID_PRIVATE_INTERNAL);
if (mPrivappPermissionsViolations != null) {
- throw new IllegalStateException("Signature|privileged permissions not in "
+ Slog.wtf(TAG,"Signature|privileged permissions not in "
+ "privapp-permissions whitelist: " + mPrivappPermissionsViolations);
+ mPrivappPermissionsViolations = null;
}
}
@@ -21631,6 +21784,22 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
if (!checkin && dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) {
mSettings.dumpPermissionsLPr(pw, packageName, permissionNames, dumpState);
+ if (packageName == null && permissionNames == null) {
+ for (int iperm=0; iperm<mAppOpPermissionPackages.size(); iperm++) {
+ if (iperm == 0) {
+ if (dumpState.onTitlePrinted())
+ pw.println();
+ pw.println("AppOp Permissions:");
+ }
+ pw.print(" AppOp Permission ");
+ pw.print(mAppOpPermissionPackages.keyAt(iperm));
+ pw.println(":");
+ ArraySet<String> pkgs = mAppOpPermissionPackages.valueAt(iperm);
+ for (int ipkg=0; ipkg<pkgs.size(); ipkg++) {
+ pw.print(" "); pw.println(pkgs.valueAt(ipkg));
+ }
+ }
+ }
}
if (!checkin && dumpState.isDumping(DumpState.DUMP_PROVIDERS)) {
@@ -21860,7 +22029,11 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
synchronized (mAvailableFeatures) {
final int count = mAvailableFeatures.size();
for (int i = 0; i < count; i++) {
- mAvailableFeatures.valueAt(i).writeToProto(proto, PackageServiceDumpProto.FEATURES);
+ final FeatureInfo feat = mAvailableFeatures.valueAt(i);
+ final long featureToken = proto.start(PackageServiceDumpProto.FEATURES);
+ proto.write(PackageServiceDumpProto.FeatureProto.NAME, feat.name);
+ proto.write(PackageServiceDumpProto.FeatureProto.VERSION, feat.version);
+ proto.end(featureToken);
}
}
}
@@ -21892,7 +22065,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
}
private void dumpDexoptStateLPr(PrintWriter pw, String packageName) {
- final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+ final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120);
ipw.println();
ipw.println("Dexopt state:");
ipw.increaseIndent();
@@ -21919,7 +22092,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
}
private void dumpCompilerStatsLPr(PrintWriter pw, String packageName) {
- final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+ final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120);
ipw.println();
ipw.println("Compiler stats:");
ipw.increaseIndent();
@@ -22130,7 +22303,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
+ mSdkVersion + "; regranting permissions for " + volumeUuid);
updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL;
}
- updatePermissionsLocked(null, null, volumeUuid, updateFlags);
+ updatePermissionsLPw(null, null, volumeUuid, updateFlags);
// Yay, everything is now upgraded
ver.forceCurrent();
@@ -23138,15 +23311,15 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
void onNewUserCreated(final int userId) {
synchronized(mPackages) {
mDefaultPermissionPolicy.grantDefaultPermissions(mPackages.values(), userId);
- // If permission review for legacy apps is required, we represent
- // dagerous permissions for such apps as always granted runtime
- // permissions to keep per user flag state whether review is needed.
- // Hence, if a new user is added we have to propagate dangerous
- // permission grants for these legacy apps.
- if (mPermissionReviewRequired) {
- updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
- | UPDATE_PERMISSIONS_REPLACE_ALL);
- }
+ }
+ // If permission review for legacy apps is required, we represent
+ // dagerous permissions for such apps as always granted runtime
+ // permissions to keep per user flag state whether review is needed.
+ // Hence, if a new user is added we have to propagate dangerous
+ // permission grants for these legacy apps.
+ if (mPermissionReviewRequired) {
+ updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
+ | UPDATE_PERMISSIONS_REPLACE_ALL);
}
}
@@ -23590,12 +23763,12 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
}
@Override
- public PackageParser.PermissionGroup getPermissionGroupTEMP(String groupName) {
+ public Object enforcePermissionTreeTEMP(String permName, int callingUid) {
synchronized (mPackages) {
- return mPermissionGroups.get(groupName);
+ return BasePermission.enforcePermissionTreeLP(
+ mSettings.mPermissionTrees, permName, callingUid);
}
}
-
@Override
public boolean isInstantApp(String packageName, int userId) {
return PackageManagerService.this.isInstantApp(packageName, userId);
diff --git a/com/android/server/pm/Settings.java b/com/android/server/pm/Settings.java
index 191b43a6..00844114 100644
--- a/com/android/server/pm/Settings.java
+++ b/com/android/server/pm/Settings.java
@@ -378,6 +378,10 @@ public final class Settings {
private final ArrayMap<Long, Integer> mKeySetRefs =
new ArrayMap<Long, Integer>();
+ // Mapping from permission tree names to info about them.
+ final ArrayMap<String, BasePermission> mPermissionTrees =
+ new ArrayMap<String, BasePermission>();
+
// Packages that have been uninstalled and still need their external
// storage data deleted.
final ArrayList<PackageCleanItem> mPackagesToBeCleaned = new ArrayList<PackageCleanItem>();
@@ -412,7 +416,7 @@ public final class Settings {
public final KeySetManagerService mKeySetManagerService = new KeySetManagerService(mPackages);
/** Settings and other information about permissions */
- final PermissionSettings mPermissions;
+ private final PermissionSettings mPermissions;
Settings(PermissionSettings permissions, Object lock) {
this(Environment.getDataDirectory(), permissions, lock);
@@ -618,10 +622,6 @@ public final class Settings {
return null;
}
- void addAppOpPackage(String permName, String packageName) {
- mPermissions.addAppOpPackage(permName, packageName);
- }
-
SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) {
SharedUserSetting s = mSharedUsers.get(name);
if (s != null) {
@@ -666,6 +666,13 @@ public final class Settings {
}
/**
+ * Transfers ownership of permissions from one package to another.
+ */
+ void transferPermissionsLPw(String origPackageName, String newPackageName) {
+ mPermissions.transferPermissions(origPackageName, newPackageName, mPermissionTrees);
+ }
+
+ /**
* Creates a new {@code PackageSetting} object.
* Use this method instead of the constructor to ensure a settings object is created
* with the correct base.
@@ -2489,7 +2496,9 @@ public final class Settings {
}
serializer.startTag(null, "permission-trees");
- mPermissions.writePermissionTrees(serializer);
+ for (BasePermission bp : mPermissionTrees.values()) {
+ writePermissionLPr(serializer, bp);
+ }
serializer.endTag(null, "permission-trees");
serializer.startTag(null, "permissions");
@@ -3033,7 +3042,7 @@ public final class Settings {
} else if (tagName.equals("permissions")) {
mPermissions.readPermissions(parser);
} else if (tagName.equals("permission-trees")) {
- mPermissions.readPermissionTrees(parser);
+ PermissionSettings.readPermissions(mPermissionTrees, parser);
} else if (tagName.equals("shared-user")) {
readSharedUserLPw(parser);
} else if (tagName.equals("preferred-packages")) {
@@ -4929,7 +4938,11 @@ public final class Settings {
void dumpSharedUsersProto(ProtoOutputStream proto) {
final int count = mSharedUsers.size();
for (int i = 0; i < count; i++) {
- mSharedUsers.valueAt(i).writeToProto(proto, PackageServiceDumpProto.SHARED_USERS);
+ final SharedUserSetting su = mSharedUsers.valueAt(i);
+ final long sharedUserToken = proto.start(PackageServiceDumpProto.SHARED_USERS);
+ proto.write(PackageServiceDumpProto.SharedUserProto.USER_ID, su.userId);
+ proto.write(PackageServiceDumpProto.SharedUserProto.NAME, su.name);
+ proto.end(sharedUserToken);
}
}
diff --git a/com/android/server/pm/SharedUserSetting.java b/com/android/server/pm/SharedUserSetting.java
index 877da144..a0dadae3 100644
--- a/com/android/server/pm/SharedUserSetting.java
+++ b/com/android/server/pm/SharedUserSetting.java
@@ -18,9 +18,7 @@ package com.android.server.pm;
import android.annotation.Nullable;
import android.content.pm.PackageParser;
-import android.service.pm.PackageServiceDumpProto;
import android.util.ArraySet;
-import android.util.proto.ProtoOutputStream;
import java.util.ArrayList;
import java.util.Collection;
@@ -55,13 +53,6 @@ public final class SharedUserSetting extends SettingBase {
+ name + "/" + userId + "}";
}
- public void writeToProto(ProtoOutputStream proto, long fieldId) {
- long token = proto.start(fieldId);
- proto.write(PackageServiceDumpProto.SharedUserProto.USER_ID, userId);
- proto.write(PackageServiceDumpProto.SharedUserProto.NAME, name);
- proto.end(token);
- }
-
void removePackage(PackageSetting packageSetting) {
if (packages.remove(packageSetting)) {
// recalculate the pkgFlags for this shared user if needed
diff --git a/com/android/server/pm/ShortcutBitmapSaver.java b/com/android/server/pm/ShortcutBitmapSaver.java
index 815f8851..4f5d1560 100644
--- a/com/android/server/pm/ShortcutBitmapSaver.java
+++ b/com/android/server/pm/ShortcutBitmapSaver.java
@@ -21,8 +21,6 @@ import android.content.pm.ShortcutInfo;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.drawable.Icon;
-import android.os.StrictMode;
-import android.os.StrictMode.ThreadPolicy;
import android.os.SystemClock;
import android.util.Log;
import android.util.Slog;
@@ -167,13 +165,7 @@ public class ShortcutBitmapSaver {
// Compress it and enqueue to the requests.
final byte[] bytes;
- final StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
try {
- // compress() triggers a slow call, but in this case it's needed to save RAM and also
- // the target bitmap is of an icon size, so let's just permit it.
- StrictMode.setThreadPolicy(new ThreadPolicy.Builder(oldPolicy)
- .permitCustomSlowCalls()
- .build());
final Bitmap shrunk = mService.shrinkBitmap(original, maxDimension);
try {
try (final ByteArrayOutputStream out = new ByteArrayOutputStream(64 * 1024)) {
@@ -192,8 +184,6 @@ public class ShortcutBitmapSaver {
} catch (IOException | RuntimeException | OutOfMemoryError e) {
Slog.wtf(ShortcutService.TAG, "Unable to write bitmap to file", e);
return;
- } finally {
- StrictMode.setThreadPolicy(oldPolicy);
}
shortcut.addFlags(
diff --git a/com/android/server/pm/ShortcutLauncher.java b/com/android/server/pm/ShortcutLauncher.java
index cedf4763..f922ad19 100644
--- a/com/android/server/pm/ShortcutLauncher.java
+++ b/com/android/server/pm/ShortcutLauncher.java
@@ -83,16 +83,11 @@ class ShortcutLauncher extends ShortcutPackageItem {
return mOwnerUserId;
}
- @Override
- protected boolean canRestoreAnyVersion() {
- // Launcher's pinned shortcuts can be restored to an older version.
- return true;
- }
-
/**
* Called when the new package can't receive the backup, due to signature or version mismatch.
*/
- private void onRestoreBlocked() {
+ @Override
+ protected void onRestoreBlocked() {
final ArrayList<PackageWithUser> pinnedPackages =
new ArrayList<>(mPinnedShortcuts.keySet());
mPinnedShortcuts.clear();
@@ -106,21 +101,15 @@ class ShortcutLauncher extends ShortcutPackageItem {
}
@Override
- protected void onRestored(int restoreBlockReason) {
- // For launcher, possible reasons here are DISABLED_REASON_SIGNATURE_MISMATCH or
- // DISABLED_REASON_BACKUP_NOT_SUPPORTED.
- // DISABLED_REASON_VERSION_LOWER will NOT happen because we don't check version
- // code for launchers.
- if (restoreBlockReason != ShortcutInfo.DISABLED_REASON_NOT_DISABLED) {
- onRestoreBlocked();
- }
+ protected void onRestored() {
+ // Nothing to do.
}
/**
* Pin the given shortcuts, replacing the current pinned ones.
*/
public void pinShortcuts(@UserIdInt int packageUserId,
- @NonNull String packageName, @NonNull List<String> ids, boolean forPinRequest) {
+ @NonNull String packageName, @NonNull List<String> ids) {
final ShortcutPackage packageShortcuts =
mShortcutUser.getPackageShortcutsIfExists(packageName);
if (packageShortcuts == null) {
@@ -135,12 +124,8 @@ class ShortcutLauncher extends ShortcutPackageItem {
} else {
final ArraySet<String> prevSet = mPinnedShortcuts.get(pu);
- // Actually pin shortcuts.
- // This logic here is to make sure a launcher cannot pin a shortcut that is floating
- // (i.e. not dynamic nor manifest but is pinned) and pinned by another launcher.
- // In this case, technically the shortcut doesn't exist to this launcher, so it can't
- // pin it.
- // (Maybe unnecessarily strict...)
+ // Pin shortcuts. Make sure only pin the ones that were visible to the caller.
+ // i.e. a non-dynamic, pinned shortcut by *other launchers* shouldn't be pinned here.
final ArraySet<String> newSet = new ArraySet<>();
@@ -150,10 +135,8 @@ class ShortcutLauncher extends ShortcutPackageItem {
if (si == null) {
continue;
}
- if (si.isDynamic()
- || si.isManifestShortcut()
- || (prevSet != null && prevSet.contains(id))
- || forPinRequest) {
+ if (si.isDynamic() || si.isManifestShortcut()
+ || (prevSet != null && prevSet.contains(id))) {
newSet.add(id);
}
}
@@ -172,7 +155,7 @@ class ShortcutLauncher extends ShortcutPackageItem {
}
/**
- * Return true if the given shortcut is pinned by this launcher.<code></code>
+ * Return true if the given shortcut is pinned by this launcher.
*/
public boolean hasPinned(ShortcutInfo shortcut) {
final ArraySet<String> pinned =
@@ -181,10 +164,10 @@ class ShortcutLauncher extends ShortcutPackageItem {
}
/**
- * Additionally pin a shortcut. c.f. {@link #pinShortcuts(int, String, List, boolean)}
+ * Additionally pin a shortcut. c.f. {@link #pinShortcuts(int, String, List)}
*/
public void addPinnedShortcut(@NonNull String packageName, @UserIdInt int packageUserId,
- String id, boolean forPinRequest) {
+ String id) {
final ArraySet<String> pinnedSet = getPinnedShortcutIds(packageName, packageUserId);
final ArrayList<String> pinnedList;
if (pinnedSet != null) {
@@ -195,21 +178,21 @@ class ShortcutLauncher extends ShortcutPackageItem {
}
pinnedList.add(id);
- pinShortcuts(packageUserId, packageName, pinnedList, forPinRequest);
+ pinShortcuts(packageUserId, packageName, pinnedList);
}
boolean cleanUpPackage(String packageName, @UserIdInt int packageUserId) {
return mPinnedShortcuts.remove(PackageWithUser.of(packageUserId, packageName)) != null;
}
- public void ensurePackageInfo() {
+ public void ensureVersionInfo() {
final PackageInfo pi = mShortcutUser.mService.getPackageInfoWithSignatures(
getPackageName(), getPackageUserId());
if (pi == null) {
Slog.w(TAG, "Package not found: " + getPackageName());
return;
}
- getPackageInfo().updateFromPackageInfo(pi);
+ getPackageInfo().updateVersionInfo(pi);
}
/**
@@ -218,10 +201,6 @@ class ShortcutLauncher extends ShortcutPackageItem {
@Override
public void saveToXml(XmlSerializer out, boolean forBackup)
throws IOException {
- if (forBackup && !getPackageInfo().isBackupAllowed()) {
- // If an launcher app doesn't support backup&restore, then nothing to do.
- return;
- }
final int size = mPinnedShortcuts.size();
if (size == 0) {
return; // Nothing to write.
@@ -230,7 +209,7 @@ class ShortcutLauncher extends ShortcutPackageItem {
out.startTag(null, TAG_ROOT);
ShortcutService.writeAttr(out, ATTR_PACKAGE_NAME, getPackageName());
ShortcutService.writeAttr(out, ATTR_LAUNCHER_USER_ID, getPackageUserId());
- getPackageInfo().saveToXml(out, forBackup);
+ getPackageInfo().saveToXml(out);
for (int i = 0; i < size; i++) {
final PackageWithUser pu = mPinnedShortcuts.keyAt(i);
diff --git a/com/android/server/pm/ShortcutPackage.java b/com/android/server/pm/ShortcutPackage.java
index 12f490fa..6fc1e738 100644
--- a/com/android/server/pm/ShortcutPackage.java
+++ b/com/android/server/pm/ShortcutPackage.java
@@ -84,7 +84,6 @@ class ShortcutPackage extends ShortcutPackageItem {
private static final String ATTR_DISABLED_MESSAGE = "dmessage";
private static final String ATTR_DISABLED_MESSAGE_RES_ID = "dmessageid";
private static final String ATTR_DISABLED_MESSAGE_RES_NAME = "dmessagename";
- private static final String ATTR_DISABLED_REASON = "disabled-reason";
private static final String ATTR_INTENT_LEGACY = "intent";
private static final String ATTR_INTENT_NO_EXTRA = "intent-base";
private static final String ATTR_RANK = "rank";
@@ -157,25 +156,13 @@ class ShortcutPackage extends ShortcutPackageItem {
}
@Override
- protected boolean canRestoreAnyVersion() {
- return false;
+ protected void onRestoreBlocked() {
+ // Can't restore due to version/signature mismatch. Remove all shortcuts.
+ mShortcuts.clear();
}
@Override
- protected void onRestored(int restoreBlockReason) {
- // Shortcuts have been restored.
- // - Unshadow all shortcuts.
- // - Set disabled reason.
- // - Disable if needed.
- for (int i = mShortcuts.size() - 1; i >= 0; i--) {
- ShortcutInfo si = mShortcuts.valueAt(i);
- si.clearFlags(ShortcutInfo.FLAG_SHADOW);
-
- si.setDisabledReason(restoreBlockReason);
- if (restoreBlockReason != ShortcutInfo.DISABLED_REASON_NOT_DISABLED) {
- si.addFlags(ShortcutInfo.FLAG_DISABLED);
- }
- }
+ protected void onRestored() {
// Because some launchers may not have been restored (e.g. allowBackup=false),
// we need to re-calculate the pinned shortcuts.
refreshPinnedFlags();
@@ -189,47 +176,31 @@ class ShortcutPackage extends ShortcutPackageItem {
return mShortcuts.get(id);
}
- public boolean isShortcutExistsAndInvisibleToPublisher(String id) {
- ShortcutInfo si = findShortcutById(id);
- return si != null && !si.isVisibleToPublisher();
- }
-
- public boolean isShortcutExistsAndVisibleToPublisher(String id) {
- ShortcutInfo si = findShortcutById(id);
- return si != null && si.isVisibleToPublisher();
- }
-
- private void ensureNotImmutable(@Nullable ShortcutInfo shortcut, boolean ignoreInvisible) {
- if (shortcut != null && shortcut.isImmutable()
- && (!ignoreInvisible || shortcut.isVisibleToPublisher())) {
+ private void ensureNotImmutable(@Nullable ShortcutInfo shortcut) {
+ if (shortcut != null && shortcut.isImmutable()) {
throw new IllegalArgumentException(
"Manifest shortcut ID=" + shortcut.getId()
+ " may not be manipulated via APIs");
}
}
- public void ensureNotImmutable(@NonNull String id, boolean ignoreInvisible) {
- ensureNotImmutable(mShortcuts.get(id), ignoreInvisible);
+ public void ensureNotImmutable(@NonNull String id) {
+ ensureNotImmutable(mShortcuts.get(id));
}
- public void ensureImmutableShortcutsNotIncludedWithIds(@NonNull List<String> shortcutIds,
- boolean ignoreInvisible) {
+ public void ensureImmutableShortcutsNotIncludedWithIds(@NonNull List<String> shortcutIds) {
for (int i = shortcutIds.size() - 1; i >= 0; i--) {
- ensureNotImmutable(shortcutIds.get(i), ignoreInvisible);
+ ensureNotImmutable(shortcutIds.get(i));
}
}
- public void ensureImmutableShortcutsNotIncluded(@NonNull List<ShortcutInfo> shortcuts,
- boolean ignoreInvisible) {
+ public void ensureImmutableShortcutsNotIncluded(@NonNull List<ShortcutInfo> shortcuts) {
for (int i = shortcuts.size() - 1; i >= 0; i--) {
- ensureNotImmutable(shortcuts.get(i).getId(), ignoreInvisible);
+ ensureNotImmutable(shortcuts.get(i).getId());
}
}
- /**
- * Delete a shortcut by ID. This will *always* remove it even if it's immutable or invisible.
- */
- private ShortcutInfo forceDeleteShortcutInner(@NonNull String id) {
+ private ShortcutInfo deleteShortcutInner(@NonNull String id) {
final ShortcutInfo shortcut = mShortcuts.remove(id);
if (shortcut != null) {
mShortcutUser.mService.removeIconLocked(shortcut);
@@ -239,14 +210,10 @@ class ShortcutPackage extends ShortcutPackageItem {
return shortcut;
}
- /**
- * Force replace a shortcut. If there's already a shortcut with the same ID, it'll be removed,
- * even if it's invisible.
- */
- private void forceReplaceShortcutInner(@NonNull ShortcutInfo newShortcut) {
+ private void addShortcutInner(@NonNull ShortcutInfo newShortcut) {
final ShortcutService s = mShortcutUser.mService;
- forceDeleteShortcutInner(newShortcut.getId());
+ deleteShortcutInner(newShortcut.getId());
// Extract Icon and update the icon res ID and the bitmap path.
s.saveIconAndFixUpShortcutLocked(newShortcut);
@@ -255,12 +222,11 @@ class ShortcutPackage extends ShortcutPackageItem {
}
/**
- * Add a shortcut. If there's already a one with the same ID, it'll be removed, even if it's
- * invisible.
+ * Add a shortcut, or update one with the same ID, with taking over existing flags.
*
* It checks the max number of dynamic shortcuts.
*/
- public void addOrReplaceDynamicShortcut(@NonNull ShortcutInfo newShortcut) {
+ public void addOrUpdateDynamicShortcut(@NonNull ShortcutInfo newShortcut) {
Preconditions.checkArgument(newShortcut.isEnabled(),
"add/setDynamicShortcuts() cannot publish disabled shortcuts");
@@ -276,7 +242,7 @@ class ShortcutPackage extends ShortcutPackageItem {
} else {
// It's an update case.
// Make sure the target is updatable. (i.e. should be mutable.)
- oldShortcut.ensureUpdatableWith(newShortcut, /*isUpdating=*/ false);
+ oldShortcut.ensureUpdatableWith(newShortcut);
wasPinned = oldShortcut.isPinned();
}
@@ -286,7 +252,7 @@ class ShortcutPackage extends ShortcutPackageItem {
newShortcut.addFlags(ShortcutInfo.FLAG_PINNED);
}
- forceReplaceShortcutInner(newShortcut);
+ addShortcutInner(newShortcut);
}
/**
@@ -307,7 +273,7 @@ class ShortcutPackage extends ShortcutPackageItem {
}
if (removeList != null) {
for (int i = removeList.size() - 1; i >= 0; i--) {
- forceDeleteShortcutInner(removeList.get(i));
+ deleteShortcutInner(removeList.get(i));
}
}
}
@@ -315,13 +281,13 @@ class ShortcutPackage extends ShortcutPackageItem {
/**
* Remove all dynamic shortcuts.
*/
- public void deleteAllDynamicShortcuts(boolean ignoreInvisible) {
+ public void deleteAllDynamicShortcuts() {
final long now = mShortcutUser.mService.injectCurrentTimeMillis();
boolean changed = false;
for (int i = mShortcuts.size() - 1; i >= 0; i--) {
final ShortcutInfo si = mShortcuts.valueAt(i);
- if (si.isDynamic() && (!ignoreInvisible || si.isVisibleToPublisher())) {
+ if (si.isDynamic()) {
changed = true;
si.setTimestamp(now);
@@ -341,10 +307,9 @@ class ShortcutPackage extends ShortcutPackageItem {
* @return true if it's actually removed because it wasn't pinned, or false if it's still
* pinned.
*/
- public boolean deleteDynamicWithId(@NonNull String shortcutId, boolean ignoreInvisible) {
+ public boolean deleteDynamicWithId(@NonNull String shortcutId) {
final ShortcutInfo removed = deleteOrDisableWithId(
- shortcutId, /* disable =*/ false, /* overrideImmutable=*/ false, ignoreInvisible,
- ShortcutInfo.DISABLED_REASON_NOT_DISABLED);
+ shortcutId, /* disable =*/ false, /* overrideImmutable=*/ false);
return removed == null;
}
@@ -355,11 +320,9 @@ class ShortcutPackage extends ShortcutPackageItem {
* @return true if it's actually removed because it wasn't pinned, or false if it's still
* pinned.
*/
- private boolean disableDynamicWithId(@NonNull String shortcutId, boolean ignoreInvisible,
- int disabledReason) {
+ private boolean disableDynamicWithId(@NonNull String shortcutId) {
final ShortcutInfo disabled = deleteOrDisableWithId(
- shortcutId, /* disable =*/ true, /* overrideImmutable=*/ false, ignoreInvisible,
- disabledReason);
+ shortcutId, /* disable =*/ true, /* overrideImmutable=*/ false);
return disabled == null;
}
@@ -368,10 +331,9 @@ class ShortcutPackage extends ShortcutPackageItem {
* is pinned, it'll remain as a pinned shortcut but will be disabled.
*/
public void disableWithId(@NonNull String shortcutId, String disabledMessage,
- int disabledMessageResId, boolean overrideImmutable, boolean ignoreInvisible,
- int disabledReason) {
+ int disabledMessageResId, boolean overrideImmutable) {
final ShortcutInfo disabled = deleteOrDisableWithId(shortcutId, /* disable =*/ true,
- overrideImmutable, ignoreInvisible, disabledReason);
+ overrideImmutable);
if (disabled != null) {
if (disabledMessage != null) {
@@ -386,18 +348,14 @@ class ShortcutPackage extends ShortcutPackageItem {
@Nullable
private ShortcutInfo deleteOrDisableWithId(@NonNull String shortcutId, boolean disable,
- boolean overrideImmutable, boolean ignoreInvisible, int disabledReason) {
- Preconditions.checkState(
- (disable == (disabledReason != ShortcutInfo.DISABLED_REASON_NOT_DISABLED)),
- "disable and disabledReason disagree: " + disable + " vs " + disabledReason);
+ boolean overrideImmutable) {
final ShortcutInfo oldShortcut = mShortcuts.get(shortcutId);
- if (oldShortcut == null || !oldShortcut.isEnabled()
- && (ignoreInvisible && !oldShortcut.isVisibleToPublisher())) {
+ if (oldShortcut == null || !oldShortcut.isEnabled()) {
return null; // Doesn't exist or already disabled.
}
if (!overrideImmutable) {
- ensureNotImmutable(oldShortcut, /*ignoreInvisible=*/ true);
+ ensureNotImmutable(oldShortcut);
}
if (oldShortcut.isPinned()) {
@@ -405,10 +363,6 @@ class ShortcutPackage extends ShortcutPackageItem {
oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST);
if (disable) {
oldShortcut.addFlags(ShortcutInfo.FLAG_DISABLED);
- // Do not overwrite the disabled reason if one is alreay set.
- if (oldShortcut.getDisabledReason() == ShortcutInfo.DISABLED_REASON_NOT_DISABLED) {
- oldShortcut.setDisabledReason(disabledReason);
- }
}
oldShortcut.setTimestamp(mShortcutUser.mService.injectCurrentTimeMillis());
@@ -419,7 +373,7 @@ class ShortcutPackage extends ShortcutPackageItem {
return oldShortcut;
} else {
- forceDeleteShortcutInner(shortcutId);
+ deleteShortcutInner(shortcutId);
return null;
}
}
@@ -427,25 +381,11 @@ class ShortcutPackage extends ShortcutPackageItem {
public void enableWithId(@NonNull String shortcutId) {
final ShortcutInfo shortcut = mShortcuts.get(shortcutId);
if (shortcut != null) {
- ensureNotImmutable(shortcut, /*ignoreInvisible=*/ true);
+ ensureNotImmutable(shortcut);
shortcut.clearFlags(ShortcutInfo.FLAG_DISABLED);
- shortcut.setDisabledReason(ShortcutInfo.DISABLED_REASON_NOT_DISABLED);
}
}
- public void updateInvisibleShortcutForPinRequestWith(@NonNull ShortcutInfo shortcut) {
- final ShortcutInfo source = mShortcuts.get(shortcut.getId());
- Preconditions.checkNotNull(source);
-
- mShortcutUser.mService.validateShortcutForPinRequest(shortcut);
-
- shortcut.addFlags(ShortcutInfo.FLAG_PINNED);
-
- forceReplaceShortcutInner(shortcut);
-
- adjustRanks();
- }
-
/**
* Called after a launcher updates the pinned set. For each shortcut in this package,
* set FLAG_PINNED if any launcher has pinned it. Otherwise, clear it.
@@ -570,7 +510,7 @@ class ShortcutPackage extends ShortcutPackageItem {
*/
public void findAll(@NonNull List<ShortcutInfo> result,
@Nullable Predicate<ShortcutInfo> query, int cloneFlag) {
- findAll(result, query, cloneFlag, null, 0, /*getPinnedByAnyLauncher=*/ false);
+ findAll(result, query, cloneFlag, null, 0);
}
/**
@@ -582,7 +522,7 @@ class ShortcutPackage extends ShortcutPackageItem {
*/
public void findAll(@NonNull List<ShortcutInfo> result,
@Nullable Predicate<ShortcutInfo> query, int cloneFlag,
- @Nullable String callingLauncher, int launcherUserId, boolean getPinnedByAnyLauncher) {
+ @Nullable String callingLauncher, int launcherUserId) {
if (getPackageInfo().isShadow()) {
// Restored and the app not installed yet, so don't return any.
return;
@@ -604,11 +544,9 @@ class ShortcutPackage extends ShortcutPackageItem {
final boolean isPinnedByCaller = (callingLauncher == null)
|| ((pinnedByCallerSet != null) && pinnedByCallerSet.contains(si.getId()));
- if (!getPinnedByAnyLauncher) {
- if (si.isFloating()) {
- if (!isPinnedByCaller) {
- continue;
- }
+ if (si.isFloating()) {
+ if (!isPinnedByCaller) {
+ continue;
}
}
final ShortcutInfo clone = si.clone(cloneFlag);
@@ -755,27 +693,7 @@ class ShortcutPackage extends ShortcutPackageItem {
getPackageInfo().getVersionCode(), pi.versionCode));
}
- getPackageInfo().updateFromPackageInfo(pi);
- final int newVersionCode = getPackageInfo().getVersionCode();
-
- // See if there are any shortcuts that were prevented restoring because the app was of a
- // lower version, and re-enable them.
- for (int i = mShortcuts.size() - 1; i >= 0; i--) {
- final ShortcutInfo si = mShortcuts.valueAt(i);
- if (si.getDisabledReason() != ShortcutInfo.DISABLED_REASON_VERSION_LOWER) {
- continue;
- }
- if (getPackageInfo().getBackupSourceVersionCode() > newVersionCode) {
- if (ShortcutService.DEBUG) {
- Slog.d(TAG, String.format("Shortcut %s require version %s, still not restored.",
- si.getId(), getPackageInfo().getBackupSourceVersionCode()));
- }
- continue;
- }
- Slog.i(TAG, String.format("Restoring shortcut: %s", si.getId()));
- si.clearFlags(ShortcutInfo.FLAG_DISABLED);
- si.setDisabledReason(ShortcutInfo.DISABLED_REASON_NOT_DISABLED);
- }
+ getPackageInfo().updateVersionInfo(pi);
// For existing shortcuts, update timestamps if they have any resources.
// Also check if shortcuts' activities are still main activities. Otherwise, disable them.
@@ -795,8 +713,7 @@ class ShortcutPackage extends ShortcutPackageItem {
Slog.w(TAG, String.format(
"%s is no longer main activity. Disabling shorcut %s.",
getPackageName(), si.getId()));
- if (disableDynamicWithId(si.getId(), /*ignoreInvisible*/ false,
- ShortcutInfo.DISABLED_REASON_APP_CHANGED)) {
+ if (disableDynamicWithId(si.getId())) {
continue; // Actually removed.
}
// Still pinned, so fall-through and possibly update the resources.
@@ -892,7 +809,7 @@ class ShortcutPackage extends ShortcutPackageItem {
// Note even if enabled=false, we still need to update all fields, so do it
// regardless.
- forceReplaceShortcutInner(newShortcut); // This will clean up the old one too.
+ addShortcutInner(newShortcut); // This will clean up the old one too.
if (!newDisabled && toDisableList != null) {
// Still alive, don't remove.
@@ -914,8 +831,7 @@ class ShortcutPackage extends ShortcutPackageItem {
final String id = toDisableList.valueAt(i);
disableWithId(id, /* disable message =*/ null, /* disable message resid */ 0,
- /* overrideImmutable=*/ true, /*ignoreInvisible=*/ false,
- ShortcutInfo.DISABLED_REASON_APP_CHANGED);
+ /* overrideImmutable=*/ true);
}
removeOrphans();
}
@@ -953,7 +869,7 @@ class ShortcutPackage extends ShortcutPackageItem {
service.wtf("Found manifest shortcuts in excess list.");
continue;
}
- deleteDynamicWithId(shortcut.getId(), /*ignoreInvisible=*/ true);
+ deleteDynamicWithId(shortcut.getId());
}
}
@@ -1159,7 +1075,7 @@ class ShortcutPackage extends ShortcutPackageItem {
if (ret != 0) {
return ret;
}
- // If they're still tie, just sort by their IDs.
+ // If they're stil tie, just sort by their IDs.
// This may happen with updateShortcuts() -- see
// the testUpdateShortcuts_noManifestShortcuts() test.
return a.getId().compareTo(b.getId());
@@ -1341,34 +1257,25 @@ class ShortcutPackage extends ShortcutPackageItem {
ShortcutService.writeAttr(out, ATTR_NAME, getPackageName());
ShortcutService.writeAttr(out, ATTR_CALL_COUNT, mApiCallCount);
ShortcutService.writeAttr(out, ATTR_LAST_RESET, mLastResetTime);
- getPackageInfo().saveToXml(out, forBackup);
+ getPackageInfo().saveToXml(out);
for (int j = 0; j < size; j++) {
- saveShortcut(out, mShortcuts.valueAt(j), forBackup,
- getPackageInfo().isBackupAllowed());
+ saveShortcut(out, mShortcuts.valueAt(j), forBackup);
}
out.endTag(null, TAG_ROOT);
}
- private void saveShortcut(XmlSerializer out, ShortcutInfo si, boolean forBackup,
- boolean appSupportsBackup)
+ private void saveShortcut(XmlSerializer out, ShortcutInfo si, boolean forBackup)
throws IOException, XmlPullParserException {
final ShortcutService s = mShortcutUser.mService;
if (forBackup) {
if (!(si.isPinned() && si.isEnabled())) {
- // We only backup pinned shortcuts that are enabled.
- // Note, this means, shortcuts that are restored but are blocked restore, e.g. due
- // to a lower version code, will not be ported to a new device.
- return;
+ return; // We only backup pinned shortcuts that are enabled.
}
}
- final boolean shouldBackupDetails =
- !forBackup // It's not backup
- || appSupportsBackup; // Or, it's a backup and app supports backup.
-
// Note: at this point no shortcuts should have bitmaps pending save, but if they do,
// just remove the bitmap.
if (si.isIconPendingSave()) {
@@ -1385,31 +1292,20 @@ class ShortcutPackage extends ShortcutPackageItem {
ShortcutService.writeAttr(out, ATTR_TEXT, si.getText());
ShortcutService.writeAttr(out, ATTR_TEXT_RES_ID, si.getTextResId());
ShortcutService.writeAttr(out, ATTR_TEXT_RES_NAME, si.getTextResName());
- if (shouldBackupDetails) {
- ShortcutService.writeAttr(out, ATTR_DISABLED_MESSAGE, si.getDisabledMessage());
- ShortcutService.writeAttr(out, ATTR_DISABLED_MESSAGE_RES_ID,
- si.getDisabledMessageResourceId());
- ShortcutService.writeAttr(out, ATTR_DISABLED_MESSAGE_RES_NAME,
- si.getDisabledMessageResName());
- }
- ShortcutService.writeAttr(out, ATTR_DISABLED_REASON, si.getDisabledReason());
+ ShortcutService.writeAttr(out, ATTR_DISABLED_MESSAGE, si.getDisabledMessage());
+ ShortcutService.writeAttr(out, ATTR_DISABLED_MESSAGE_RES_ID,
+ si.getDisabledMessageResourceId());
+ ShortcutService.writeAttr(out, ATTR_DISABLED_MESSAGE_RES_NAME,
+ si.getDisabledMessageResName());
ShortcutService.writeAttr(out, ATTR_TIMESTAMP,
si.getLastChangedTimestamp());
if (forBackup) {
// Don't write icon information. Also drop the dynamic flag.
-
- int flags = si.getFlags() &
- ~(ShortcutInfo.FLAG_HAS_ICON_FILE | ShortcutInfo.FLAG_HAS_ICON_RES
+ ShortcutService.writeAttr(out, ATTR_FLAGS,
+ si.getFlags() &
+ ~(ShortcutInfo.FLAG_HAS_ICON_FILE | ShortcutInfo.FLAG_HAS_ICON_RES
| ShortcutInfo.FLAG_ICON_FILE_PENDING_SAVE
- | ShortcutInfo.FLAG_DYNAMIC);
- ShortcutService.writeAttr(out, ATTR_FLAGS, flags);
-
- // Set the publisher version code at every backup.
- final int packageVersionCode = getPackageInfo().getVersionCode();
- if (packageVersionCode == 0) {
- s.wtf("Package version code should be available at this point.");
- // However, 0 is a valid version code, so we just go ahead with it...
- }
+ | ShortcutInfo.FLAG_DYNAMIC));
} else {
// When writing for backup, ranks shouldn't be saved, since shortcuts won't be restored
// as dynamic.
@@ -1421,28 +1317,26 @@ class ShortcutPackage extends ShortcutPackageItem {
ShortcutService.writeAttr(out, ATTR_BITMAP_PATH, si.getBitmapPath());
}
- if (shouldBackupDetails) {
- {
- final Set<String> cat = si.getCategories();
- if (cat != null && cat.size() > 0) {
- out.startTag(null, TAG_CATEGORIES);
- XmlUtils.writeStringArrayXml(cat.toArray(new String[cat.size()]),
- NAME_CATEGORIES, out);
- out.endTag(null, TAG_CATEGORIES);
- }
- }
- final Intent[] intentsNoExtras = si.getIntentsNoExtras();
- final PersistableBundle[] intentsExtras = si.getIntentPersistableExtrases();
- final int numIntents = intentsNoExtras.length;
- for (int i = 0; i < numIntents; i++) {
- out.startTag(null, TAG_INTENT);
- ShortcutService.writeAttr(out, ATTR_INTENT_NO_EXTRA, intentsNoExtras[i]);
- ShortcutService.writeTagExtra(out, TAG_EXTRAS, intentsExtras[i]);
- out.endTag(null, TAG_INTENT);
+ {
+ final Set<String> cat = si.getCategories();
+ if (cat != null && cat.size() > 0) {
+ out.startTag(null, TAG_CATEGORIES);
+ XmlUtils.writeStringArrayXml(cat.toArray(new String[cat.size()]),
+ NAME_CATEGORIES, out);
+ out.endTag(null, TAG_CATEGORIES);
}
-
- ShortcutService.writeTagExtra(out, TAG_EXTRAS, si.getExtras());
}
+ final Intent[] intentsNoExtras = si.getIntentsNoExtras();
+ final PersistableBundle[] intentsExtras = si.getIntentPersistableExtrases();
+ final int numIntents = intentsNoExtras.length;
+ for (int i = 0; i < numIntents; i++) {
+ out.startTag(null, TAG_INTENT);
+ ShortcutService.writeAttr(out, ATTR_INTENT_NO_EXTRA, intentsNoExtras[i]);
+ ShortcutService.writeTagExtra(out, TAG_EXTRAS, intentsExtras[i]);
+ out.endTag(null, TAG_INTENT);
+ }
+
+ ShortcutService.writeTagExtra(out, TAG_EXTRAS, si.getExtras());
out.endTag(null, TAG_SHORTCUT);
}
@@ -1462,7 +1356,6 @@ class ShortcutPackage extends ShortcutPackageItem {
ret.mLastResetTime =
ShortcutService.parseLongAttribute(parser, ATTR_LAST_RESET);
-
final int outerDepth = parser.getDepth();
int type;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -1476,11 +1369,10 @@ class ShortcutPackage extends ShortcutPackageItem {
switch (tag) {
case ShortcutPackageInfo.TAG_ROOT:
ret.getPackageInfo().loadFromXml(parser, fromBackup);
-
continue;
case TAG_SHORTCUT:
final ShortcutInfo si = parseShortcut(parser, packageName,
- shortcutUser.getUserId(), fromBackup);
+ shortcutUser.getUserId());
// Don't use addShortcut(), we don't need to save the icon.
ret.mShortcuts.put(si.getId(), si);
@@ -1493,8 +1385,7 @@ class ShortcutPackage extends ShortcutPackageItem {
}
private static ShortcutInfo parseShortcut(XmlPullParser parser, String packageName,
- @UserIdInt int userId, boolean fromBackup)
- throws IOException, XmlPullParserException {
+ @UserIdInt int userId) throws IOException, XmlPullParserException {
String id;
ComponentName activityComponent;
// Icon icon;
@@ -1507,7 +1398,6 @@ class ShortcutPackage extends ShortcutPackageItem {
String disabledMessage;
int disabledMessageResId;
String disabledMessageResName;
- int disabledReason;
Intent intentLegacy;
PersistableBundle intentPersistableExtrasLegacy = null;
ArrayList<Intent> intents = new ArrayList<>();
@@ -1518,7 +1408,6 @@ class ShortcutPackage extends ShortcutPackageItem {
int iconResId;
String iconResName;
String bitmapPath;
- int backupVersionCode;
ArraySet<String> categories = null;
id = ShortcutService.parseStringAttribute(parser, ATTR_ID);
@@ -1535,7 +1424,6 @@ class ShortcutPackage extends ShortcutPackageItem {
ATTR_DISABLED_MESSAGE_RES_ID);
disabledMessageResName = ShortcutService.parseStringAttribute(parser,
ATTR_DISABLED_MESSAGE_RES_NAME);
- disabledReason = ShortcutService.parseIntAttribute(parser, ATTR_DISABLED_REASON);
intentLegacy = ShortcutService.parseIntentAttributeNoDefault(parser, ATTR_INTENT_LEGACY);
rank = (int) ShortcutService.parseLongAttribute(parser, ATTR_RANK);
lastChangedTimestamp = ShortcutService.parseLongAttribute(parser, ATTR_TIMESTAMP);
@@ -1592,19 +1480,6 @@ class ShortcutPackage extends ShortcutPackageItem {
intents.add(intentLegacy);
}
-
- if ((disabledReason == ShortcutInfo.DISABLED_REASON_NOT_DISABLED)
- && ((flags & ShortcutInfo.FLAG_DISABLED) != 0)) {
- // We didn't used to have the disabled reason, so if a shortcut is disabled
- // and has no reason, we assume it was disabled by publisher.
- disabledReason = ShortcutInfo.DISABLED_REASON_BY_APP;
- }
-
- // All restored shortcuts are initially "shadow".
- if (fromBackup) {
- flags |= ShortcutInfo.FLAG_SHADOW;
- }
-
return new ShortcutInfo(
userId, id, packageName, activityComponent, /* icon =*/ null,
title, titleResId, titleResName, text, textResId, textResName,
@@ -1612,7 +1487,7 @@ class ShortcutPackage extends ShortcutPackageItem {
categories,
intents.toArray(new Intent[intents.size()]),
rank, extras, lastChangedTimestamp, flags,
- iconResId, iconResName, bitmapPath, disabledReason);
+ iconResId, iconResName, bitmapPath);
}
private static Intent parseIntent(XmlPullParser parser)
@@ -1727,20 +1602,6 @@ class ShortcutPackage extends ShortcutPackageItem {
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+ " has both resource and bitmap icons");
}
- if (si.isEnabled()
- != (si.getDisabledReason() == ShortcutInfo.DISABLED_REASON_NOT_DISABLED)) {
- failed = true;
- Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
- + " isEnabled() and getDisabledReason() disagree: "
- + si.isEnabled() + " vs " + si.getDisabledReason());
- }
- if ((si.getDisabledReason() == ShortcutInfo.DISABLED_REASON_VERSION_LOWER)
- && (getPackageInfo().getBackupSourceVersionCode()
- == ShortcutInfo.VERSION_CODE_UNKNOWN)) {
- failed = true;
- Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
- + " RESTORED_VERSION_LOWER with no backup source version code.");
- }
if (s.isDummyMainActivity(si.getActivity())) {
failed = true;
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
diff --git a/com/android/server/pm/ShortcutPackageInfo.java b/com/android/server/pm/ShortcutPackageInfo.java
index 3a9bbc89..e5a2f5ac 100644
--- a/com/android/server/pm/ShortcutPackageInfo.java
+++ b/com/android/server/pm/ShortcutPackageInfo.java
@@ -18,7 +18,6 @@ package com.android.server.pm;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.content.pm.PackageInfo;
-import android.content.pm.ShortcutInfo;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
@@ -46,45 +45,32 @@ class ShortcutPackageInfo {
static final String TAG_ROOT = "package-info";
private static final String ATTR_VERSION = "version";
private static final String ATTR_LAST_UPDATE_TIME = "last_udpate_time";
- private static final String ATTR_BACKUP_SOURCE_VERSION = "bk_src_version";
- private static final String ATTR_BACKUP_ALLOWED = "allow-backup";
- private static final String ATTR_BACKUP_SOURCE_BACKUP_ALLOWED = "bk_src_backup-allowed";
private static final String ATTR_SHADOW = "shadow";
private static final String TAG_SIGNATURE = "signature";
private static final String ATTR_SIGNATURE_HASH = "hash";
+ private static final int VERSION_UNKNOWN = -1;
+
/**
* When true, this package information was restored from the previous device, and the app hasn't
* been installed yet.
*/
private boolean mIsShadow;
- private int mVersionCode = ShortcutInfo.VERSION_CODE_UNKNOWN;
- private int mBackupSourceVersionCode = ShortcutInfo.VERSION_CODE_UNKNOWN;
+ private int mVersionCode = VERSION_UNKNOWN;
private long mLastUpdateTime;
private ArrayList<byte[]> mSigHashes;
- // mBackupAllowed didn't used to be parsisted, so we don't restore it from a file.
- // mBackupAllowed will always start with false, and will have been updated before making a
- // backup next time, which works file.
- // We just don't want to print an uninitialzied mBackupAlldowed value on dumpsys, so
- // we use this boolean to control dumpsys.
- private boolean mBackupAllowedInitialized;
- private boolean mBackupAllowed;
- private boolean mBackupSourceBackupAllowed;
-
private ShortcutPackageInfo(int versionCode, long lastUpdateTime,
ArrayList<byte[]> sigHashes, boolean isShadow) {
mVersionCode = versionCode;
mLastUpdateTime = lastUpdateTime;
mIsShadow = isShadow;
mSigHashes = sigHashes;
- mBackupAllowed = false; // By default, we assume false.
- mBackupSourceBackupAllowed = false;
}
public static ShortcutPackageInfo newEmpty() {
- return new ShortcutPackageInfo(ShortcutInfo.VERSION_CODE_UNKNOWN, /* last update time =*/ 0,
+ return new ShortcutPackageInfo(VERSION_UNKNOWN, /* last update time =*/ 0,
new ArrayList<>(0), /* isShadow */ false);
}
@@ -100,33 +86,15 @@ class ShortcutPackageInfo {
return mVersionCode;
}
- public int getBackupSourceVersionCode() {
- return mBackupSourceVersionCode;
- }
-
- @VisibleForTesting
- public boolean isBackupSourceBackupAllowed() {
- return mBackupSourceBackupAllowed;
- }
-
public long getLastUpdateTime() {
return mLastUpdateTime;
}
- public boolean isBackupAllowed() {
- return mBackupAllowed;
- }
-
- /**
- * Set {@link #mVersionCode}, {@link #mLastUpdateTime} and {@link #mBackupAllowed}
- * from a {@link PackageInfo}.
- */
- public void updateFromPackageInfo(@NonNull PackageInfo pi) {
+ /** Set {@link #mVersionCode} and {@link #mLastUpdateTime} from a {@link PackageInfo}. */
+ public void updateVersionInfo(@NonNull PackageInfo pi) {
if (pi != null) {
mVersionCode = pi.versionCode;
mLastUpdateTime = pi.lastUpdateTime;
- mBackupAllowed = ShortcutService.shouldBackupApp(pi);
- mBackupAllowedInitialized = true;
}
}
@@ -134,24 +102,23 @@ class ShortcutPackageInfo {
return mSigHashes.size() > 0;
}
- //@DisabledReason
- public int canRestoreTo(ShortcutService s, PackageInfo currentPackage, boolean anyVersionOkay) {
- if (!BackupUtils.signaturesMatch(mSigHashes, currentPackage)) {
- Slog.w(TAG, "Can't restore: Package signature mismatch");
- return ShortcutInfo.DISABLED_REASON_SIGNATURE_MISMATCH;
- }
- if (!ShortcutService.shouldBackupApp(currentPackage) || !mBackupSourceBackupAllowed) {
+ public boolean canRestoreTo(ShortcutService s, PackageInfo target) {
+ if (!s.shouldBackupApp(target)) {
// "allowBackup" was true when backed up, but now false.
- Slog.w(TAG, "Can't restore: package didn't or doesn't allow backup");
- return ShortcutInfo.DISABLED_REASON_BACKUP_NOT_SUPPORTED;
+ Slog.w(TAG, "Can't restore: package no longer allows backup");
+ return false;
}
- if (!anyVersionOkay && (currentPackage.versionCode < mBackupSourceVersionCode)) {
+ if (target.versionCode < mVersionCode) {
Slog.w(TAG, String.format(
"Can't restore: package current version %d < backed up version %d",
- currentPackage.versionCode, mBackupSourceVersionCode));
- return ShortcutInfo.DISABLED_REASON_VERSION_LOWER;
+ target.versionCode, mVersionCode));
+ return false;
+ }
+ if (!BackupUtils.signaturesMatch(mSigHashes, target)) {
+ Slog.w(TAG, "Can't restore: Package signature mismatch");
+ return false;
}
- return ShortcutInfo.DISABLED_REASON_NOT_DISABLED;
+ return true;
}
@VisibleForTesting
@@ -165,8 +132,6 @@ class ShortcutPackageInfo {
final ShortcutPackageInfo ret = new ShortcutPackageInfo(pi.versionCode, pi.lastUpdateTime,
BackupUtils.hashSignatureArray(pi.signatures), /* shadow=*/ false);
- ret.mBackupSourceBackupAllowed = s.shouldBackupApp(pi);
- ret.mBackupSourceVersionCode = pi.versionCode;
return ret;
}
@@ -186,19 +151,13 @@ class ShortcutPackageInfo {
mSigHashes = BackupUtils.hashSignatureArray(pi.signatures);
}
- public void saveToXml(XmlSerializer out, boolean forBackup) throws IOException {
+ public void saveToXml(XmlSerializer out) throws IOException {
out.startTag(null, TAG_ROOT);
ShortcutService.writeAttr(out, ATTR_VERSION, mVersionCode);
ShortcutService.writeAttr(out, ATTR_LAST_UPDATE_TIME, mLastUpdateTime);
ShortcutService.writeAttr(out, ATTR_SHADOW, mIsShadow);
- ShortcutService.writeAttr(out, ATTR_BACKUP_ALLOWED, mBackupAllowed);
-
- ShortcutService.writeAttr(out, ATTR_BACKUP_SOURCE_VERSION, mBackupSourceVersionCode);
- ShortcutService.writeAttr(out,
- ATTR_BACKUP_SOURCE_BACKUP_ALLOWED, mBackupSourceBackupAllowed);
-
for (int i = 0; i < mSigHashes.size(); i++) {
out.startTag(null, TAG_SIGNATURE);
@@ -212,9 +171,7 @@ class ShortcutPackageInfo {
public void loadFromXml(XmlPullParser parser, boolean fromBackup)
throws IOException, XmlPullParserException {
- // Don't use the version code from the backup file.
- final int versionCode = ShortcutService.parseIntAttribute(parser, ATTR_VERSION,
- ShortcutInfo.VERSION_CODE_UNKNOWN);
+ final int versionCode = ShortcutService.parseIntAttribute(parser, ATTR_VERSION);
final long lastUpdateTime = ShortcutService.parseLongAttribute(
parser, ATTR_LAST_UPDATE_TIME);
@@ -223,20 +180,6 @@ class ShortcutPackageInfo {
final boolean shadow =
fromBackup || ShortcutService.parseBooleanAttribute(parser, ATTR_SHADOW);
- // We didn't used to save these attributes, and all backed up shortcuts were from
- // apps that support backups, so the default values take this fact into consideration.
- final int backupSourceVersion = ShortcutService.parseIntAttribute(parser,
- ATTR_BACKUP_SOURCE_VERSION, ShortcutInfo.VERSION_CODE_UNKNOWN);
-
- // Note the only time these "true" default value is used is when restoring from an old
- // build that didn't save ATTR_BACKUP_ALLOWED, and that means all the data included in
- // a backup file were from apps that support backup, so we can just use "true" as the
- // default.
- final boolean backupAllowed = ShortcutService.parseBooleanAttribute(
- parser, ATTR_BACKUP_ALLOWED, true);
- final boolean backupSourceBackupAllowed = ShortcutService.parseBooleanAttribute(
- parser, ATTR_BACKUP_SOURCE_BACKUP_ALLOWED, true);
-
final ArrayList<byte[]> hashes = new ArrayList<>();
final int outerDepth = parser.getDepth();
@@ -264,28 +207,11 @@ class ShortcutPackageInfo {
ShortcutService.warnForInvalidTag(depth, tag);
}
- // Successfully loaded; replace the fields.
- if (fromBackup) {
- mVersionCode = ShortcutInfo.VERSION_CODE_UNKNOWN;
- mBackupSourceVersionCode = versionCode;
- mBackupSourceBackupAllowed = backupAllowed;
- } else {
- mVersionCode = versionCode;
- mBackupSourceVersionCode = backupSourceVersion;
- mBackupSourceBackupAllowed = backupSourceBackupAllowed;
- }
+ // Successfully loaded; replace the feilds.
+ mVersionCode = versionCode;
mLastUpdateTime = lastUpdateTime;
mIsShadow = shadow;
mSigHashes = hashes;
-
- // Note we don't restore it from the file because it didn't used to be saved.
- // We always start by assuming backup is disabled for the current package,
- // and this field will have been updated before we actually create a backup, at the same
- // time when we update the version code.
- // Until then, the value of mBackupAllowed shouldn't matter, but we don't want to print
- // a false flag on dumpsys, so set mBackupAllowedInitialized to false.
- mBackupAllowed = false;
- mBackupAllowedInitialized = false;
}
public void dump(PrintWriter pw, String prefix) {
@@ -297,7 +223,6 @@ class ShortcutPackageInfo {
pw.print(prefix);
pw.print(" IsShadow: ");
pw.print(mIsShadow);
- pw.print(mIsShadow ? " (not installed)" : " (installed)");
pw.println();
pw.print(prefix);
@@ -305,25 +230,6 @@ class ShortcutPackageInfo {
pw.print(mVersionCode);
pw.println();
- if (mBackupAllowedInitialized) {
- pw.print(prefix);
- pw.print(" Backup Allowed: ");
- pw.print(mBackupAllowed);
- pw.println();
- }
-
- if (mBackupSourceVersionCode != ShortcutInfo.VERSION_CODE_UNKNOWN) {
- pw.print(prefix);
- pw.print(" Backup source version: ");
- pw.print(mBackupSourceVersionCode);
- pw.println();
-
- pw.print(prefix);
- pw.print(" Backup source backup allowed: ");
- pw.print(mBackupSourceBackupAllowed);
- pw.println();
- }
-
pw.print(prefix);
pw.print(" Last package update time: ");
pw.print(mLastUpdateTime);
diff --git a/com/android/server/pm/ShortcutPackageItem.java b/com/android/server/pm/ShortcutPackageItem.java
index 689099cf..e59d69f4 100644
--- a/com/android/server/pm/ShortcutPackageItem.java
+++ b/com/android/server/pm/ShortcutPackageItem.java
@@ -17,7 +17,6 @@ package com.android.server.pm;
import android.annotation.NonNull;
import android.content.pm.PackageInfo;
-import android.content.pm.ShortcutInfo;
import android.util.Slog;
import com.android.internal.util.Preconditions;
@@ -102,42 +101,51 @@ abstract class ShortcutPackageItem {
final ShortcutService s = mShortcutUser.mService;
if (!s.isPackageInstalled(mPackageName, mPackageUserId)) {
if (ShortcutService.DEBUG) {
- Slog.d(TAG, String.format("Package still not installed: %s/u%d",
+ Slog.d(TAG, String.format("Package still not installed: %s user=%d",
mPackageName, mPackageUserId));
}
return; // Not installed, no need to restore yet.
}
- int restoreBlockReason;
- int currentVersionCode = ShortcutInfo.VERSION_CODE_UNKNOWN;
-
+ boolean blockRestore = false;
if (!mPackageInfo.hasSignatures()) {
- s.wtf("Attempted to restore package " + mPackageName + "/u" + mPackageUserId
+ s.wtf("Attempted to restore package " + mPackageName + ", user=" + mPackageUserId
+ " but signatures not found in the restore data.");
- restoreBlockReason = ShortcutInfo.DISABLED_REASON_SIGNATURE_MISMATCH;
- } else {
+ blockRestore = true;
+ }
+ if (!blockRestore) {
final PackageInfo pi = s.getPackageInfoWithSignatures(mPackageName, mPackageUserId);
- currentVersionCode = pi.versionCode;
- restoreBlockReason = mPackageInfo.canRestoreTo(s, pi, canRestoreAnyVersion());
+ if (!mPackageInfo.canRestoreTo(s, pi)) {
+ // Package is now installed, but can't restore. Let the subclass do the cleanup.
+ blockRestore = true;
+ }
}
+ if (blockRestore) {
+ onRestoreBlocked();
+ } else {
+ if (ShortcutService.DEBUG) {
+ Slog.d(TAG, String.format("Restored package: %s/%d on user %d", mPackageName,
+ mPackageUserId, getOwnerUserId()));
+ }
- if (ShortcutService.DEBUG) {
- Slog.d(TAG, String.format("Restoring package: %s/u%d (version=%d) %s for u%d",
- mPackageName, mPackageUserId, currentVersionCode,
- ShortcutInfo.getDisabledReasonDebugString(restoreBlockReason),
- getOwnerUserId()));
+ onRestored();
}
- onRestored(restoreBlockReason);
-
// Either way, it's no longer a shadow.
mPackageInfo.setShadow(false);
s.scheduleSaveUser(mPackageUserId);
}
- protected abstract boolean canRestoreAnyVersion();
+ /**
+ * Called when the new package can't be restored because it has a lower version number
+ * or different signatures.
+ */
+ protected abstract void onRestoreBlocked();
- protected abstract void onRestored(int restoreBlockReason);
+ /**
+ * Called when the new package is successfully restored.
+ */
+ protected abstract void onRestored();
public abstract void saveToXml(@NonNull XmlSerializer out, boolean forBackup)
throws IOException, XmlPullParserException;
diff --git a/com/android/server/pm/ShortcutParser.java b/com/android/server/pm/ShortcutParser.java
index 866c46c6..3cf4200b 100644
--- a/com/android/server/pm/ShortcutParser.java
+++ b/com/android/server/pm/ShortcutParser.java
@@ -337,9 +337,6 @@ public class ShortcutParser {
(enabled ? ShortcutInfo.FLAG_MANIFEST : ShortcutInfo.FLAG_DISABLED)
| ShortcutInfo.FLAG_IMMUTABLE
| ((iconResId != 0) ? ShortcutInfo.FLAG_HAS_ICON_RES : 0);
- final int disabledReason =
- enabled ? ShortcutInfo.DISABLED_REASON_NOT_DISABLED
- : ShortcutInfo.DISABLED_REASON_BY_APP;
// Note we don't need to set resource names here yet. They'll be set when they're about
// to be published.
@@ -366,7 +363,6 @@ public class ShortcutParser {
flags,
iconResId,
null, // icon res name
- null, // bitmap path
- disabledReason);
+ null); // bitmap path
}
}
diff --git a/com/android/server/pm/ShortcutRequestPinProcessor.java b/com/android/server/pm/ShortcutRequestPinProcessor.java
index 3e44de98..8a8128db 100644
--- a/com/android/server/pm/ShortcutRequestPinProcessor.java
+++ b/com/android/server/pm/ShortcutRequestPinProcessor.java
@@ -300,12 +300,10 @@ class ShortcutRequestPinProcessor {
final ShortcutInfo existing = ps.findShortcutById(inShortcut.getId());
final boolean existsAlready = existing != null;
- final boolean existingIsVisible = existsAlready && existing.isVisibleToPublisher();
if (DEBUG) {
Slog.d(TAG, "requestPinnedShortcut: package=" + inShortcut.getPackage()
+ " existsAlready=" + existsAlready
- + " existingIsVisible=" + existingIsVisible
+ " shortcut=" + inShortcut.toInsecureString());
}
@@ -380,6 +378,7 @@ class ShortcutRequestPinProcessor {
// manifest shortcut.)
Preconditions.checkArgument(shortcutInfo.isEnabled(),
"Shortcut ID=" + shortcutInfo + " already exists but disabled.");
+
}
private boolean startRequestConfirmActivity(ComponentName activity, int launcherUserId,
@@ -464,7 +463,7 @@ class ShortcutRequestPinProcessor {
launcher.attemptToRestoreIfNeededAndSave();
if (launcher.hasPinned(original)) {
if (DEBUG) {
- Slog.d(TAG, "Shortcut " + original + " already pinned."); // This too.
+ Slog.d(TAG, "Shortcut " + original + " already pinned.");
}
return true;
}
@@ -498,7 +497,7 @@ class ShortcutRequestPinProcessor {
if (original.getActivity() == null) {
original.setActivity(mService.getDummyMainActivity(appPackageName));
}
- ps.addOrReplaceDynamicShortcut(original);
+ ps.addOrUpdateDynamicShortcut(original);
}
// Pin the shortcut.
@@ -506,14 +505,13 @@ class ShortcutRequestPinProcessor {
Slog.d(TAG, "Pinning " + shortcutId);
}
- launcher.addPinnedShortcut(appPackageName, appUserId, shortcutId,
- /*forPinRequest=*/ true);
+ launcher.addPinnedShortcut(appPackageName, appUserId, shortcutId);
if (current == null) {
if (DEBUG) {
Slog.d(TAG, "Removing " + shortcutId + " as dynamic");
}
- ps.deleteDynamicWithId(shortcutId, /*ignoreInvisible=*/ false);
+ ps.deleteDynamicWithId(shortcutId);
}
ps.adjustRanks(); // Shouldn't be needed, but just in case.
diff --git a/com/android/server/pm/ShortcutService.java b/com/android/server/pm/ShortcutService.java
index 1c002aa4..27560c5f 100644
--- a/com/android/server/pm/ShortcutService.java
+++ b/com/android/server/pm/ShortcutService.java
@@ -553,9 +553,6 @@ public class ShortcutService extends IShortcutService.Stub {
public Lifecycle(Context context) {
super(context);
- if (DEBUG) {
- Binder.LOG_RUNTIME_EXCEPTION = true;
- }
mService = new ShortcutService(context);
}
@@ -741,10 +738,6 @@ public class ShortcutService extends IShortcutService.Stub {
return parseLongAttribute(parser, attribute) == 1;
}
- static boolean parseBooleanAttribute(XmlPullParser parser, String attribute, boolean def) {
- return parseLongAttribute(parser, attribute, (def ? 1 : 0)) == 1;
- }
-
static int parseIntAttribute(XmlPullParser parser, String attribute) {
return (int) parseLongAttribute(parser, attribute);
}
@@ -842,8 +835,6 @@ public class ShortcutService extends IShortcutService.Stub {
static void writeAttr(XmlSerializer out, String name, boolean value) throws IOException {
if (value) {
writeAttr(out, name, "1");
- } else {
- writeAttr(out, name, "0");
}
}
@@ -1698,7 +1689,7 @@ public class ShortcutService extends IShortcutService.Stub {
final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
- ps.ensureImmutableShortcutsNotIncluded(newShortcuts, /*ignoreInvisible=*/ true);
+ ps.ensureImmutableShortcutsNotIncluded(newShortcuts);
fillInDefaultActivity(newShortcuts);
@@ -1718,12 +1709,12 @@ public class ShortcutService extends IShortcutService.Stub {
}
// First, remove all un-pinned; dynamic shortcuts
- ps.deleteAllDynamicShortcuts(/*ignoreInvisible=*/ true);
+ ps.deleteAllDynamicShortcuts();
// Then, add/update all. We need to make sure to take over "pinned" flag.
for (int i = 0; i < size; i++) {
final ShortcutInfo newShortcut = newShortcuts.get(i);
- ps.addOrReplaceDynamicShortcut(newShortcut);
+ ps.addOrUpdateDynamicShortcut(newShortcut);
}
// Lastly, adjust the ranks.
@@ -1749,7 +1740,7 @@ public class ShortcutService extends IShortcutService.Stub {
final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
- ps.ensureImmutableShortcutsNotIncluded(newShortcuts, /*ignoreInvisible=*/ true);
+ ps.ensureImmutableShortcutsNotIncluded(newShortcuts);
// For update, don't fill in the default activity. Having null activity means
// "don't update the activity" here.
@@ -1770,9 +1761,7 @@ public class ShortcutService extends IShortcutService.Stub {
fixUpIncomingShortcutInfo(source, /* forUpdate= */ true);
final ShortcutInfo target = ps.findShortcutById(source.getId());
-
- // Invisible shortcuts can't be updated.
- if (target == null || !target.isVisibleToPublisher()) {
+ if (target == null) {
continue;
}
@@ -1819,7 +1808,7 @@ public class ShortcutService extends IShortcutService.Stub {
}
@Override
- public boolean addDynamicShortcuts(String packageName, ParceledListSlice shortcutInfoList,
+ public boolean addDynamicShortcuts(String packageName, ParceledListSlice shortcutInfoList,
@UserIdInt int userId) {
verifyCaller(packageName, userId);
@@ -1831,7 +1820,7 @@ public class ShortcutService extends IShortcutService.Stub {
final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
- ps.ensureImmutableShortcutsNotIncluded(newShortcuts, /*ignoreInvisible=*/ true);
+ ps.ensureImmutableShortcutsNotIncluded(newShortcuts);
fillInDefaultActivity(newShortcuts);
@@ -1856,7 +1845,7 @@ public class ShortcutService extends IShortcutService.Stub {
newShortcut.setRankChanged();
// Add it.
- ps.addOrReplaceDynamicShortcut(newShortcut);
+ ps.addOrUpdateDynamicShortcut(newShortcut);
}
// Lastly, adjust the ranks.
@@ -1912,22 +1901,6 @@ public class ShortcutService extends IShortcutService.Stub {
Preconditions.checkState(isUidForegroundLocked(injectBinderCallingUid()),
"Calling application must have a foreground activity or a foreground service");
- // If it's a pin shortcut request, and there's already a shortcut with the same ID
- // that's not visible to the caller (i.e. restore-blocked; meaning it's pinned by
- // someone already), then we just replace the existing one with this new one,
- // and then proceed the rest of the process.
- if (shortcut != null) {
- final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(
- packageName, userId);
- final String id = shortcut.getId();
- if (ps.isShortcutExistsAndInvisibleToPublisher(id)) {
-
- ps.updateInvisibleShortcutForPinRequestWith(shortcut);
-
- packageShortcutsChanged(packageName, userId);
- }
- }
-
// Send request to the launcher, if supported.
ret = mShortcutRequestPinProcessor.requestPinItemLocked(shortcut, appWidget, extras,
userId, resultIntent);
@@ -1949,21 +1922,15 @@ public class ShortcutService extends IShortcutService.Stub {
final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
- ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds,
- /*ignoreInvisible=*/ true);
+ ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds);
final String disabledMessageString =
(disabledMessage == null) ? null : disabledMessage.toString();
for (int i = shortcutIds.size() - 1; i >= 0; i--) {
- final String id = Preconditions.checkStringNotEmpty((String) shortcutIds.get(i));
- if (!ps.isShortcutExistsAndVisibleToPublisher(id)) {
- continue;
- }
- ps.disableWithId(id,
+ ps.disableWithId(Preconditions.checkStringNotEmpty((String) shortcutIds.get(i)),
disabledMessageString, disabledMessageResId,
- /* overrideImmutable=*/ false, /*ignoreInvisible=*/ true,
- ShortcutInfo.DISABLED_REASON_BY_APP);
+ /* overrideImmutable=*/ false);
}
// We may have removed dynamic shortcuts which may have left a gap, so adjust the ranks.
@@ -1984,15 +1951,10 @@ public class ShortcutService extends IShortcutService.Stub {
final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
- ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds,
- /*ignoreInvisible=*/ true);
+ ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds);
for (int i = shortcutIds.size() - 1; i >= 0; i--) {
- final String id = Preconditions.checkStringNotEmpty((String) shortcutIds.get(i));
- if (!ps.isShortcutExistsAndVisibleToPublisher(id)) {
- continue;
- }
- ps.enableWithId(id);
+ ps.enableWithId((String) shortcutIds.get(i));
}
}
packageShortcutsChanged(packageName, userId);
@@ -2011,15 +1973,11 @@ public class ShortcutService extends IShortcutService.Stub {
final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
- ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds,
- /*ignoreInvisible=*/ true);
+ ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds);
for (int i = shortcutIds.size() - 1; i >= 0; i--) {
- final String id = Preconditions.checkStringNotEmpty((String) shortcutIds.get(i));
- if (!ps.isShortcutExistsAndVisibleToPublisher(id)) {
- continue;
- }
- ps.deleteDynamicWithId(id, /*ignoreInvisible=*/ true);
+ ps.deleteDynamicWithId(
+ Preconditions.checkStringNotEmpty((String) shortcutIds.get(i)));
}
// We may have removed dynamic shortcuts which may have left a gap, so adjust the ranks.
@@ -2038,7 +1996,7 @@ public class ShortcutService extends IShortcutService.Stub {
throwIfUserLockedL(userId);
final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
- ps.deleteAllDynamicShortcuts(/*ignoreInvisible=*/ true);
+ ps.deleteAllDynamicShortcuts();
}
packageShortcutsChanged(packageName, userId);
@@ -2055,7 +2013,7 @@ public class ShortcutService extends IShortcutService.Stub {
return getShortcutsWithQueryLocked(
packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR,
- ShortcutInfo::isDynamicVisible);
+ ShortcutInfo::isDynamic);
}
}
@@ -2069,7 +2027,7 @@ public class ShortcutService extends IShortcutService.Stub {
return getShortcutsWithQueryLocked(
packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR,
- ShortcutInfo::isManifestVisible);
+ ShortcutInfo::isManifestShortcut);
}
}
@@ -2083,7 +2041,7 @@ public class ShortcutService extends IShortcutService.Stub {
return getShortcutsWithQueryLocked(
packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR,
- ShortcutInfo::isPinnedVisible);
+ ShortcutInfo::isPinned);
}
}
@@ -2232,11 +2190,7 @@ public class ShortcutService extends IShortcutService.Stub {
}
// We override this method in unit tests to do a simpler check.
- boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId,
- int callingPid, int callingUid) {
- if (injectCheckAccessShortcutsPermission(callingPid, callingUid)) {
- return true;
- }
+ boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId) {
final long start = injectElapsedRealtime();
try {
return hasShortcutHostPermissionInner(callingPackage, userId);
@@ -2245,14 +2199,6 @@ public class ShortcutService extends IShortcutService.Stub {
}
}
- /**
- * Returns true if the caller has the "ACCESS_SHORTCUTS" permission.
- */
- boolean injectCheckAccessShortcutsPermission(int callingPid, int callingUid) {
- return mContext.checkPermission(android.Manifest.permission.ACCESS_SHORTCUTS,
- callingPid, callingUid) == PackageManager.PERMISSION_GRANTED;
- }
-
// This method is extracted so we can directly call this method from unit tests,
// even when hasShortcutPermission() is overridden.
@VisibleForTesting
@@ -2433,7 +2379,7 @@ public class ShortcutService extends IShortcutService.Stub {
@NonNull String callingPackage, long changedSince,
@Nullable String packageName, @Nullable List<String> shortcutIds,
@Nullable ComponentName componentName,
- int queryFlags, int userId, int callingPid, int callingUid) {
+ int queryFlags, int userId) {
final ArrayList<ShortcutInfo> ret = new ArrayList<>();
final boolean cloneKeyFieldOnly =
@@ -2454,15 +2400,13 @@ public class ShortcutService extends IShortcutService.Stub {
if (packageName != null) {
getShortcutsInnerLocked(launcherUserId,
callingPackage, packageName, shortcutIds, changedSince,
- componentName, queryFlags, userId, ret, cloneFlag,
- callingPid, callingUid);
+ componentName, queryFlags, userId, ret, cloneFlag);
} else {
final List<String> shortcutIdsF = shortcutIds;
getUserShortcutsLocked(userId).forAllPackages(p -> {
getShortcutsInnerLocked(launcherUserId,
callingPackage, p.getPackageName(), shortcutIdsF, changedSince,
- componentName, queryFlags, userId, ret, cloneFlag,
- callingPid, callingUid);
+ componentName, queryFlags, userId, ret, cloneFlag);
});
}
}
@@ -2472,8 +2416,7 @@ public class ShortcutService extends IShortcutService.Stub {
private void getShortcutsInnerLocked(int launcherUserId, @NonNull String callingPackage,
@Nullable String packageName, @Nullable List<String> shortcutIds, long changedSince,
@Nullable ComponentName componentName, int queryFlags,
- int userId, ArrayList<ShortcutInfo> ret, int cloneFlag,
- int callingPid, int callingUid) {
+ int userId, ArrayList<ShortcutInfo> ret, int cloneFlag) {
final ArraySet<String> ids = shortcutIds == null ? null
: new ArraySet<>(shortcutIds);
@@ -2482,13 +2425,6 @@ public class ShortcutService extends IShortcutService.Stub {
if (p == null) {
return; // No need to instantiate ShortcutPackage.
}
- final boolean matchDynamic = (queryFlags & ShortcutQuery.FLAG_MATCH_DYNAMIC) != 0;
- final boolean matchPinned = (queryFlags & ShortcutQuery.FLAG_MATCH_PINNED) != 0;
- final boolean matchManifest = (queryFlags & ShortcutQuery.FLAG_MATCH_MANIFEST) != 0;
-
- final boolean getPinnedByAnyLauncher =
- ((queryFlags & ShortcutQuery.FLAG_MATCH_ALL_PINNED) != 0)
- && injectCheckAccessShortcutsPermission(callingPid, callingUid);
p.findAll(ret,
(ShortcutInfo si) -> {
@@ -2504,17 +2440,20 @@ public class ShortcutService extends IShortcutService.Stub {
return false;
}
}
- if (matchDynamic && si.isDynamic()) {
+ if (((queryFlags & ShortcutQuery.FLAG_GET_DYNAMIC) != 0)
+ && si.isDynamic()) {
return true;
}
- if ((matchPinned && si.isPinned()) || getPinnedByAnyLauncher) {
+ if (((queryFlags & ShortcutQuery.FLAG_GET_PINNED) != 0)
+ && si.isPinned()) {
return true;
}
- if (matchManifest && si.isDeclaredInManifest()) {
+ if (((queryFlags & ShortcutQuery.FLAG_GET_MANIFEST) != 0)
+ && si.isManifestShortcut()) {
return true;
}
return false;
- }, cloneFlag, callingPackage, launcherUserId, getPinnedByAnyLauncher);
+ }, cloneFlag, callingPackage, launcherUserId);
}
@Override
@@ -2531,16 +2470,14 @@ public class ShortcutService extends IShortcutService.Stub {
.attemptToRestoreIfNeededAndSave();
final ShortcutInfo si = getShortcutInfoLocked(
- launcherUserId, callingPackage, packageName, shortcutId, userId,
- /*getPinnedByAnyLauncher=*/ false);
+ launcherUserId, callingPackage, packageName, shortcutId, userId);
return si != null && si.isPinned();
}
}
private ShortcutInfo getShortcutInfoLocked(
int launcherUserId, @NonNull String callingPackage,
- @NonNull String packageName, @NonNull String shortcutId, int userId,
- boolean getPinnedByAnyLauncher) {
+ @NonNull String packageName, @NonNull String shortcutId, int userId) {
Preconditions.checkStringNotEmpty(packageName, "packageName");
Preconditions.checkStringNotEmpty(shortcutId, "shortcutId");
@@ -2556,7 +2493,7 @@ public class ShortcutService extends IShortcutService.Stub {
final ArrayList<ShortcutInfo> list = new ArrayList<>(1);
p.findAll(list,
(ShortcutInfo si) -> shortcutId.equals(si.getId()),
- /* clone flags=*/ 0, callingPackage, launcherUserId, getPinnedByAnyLauncher);
+ /* clone flags=*/ 0, callingPackage, launcherUserId);
return list.size() == 0 ? null : list.get(0);
}
@@ -2576,7 +2513,7 @@ public class ShortcutService extends IShortcutService.Stub {
getLauncherShortcutsLocked(callingPackage, userId, launcherUserId);
launcher.attemptToRestoreIfNeededAndSave();
- launcher.pinShortcuts(userId, packageName, shortcutIds, /*forPinRequest=*/ false);
+ launcher.pinShortcuts(userId, packageName, shortcutIds);
}
packageShortcutsChanged(packageName, userId);
@@ -2586,8 +2523,7 @@ public class ShortcutService extends IShortcutService.Stub {
@Override
public Intent[] createShortcutIntents(int launcherUserId,
@NonNull String callingPackage,
- @NonNull String packageName, @NonNull String shortcutId, int userId,
- int callingPid, int callingUid) {
+ @NonNull String packageName, @NonNull String shortcutId, int userId) {
// Calling permission must be checked by LauncherAppsImpl.
Preconditions.checkStringNotEmpty(packageName, "packageName can't be empty");
Preconditions.checkStringNotEmpty(shortcutId, "shortcutId can't be empty");
@@ -2599,13 +2535,9 @@ public class ShortcutService extends IShortcutService.Stub {
getLauncherShortcutsLocked(callingPackage, userId, launcherUserId)
.attemptToRestoreIfNeededAndSave();
- final boolean getPinnedByAnyLauncher =
- injectCheckAccessShortcutsPermission(callingPid, callingUid);
-
// Make sure the shortcut is actually visible to the launcher.
final ShortcutInfo si = getShortcutInfoLocked(
- launcherUserId, callingPackage, packageName, shortcutId, userId,
- getPinnedByAnyLauncher);
+ launcherUserId, callingPackage, packageName, shortcutId, userId);
// "si == null" should suffice here, but check the flags too just to make sure.
if (si == null || !si.isEnabled() || !si.isAlive()) {
Log.e(TAG, "Shortcut " + shortcutId + " does not exist or disabled");
@@ -2691,9 +2623,8 @@ public class ShortcutService extends IShortcutService.Stub {
@Override
public boolean hasShortcutHostPermission(int launcherUserId,
- @NonNull String callingPackage, int callingPid, int callingUid) {
- return ShortcutService.this.hasShortcutHostPermission(callingPackage, launcherUserId,
- callingPid, callingUid);
+ @NonNull String callingPackage) {
+ return ShortcutService.this.hasShortcutHostPermission(callingPackage, launcherUserId);
}
@Override
@@ -3412,7 +3343,7 @@ public class ShortcutService extends IShortcutService.Stub {
return isApplicationFlagSet(packageName, userId, ApplicationInfo.FLAG_ALLOW_BACKUP);
}
- static boolean shouldBackupApp(PackageInfo pi) {
+ boolean shouldBackupApp(PackageInfo pi) {
return (pi.applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0;
}
@@ -3440,7 +3371,7 @@ public class ShortcutService extends IShortcutService.Stub {
// Set the version code for the launchers.
// We shouldn't do this for publisher packages, because we don't want to update the
// version code without rescanning the manifest.
- user.forAllLaunchers(launcher -> launcher.ensurePackageInfo());
+ user.forAllLaunchers(launcher -> launcher.ensureVersionInfo());
// Save to the filesystem.
scheduleSaveUser(userId);
diff --git a/com/android/server/pm/ShortcutUser.java b/com/android/server/pm/ShortcutUser.java
index 48eccd02..55e6d28a 100644
--- a/com/android/server/pm/ShortcutUser.java
+++ b/com/android/server/pm/ShortcutUser.java
@@ -364,6 +364,9 @@ class ShortcutUser {
private void saveShortcutPackageItem(XmlSerializer out,
ShortcutPackageItem spi, boolean forBackup) throws IOException, XmlPullParserException {
if (forBackup) {
+ if (!mService.shouldBackupApp(spi.getPackageName(), spi.getPackageUserId())) {
+ return; // Don't save.
+ }
if (spi.getPackageUserId() != spi.getOwnerUserId()) {
return; // Don't save cross-user information.
}
diff --git a/com/android/server/pm/UserRestrictionsUtils.java b/com/android/server/pm/UserRestrictionsUtils.java
index c18a71d3..a6b05d71 100644
--- a/com/android/server/pm/UserRestrictionsUtils.java
+++ b/com/android/server/pm/UserRestrictionsUtils.java
@@ -96,7 +96,6 @@ public class UserRestrictionsUtils {
UserManager.DISALLOW_SMS,
UserManager.DISALLOW_FUN,
UserManager.DISALLOW_CREATE_WINDOWS,
- UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS,
UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE,
UserManager.DISALLOW_OUTGOING_BEAM,
UserManager.DISALLOW_WALLPAPER,
@@ -157,7 +156,6 @@ public class UserRestrictionsUtils {
private static final Set<String> GLOBAL_RESTRICTIONS = Sets.newArraySet(
UserManager.DISALLOW_ADJUST_VOLUME,
UserManager.DISALLOW_BLUETOOTH_SHARING,
- UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS,
UserManager.DISALLOW_RUN_IN_BACKGROUND,
UserManager.DISALLOW_UNMUTE_MICROPHONE,
UserManager.DISALLOW_UNMUTE_DEVICE
diff --git a/com/android/server/pm/permission/BasePermission.java b/com/android/server/pm/permission/BasePermission.java
index 71d3202d..09a6e9c0 100644
--- a/com/android/server/pm/permission/BasePermission.java
+++ b/com/android/server/pm/permission/BasePermission.java
@@ -48,7 +48,6 @@ import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -78,7 +77,7 @@ public final class BasePermission {
final String name;
- final @PermissionType int type;
+ @PermissionType final int type;
String sourcePackageName;
@@ -253,12 +252,12 @@ public final class BasePermission {
return changed;
}
- public void updateDynamicPermission(Collection<BasePermission> permissionTrees) {
+ public void updateDynamicPermission(Map<String, BasePermission> permissionTrees) {
if (PackageManagerService.DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
+ getName() + " pkg=" + getSourcePackageName()
+ " info=" + pendingPermissionInfo);
if (sourcePackageSetting == null && pendingPermissionInfo != null) {
- final BasePermission tree = findPermissionTree(permissionTrees, name);
+ final BasePermission tree = findPermissionTreeLP(permissionTrees, name);
if (tree != null && tree.perm != null) {
sourcePackageSetting = tree.sourcePackageSetting;
perm = new PackageParser.Permission(tree.perm.owner,
@@ -270,8 +269,8 @@ public final class BasePermission {
}
}
- static BasePermission createOrUpdate(@Nullable BasePermission bp, @NonNull Permission p,
- @NonNull PackageParser.Package pkg, Collection<BasePermission> permissionTrees,
+ public static BasePermission createOrUpdate(@Nullable BasePermission bp, @NonNull Permission p,
+ @NonNull PackageParser.Package pkg, Map<String, BasePermission> permissionTrees,
boolean chatty) {
final PackageSettingBase pkgSetting = (PackageSettingBase) pkg.mExtras;
// Allow system apps to redefine non-system permissions
@@ -301,7 +300,7 @@ public final class BasePermission {
if (bp.perm == null) {
if (bp.sourcePackageName == null
|| bp.sourcePackageName.equals(p.info.packageName)) {
- final BasePermission tree = findPermissionTree(permissionTrees, p.info.name);
+ final BasePermission tree = findPermissionTreeLP(permissionTrees, p.info.name);
if (tree == null
|| tree.sourcePackageName.equals(p.info.packageName)) {
bp.sourcePackageSetting = pkgSetting;
@@ -346,12 +345,12 @@ public final class BasePermission {
return bp;
}
- static BasePermission enforcePermissionTree(
- Collection<BasePermission> permissionTrees, String permName, int callingUid) {
+ public static BasePermission enforcePermissionTreeLP(
+ Map<String, BasePermission> permissionTrees, String permName, int callingUid) {
if (permName != null) {
- BasePermission bp = findPermissionTree(permissionTrees, permName);
+ BasePermission bp = findPermissionTreeLP(permissionTrees, permName);
if (bp != null) {
- if (bp.uid == UserHandle.getAppId(callingUid)) {
+ if (bp.uid == UserHandle.getAppId(callingUid)) {//UserHandle.getAppId(Binder.getCallingUid())) {
return bp;
}
throw new SecurityException("Calling uid " + callingUid
@@ -374,9 +373,9 @@ public final class BasePermission {
}
}
- private static BasePermission findPermissionTree(
- Collection<BasePermission> permissionTrees, String permName) {
- for (BasePermission bp : permissionTrees) {
+ private static BasePermission findPermissionTreeLP(
+ Map<String, BasePermission> permissionTrees, String permName) {
+ for (BasePermission bp : permissionTrees.values()) {
if (permName.startsWith(bp.name) &&
permName.length() > bp.name.length() &&
permName.charAt(bp.name.length()) == '.') {
diff --git a/com/android/server/pm/permission/PermissionManagerInternal.java b/com/android/server/pm/permission/PermissionManagerInternal.java
index 8aac52ae..3b20b42b 100644
--- a/com/android/server/pm/permission/PermissionManagerInternal.java
+++ b/com/android/server/pm/permission/PermissionManagerInternal.java
@@ -31,7 +31,6 @@ import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Set;
/**
* Internal interfaces to be used by other components within the system server.
@@ -82,26 +81,11 @@ public abstract class PermissionManagerInternal {
@NonNull int[] allUserIds);
- /**
- * Add all permissions in the given package.
- * <p>
- * NOTE: argument {@code groupTEMP} is temporary until mPermissionGroups is moved to
- * the permission settings.
- */
- public abstract void addAllPermissions(@NonNull PackageParser.Package pkg, boolean chatty);
- public abstract void removeAllPermissions(@NonNull PackageParser.Package pkg, boolean chatty);
- public abstract boolean addDynamicPermission(@NonNull PermissionInfo info, boolean async,
+ public abstract boolean addPermission(@NonNull PermissionInfo info, boolean async,
int callingUid, @Nullable PermissionCallback callback);
- public abstract void removeDynamicPermission(@NonNull String permName, int callingUid,
+ public abstract void removePermission(@NonNull String permName, int callingUid,
@Nullable PermissionCallback callback);
- public abstract int updatePermissions(@Nullable String changingPkg,
- @Nullable PackageParser.Package pkgInfo, int flags);
- public abstract int updatePermissionTrees(@Nullable String changingPkg,
- @Nullable PackageParser.Package pkgInfo, int flags);
-
- public abstract @Nullable String[] getAppOpPermissionPackages(@NonNull String permName);
-
public abstract int getPermissionFlags(@NonNull String permName,
@NonNull String packageName, int callingUid, int userId);
/**
@@ -114,6 +98,8 @@ public abstract class PermissionManagerInternal {
*/
public abstract @Nullable List<PermissionInfo> getPermissionInfoByGroup(@NonNull String group,
@PermissionInfoFlags int flags, int callingUid);
+ public abstract boolean isPermissionAppOp(@NonNull String permName);
+ public abstract boolean isPermissionInstant(@NonNull String permName);
/**
* Updates the flags associated with a permission by replacing the flags in
diff --git a/com/android/server/pm/permission/PermissionManagerService.java b/com/android/server/pm/permission/PermissionManagerService.java
index d2d857ca..6c031a6a 100644
--- a/com/android/server/pm/permission/PermissionManagerService.java
+++ b/com/android/server/pm/permission/PermissionManagerService.java
@@ -69,7 +69,6 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
-import java.util.Set;
/**
* Manages all permissions and handles permissions related tasks.
@@ -261,7 +260,7 @@ public class PermissionManagerService {
// }
final ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
- for (BasePermission bp : mSettings.mPermissions.values()) {
+ for (BasePermission bp : mSettings.getAllPermissionsLocked()) {
final PermissionInfo pi = bp.generatePermissionInfo(groupName, flags);
if (pi != null) {
out.add(pi);
@@ -306,98 +305,7 @@ public class PermissionManagerService {
return protectionLevel;
}
- private void addAllPermissions(PackageParser.Package pkg, boolean chatty) {
- final int N = pkg.permissions.size();
- for (int i=0; i<N; i++) {
- PackageParser.Permission p = pkg.permissions.get(i);
-
- // Assume by default that we did not install this permission into the system.
- p.info.flags &= ~PermissionInfo.FLAG_INSTALLED;
-
- // Now that permission groups have a special meaning, we ignore permission
- // groups for legacy apps to prevent unexpected behavior. In particular,
- // permissions for one app being granted to someone just because they happen
- // to be in a group defined by another app (before this had no implications).
- if (pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
- p.group = mPackageManagerInt.getPermissionGroupTEMP(p.info.group);
- // Warn for a permission in an unknown group.
- if (PackageManagerService.DEBUG_PERMISSIONS
- && p.info.group != null && p.group == null) {
- Slog.i(TAG, "Permission " + p.info.name + " from package "
- + p.info.packageName + " in an unknown group " + p.info.group);
- }
- }
-
- synchronized (PermissionManagerService.this.mLock) {
- if (p.tree) {
- final BasePermission bp = BasePermission.createOrUpdate(
- mSettings.getPermissionTreeLocked(p.info.name), p, pkg,
- mSettings.getAllPermissionTreesLocked(), chatty);
- mSettings.putPermissionTreeLocked(p.info.name, bp);
- } else {
- final BasePermission bp = BasePermission.createOrUpdate(
- mSettings.getPermissionLocked(p.info.name),
- p, pkg, mSettings.getAllPermissionTreesLocked(), chatty);
- mSettings.putPermissionLocked(p.info.name, bp);
- }
- }
- }
- }
-
- private void removeAllPermissions(PackageParser.Package pkg, boolean chatty) {
- synchronized (mLock) {
- int N = pkg.permissions.size();
- StringBuilder r = null;
- for (int i=0; i<N; i++) {
- PackageParser.Permission p = pkg.permissions.get(i);
- BasePermission bp = (BasePermission) mSettings.mPermissions.get(p.info.name);
- if (bp == null) {
- bp = mSettings.mPermissionTrees.get(p.info.name);
- }
- if (bp != null && bp.isPermission(p)) {
- bp.setPermission(null);
- if (PackageManagerService.DEBUG_REMOVE && chatty) {
- if (r == null) {
- r = new StringBuilder(256);
- } else {
- r.append(' ');
- }
- r.append(p.info.name);
- }
- }
- if (p.isAppOp()) {
- ArraySet<String> appOpPkgs =
- mSettings.mAppOpPermissionPackages.get(p.info.name);
- if (appOpPkgs != null) {
- appOpPkgs.remove(pkg.packageName);
- }
- }
- }
- if (r != null) {
- if (PackageManagerService.DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
- }
-
- N = pkg.requestedPermissions.size();
- r = null;
- for (int i=0; i<N; i++) {
- String perm = pkg.requestedPermissions.get(i);
- if (mSettings.isPermissionAppOp(perm)) {
- ArraySet<String> appOpPkgs = mSettings.mAppOpPermissionPackages.get(perm);
- if (appOpPkgs != null) {
- appOpPkgs.remove(pkg.packageName);
- if (appOpPkgs.isEmpty()) {
- mSettings.mAppOpPermissionPackages.remove(perm);
- }
- }
- }
- }
- if (r != null) {
- if (PackageManagerService.DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
- }
- }
- }
-
- private boolean addDynamicPermission(
+ private boolean addPermission(
PermissionInfo info, int callingUid, PermissionCallback callback) {
if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
throw new SecurityException("Instant apps can't add permissions");
@@ -405,7 +313,8 @@ public class PermissionManagerService {
if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
throw new SecurityException("Label must be specified in permission");
}
- final BasePermission tree = mSettings.enforcePermissionTree(info.name, callingUid);
+ final BasePermission tree = (BasePermission) mPackageManagerInt.enforcePermissionTreeTEMP(
+ info.name, callingUid);
final boolean added;
final boolean changed;
synchronized (mLock) {
@@ -417,8 +326,8 @@ public class PermissionManagerService {
bp = new BasePermission(info.name, tree.getSourcePackageName(),
BasePermission.TYPE_DYNAMIC);
} else if (bp.isDynamic()) {
- // TODO: switch this back to SecurityException
- Slog.wtf(TAG, "Not allowed to modify non-dynamic permission "
+ throw new SecurityException(
+ "Not allowed to modify non-dynamic permission "
+ info.name);
}
changed = bp.addToTree(fixedLevel, info, tree);
@@ -432,20 +341,21 @@ public class PermissionManagerService {
return added;
}
- private void removeDynamicPermission(
+ private void removePermission(
String permName, int callingUid, PermissionCallback callback) {
if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
throw new SecurityException("Instant applications don't have access to this method");
}
- final BasePermission tree = mSettings.enforcePermissionTree(permName, callingUid);
+ final BasePermission tree = (BasePermission) mPackageManagerInt.enforcePermissionTreeTEMP(
+ permName, callingUid);
synchronized (mLock) {
final BasePermission bp = mSettings.getPermissionLocked(permName);
if (bp == null) {
return;
}
if (bp.isDynamic()) {
- // TODO: switch this back to SecurityException
- Slog.wtf(TAG, "Not allowed to modify non-dynamic permission "
+ throw new SecurityException(
+ "Not allowed to modify non-dynamic permission "
+ permName);
}
mSettings.removePermissionLocked(permName);
@@ -803,21 +713,7 @@ public class PermissionManagerService {
return runtimePermissionChangedUserIds;
}
- private String[] getAppOpPermissionPackages(String permName) {
- if (mPackageManagerInt.getInstantAppPackageName(Binder.getCallingUid()) != null) {
- return null;
- }
- synchronized (mLock) {
- final ArraySet<String> pkgs = mSettings.mAppOpPermissionPackages.get(permName);
- if (pkgs == null) {
- return null;
- }
- return pkgs.toArray(new String[pkgs.size()]);
- }
- }
-
- private int getPermissionFlags(
- String permName, String packageName, int callingUid, int userId) {
+ private int getPermissionFlags(String permName, String packageName, int callingUid, int userId) {
if (!mUserManagerInt.exists(userId)) {
return 0;
}
@@ -845,96 +741,6 @@ public class PermissionManagerService {
return permissionsState.getPermissionFlags(permName, userId);
}
- private int updatePermissions(String packageName, PackageParser.Package pkgInfo, int flags) {
- Set<BasePermission> needsUpdate = null;
- synchronized (mLock) {
- final Iterator<BasePermission> it = mSettings.mPermissions.values().iterator();
- while (it.hasNext()) {
- final BasePermission bp = it.next();
- if (bp.isDynamic()) {
- bp.updateDynamicPermission(mSettings.mPermissionTrees.values());
- }
- if (bp.getSourcePackageSetting() != null) {
- if (packageName != null && packageName.equals(bp.getSourcePackageName())
- && (pkgInfo == null || !hasPermission(pkgInfo, bp.getName()))) {
- Slog.i(TAG, "Removing old permission tree: " + bp.getName()
- + " from package " + bp.getSourcePackageName());
- flags |= PackageManagerService.UPDATE_PERMISSIONS_ALL;
- it.remove();
- }
- continue;
- }
- if (needsUpdate == null) {
- needsUpdate = new ArraySet<>(mSettings.mPermissions.size());
- }
- needsUpdate.add(bp);
- }
- }
- if (needsUpdate != null) {
- for (final BasePermission bp : needsUpdate) {
- final PackageParser.Package pkg =
- mPackageManagerInt.getPackage(bp.getSourcePackageName());
- synchronized (mLock) {
- if (pkg != null && pkg.mExtras != null) {
- final PackageSetting ps = (PackageSetting) pkg.mExtras;
- if (bp.getSourcePackageSetting() == null) {
- bp.setSourcePackageSetting(ps);
- }
- continue;
- }
- Slog.w(TAG, "Removing dangling permission: " + bp.getName()
- + " from package " + bp.getSourcePackageName());
- mSettings.removePermissionLocked(bp.getName());
- }
- }
- }
- return flags;
- }
-
- private int updatePermissionTrees(String packageName, PackageParser.Package pkgInfo,
- int flags) {
- Set<BasePermission> needsUpdate = null;
- synchronized (mLock) {
- final Iterator<BasePermission> it = mSettings.mPermissionTrees.values().iterator();
- while (it.hasNext()) {
- final BasePermission bp = it.next();
- if (bp.getSourcePackageSetting() != null) {
- if (packageName != null && packageName.equals(bp.getSourcePackageName())
- && (pkgInfo == null || !hasPermission(pkgInfo, bp.getName()))) {
- Slog.i(TAG, "Removing old permission tree: " + bp.getName()
- + " from package " + bp.getSourcePackageName());
- flags |= PackageManagerService.UPDATE_PERMISSIONS_ALL;
- it.remove();
- }
- continue;
- }
- if (needsUpdate == null) {
- needsUpdate = new ArraySet<>(mSettings.mPermissionTrees.size());
- }
- needsUpdate.add(bp);
- }
- }
- if (needsUpdate != null) {
- for (final BasePermission bp : needsUpdate) {
- final PackageParser.Package pkg =
- mPackageManagerInt.getPackage(bp.getSourcePackageName());
- synchronized (mLock) {
- if (pkg != null && pkg.mExtras != null) {
- final PackageSetting ps = (PackageSetting) pkg.mExtras;
- if (bp.getSourcePackageSetting() == null) {
- bp.setSourcePackageSetting(ps);
- }
- continue;
- }
- Slog.w(TAG, "Removing dangling permission tree: " + bp.getName()
- + " from package " + bp.getSourcePackageName());
- mSettings.removePermissionLocked(bp.getName());
- }
- }
- }
- return flags;
- }
-
private void updatePermissionFlags(String permName, String packageName, int flagMask,
int flagValues, int callingUid, int userId, PermissionCallback callback) {
if (!mUserManagerInt.exists(userId)) {
@@ -1066,7 +872,7 @@ public class PermissionManagerService {
private int calculateCurrentPermissionFootprintLocked(BasePermission tree) {
int size = 0;
- for (BasePermission perm : mSettings.mPermissions.values()) {
+ for (BasePermission perm : mSettings.getAllPermissionsLocked()) {
size += tree.calculateFootprint(perm);
}
return size;
@@ -1083,15 +889,6 @@ public class PermissionManagerService {
}
}
- private static boolean hasPermission(PackageParser.Package pkgInfo, String permName) {
- for (int i=pkgInfo.permissions.size()-1; i>=0; i--) {
- if (pkgInfo.permissions.get(i).info.name.equals(permName)) {
- return true;
- }
- }
- return false;
- }
-
/**
* Get the first event id for the permission.
*
@@ -1154,22 +951,14 @@ public class PermissionManagerService {
private class PermissionManagerInternalImpl extends PermissionManagerInternal {
@Override
- public void addAllPermissions(Package pkg, boolean chatty) {
- PermissionManagerService.this.addAllPermissions(pkg, chatty);
- }
- @Override
- public void removeAllPermissions(Package pkg, boolean chatty) {
- PermissionManagerService.this.removeAllPermissions(pkg, chatty);
- }
- @Override
- public boolean addDynamicPermission(PermissionInfo info, boolean async, int callingUid,
+ public boolean addPermission(PermissionInfo info, boolean async, int callingUid,
PermissionCallback callback) {
- return PermissionManagerService.this.addDynamicPermission(info, callingUid, callback);
+ return PermissionManagerService.this.addPermission(info, callingUid, callback);
}
@Override
- public void removeDynamicPermission(String permName, int callingUid,
+ public void removePermission(String permName, int callingUid,
PermissionCallback callback) {
- PermissionManagerService.this.removeDynamicPermission(permName, callingUid, callback);
+ PermissionManagerService.this.removePermission(permName, callingUid, callback);
}
@Override
public void grantRuntimePermission(String permName, String packageName,
@@ -1204,26 +993,12 @@ public class PermissionManagerService {
(SharedUserSetting) suSetting, allUserIds);
}
@Override
- public String[] getAppOpPermissionPackages(String permName) {
- return PermissionManagerService.this.getAppOpPermissionPackages(permName);
- }
- @Override
public int getPermissionFlags(String permName, String packageName, int callingUid,
int userId) {
return PermissionManagerService.this.getPermissionFlags(permName, packageName,
callingUid, userId);
}
@Override
- public int updatePermissions(String packageName,
- PackageParser.Package pkgInfo, int flags) {
- return PermissionManagerService.this.updatePermissions(packageName, pkgInfo, flags);
- }
- @Override
- public int updatePermissionTrees(String packageName,
- PackageParser.Package pkgInfo, int flags) {
- return PermissionManagerService.this.updatePermissionTrees(packageName, pkgInfo, flags);
- }
- @Override
public void updatePermissionFlags(String permName, String packageName, int flagMask,
int flagValues, int callingUid, int userId, PermissionCallback callback) {
PermissionManagerService.this.updatePermissionFlags(
@@ -1263,6 +1038,20 @@ public class PermissionManagerService {
return PermissionManagerService.this.getPermissionInfoByGroup(group, flags, callingUid);
}
@Override
+ public boolean isPermissionInstant(String permName) {
+ synchronized (PermissionManagerService.this.mLock) {
+ final BasePermission bp = mSettings.getPermissionLocked(permName);
+ return (bp != null && bp.isInstant());
+ }
+ }
+ @Override
+ public boolean isPermissionAppOp(String permName) {
+ synchronized (PermissionManagerService.this.mLock) {
+ final BasePermission bp = mSettings.getPermissionLocked(permName);
+ return (bp != null && bp.isAppOp());
+ }
+ }
+ @Override
public PermissionSettings getPermissionSettings() {
return mSettings;
}
diff --git a/com/android/server/pm/permission/PermissionSettings.java b/com/android/server/pm/permission/PermissionSettings.java
index 7d125c9e..7a2e5ecc 100644
--- a/com/android/server/pm/permission/PermissionSettings.java
+++ b/com/android/server/pm/permission/PermissionSettings.java
@@ -24,7 +24,6 @@ import android.util.ArraySet;
import android.util.Log;
import com.android.internal.R;
-import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.XmlUtils;
import com.android.server.pm.DumpState;
import com.android.server.pm.PackageManagerService;
@@ -36,7 +35,6 @@ import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
-import java.util.Set;
/**
* Permissions and other related data. This class is not meant for
@@ -51,25 +49,8 @@ public class PermissionSettings {
* All of the permissions known to the system. The mapping is from permission
* name to permission object.
*/
- @GuardedBy("mLock")
- final ArrayMap<String, BasePermission> mPermissions =
+ private final ArrayMap<String, BasePermission> mPermissions =
new ArrayMap<String, BasePermission>();
-
- /**
- * All permission trees known to the system. The mapping is from permission tree
- * name to permission object.
- */
- @GuardedBy("mLock")
- final ArrayMap<String, BasePermission> mPermissionTrees =
- new ArrayMap<String, BasePermission>();
-
- /**
- * Set of packages that request a particular app op. The mapping is from permission
- * name to package names.
- */
- @GuardedBy("mLock")
- final ArrayMap<String, ArraySet<String>> mAppOpPermissionPackages = new ArrayMap<>();
-
private final Object mLock;
PermissionSettings(@NonNull Context context, @NonNull Object lock) {
@@ -84,23 +65,15 @@ public class PermissionSettings {
}
}
- public void addAppOpPackage(String permName, String packageName) {
- ArraySet<String> pkgs = mAppOpPermissionPackages.get(permName);
- if (pkgs == null) {
- pkgs = new ArraySet<>();
- mAppOpPermissionPackages.put(permName, pkgs);
- }
- pkgs.add(packageName);
- }
-
/**
* Transfers ownership of permissions from one package to another.
*/
- public void transferPermissions(String origPackageName, String newPackageName) {
+ public void transferPermissions(String origPackageName, String newPackageName,
+ ArrayMap<String, BasePermission> permissionTrees) {
synchronized (mLock) {
for (int i=0; i<2; i++) {
ArrayMap<String, BasePermission> permissions =
- i == 0 ? mPermissionTrees : mPermissions;
+ i == 0 ? permissionTrees : mPermissions;
for (BasePermission bp : permissions.values()) {
bp.transfer(origPackageName, newPackageName);
}
@@ -121,26 +94,9 @@ public class PermissionSettings {
}
}
- public void readPermissionTrees(XmlPullParser parser)
- throws IOException, XmlPullParserException {
- synchronized (mLock) {
- readPermissions(mPermissionTrees, parser);
- }
- }
-
public void writePermissions(XmlSerializer serializer) throws IOException {
- synchronized (mLock) {
- for (BasePermission bp : mPermissions.values()) {
- bp.writeLPr(serializer);
- }
- }
- }
-
- public void writePermissionTrees(XmlSerializer serializer) throws IOException {
- synchronized (mLock) {
- for (BasePermission bp : mPermissionTrees.values()) {
- bp.writeLPr(serializer);
- }
+ for (BasePermission bp : mPermissions.values()) {
+ bp.writeLPr(serializer);
}
}
@@ -172,22 +128,6 @@ public class PermissionSettings {
printedSomething = bp.dumpPermissionsLPr(pw, packageName, permissionNames,
externalStorageEnforced, printedSomething, dumpState);
}
- if (packageName == null && permissionNames == null) {
- for (int iperm = 0; iperm<mAppOpPermissionPackages.size(); iperm++) {
- if (iperm == 0) {
- if (dumpState.onTitlePrinted())
- pw.println();
- pw.println("AppOp Permissions:");
- }
- pw.print(" AppOp Permission ");
- pw.print(mAppOpPermissionPackages.keyAt(iperm));
- pw.println(":");
- ArraySet<String> pkgs = mAppOpPermissionPackages.valueAt(iperm);
- for (int ipkg=0; ipkg<pkgs.size(); ipkg++) {
- pw.print(" "); pw.println(pkgs.valueAt(ipkg));
- }
- }
- }
}
}
@@ -195,58 +135,15 @@ public class PermissionSettings {
return mPermissions.get(permName);
}
- @Nullable BasePermission getPermissionTreeLocked(@NonNull String permName) {
- return mPermissionTrees.get(permName);
- }
-
void putPermissionLocked(@NonNull String permName, @NonNull BasePermission permission) {
mPermissions.put(permName, permission);
}
- void putPermissionTreeLocked(@NonNull String permName, @NonNull BasePermission permission) {
- mPermissionTrees.put(permName, permission);
- }
-
void removePermissionLocked(@NonNull String permName) {
mPermissions.remove(permName);
}
- void removePermissionTreeLocked(@NonNull String permName) {
- mPermissionTrees.remove(permName);
- }
-
- @NonNull Collection<BasePermission> getAllPermissionsLocked() {
+ Collection<BasePermission> getAllPermissionsLocked() {
return mPermissions.values();
}
-
- @NonNull Collection<BasePermission> getAllPermissionTreesLocked() {
- return mPermissionTrees.values();
- }
-
- /**
- * Returns the permission tree for the given permission.
- * @throws SecurityException If the calling UID is not allowed to add permissions to the
- * found permission tree.
- */
- @Nullable BasePermission enforcePermissionTree(@NonNull String permName, int callingUid) {
- synchronized (mLock) {
- return BasePermission.enforcePermissionTree(
- mPermissionTrees.values(), permName, callingUid);
- }
- }
-
- public boolean isPermissionInstant(String permName) {
- synchronized (mLock) {
- final BasePermission bp = mPermissions.get(permName);
- return (bp != null && bp.isInstant());
- }
- }
-
- boolean isPermissionAppOp(String permName) {
- synchronized (mLock) {
- final BasePermission bp = mPermissions.get(permName);
- return (bp != null && bp.isAppOp());
- }
- }
-
}
diff --git a/com/android/server/policy/GlobalActions.java b/com/android/server/policy/GlobalActions.java
index 7a2e630c..342ec4b7 100644
--- a/com/android/server/policy/GlobalActions.java
+++ b/com/android/server/policy/GlobalActions.java
@@ -58,9 +58,6 @@ class GlobalActions implements GlobalActionsListener {
public void showDialog(boolean keyguardShowing, boolean deviceProvisioned) {
if (DEBUG) Slog.d(TAG, "showDialog " + keyguardShowing + " " + deviceProvisioned);
- if (mStatusBarInternal.isGlobalActionsDisabled()) {
- return;
- }
mKeyguardShowing = keyguardShowing;
mDeviceProvisioned = deviceProvisioned;
mShowing = true;
diff --git a/com/android/server/policy/PhoneWindowManager.java b/com/android/server/policy/PhoneWindowManager.java
index ceb0ad07..db7817ec 100644
--- a/com/android/server/policy/PhoneWindowManager.java
+++ b/com/android/server/policy/PhoneWindowManager.java
@@ -18,14 +18,13 @@ package com.android.server.policy;
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
import static android.app.AppOpsManager.OP_TOAST_WINDOW;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Context.CONTEXT_RESTRICTED;
import static android.content.Context.DISPLAY_SERVICE;
@@ -553,6 +552,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
int mUserRotation = Surface.ROTATION_0;
+ boolean mAccelerometerDefault;
boolean mSupportAutoRotation;
int mAllowAllRotations = -1;
@@ -707,6 +707,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Intent mVrHeadsetHomeIntent;
boolean mSearchKeyShortcutPending;
boolean mConsumeSearchKeyUp;
+ boolean mAssistKeyLongPressed;
boolean mPendingMetaAction;
boolean mPendingCapsLockToggle;
int mMetaState;
@@ -837,8 +838,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private static final int MSG_DISPATCH_BACK_KEY_TO_AUTOFILL = 24;
private static final int MSG_SYSTEM_KEY_PRESS = 25;
private static final int MSG_HANDLE_ALL_APPS = 26;
- private static final int MSG_LAUNCH_ASSIST = 27;
- private static final int MSG_LAUNCH_ASSIST_LONG_PRESS = 28;
private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
@@ -880,16 +879,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case MSG_HIDE_BOOT_MESSAGE:
handleHideBootMessage();
break;
- case MSG_LAUNCH_ASSIST:
- final int deviceId = msg.arg1;
- final String hint = (String) msg.obj;
- launchAssistAction(hint, deviceId);
- break;
- case MSG_LAUNCH_ASSIST_LONG_PRESS:
- launchAssistLongPressAction();
- break;
case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK:
- launchVoiceAssistWithWakeLock();
+ launchVoiceAssistWithWakeLock(msg.arg1 != 0);
break;
case MSG_POWER_DELAYED_PRESS:
powerPress((Long)msg.obj, msg.arg1 != 0, msg.arg2);
@@ -919,7 +910,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
disposeInputConsumer((InputConsumer) msg.obj);
break;
case MSG_BACK_DELAYED_PRESS:
- backMultiPressAction(msg.arg1);
+ backMultiPressAction((Long) msg.obj, msg.arg1);
finishBackKeyPress();
break;
case MSG_ACCESSIBILITY_SHORTCUT:
@@ -1423,7 +1414,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
- private void backMultiPressAction(int count) {
+ private void backMultiPressAction(long eventTime, int count) {
if (count >= PANIC_PRESS_BACK_COUNT) {
switch (mPanicPressOnBackBehavior) {
case PANIC_PRESS_BACK_NOTHING:
@@ -1592,7 +1583,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
- private void sleepPress() {
+ private void sleepPress(long eventTime) {
if (mShortPressOnSleepBehavior == SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME) {
launchHomeFromHotKey(false /* awakenDreams */, true /*respectKeyguard*/);
}
@@ -2279,11 +2270,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
// http://developer.android.com/guide/practices/screens_support.html#range
- // For car, ignore the dp limitation. It's physically impossible to rotate the car's screen
- // so if the orientation is forced, we need to respect that no matter what.
- boolean isCar = mContext.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_AUTOMOTIVE);
- mForceDefaultOrientation = ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar) &&
+ mForceDefaultOrientation = longSizeDp >= 960 && shortSizeDp >= 720 &&
res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
// For debug purposes the next line turns this feature off with:
// $ adb shell setprop config.override_forced_orient true
@@ -2857,7 +2844,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean keyguardLocked = isKeyguardLocked();
boolean hideDockDivider = attrs.type == TYPE_DOCK_DIVIDER
- && !mWindowManagerInternal.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+ && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
return (keyguardLocked && !allowWhenLocked && win.getDisplayId() == DEFAULT_DISPLAY)
|| hideDockDivider;
}
@@ -3550,11 +3537,44 @@ public class PhoneWindowManager implements WindowManagerPolicy {
toggleKeyboardShortcutsMenu(event.getDeviceId());
}
} else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
- Slog.wtf(TAG, "KEYCODE_ASSIST should be handled in interceptKeyBeforeQueueing");
+ if (down) {
+ if (repeatCount == 0) {
+ mAssistKeyLongPressed = false;
+ } else if (repeatCount == 1) {
+ mAssistKeyLongPressed = true;
+ if (!keyguardOn) {
+ launchAssistLongPressAction();
+ }
+ }
+ } else {
+ if (mAssistKeyLongPressed) {
+ mAssistKeyLongPressed = false;
+ } else {
+ if (!keyguardOn) {
+ launchAssistAction(null, event.getDeviceId());
+ }
+ }
+ }
return -1;
} else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) {
- Slog.wtf(TAG, "KEYCODE_VOICE_ASSIST should be handled in interceptKeyBeforeQueueing");
- return -1;
+ if (!down) {
+ Intent voiceIntent;
+ if (!keyguardOn) {
+ voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
+ } else {
+ IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
+ ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
+ if (dic != null) {
+ try {
+ dic.exitIdle("voice-search");
+ } catch (RemoteException e) {
+ }
+ }
+ voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
+ voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
+ }
+ startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
+ }
} else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {
if (down && repeatCount == 0) {
mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
@@ -5425,10 +5445,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
&& attrs.type < FIRST_SYSTEM_WINDOW;
- final int windowingMode = win.getWindowingMode();
- final boolean inFullScreenOrSplitScreenSecondaryWindowingMode =
- windowingMode == WINDOWING_MODE_FULLSCREEN
- || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+ final int stackId = win.getStackId();
if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi) {
if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
mForceStatusBar = true;
@@ -5447,7 +5464,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// represent should be hidden or if we should hide the lockscreen. For attached app
// windows we defer the decision to the window it is attached to.
if (appWindow && attached == null) {
- if (attrs.isFullscreen() && inFullScreenOrSplitScreenSecondaryWindowingMode) {
+ if (attrs.isFullscreen() && StackId.normallyFullscreenWindows(stackId)) {
if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
mTopFullscreenOpaqueWindowState = win;
if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
@@ -5478,7 +5495,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Keep track of the window if it's dimming but not necessarily fullscreen.
if (mTopFullscreenOpaqueOrDimmingWindowState == null && affectsSystemUi
- && win.isDimming() && inFullScreenOrSplitScreenSecondaryWindowingMode) {
+ && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) {
mTopFullscreenOpaqueOrDimmingWindowState = win;
}
@@ -5486,7 +5503,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// separately, because both the "real fullscreen" opaque window and the one for the docked
// stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
if (mTopDockedOpaqueWindowState == null && affectsSystemUi && appWindow && attached == null
- && attrs.isFullscreen() && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+ && attrs.isFullscreen() && stackId == DOCKED_STACK_ID) {
mTopDockedOpaqueWindowState = win;
if (mTopDockedOpaqueOrDimmingWindowState == null) {
mTopDockedOpaqueOrDimmingWindowState = win;
@@ -5496,7 +5513,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Also keep track of any windows that are dimming but not necessarily fullscreen in the
// docked stack.
if (mTopDockedOpaqueOrDimmingWindowState == null && affectsSystemUi && win.isDimming()
- && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+ && stackId == DOCKED_STACK_ID) {
mTopDockedOpaqueOrDimmingWindowState = win;
}
@@ -5591,9 +5608,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
changes |= FINISH_LAYOUT_REDO_LAYOUT;
}
} else if (topIsFullscreen
- && !mWindowManagerInternal.isStackVisible(WINDOWING_MODE_FREEFORM)
- && !mWindowManagerInternal.isStackVisible(
- WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
+ && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID)
+ && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) {
if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
if (mStatusBarController.setBarShowingLw(false)) {
changes |= FINISH_LAYOUT_REDO_LAYOUT;
@@ -6175,7 +6191,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
useHapticFeedback = false; // suppress feedback if already non-interactive
}
if (down) {
- sleepPress();
+ sleepPress(event.getEventTime());
} else {
sleepRelease(event.getEventTime());
}
@@ -6246,30 +6262,18 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
break;
}
- case KeyEvent.KEYCODE_ASSIST: {
- final boolean longPressed = event.getRepeatCount() > 0;
- if (down && longPressed) {
- Message msg = mHandler.obtainMessage(MSG_LAUNCH_ASSIST_LONG_PRESS);
- msg.setAsynchronous(true);
- msg.sendToTarget();
- }
- if (!down && !longPressed) {
- Message msg = mHandler.obtainMessage(MSG_LAUNCH_ASSIST, event.getDeviceId(),
- 0 /* unused */, null /* hint */);
- msg.setAsynchronous(true);
- msg.sendToTarget();
- }
- result &= ~ACTION_PASS_TO_USER;
- break;
- }
case KeyEvent.KEYCODE_VOICE_ASSIST: {
- if (!down) {
+ // Only do this if we would otherwise not pass it to the user. In that case,
+ // interceptKeyBeforeDispatching would apply a similar but different policy in
+ // order to invoke voice assist actions. Note that we need to make a copy of the
+ // key event here because the original key event will be recycled when we return.
+ if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
mBroadcastWakeLock.acquire();
- Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK);
+ Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
+ keyguardActive ? 1 : 0, 0);
msg.setAsynchronous(true);
msg.sendToTarget();
}
- result &= ~ACTION_PASS_TO_USER;
break;
}
case KeyEvent.KEYCODE_WINDOW: {
@@ -6538,22 +6542,18 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
- void launchVoiceAssistWithWakeLock() {
- final Intent voiceIntent;
- if (!keyguardOn()) {
- voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
- } else {
- IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
- ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
- if (dic != null) {
- try {
- dic.exitIdle("voice-search");
- } catch (RemoteException e) {
- }
+ void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
+ IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
+ ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
+ if (dic != null) {
+ try {
+ dic.exitIdle("voice-search");
+ } catch (RemoteException e) {
}
- voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
- voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
}
+ Intent voiceIntent =
+ new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
+ voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
mBroadcastWakeLock.release();
}
@@ -8009,10 +8009,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
- final boolean dockedStackVisible =
- mWindowManagerInternal.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+ final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
final boolean freeformStackVisible =
- mWindowManagerInternal.isStackVisible(WINDOWING_MODE_FREEFORM);
+ mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);
final boolean resizing = mWindowManagerInternal.isDockedDividerResizing();
// We need to force system bars when the docked stack is visible, when the freeform stack
diff --git a/com/android/server/stats/StatsCompanionService.java b/com/android/server/stats/StatsCompanionService.java
index ca3dd058..f1fb3e7b 100644
--- a/com/android/server/stats/StatsCompanionService.java
+++ b/com/android/server/stats/StatsCompanionService.java
@@ -20,25 +20,15 @@ import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
-import android.content.IntentFilter;
import android.os.Binder;
-import android.os.Bundle;
import android.os.IBinder;
import android.os.IStatsCompanionService;
import android.os.IStatsManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.UserHandle;
-import android.os.UserManager;
import android.util.Slog;
-import java.util.ArrayList;
-import java.util.List;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.KernelWakelockReader;
import com.android.internal.os.KernelWakelockStats;
@@ -63,8 +53,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
private final PendingIntent mAnomalyAlarmIntent;
private final PendingIntent mPollingAlarmIntent;
- private final BroadcastReceiver mAppUpdateReceiver;
- private final BroadcastReceiver mUserUpdateReceiver;
public StatsCompanionService(Context context) {
super();
@@ -75,113 +63,8 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
new Intent(mContext, AnomalyAlarmReceiver.class), 0);
mPollingAlarmIntent = PendingIntent.getBroadcast(mContext, 0,
new Intent(mContext, PollingAlarmReceiver.class), 0);
- mAppUpdateReceiver = new AppUpdateReceiver();
- mUserUpdateReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- synchronized (sStatsdLock) {
- sStatsd = fetchStatsdService();
- if (sStatsd == null) {
- Slog.w(TAG, "Could not access statsd");
- return;
- }
- try {
- // Pull the latest state of UID->app name, version mapping.
- // Needed since the new user basically has a version of every app.
- informAllUidsLocked(context);
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to inform statsd that statscompanion is ready", e);
- forgetEverything();
- }
- }
- }
- };
- Slog.w(TAG, "Registered receiver for ACTION_PACKAGE_REPLACE AND ADDED.");
}
- private final static int[] toIntArray(List<Integer> list){
- int[] ret = new int[list.size()];
- for(int i = 0;i < ret.length;i++) {
- ret[i] = list.get(i);
- }
- return ret;
- }
-
- // Assumes that sStatsdLock is held.
- private final void informAllUidsLocked(Context context) throws RemoteException {
- UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
- PackageManager pm = context.getPackageManager();
- final List<UserInfo> users = um.getUsers(true);
- if (DEBUG) {
- Slog.w(TAG, "Iterating over "+users.size() + " profiles.");
- }
-
- List<Integer> uids = new ArrayList();
- List<Integer> versions = new ArrayList();
- List<String> apps = new ArrayList();
-
- // Add in all the apps for every user/profile.
- for (UserInfo profile : users) {
- List<PackageInfo> pi = pm.getInstalledPackagesAsUser(0, profile.id);
- for (int j = 0; j < pi.size(); j++) {
- if (pi.get(j).applicationInfo != null) {
- uids.add(pi.get(j).applicationInfo.uid);
- versions.add(pi.get(j).versionCode);
- apps.add(pi.get(j).packageName);
- }
- }
- }
- sStatsd.informAllUidData(toIntArray(uids), toIntArray(versions), apps.toArray(new
- String[apps.size()]));
- if (DEBUG) {
- Slog.w(TAG, "Sent data for "+uids.size() +" apps");
- }
- }
-
- public final static class AppUpdateReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- Slog.i(TAG, "StatsCompanionService noticed an app was updated.");
- /**
- * App updates actually consist of REMOVE, ADD, and then REPLACE broadcasts. To avoid
- * waste, we ignore the REMOVE and ADD broadcasts that contain the replacing flag.
- */
- if (!intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED) &&
- intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
- return; // Keep only replacing or normal add and remove.
- }
- synchronized (sStatsdLock) {
- if (sStatsd == null) {
- Slog.w(TAG, "Could not access statsd to inform it of anomaly alarm firing");
- return;
- }
- try {
- if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) {
- Bundle b = intent.getExtras();
- int uid = b.getInt(Intent.EXTRA_UID);
- boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
- if (!replacing) {
- // Don't bother sending an update if we're right about to get another
- // intent for the new version that's added.
- PackageManager pm = context.getPackageManager();
- String app = intent.getData().getSchemeSpecificPart();
- sStatsd.informOnePackageRemoved(app, uid);
- }
- } else {
- PackageManager pm = context.getPackageManager();
- Bundle b = intent.getExtras();
- int uid = b.getInt(Intent.EXTRA_UID);
- String app = intent.getData().getSchemeSpecificPart();
- PackageInfo pi = pm.getPackageInfo(app, PackageManager.MATCH_ANY_USER);
- sStatsd.informOnePackage(app, uid, pi.versionCode);
- }
- } catch (Exception e) {
- Slog.w(TAG, "Failed to inform statsd of an app update", e);
- }
- }
- }
- };
-
public final static class AnomalyAlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
@@ -392,23 +275,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
Slog.e(TAG, "linkToDeath(StatsdDeathRecipient) failed", e);
forgetEverything();
}
- // Setup broadcast receiver for updates
- IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REPLACED);
- filter.addAction(Intent.ACTION_PACKAGE_ADDED);
- filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- filter.addDataScheme("package");
- mContext.registerReceiverAsUser(mAppUpdateReceiver, UserHandle.ALL, filter, null,
- null);
-
- // Setup receiver for user initialize (which happens once for a new user) and
- // if a user is removed.
- filter = new IntentFilter(Intent.ACTION_USER_INITIALIZE);
- filter.addAction(Intent.ACTION_USER_REMOVED);
- mContext.registerReceiverAsUser(mUserUpdateReceiver, UserHandle.ALL,
- filter, null, null);
-
- // Pull the latest state of UID->app name, version mapping when statsd starts.
- informAllUidsLocked(mContext);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to inform statsd that statscompanion is ready", e);
forgetEverything();
@@ -427,8 +293,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
private void forgetEverything() {
synchronized (sStatsdLock) {
sStatsd = null;
- mContext.unregisterReceiver(mAppUpdateReceiver);
- mContext.unregisterReceiver(mUserUpdateReceiver);
cancelAnomalyAlarm();
cancelPollingAlarms();
}
diff --git a/com/android/server/statusbar/StatusBarManagerInternal.java b/com/android/server/statusbar/StatusBarManagerInternal.java
index b07fe98d..08846784 100644
--- a/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -77,7 +77,6 @@ public interface StatusBarManagerInternal {
void setCurrentUser(int newUserId);
- boolean isGlobalActionsDisabled();
void setGlobalActionsListener(GlobalActionsListener listener);
void showGlobalActions();
diff --git a/com/android/server/statusbar/StatusBarManagerService.java b/com/android/server/statusbar/StatusBarManagerService.java
index c78a3406..bdfbe481 100644
--- a/com/android/server/statusbar/StatusBarManagerService.java
+++ b/com/android/server/statusbar/StatusBarManagerService.java
@@ -16,8 +16,6 @@
package com.android.server.statusbar;
-import static android.app.StatusBarManager.DISABLE2_GLOBAL_ACTIONS;
-
import android.app.ActivityThread;
import android.app.StatusBarManager;
import android.content.ComponentName;
@@ -365,11 +363,6 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
}
@Override
- public boolean isGlobalActionsDisabled() {
- return (mDisabled2 & DISABLE2_GLOBAL_ACTIONS) != 0;
- }
-
- @Override
public void setGlobalActionsListener(GlobalActionsListener listener) {
mGlobalActionListener = listener;
mGlobalActionListener.onStatusBarConnectedChanged(mBar != null);
diff --git a/com/android/server/tv/TvInputHardwareManager.java b/com/android/server/tv/TvInputHardwareManager.java
index c1607e94..6117da7b 100644
--- a/com/android/server/tv/TvInputHardwareManager.java
+++ b/com/android/server/tv/TvInputHardwareManager.java
@@ -1022,6 +1022,20 @@ class TvInputHardwareManager implements TvInputHal.Callback {
}
}
+ @Override
+ public boolean dispatchKeyEventToHdmi(KeyEvent event) throws RemoteException {
+ synchronized (mImplLock) {
+ if (mReleased) {
+ throw new IllegalStateException("Device already released.");
+ }
+ }
+ if (mInfo.getType() != TvInputHardwareInfo.TV_INPUT_TYPE_HDMI) {
+ return false;
+ }
+ // TODO(hdmi): mHdmiClient.sendKeyEvent(event);
+ return false;
+ }
+
private boolean startCapture(Surface surface, TvStreamConfig config) {
synchronized (mImplLock) {
if (mReleased) {
diff --git a/com/android/server/usb/UsbAlsaManager.java b/com/android/server/usb/UsbAlsaManager.java
index d359b704..acc27bee 100644
--- a/com/android/server/usb/UsbAlsaManager.java
+++ b/com/android/server/usb/UsbAlsaManager.java
@@ -132,9 +132,7 @@ public final class UsbAlsaManager {
mHasMidiFeature = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI);
// initial scan
- if (mCardsParser.scan() != AlsaCardsParser.SCANSTATUS_SUCCESS) {
- Slog.e(TAG, "Error scanning ASLA cards file.");
- }
+ mCardsParser.scan();
}
public void systemReady() {
@@ -316,7 +314,7 @@ public final class UsbAlsaManager {
return null;
}
- if (mDevicesParser.scan() != AlsaDevicesParser.SCANSTATUS_SUCCESS) {
+ if (!mDevicesParser.scan()) {
Slog.e(TAG, "Error parsing ALSA devices file.");
return null;
}
@@ -532,9 +530,6 @@ public final class UsbAlsaManager {
//
// called by UsbService.dump
public void dump(IndentingPrintWriter pw) {
- pw.println("Parsers Scan Status:");
- pw.println(" Cards Parser: " + mCardsParser.getScanStatus());
- pw.println(" Devices Parser: " + mDevicesParser.getScanStatus());
pw.println("USB Audio Devices:");
for (UsbDevice device : mAudioDevices.keySet()) {
pw.println(" " + device.getDeviceName() + ": " + mAudioDevices.get(device));
diff --git a/com/android/server/usb/UsbHostManager.java b/com/android/server/usb/UsbHostManager.java
index 095fdc63..c657a1b4 100644
--- a/com/android/server/usb/UsbHostManager.java
+++ b/com/android/server/usb/UsbHostManager.java
@@ -376,8 +376,6 @@ public class UsbHostManager {
}
}
}
-
- mUsbAlsaManager.dump(pw);
}
private native void monitorUsbHostBus();
diff --git a/com/android/server/wifi/SelfRecovery.java b/com/android/server/wifi/SelfRecovery.java
index e39e0d5b..21a3e0ac 100644
--- a/com/android/server/wifi/SelfRecovery.java
+++ b/com/android/server/wifi/SelfRecovery.java
@@ -72,7 +72,7 @@ public class SelfRecovery {
Log.e(TAG, "Invalid trigger reason. Ignoring...");
return;
}
- Log.e(TAG, "Triggering recovery for reason: " + REASON_STRINGS[reason]);
+ Log.wtf(TAG, "Triggering recovery for reason: " + REASON_STRINGS[reason]);
if (reason == REASON_WIFICOND_CRASH || reason == REASON_HAL_CRASH) {
trimPastRestartTimes();
// Ensure there haven't been too many restarts within MAX_RESTARTS_TIME_WINDOW
diff --git a/com/android/server/wifi/WifiNative.java b/com/android/server/wifi/WifiNative.java
index 35dec2e7..0b1719db 100644
--- a/com/android/server/wifi/WifiNative.java
+++ b/com/android/server/wifi/WifiNative.java
@@ -16,7 +16,6 @@
package com.android.server.wifi;
-import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.apf.ApfCapabilities;
import android.net.wifi.IApInterface;
@@ -110,12 +109,12 @@ public class WifiNative {
* @return Pair of <Integer, IClientInterface> to indicate the status and the associated wificond
* client interface binder handler (will be null on failure).
*/
- public Pair<Integer, IClientInterface> setupForClientMode(@NonNull String ifaceName) {
+ public Pair<Integer, IClientInterface> setupForClientMode() {
if (!startHalIfNecessary(true)) {
Log.e(mTAG, "Failed to start HAL for client mode");
return Pair.create(SETUP_FAILURE_HAL, null);
}
- IClientInterface iClientInterface = mWificondControl.setupDriverForClientMode(ifaceName);
+ IClientInterface iClientInterface = mWificondControl.setupDriverForClientMode();
if (iClientInterface == null) {
return Pair.create(SETUP_FAILURE_WIFICOND, null);
}
@@ -131,12 +130,12 @@ public class WifiNative {
* @return Pair of <Integer, IApInterface> to indicate the status and the associated wificond
* AP interface binder handler (will be null on failure).
*/
- public Pair<Integer, IApInterface> setupForSoftApMode(@NonNull String ifaceName) {
+ public Pair<Integer, IApInterface> setupForSoftApMode() {
if (!startHalIfNecessary(false)) {
Log.e(mTAG, "Failed to start HAL for AP mode");
return Pair.create(SETUP_FAILURE_HAL, null);
}
- IApInterface iApInterface = mWificondControl.setupDriverForSoftApMode(ifaceName);
+ IApInterface iApInterface = mWificondControl.setupDriverForSoftApMode();
if (iApInterface == null) {
return Pair.create(SETUP_FAILURE_WIFICOND, null);
}
diff --git a/com/android/server/wifi/WifiStateMachine.java b/com/android/server/wifi/WifiStateMachine.java
index 0c2cc32f..1f6cada7 100644
--- a/com/android/server/wifi/WifiStateMachine.java
+++ b/com/android/server/wifi/WifiStateMachine.java
@@ -4165,7 +4165,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
switch (message.what) {
case CMD_START_SUPPLICANT:
Pair<Integer, IClientInterface> statusAndInterface =
- mWifiNative.setupForClientMode(mInterfaceName);
+ mWifiNative.setupForClientMode();
if (statusAndInterface.first == WifiNative.SETUP_SUCCESS) {
mClientInterface = statusAndInterface.second;
} else {
@@ -6954,8 +6954,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
mMode = config.getTargetMode();
IApInterface apInterface = null;
- Pair<Integer, IApInterface> statusAndInterface =
- mWifiNative.setupForSoftApMode(mInterfaceName);
+ Pair<Integer, IApInterface> statusAndInterface = mWifiNative.setupForSoftApMode();
if (statusAndInterface.first == WifiNative.SETUP_SUCCESS) {
apInterface = statusAndInterface.second;
} else {
diff --git a/com/android/server/wifi/WifiStateMachinePrime.java b/com/android/server/wifi/WifiStateMachinePrime.java
index cd1948f1..20068849 100644
--- a/com/android/server/wifi/WifiStateMachinePrime.java
+++ b/com/android/server/wifi/WifiStateMachinePrime.java
@@ -290,8 +290,7 @@ public class WifiStateMachinePrime {
}
try {
- mApInterface = mWificond.createApInterface(
- mWifiInjector.getWifiNative().getInterfaceName());
+ mApInterface = mWificond.createApInterface();
} catch (RemoteException e1) { }
if (mApInterface == null) {
diff --git a/com/android/server/wifi/WificondControl.java b/com/android/server/wifi/WificondControl.java
index df4e785b..b6104a8c 100644
--- a/com/android/server/wifi/WificondControl.java
+++ b/com/android/server/wifi/WificondControl.java
@@ -16,7 +16,6 @@
package com.android.server.wifi;
-import android.annotation.NonNull;
import android.net.wifi.IApInterface;
import android.net.wifi.IClientInterface;
import android.net.wifi.IPnoScanEvent;
@@ -134,7 +133,7 @@ public class WificondControl {
* @return An IClientInterface as wificond client interface binder handler.
* Returns null on failure.
*/
- public IClientInterface setupDriverForClientMode(@NonNull String ifaceName) {
+ public IClientInterface setupDriverForClientMode() {
Log.d(TAG, "Setting up driver for client mode");
mWificond = mWifiInjector.makeWificond();
if (mWificond == null) {
@@ -144,7 +143,7 @@ public class WificondControl {
IClientInterface clientInterface = null;
try {
- clientInterface = mWificond.createClientInterface(ifaceName);
+ clientInterface = mWificond.createClientInterface();
} catch (RemoteException e1) {
Log.e(TAG, "Failed to get IClientInterface due to remote exception");
return null;
@@ -182,7 +181,7 @@ public class WificondControl {
* @return An IApInterface as wificond Ap interface binder handler.
* Returns null on failure.
*/
- public IApInterface setupDriverForSoftApMode(@NonNull String ifaceName) {
+ public IApInterface setupDriverForSoftApMode() {
Log.d(TAG, "Setting up driver for soft ap mode");
mWificond = mWifiInjector.makeWificond();
if (mWificond == null) {
@@ -192,7 +191,7 @@ public class WificondControl {
IApInterface apInterface = null;
try {
- apInterface = mWificond.createApInterface(ifaceName);
+ apInterface = mWificond.createApInterface();
} catch (RemoteException e1) {
Log.e(TAG, "Failed to get IApInterface due to remote exception");
return null;
diff --git a/com/android/server/wifi/scanner/WificondScannerImpl.java b/com/android/server/wifi/scanner/WificondScannerImpl.java
index 10fc8e3e..fb878e67 100644
--- a/com/android/server/wifi/scanner/WificondScannerImpl.java
+++ b/com/android/server/wifi/scanner/WificondScannerImpl.java
@@ -167,12 +167,12 @@ public class WificondScannerImpl extends WifiScannerImpl implements Handler.Call
+ ",eventHandler=" + eventHandler);
return false;
}
+ if (mPendingSingleScanSettings != null
+ || (mLastScanSettings != null && mLastScanSettings.singleScanActive)) {
+ Log.w(TAG, "A single scan is already running");
+ return false;
+ }
synchronized (mSettingsLock) {
- if (mPendingSingleScanSettings != null
- || (mLastScanSettings != null && mLastScanSettings.singleScanActive)) {
- Log.w(TAG, "A single scan is already running");
- return false;
- }
mPendingSingleScanSettings = settings;
mPendingSingleScanEventHandler = eventHandler;
processPendingScans();
@@ -518,10 +518,8 @@ public class WificondScannerImpl extends WifiScannerImpl implements Handler.Call
}
private boolean isHwPnoScanRequired() {
- synchronized (mSettingsLock) {
- if (mPnoSettings == null) return false;
- return isHwPnoScanRequired(mPnoSettings.isConnected);
- }
+ if (mPnoSettings == null) return false;
+ return isHwPnoScanRequired(mPnoSettings.isConnected);
}
@Override
diff --git a/com/android/server/wifi/util/InformationElementUtil.java b/com/android/server/wifi/util/InformationElementUtil.java
index 14912b5f..c8f9ca34 100644
--- a/com/android/server/wifi/util/InformationElementUtil.java
+++ b/com/android/server/wifi/util/InformationElementUtil.java
@@ -247,10 +247,6 @@ public class InformationElementUtil {
"Bad Interworking element length: " + ie.bytes.length);
}
- if (ie.bytes.length == 3 || ie.bytes.length == 9) {
- int venueInfo = (int) ByteBufferReader.readInteger(data, ByteOrder.BIG_ENDIAN, 2);
- }
-
if (ie.bytes.length == 7 || ie.bytes.length == 9) {
hessid = ByteBufferReader.readInteger(data, ByteOrder.BIG_ENDIAN, 6);
}
diff --git a/com/android/server/wm/AppWindowToken.java b/com/android/server/wm/AppWindowToken.java
index 5d034935..a1eeff84 100644
--- a/com/android/server/wm/AppWindowToken.java
+++ b/com/android/server/wm/AppWindowToken.java
@@ -823,7 +823,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
// For freeform windows, we can't freeze the bounds at the moment because this would make
// the resizing unresponsive.
- if (task == null || task.inFreeformWindowingMode()) {
+ if (task == null || task.inFreeformWorkspace()) {
return false;
}
@@ -1310,7 +1310,8 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
// Notify the pinned stack upon all windows drawn. If there was an animation in
// progress then this signal will resume that animation.
- final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
+ final TaskStack pinnedStack =
+ mDisplayContent.getStack(WINDOWING_MODE_PINNED);
if (pinnedStack != null) {
pinnedStack.onAllWindowsDrawn();
}
diff --git a/com/android/server/wm/BlackFrame.java b/com/android/server/wm/BlackFrame.java
index d206554c..5c29a0aa 100644
--- a/com/android/server/wm/BlackFrame.java
+++ b/com/android/server/wm/BlackFrame.java
@@ -18,6 +18,7 @@ package com.android.server.wm;
import static android.graphics.PixelFormat.OPAQUE;
import static android.view.SurfaceControl.FX_SURFACE_DIM;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -50,8 +51,14 @@ public class BlackFrame {
int w = r-l;
int h = b-t;
- surface = new SurfaceControl(session, "BlackSurface",
- w, h, OPAQUE, FX_SURFACE_DIM | SurfaceControl.HIDDEN);
+ if (DEBUG_SURFACE_TRACE) {
+ surface = new WindowSurfaceController.SurfaceTrace(session, "BlackSurface("
+ + l + ", " + t + ")",
+ w, h, OPAQUE, FX_SURFACE_DIM | SurfaceControl.HIDDEN);
+ } else {
+ surface = new SurfaceControl(session, "BlackSurface",
+ w, h, OPAQUE, FX_SURFACE_DIM | SurfaceControl.HIDDEN);
+ }
surface.setAlpha(1);
surface.setLayerStack(layerStack);
diff --git a/com/android/server/wm/CircularDisplayMask.java b/com/android/server/wm/CircularDisplayMask.java
index 85f468b5..ae415413 100644
--- a/com/android/server/wm/CircularDisplayMask.java
+++ b/com/android/server/wm/CircularDisplayMask.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -66,9 +67,14 @@ class CircularDisplayMask {
SurfaceControl ctrl = null;
try {
- ctrl = new SurfaceControl(session, "CircularDisplayMask", mScreenSize.x,
- mScreenSize.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
-
+ if (DEBUG_SURFACE_TRACE) {
+ ctrl = new WindowSurfaceController.SurfaceTrace(session, "CircularDisplayMask",
+ mScreenSize.x, mScreenSize.y, PixelFormat.TRANSLUCENT,
+ SurfaceControl.HIDDEN);
+ } else {
+ ctrl = new SurfaceControl(session, "CircularDisplayMask", mScreenSize.x,
+ mScreenSize.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+ }
ctrl.setLayerStack(display.getLayerStack());
ctrl.setLayer(zOrder);
ctrl.setPosition(0, 0);
diff --git a/com/android/server/wm/ConfigurationContainer.java b/com/android/server/wm/ConfigurationContainer.java
index 5bfea989..9e028d38 100644
--- a/com/android/server/wm/ConfigurationContainer.java
+++ b/com/android/server/wm/ConfigurationContainer.java
@@ -21,9 +21,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
@@ -184,11 +182,6 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
return windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
}
- public boolean inSplitScreenPrimaryWindowingMode() {
- return mFullConfiguration.windowConfiguration.getWindowingMode()
- == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
- }
-
/**
* Returns true if this container can be put in either
* {@link WindowConfiguration#WINDOWING_MODE_SPLIT_SCREEN_PRIMARY} or
@@ -199,14 +192,6 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
return mFullConfiguration.windowConfiguration.supportSplitScreenWindowingMode();
}
- public boolean inPinnedWindowingMode() {
- return mFullConfiguration.windowConfiguration.getWindowingMode() == WINDOWING_MODE_PINNED;
- }
-
- public boolean inFreeformWindowingMode() {
- return mFullConfiguration.windowConfiguration.getWindowingMode() == WINDOWING_MODE_FREEFORM;
- }
-
/** Returns the activity type associated with the the configuration container. */
/*@WindowConfiguration.ActivityType*/
public int getActivityType() {
diff --git a/com/android/server/wm/DimLayer.java b/com/android/server/wm/DimLayer.java
index 48181d30..708973d5 100644
--- a/com/android/server/wm/DimLayer.java
+++ b/com/android/server/wm/DimLayer.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DIM_LAYER;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -104,10 +105,16 @@ public class DimLayer {
private void constructSurface(WindowManagerService service) {
service.openSurfaceTransaction();
try {
- mDimSurface = new SurfaceControl(service.mFxSession, mName,
+ if (DEBUG_SURFACE_TRACE) {
+ mDimSurface = new WindowSurfaceController.SurfaceTrace(service.mFxSession,
+ "DimSurface",
16, 16, PixelFormat.OPAQUE,
SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
-
+ } else {
+ mDimSurface = new SurfaceControl(service.mFxSession, mName,
+ 16, 16, PixelFormat.OPAQUE,
+ SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
+ }
if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG,
" DIM " + mDimSurface + ": CREATE");
mDimSurface.setLayerStack(mDisplayId);
diff --git a/com/android/server/wm/DisplayContent.java b/com/android/server/wm/DisplayContent.java
index 03fdc968..0e68a8f6 100644
--- a/com/android/server/wm/DisplayContent.java
+++ b/com/android/server/wm/DisplayContent.java
@@ -16,9 +16,10 @@
package com.android.server.wm;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
@@ -117,7 +118,7 @@ import static com.android.server.wm.proto.DisplayProto.WINDOW_CONTAINER;
import android.annotation.CallSuper;
import android.annotation.NonNull;
-import android.content.pm.PackageManager;
+import android.app.ActivityManager.StackId;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
@@ -296,6 +297,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
/** Window tokens that are in the process of exiting, but still on screen for animations. */
final ArrayList<WindowToken> mExitingTokens = new ArrayList<>();
+ /** A special TaskStack with id==HOME_STACK_ID that moves to the bottom whenever any TaskStack
+ * (except a future lockscreen TaskStack) moves to the top. */
+ private TaskStack mHomeStack = null;
+
/** Detect user tapping outside of current focused task bounds .*/
TaskTapPointerEventListener mTapDetector;
@@ -974,8 +979,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
// In the presence of the PINNED stack or System Alert
- // windows we unfortunately can not seamlessly rotate.
- if (hasPinnedStack()) {
+ // windows we unforuntately can not seamlessly rotate.
+ if (getStackById(PINNED_STACK_ID) != null) {
mayRotateSeamlessly = false;
}
for (int i = 0; i < mService.mSessions.size(); i++) {
@@ -1446,31 +1451,20 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
TaskStack getHomeStack() {
- return mTaskStackContainers.getHomeStack();
- }
-
- /**
- * @return The primary split-screen stack, but only if it is visible, and {@code null} otherwise.
- */
- TaskStack getSplitScreenPrimaryStackStack() {
- TaskStack stack = mTaskStackContainers.getSplitScreenPrimaryStackStack();
- return (stack != null && stack.isVisible()) ? stack : null;
- }
-
- /**
- * Like {@link #getSplitScreenPrimaryStackStack}, but also returns the stack if it's currently
- * not visible.
- */
- TaskStack getSplitScreenPrimaryStackStackIgnoringVisibility() {
- return mTaskStackContainers.getSplitScreenPrimaryStackStack();
- }
-
- TaskStack getPinnedStack() {
- return mTaskStackContainers.getPinnedStack();
+ if (mHomeStack == null && mDisplayId == DEFAULT_DISPLAY) {
+ Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this);
+ }
+ return mHomeStack;
}
- private boolean hasPinnedStack() {
- return mTaskStackContainers.getPinnedStack() != null;
+ TaskStack getStackById(int stackId) {
+ for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+ final TaskStack stack = mTaskStackContainers.get(i);
+ if (stack.mStackId == stackId) {
+ return stack;
+ }
+ }
+ return null;
}
/**
@@ -1486,16 +1480,29 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
* activity type. Null is no compatible stack on the display.
*/
TaskStack getStack(int windowingMode, int activityType) {
- return mTaskStackContainers.getStack(windowingMode, activityType);
+ for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+ final TaskStack stack = mTaskStackContainers.get(i);
+ if (stack.isCompatible(windowingMode, activityType)) {
+ return stack;
+ }
+ }
+ return null;
}
@VisibleForTesting
- TaskStack getTopStack() {
- return mTaskStackContainers.getTopStack();
+ int getStackCount() {
+ return mTaskStackContainers.size();
}
- void onStackWindowingModeChanged(TaskStack stack) {
- mTaskStackContainers.onStackWindowingModeChanged(stack);
+ @VisibleForTesting
+ int getStackPosition(int windowingMode, int activityType) {
+ for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+ final TaskStack stack = mTaskStackContainers.get(i);
+ if (stack.isCompatible(windowingMode, activityType)) {
+ return i;
+ }
+ }
+ return -1;
}
@Override
@@ -1516,8 +1523,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
* bounds were updated.
*/
void updateStackBoundsAfterConfigChange(@NonNull List<Integer> changedStackList) {
- for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
- final TaskStack stack = mTaskStackContainers.getChildAt(i);
+ for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+ final TaskStack stack = mTaskStackContainers.get(i);
if (stack.updateBoundsAfterConfigChange()) {
changedStackList.add(stack.mStackId);
}
@@ -1526,7 +1533,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// If there was no pinned stack, we still need to notify the controller of the display info
// update as a result of the config change. We do this here to consolidate the flow between
// changes when there is and is not a stack.
- if (!hasPinnedStack()) {
+ if (getStack(WINDOWING_MODE_PINNED) == null) {
mPinnedStackControllerLocked.onDisplayInfoChanged();
}
}
@@ -1625,8 +1632,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mDisplay.getDisplayInfo(mDisplayInfo);
mDisplay.getMetrics(mDisplayMetrics);
- for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
- mTaskStackContainers.getChildAt(i).updateDisplayInfo(null);
+ for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+ mTaskStackContainers.get(i).updateDisplayInfo(null);
}
}
@@ -1747,14 +1754,26 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
out.set(mContentRect);
}
- TaskStack createStack(int stackId, boolean onTop, StackWindowController controller) {
+ TaskStack addStackToDisplay(int stackId, boolean onTop, StackWindowController controller) {
if (DEBUG_STACK) Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId="
+ mDisplayId);
- final TaskStack stack = new TaskStack(mService, stackId, controller);
- mTaskStackContainers.addStackToDisplay(stack, onTop);
+ TaskStack stack = getStackById(stackId);
+ if (stack != null) {
+ // It's already attached to the display...clear mDeferRemoval, set controller, and move
+ // stack to appropriate z-order on display as needed.
+ stack.mDeferRemoval = false;
+ stack.setController(controller);
+ // We're not moving the display to front when we're adding stacks, only when
+ // requested to change the position of stack explicitly.
+ mTaskStackContainers.positionChildAt(onTop ? POSITION_TOP : POSITION_BOTTOM, stack,
+ false /* includingParents */);
+ } else {
+ stack = new TaskStack(mService, stackId, controller);
+ mTaskStackContainers.addStackToDisplay(stack, onTop);
+ }
- if (stack.inSplitScreenPrimaryWindowingMode()) {
+ if (stackId == DOCKED_STACK_ID) {
mDividerControllerLocked.notifyDockedStackExistsChanged(true);
}
return stack;
@@ -1771,7 +1790,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
+ " to its current displayId=" + mDisplayId);
}
- prevDc.mTaskStackContainers.removeChild(stack);
+ prevDc.mTaskStackContainers.removeStackFromDisplay(stack);
mTaskStackContainers.addStackToDisplay(stack, onTop);
}
@@ -1805,8 +1824,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
int taskIdFromPoint(int x, int y) {
- for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
+ for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
+ final TaskStack stack = mTaskStackContainers.get(stackNdx);
final int taskId = stack.taskIdFromPoint(x, y);
if (taskId != -1) {
return taskId;
@@ -1822,8 +1841,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
Task findTaskForResizePoint(int x, int y) {
final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
mTmpTaskForResizePointSearchResult.reset();
- for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
+ for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
+ final TaskStack stack = mTaskStackContainers.get(stackNdx);
if (!stack.getWindowConfiguration().canResizeTask()) {
return null;
}
@@ -1845,8 +1864,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mTouchExcludeRegion.set(mBaseDisplayRect);
final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
mTmpRect2.setEmpty();
- for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
+ for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
+ final TaskStack stack = mTaskStackContainers.get(stackNdx);
stack.setTouchExcludeRegion(
focusedTask, delta, mTouchExcludeRegion, mContentRect, mTmpRect2);
}
@@ -1877,7 +1896,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
}
// TODO(multi-display): Support docked stacks on secondary displays.
- if (mDisplayId == DEFAULT_DISPLAY && getSplitScreenPrimaryStackStack() != null) {
+ if (mDisplayId == DEFAULT_DISPLAY && getDockedStackLocked() != null) {
mDividerControllerLocked.getTouchRegion(mTmpRect);
mTmpRegion.set(mTmpRect);
mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
@@ -1894,8 +1913,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
private void resetAnimationBackgroundAnimator() {
- for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- mTaskStackContainers.getChildAt(stackNdx).resetAnimationBackgroundAnimator();
+ for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
+ mTaskStackContainers.get(stackNdx).resetAnimationBackgroundAnimator();
}
}
@@ -1966,8 +1985,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
float dividerAnimationTarget) {
boolean updated = false;
- for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
- final TaskStack stack = mTaskStackContainers.getChildAt(i);
+ for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+ final TaskStack stack = mTaskStackContainers.get(i);
if (stack == null || !stack.isAdjustedForIme()) {
continue;
}
@@ -1995,8 +2014,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
boolean clearImeAdjustAnimation() {
boolean changed = false;
- for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
- final TaskStack stack = mTaskStackContainers.getChildAt(i);
+ for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+ final TaskStack stack = mTaskStackContainers.get(i);
if (stack != null && stack.isAdjustedForIme()) {
stack.resetAdjustedForIme(true /* adjustBoundsNow */);
changed = true;
@@ -2006,8 +2025,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
void beginImeAdjustAnimation() {
- for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
- final TaskStack stack = mTaskStackContainers.getChildAt(i);
+ for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+ final TaskStack stack = mTaskStackContainers.get(i);
if (stack.isVisible() && stack.isAdjustedForIme()) {
stack.beginImeAdjustAnimation();
}
@@ -2018,7 +2037,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
final WindowState imeWin = mService.mInputMethodWindow;
final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
&& !mDividerControllerLocked.isImeHideRequested();
- final boolean dockVisible = isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+ final boolean dockVisible = isStackVisible(DOCKED_STACK_ID);
final TaskStack imeTargetStack = mService.getImeFocusStackLocked();
final int imeDockSide = (dockVisible && imeTargetStack != null) ?
imeTargetStack.getDockSide() : DOCKED_INVALID;
@@ -2036,8 +2055,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// - If IME is not visible, divider is not moved and is normal width.
if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) {
- for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
- final TaskStack stack = mTaskStackContainers.getChildAt(i);
+ for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+ final TaskStack stack = mTaskStackContainers.get(i);
final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM;
if (stack.isVisible() && (imeOnBottom || isDockedOnBottom)
&& stack.inSplitScreenWindowingMode()) {
@@ -2049,8 +2068,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mDividerControllerLocked.setAdjustedForIme(
imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight);
} else {
- for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
- final TaskStack stack = mTaskStackContainers.getChildAt(i);
+ for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+ final TaskStack stack = mTaskStackContainers.get(i);
stack.resetAdjustedForIme(!dockVisible);
}
mDividerControllerLocked.setAdjustedForIme(
@@ -2081,8 +2100,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
void prepareFreezingTaskBounds() {
- for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
+ for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
+ final TaskStack stack = mTaskStackContainers.get(stackNdx);
stack.prepareFreezingTaskBounds();
}
}
@@ -2141,22 +2160,22 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
final long token = proto.start(fieldId);
super.writeToProto(proto, WINDOW_CONTAINER);
proto.write(ID, mDisplayId);
- for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
+ for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
+ final TaskStack stack = mTaskStackContainers.get(stackNdx);
stack.writeToProto(proto, STACKS);
}
mDividerControllerLocked.writeToProto(proto, DOCKED_STACK_DIVIDER_CONTROLLER);
mPinnedStackControllerLocked.writeToProto(proto, PINNED_STACK_CONTROLLER);
- for (int i = mAboveAppWindowsContainers.getChildCount() - 1; i >= 0; --i) {
- final WindowToken windowToken = mAboveAppWindowsContainers.getChildAt(i);
+ for (int i = mAboveAppWindowsContainers.size() - 1; i >= 0; --i) {
+ final WindowToken windowToken = mAboveAppWindowsContainers.get(i);
windowToken.writeToProto(proto, ABOVE_APP_WINDOWS);
}
- for (int i = mBelowAppWindowsContainers.getChildCount() - 1; i >= 0; --i) {
- final WindowToken windowToken = mBelowAppWindowsContainers.getChildAt(i);
+ for (int i = mBelowAppWindowsContainers.size() - 1; i >= 0; --i) {
+ final WindowToken windowToken = mBelowAppWindowsContainers.get(i);
windowToken.writeToProto(proto, BELOW_APP_WINDOWS);
}
- for (int i = mImeWindowsContainers.getChildCount() - 1; i >= 0; --i) {
- final WindowToken windowToken = mImeWindowsContainers.getChildAt(i);
+ for (int i = mImeWindowsContainers.size() - 1; i >= 0; --i) {
+ final WindowToken windowToken = mImeWindowsContainers.get(i);
windowToken.writeToProto(proto, IME_WINDOWS);
}
proto.write(DPI, mBaseDisplayDensity);
@@ -2202,8 +2221,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
pw.println();
pw.println(prefix + "Application tokens in top down Z order:");
- for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
+ for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
+ final TaskStack stack = mTaskStackContainers.get(stackNdx);
stack.dump(prefix + " ", pw);
}
@@ -2222,22 +2241,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
pw.println();
mDimLayerController.dump(prefix, pw);
pw.println();
-
- // Dump stack references
- final TaskStack homeStack = getHomeStack();
- if (homeStack != null) {
- pw.println(prefix + "homeStack=" + homeStack.getName());
- }
- final TaskStack pinnedStack = getPinnedStack();
- if (pinnedStack != null) {
- pw.println(prefix + "pinnedStack=" + pinnedStack.getName());
- }
- final TaskStack splitScreenPrimaryStack = getSplitScreenPrimaryStackStack();
- if (splitScreenPrimaryStack != null) {
- pw.println(prefix + "splitScreenPrimaryStack=" + splitScreenPrimaryStack.getName());
- }
-
- pw.println();
mDividerControllerLocked.dump(prefix, pw);
pw.println();
mPinnedStackControllerLocked.dump(prefix, pw);
@@ -2257,10 +2260,26 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
return "Display " + mDisplayId + " name=\"" + mDisplayInfo.name + "\"";
}
- /** Returns true if the stack in the windowing mode is visible. */
- boolean isStackVisible(int windowingMode) {
- final TaskStack stack = getStack(windowingMode);
- return stack != null && stack.isVisible();
+ /** Checks if stack with provided id is visible on this display. */
+ boolean isStackVisible(int stackId) {
+ final TaskStack stack = getStackById(stackId);
+ return (stack != null && stack.isVisible());
+ }
+
+ /**
+ * @return The docked stack, but only if it is visible, and {@code null} otherwise.
+ */
+ TaskStack getDockedStackLocked() {
+ final TaskStack stack = getStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+ return (stack != null && stack.isVisible()) ? stack : null;
+ }
+
+ /**
+ * Like {@link #getDockedStackLocked}, but also returns the docked stack if it's currently not
+ * visible.
+ */
+ TaskStack getDockedStackIgnoringVisibility() {
+ return getStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
}
/** Find the visible, touch-deliverable window under the given point */
@@ -3339,6 +3358,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
*/
static class DisplayChildWindowContainer<E extends WindowContainer> extends WindowContainer<E> {
+ int size() {
+ return mChildren.size();
+ }
+
+ E get(int index) {
+ return mChildren.get(index);
+ }
+
@Override
boolean fillsParent() {
return true;
@@ -3356,108 +3383,25 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
*/
private final class TaskStackContainers extends DisplayChildWindowContainer<TaskStack> {
- // Cached reference to some special stacks we tend to get a lot so we don't need to loop
- // through the list to find them.
- private TaskStack mHomeStack = null;
- private TaskStack mPinnedStack = null;
- private TaskStack mSplitScreenPrimaryStack = null;
-
- /**
- * Returns the topmost stack on the display that is compatible with the input windowing mode
- * and activity type. Null is no compatible stack on the display.
- */
- TaskStack getStack(int windowingMode, int activityType) {
- if (activityType == ACTIVITY_TYPE_HOME) {
- return mHomeStack;
- }
- if (windowingMode == WINDOWING_MODE_PINNED) {
- return mPinnedStack;
- } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
- return mSplitScreenPrimaryStack;
- }
- for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
- final TaskStack stack = mTaskStackContainers.getChildAt(i);
- if (stack.isCompatible(windowingMode, activityType)) {
- return stack;
- }
- }
- return null;
- }
-
- @VisibleForTesting
- TaskStack getTopStack() {
- return mTaskStackContainers.getChildCount() > 0
- ? mTaskStackContainers.getChildAt(mTaskStackContainers.getChildCount() - 1) : null;
- }
-
- TaskStack getHomeStack() {
- if (mHomeStack == null && mDisplayId == DEFAULT_DISPLAY) {
- Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this);
- }
- return mHomeStack;
- }
-
- TaskStack getPinnedStack() {
- return mPinnedStack;
- }
-
- TaskStack getSplitScreenPrimaryStackStack() {
- return mSplitScreenPrimaryStack;
- }
-
/**
* Adds the stack to this container.
- * @see DisplayContent#createStack(int, boolean, StackWindowController)
+ * @see WindowManagerService#addStackToDisplay(int, int, boolean)
*/
void addStackToDisplay(TaskStack stack, boolean onTop) {
- addStackReferenceIfNeeded(stack);
- addChild(stack, onTop);
- stack.onDisplayChanged(DisplayContent.this);
- }
-
- void onStackWindowingModeChanged(TaskStack stack) {
- removeStackReferenceIfNeeded(stack);
- addStackReferenceIfNeeded(stack);
- if (stack == mPinnedStack && getTopStack() != stack) {
- // Looks like this stack changed windowing mode to pinned. Move it to the top.
- positionChildAt(POSITION_TOP, stack, false /* includingParents */);
- }
- }
-
- private void addStackReferenceIfNeeded(TaskStack stack) {
if (stack.isActivityTypeHome()) {
if (mHomeStack != null) {
- throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
- + mHomeStack + " already exist on display=" + this + " stack=" + stack);
+ throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first.");
}
mHomeStack = stack;
}
- final int windowingMode = stack.getWindowingMode();
- if (windowingMode == WINDOWING_MODE_PINNED) {
- if (mPinnedStack != null) {
- throw new IllegalArgumentException("addStackReferenceIfNeeded: pinned stack="
- + mPinnedStack + " already exist on display=" + this
- + " stack=" + stack);
- }
- mPinnedStack = stack;
- } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
- if (mSplitScreenPrimaryStack != null) {
- throw new IllegalArgumentException("addStackReferenceIfNeeded:"
- + " split-screen-primary" + " stack=" + mSplitScreenPrimaryStack
- + " already exist on display=" + this + " stack=" + stack);
- }
- mSplitScreenPrimaryStack = stack;
- }
+ addChild(stack, onTop);
+ stack.onDisplayChanged(DisplayContent.this);
}
- private void removeStackReferenceIfNeeded(TaskStack stack) {
- if (stack == mHomeStack) {
- mHomeStack = null;
- } else if (stack == mPinnedStack) {
- mPinnedStack = null;
- } else if (stack == mSplitScreenPrimaryStack) {
- mSplitScreenPrimaryStack = null;
- }
+ /** Removes the stack from its container and prepare for changing the parent. */
+ void removeStackFromDisplay(TaskStack stack) {
+ removeChild(stack);
+ stack.onRemovedFromDisplay();
}
private void addChild(TaskStack stack, boolean toTop) {
@@ -3467,11 +3411,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
setLayoutNeeded();
}
- @Override
- protected void removeChild(TaskStack stack) {
- super.removeChild(stack);
- removeStackReferenceIfNeeded(stack);
- }
@Override
boolean isOnTop() {
@@ -3514,7 +3453,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
: requestedPosition >= topChildPosition;
int targetPosition = requestedPosition;
- if (toTop && stack.getWindowingMode() != WINDOWING_MODE_PINNED && hasPinnedStack()) {
+ if (toTop && stack.getWindowingMode() != WINDOWING_MODE_PINNED
+ && getStack(WINDOWING_MODE_PINNED) != null) {
// The pinned stack is always the top most stack (always-on-top) when it is present.
TaskStack topStack = mChildren.get(topChildPosition);
if (topStack.getWindowingMode() != WINDOWING_MODE_PINNED) {
@@ -3616,8 +3556,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
@Override
int getOrientation() {
- if (isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)
- || isStackVisible(WINDOWING_MODE_FREEFORM)) {
+ if (isStackVisible(DOCKED_STACK_ID) || isStackVisible(FREEFORM_WORKSPACE_STACK_ID)) {
// Apps and their containers are not allowed to specify an orientation while the
// docked or freeform stack is visible...except for the home stack/task if the
// docked stack is minimized and it actually set something.
@@ -3632,16 +3571,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
final int orientation = super.getOrientation();
- boolean isCar = mService.mContext.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_AUTOMOTIVE);
- if (isCar) {
- // In a car, you cannot physically rotate the screen, so it doesn't make sense to
- // allow anything but the default orientation.
- if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
- "Forcing UNSPECIFIED orientation in car. Ignoring " + orientation);
- return SCREEN_ORIENTATION_UNSPECIFIED;
- }
-
if (orientation != SCREEN_ORIENTATION_UNSET
&& orientation != SCREEN_ORIENTATION_BEHIND) {
if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
diff --git a/com/android/server/wm/DockedStackDividerController.java b/com/android/server/wm/DockedStackDividerController.java
index 52526e2f..6f441b98 100644
--- a/com/android/server/wm/DockedStackDividerController.java
+++ b/com/android/server/wm/DockedStackDividerController.java
@@ -16,6 +16,9 @@
package com.android.server.wm;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
@@ -319,7 +322,7 @@ public class DockedStackDividerController implements DimLayerUser {
if (mWindow == null) {
return;
}
- TaskStack stack = mDisplayContent.getSplitScreenPrimaryStackStackIgnoringVisibility();
+ TaskStack stack = mDisplayContent.getDockedStackIgnoringVisibility();
// If the stack is invisible, we policy force hide it in WindowAnimator.shouldForceHide
final boolean visible = stack != null;
@@ -359,7 +362,7 @@ public class DockedStackDividerController implements DimLayerUser {
}
void positionDockedStackedDivider(Rect frame) {
- TaskStack stack = mDisplayContent.getSplitScreenPrimaryStackStack();
+ TaskStack stack = mDisplayContent.getDockedStackLocked();
if (stack == null) {
// Unfortunately we might end up with still having a divider, even though the underlying
// stack was already removed. This is because we are on AM thread and the removal of the
@@ -456,7 +459,7 @@ public class DockedStackDividerController implements DimLayerUser {
long animDuration = 0;
if (animate) {
final TaskStack stack =
- mDisplayContent.getSplitScreenPrimaryStackStackIgnoringVisibility();
+ mDisplayContent.getStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
final long transitionDuration = isAnimationMaximizing()
? mService.mAppTransition.getLastClipRevealTransitionDuration()
: DEFAULT_APP_TRANSITION_DURATION;
@@ -510,8 +513,7 @@ public class DockedStackDividerController implements DimLayerUser {
void registerDockedStackListener(IDockedStackListener listener) {
mDockedStackListeners.register(listener);
notifyDockedDividerVisibilityChanged(wasVisible());
- notifyDockedStackExistsChanged(
- mDisplayContent.getSplitScreenPrimaryStackStackIgnoringVisibility() != null);
+ notifyDockedStackExistsChanged(mDisplayContent.getDockedStackIgnoringVisibility() != null);
notifyDockedStackMinimizedChanged(mMinimizedDock, false /* animate */,
isHomeStackResizable());
notifyAdjustedForImeChanged(mAdjustedForIme, 0 /* animDuration */);
@@ -530,7 +532,7 @@ public class DockedStackDividerController implements DimLayerUser {
final TaskStack stack = targetWindowingMode != WINDOWING_MODE_UNDEFINED
? mDisplayContent.getStack(targetWindowingMode)
: null;
- final TaskStack dockedStack = mDisplayContent.getSplitScreenPrimaryStackStack();
+ final TaskStack dockedStack = mDisplayContent.getDockedStackLocked();
boolean visibleAndValid = visible && stack != null && dockedStack != null;
if (visibleAndValid) {
stack.getDimBounds(mTmpRect);
@@ -586,7 +588,7 @@ public class DockedStackDividerController implements DimLayerUser {
private boolean containsAppInDockedStack(ArraySet<AppWindowToken> apps) {
for (int i = apps.size() - 1; i >= 0; i--) {
final AppWindowToken token = apps.valueAt(i);
- if (token.getTask() != null && token.inSplitScreenPrimaryWindowingMode()) {
+ if (token.getTask() != null && token.getTask().mStack.mStackId == DOCKED_STACK_ID) {
return true;
}
}
@@ -598,7 +600,7 @@ public class DockedStackDividerController implements DimLayerUser {
}
private void checkMinimizeChanged(boolean animate) {
- if (mDisplayContent.getSplitScreenPrimaryStackStackIgnoringVisibility() == null) {
+ if (mDisplayContent.getDockedStackIgnoringVisibility() == null) {
return;
}
final TaskStack homeStack = mDisplayContent.getHomeStack();
@@ -760,7 +762,7 @@ public class DockedStackDividerController implements DimLayerUser {
}
private boolean setMinimizedDockedStack(boolean minimized) {
- final TaskStack stack = mDisplayContent.getSplitScreenPrimaryStackStackIgnoringVisibility();
+ final TaskStack stack = mDisplayContent.getDockedStackIgnoringVisibility();
notifyDockedStackMinimizedChanged(minimized, false /* animate */, isHomeStackResizable());
return stack != null && stack.setAdjustedForMinimizedDock(minimized ? 1f : 0f);
}
@@ -811,7 +813,8 @@ public class DockedStackDividerController implements DimLayerUser {
}
private boolean animateForMinimizedDockedStack(long now) {
- final TaskStack stack = mDisplayContent.getSplitScreenPrimaryStackStackIgnoringVisibility();
+ final TaskStack stack =
+ mDisplayContent.getStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
if (!mAnimationStarted) {
mAnimationStarted = true;
mAnimationStartTime = now;
diff --git a/com/android/server/wm/EmulatorDisplayOverlay.java b/com/android/server/wm/EmulatorDisplayOverlay.java
index 19bd8e9d..3186d3dc 100644
--- a/com/android/server/wm/EmulatorDisplayOverlay.java
+++ b/com/android/server/wm/EmulatorDisplayOverlay.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -56,8 +57,14 @@ class EmulatorDisplayOverlay {
SurfaceControl ctrl = null;
try {
- ctrl = new SurfaceControl(session, "EmulatorDisplayOverlay", mScreenSize.x,
- mScreenSize.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+ if (DEBUG_SURFACE_TRACE) {
+ ctrl = new WindowSurfaceController.SurfaceTrace(session, "EmulatorDisplayOverlay",
+ mScreenSize.x, mScreenSize.y, PixelFormat.TRANSLUCENT,
+ SurfaceControl.HIDDEN);
+ } else {
+ ctrl = new SurfaceControl(session, "EmulatorDisplayOverlay", mScreenSize.x,
+ mScreenSize.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+ }
ctrl.setLayerStack(display.getLayerStack());
ctrl.setLayer(zOrder);
ctrl.setPosition(0, 0);
diff --git a/com/android/server/wm/InputMonitor.java b/com/android/server/wm/InputMonitor.java
index 238cb9f1..5057f632 100644
--- a/com/android/server/wm/InputMonitor.java
+++ b/com/android/server/wm/InputMonitor.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
import static android.view.WindowManager.INPUT_CONSUMER_PIP;
@@ -649,7 +650,7 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
final boolean hasFocus = w == mInputFocus;
final boolean isVisible = w.isVisibleLw();
- if (w.inPinnedWindowingMode()) {
+ if (w.getStackId() == PINNED_STACK_ID) {
if (mAddPipInputConsumerHandle
&& (inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer)) {
// Update the bounds of the Pip input consumer to match the Pinned stack
diff --git a/com/android/server/wm/PinnedStackController.java b/com/android/server/wm/PinnedStackController.java
index 365366ad..ef31598f 100644
--- a/com/android/server/wm/PinnedStackController.java
+++ b/com/android/server/wm/PinnedStackController.java
@@ -417,7 +417,8 @@ class PinnedStackController {
false /* useCurrentMinEdgeSize */);
}
final Rect animatingBounds = mTmpAnimatingBoundsRect;
- final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
+ final TaskStack pinnedStack =
+ mDisplayContent.getStack(WINDOWING_MODE_PINNED);
if (pinnedStack != null) {
pinnedStack.getAnimationOrCurrentBounds(animatingBounds);
} else {
diff --git a/com/android/server/wm/RootWindowContainer.java b/com/android/server/wm/RootWindowContainer.java
index fd574709..7832f5de 100644
--- a/com/android/server/wm/RootWindowContainer.java
+++ b/com/android/server/wm/RootWindowContainer.java
@@ -411,6 +411,17 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
}
}
+ TaskStack getStackById(int stackId) {
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final DisplayContent dc = mChildren.get(i);
+ final TaskStack stack = dc.getStackById(stackId);
+ if (stack != null) {
+ return stack;
+ }
+ }
+ return null;
+ }
+
TaskStack getStack(int windowingMode, int activityType) {
for (int i = mChildren.size() - 1; i >= 0; i--) {
final DisplayContent dc = mChildren.get(i);
diff --git a/com/android/server/wm/ScreenRotationAnimation.java b/com/android/server/wm/ScreenRotationAnimation.java
index 8e99be83..d5b6d246 100644
--- a/com/android/server/wm/ScreenRotationAnimation.java
+++ b/com/android/server/wm/ScreenRotationAnimation.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
@@ -23,6 +24,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
import static com.android.server.wm.WindowStateAnimator.WINDOW_FREEZE_LAYER;
+import static com.android.server.wm.WindowSurfaceController.SurfaceTrace;
import static com.android.server.wm.proto.ScreenRotationAnimationProto.ANIMATION_RUNNING;
import static com.android.server.wm.proto.ScreenRotationAnimationProto.STARTED;
@@ -274,10 +276,17 @@ class ScreenRotationAnimation {
flags |= SurfaceControl.SECURE;
}
- mSurfaceControl = new SurfaceControl(session, "ScreenshotSurface",
- mWidth, mHeight,
- PixelFormat.OPAQUE, flags);
-
+ if (DEBUG_SURFACE_TRACE) {
+ mSurfaceControl = new SurfaceTrace(session, "ScreenshotSurface",
+ mWidth, mHeight,
+ PixelFormat.OPAQUE, flags);
+ Slog.w(TAG, "ScreenRotationAnimation ctor: displayOffset="
+ + mOriginalDisplayRect.toShortString());
+ } else {
+ mSurfaceControl = new SurfaceControl(session, "ScreenshotSurface",
+ mWidth, mHeight,
+ PixelFormat.OPAQUE, flags);
+ }
// capture a screenshot into the surface we just created
Surface sur = new Surface();
sur.copyFrom(mSurfaceControl);
diff --git a/com/android/server/wm/StackWindowController.java b/com/android/server/wm/StackWindowController.java
index 1fda832d..c0a4cb72 100644
--- a/com/android/server/wm/StackWindowController.java
+++ b/com/android/server/wm/StackWindowController.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Handler;
@@ -43,7 +45,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
public class StackWindowController
extends WindowContainerController<TaskStack, StackWindowListener> {
- private final int mStackId;
+ final int mStackId;
private final H mHandler;
@@ -72,7 +74,7 @@ public class StackWindowController
+ " to unknown displayId=" + displayId);
}
- dc.createStack(stackId, onTop, this);
+ dc.addStackToDisplay(stackId, onTop, this);
getRawBounds(outBounds);
}
}
@@ -278,9 +280,8 @@ public class StackWindowController
if (stack.getWindowConfiguration().tasksAreFloating()) {
// Floating tasks should not be resized to the screen's bounds.
- if (stack.inPinnedWindowingMode()
- && bounds.width() == mTmpDisplayBounds.width()
- && bounds.height() == mTmpDisplayBounds.height()) {
+ if (mStackId == PINNED_STACK_ID && bounds.width() == mTmpDisplayBounds.width() &&
+ bounds.height() == mTmpDisplayBounds.height()) {
// If the bounds we are animating is the same as the fullscreen stack
// dimensions, then apply the same inset calculations that we normally do for
// the fullscreen stack, without intersecting it with the display bounds
diff --git a/com/android/server/wm/Task.java b/com/android/server/wm/Task.java
index 891d637a..7e8d1308 100644
--- a/com/android/server/wm/Task.java
+++ b/com/android/server/wm/Task.java
@@ -17,6 +17,8 @@
package com.android.server.wm;
import static android.app.ActivityManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
@@ -211,7 +213,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
// then we want to preserve our insets so that there will not
// be a jump in the area covered by system decorations. We rely
// on the pinned animation to later unset this value.
- if (stack.inPinnedWindowingMode()) {
+ if (stack.mStackId == PINNED_STACK_ID) {
mPreserveNonFloatingState = true;
} else {
mPreserveNonFloatingState = false;
@@ -419,7 +421,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
return mFillsParent
|| !inSplitScreenSecondaryWindowingMode()
|| displayContent == null
- || displayContent.getSplitScreenPrimaryStackStackIgnoringVisibility() != null;
+ || displayContent.getDockedStackIgnoringVisibility() != null;
}
/** Original bounds of the task if applicable, otherwise fullscreen rect. */
@@ -490,7 +492,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
final boolean dockedResizing = displayContent != null
&& displayContent.mDividerControllerLocked.isResizing();
if (useCurrentBounds()) {
- if (inFreeformWindowingMode() && getMaxVisibleBounds(out)) {
+ if (inFreeformWorkspace() && getMaxVisibleBounds(out)) {
return;
}
@@ -596,6 +598,14 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
return (tokensCount != 0) && mChildren.get(tokensCount - 1).mShowForAllUsers;
}
+ boolean inFreeformWorkspace() {
+ return mStack != null && mStack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
+ }
+
+ boolean inPinnedWorkspace() {
+ return mStack != null && mStack.mStackId == PINNED_STACK_ID;
+ }
+
/**
* When we are in a floating stack (Freeform, Pinned, ...) we calculate
* insets differently. However if we are animating to the fullscreen stack
diff --git a/com/android/server/wm/TaskPositioner.java b/com/android/server/wm/TaskPositioner.java
index 87de1514..c58212cd 100644
--- a/com/android/server/wm/TaskPositioner.java
+++ b/com/android/server/wm/TaskPositioner.java
@@ -20,6 +20,7 @@ import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIG
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.RESIZE_MODE_USER;
import static android.app.ActivityManager.RESIZE_MODE_USER_FORCED;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
@@ -648,7 +649,7 @@ class TaskPositioner implements DimLayer.DimLayerUser {
* shouldn't be shown.
*/
private int getDimSide(int x) {
- if (!mTask.mStack.inFreeformWindowingMode()
+ if (mTask.mStack.mStackId != FREEFORM_WORKSPACE_STACK_ID
|| !mTask.mStack.fillsParent()
|| mTask.mStack.getConfiguration().orientation != ORIENTATION_LANDSCAPE) {
return CTRL_NONE;
diff --git a/com/android/server/wm/TaskSnapshotController.java b/com/android/server/wm/TaskSnapshotController.java
index 54ef0651..bff24f6e 100644
--- a/com/android/server/wm/TaskSnapshotController.java
+++ b/com/android/server/wm/TaskSnapshotController.java
@@ -294,9 +294,7 @@ class TaskSnapshotController {
decorPainter.drawDecors(c, null /* statusBarExcludeFrame */);
node.end(c);
final Bitmap hwBitmap = ThreadedRenderer.createHardwareBitmap(node, width, height);
- if (hwBitmap == null) {
- return null;
- }
+
return new TaskSnapshot(hwBitmap.createGraphicBufferHandle(),
topChild.getConfiguration().orientation, mainWindow.mStableInsets,
ActivityManager.isLowRamDeviceStatic() /* reduced */, 1.0f /* scale */);
diff --git a/com/android/server/wm/TaskStack.java b/com/android/server/wm/TaskStack.java
index d170b6f2..65278837 100644
--- a/com/android/server/wm/TaskStack.java
+++ b/com/android/server/wm/TaskStack.java
@@ -18,6 +18,8 @@ package com.android.server.wm;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
@@ -294,7 +296,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
if (mFillsParent
|| !inSplitScreenSecondaryWindowingMode()
|| mDisplayContent == null
- || mDisplayContent.getSplitScreenPrimaryStackStack() != null) {
+ || mDisplayContent.getDockedStackLocked() != null) {
return true;
}
return false;
@@ -407,7 +409,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
return false;
}
- if (inPinnedWindowingMode()) {
+ if (mStackId == PINNED_STACK_ID) {
getAnimationOrCurrentBounds(mTmpRect2);
boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
mTmpRect2, mTmpRect3);
@@ -441,19 +443,21 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
mTmpRect2.set(mBounds);
mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
- if (inSplitScreenPrimaryWindowingMode()) {
- repositionDockedStackAfterRotation(mTmpRect2);
- snapDockedStackAfterRotation(mTmpRect2);
- final int newDockSide = getDockSide(mTmpRect2);
-
- // Update the dock create mode and clear the dock create bounds, these
- // might change after a rotation and the original values will be invalid.
- mService.setDockedStackCreateStateLocked(
- (newDockSide == DOCKED_LEFT || newDockSide == DOCKED_TOP)
- ? DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
- : DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT,
- null);
- mDisplayContent.getDockedDividerController().notifyDockSideChanged(newDockSide);
+ switch (mStackId) {
+ case DOCKED_STACK_ID:
+ repositionDockedStackAfterRotation(mTmpRect2);
+ snapDockedStackAfterRotation(mTmpRect2);
+ final int newDockSide = getDockSide(mTmpRect2);
+
+ // Update the dock create mode and clear the dock create bounds, these
+ // might change after a rotation and the original values will be invalid.
+ mService.setDockedStackCreateStateLocked(
+ (newDockSide == DOCKED_LEFT || newDockSide == DOCKED_TOP)
+ ? DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
+ : DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT,
+ null);
+ mDisplayContent.getDockedDividerController().notifyDockSideChanged(newDockSide);
+ break;
}
mBoundsAfterRotation.set(mTmpRect2);
@@ -673,16 +677,6 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
}
}
- @Override
- public void onConfigurationChanged(Configuration newParentConfig) {
- final int prevWindowingMode = getWindowingMode();
- super.onConfigurationChanged(newParentConfig);
- if (mDisplayContent != null && prevWindowingMode != getWindowingMode()) {
- mDisplayContent.onStackWindowingModeChanged(this);
- }
- }
-
- @Override
void onDisplayChanged(DisplayContent dc) {
if (mDisplayContent != null) {
throw new IllegalStateException("onDisplayChanged: Already attached");
@@ -693,8 +687,8 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
"animation background stackId=" + mStackId);
Rect bounds = null;
- final TaskStack dockedStack = dc.getSplitScreenPrimaryStackStackIgnoringVisibility();
- if (inSplitScreenPrimaryWindowingMode()
+ final TaskStack dockedStack = dc.getDockedStackIgnoringVisibility();
+ if (mStackId == DOCKED_STACK_ID
|| (dockedStack != null && inSplitScreenSecondaryWindowingMode()
&& !dockedStack.fillsParent())) {
// The existence of a docked stack affects the size of other static stack created since
@@ -709,10 +703,10 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
}
final boolean dockedOnTopOrLeft = mService.mDockedStackCreateMode
== DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
- getStackDockedModeBounds(mTmpRect, bounds, mTmpRect2,
+ getStackDockedModeBounds(mTmpRect, bounds, mStackId, mTmpRect2,
mDisplayContent.mDividerControllerLocked.getContentWidth(),
dockedOnTopOrLeft);
- } else if (inPinnedWindowingMode()) {
+ } else if (mStackId == PINNED_STACK_ID) {
// Update the bounds based on any changes to the display info
getAnimationOrCurrentBounds(mTmpRect2);
boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
@@ -772,8 +766,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
return;
}
- final TaskStack dockedStack =
- mDisplayContent.getSplitScreenPrimaryStackStackIgnoringVisibility();
+ final TaskStack dockedStack = mDisplayContent.getDockedStackIgnoringVisibility();
if (dockedStack == null) {
// Not sure why you are calling this method when there is no docked stack...
throw new IllegalStateException(
@@ -798,7 +791,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
mDisplayContent.getLogicalDisplayRect(mTmpRect);
dockedStack.getRawBounds(mTmpRect2);
final boolean dockedOnTopOrLeft = dockedSide == DOCKED_TOP || dockedSide == DOCKED_LEFT;
- getStackDockedModeBounds(mTmpRect, outStackBounds, mTmpRect2,
+ getStackDockedModeBounds(mTmpRect, outStackBounds, mStackId, mTmpRect2,
mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
}
@@ -807,15 +800,16 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
* Outputs the bounds a stack should be given the presence of a docked stack on the display.
* @param displayRect The bounds of the display the docked stack is on.
* @param outBounds Output bounds that should be used for the stack.
+ * @param stackId Id of stack we are calculating the bounds for.
* @param dockedBounds Bounds of the docked stack.
* @param dockDividerWidth We need to know the width of the divider make to the output bounds
* close to the side of the dock.
* @param dockOnTopOrLeft If the docked stack is on the top or left side of the screen.
*/
private void getStackDockedModeBounds(
- Rect displayRect, Rect outBounds, Rect dockedBounds, int dockDividerWidth,
+ Rect displayRect, Rect outBounds, int stackId, Rect dockedBounds, int dockDividerWidth,
boolean dockOnTopOrLeft) {
- final boolean dockedStack = inSplitScreenPrimaryWindowingMode();
+ final boolean dockedStack = stackId == DOCKED_STACK_ID;
final boolean splitHorizontally = displayRect.width() > displayRect.height();
outBounds.set(displayRect);
@@ -872,7 +866,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
}
void resetDockedStackToMiddle() {
- if (inSplitScreenPrimaryWindowingMode()) {
+ if (mStackId != DOCKED_STACK_ID) {
throw new IllegalStateException("Not a docked stack=" + this);
}
@@ -900,12 +894,17 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
}
@Override
- void onParentSet() {
- if (getParent() != null || mDisplayContent == null) {
- return;
- }
+ void removeImmediately() {
+ super.removeImmediately();
+
+ onRemovedFromDisplay();
+ }
- // Looks like the stack was removed from the display. Go ahead and clean things up.
+ /**
+ * Removes the stack it from its current parent, so it can be either destroyed completely or
+ * re-parented.
+ */
+ void onRemovedFromDisplay() {
mDisplayContent.mDimLayerController.removeDimLayerUser(this);
EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
@@ -914,7 +913,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
mAnimationBackgroundSurface = null;
}
- if (inSplitScreenPrimaryWindowingMode()) {
+ if (mStackId == DOCKED_STACK_ID) {
mDisplayContent.mDividerControllerLocked.notifyDockedStackExistsChanged(false);
}
@@ -1036,8 +1035,8 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
}
boolean shouldIgnoreInput() {
- return isAdjustedForMinimizedDockedStack() ||
- (inSplitScreenPrimaryWindowingMode() && isMinimizedDockAndHomeStackResizable());
+ return isAdjustedForMinimizedDockedStack() || mStackId == DOCKED_STACK_ID &&
+ isMinimizedDockAndHomeStackResizable();
}
/**
@@ -1472,7 +1471,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
postExclude.set(mTmpRect);
}
- final boolean isFreeformed = task.inFreeformWindowingMode();
+ final boolean isFreeformed = task.inFreeformWorkspace();
if (task != focusedTask || isFreeformed) {
if (isFreeformed) {
// If the task is freeformed, enlarge the area to account for outside
@@ -1530,7 +1529,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
}
}
- if (inPinnedWindowingMode()) {
+ if (mStackId == PINNED_STACK_ID) {
try {
mService.mActivityManager.notifyPinnedStackAnimationStarted();
} catch (RemoteException e) {
@@ -1562,7 +1561,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
mService.requestTraversal();
}
- if (inPinnedWindowingMode()) {
+ if (mStackId == PINNED_STACK_ID) {
// Update to the final bounds if requested. This is done here instead of in the bounds
// animator to allow us to coordinate this after we notify the PiP mode changed
@@ -1596,7 +1595,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
* bounds and we have a deferred PiP mode changed callback set with the animation.
*/
public boolean deferScheduleMultiWindowModeChanged() {
- if (inPinnedWindowingMode()) {
+ if (mStackId == PINNED_STACK_ID) {
return (mBoundsAnimatingRequested || mBoundsAnimating);
}
return false;
diff --git a/com/android/server/wm/WallpaperController.java b/com/android/server/wm/WallpaperController.java
index 629cc868..7213c951 100644
--- a/com/android/server/wm/WallpaperController.java
+++ b/com/android/server/wm/WallpaperController.java
@@ -18,7 +18,7 @@ package com.android.server.wm;
import com.android.internal.util.ToBooleanFunction;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
@@ -447,7 +447,7 @@ class WallpaperController {
private void findWallpaperTarget(DisplayContent dc) {
mFindResults.reset();
- if (dc.isStackVisible(WINDOWING_MODE_FREEFORM)) {
+ if (dc.isStackVisible(FREEFORM_WORKSPACE_STACK_ID)) {
// In freeform mode we set the wallpaper as its own target, so we don't need an
// additional window to make it visible.
mFindResults.setUseTopWallpaperAsTarget(true);
diff --git a/com/android/server/wm/WindowContainer.java b/com/android/server/wm/WindowContainer.java
index 1b0825e5..40923c82 100644
--- a/com/android/server/wm/WindowContainer.java
+++ b/com/android/server/wm/WindowContainer.java
@@ -73,12 +73,12 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
@Override
- protected int getChildCount() {
+ final protected int getChildCount() {
return mChildren.size();
}
@Override
- protected E getChildAt(int index) {
+ final protected E getChildAt(int index) {
return mChildren.get(index);
}
diff --git a/com/android/server/wm/WindowManagerDebugConfig.java b/com/android/server/wm/WindowManagerDebugConfig.java
index 9d9805ab..6d5673e2 100644
--- a/com/android/server/wm/WindowManagerDebugConfig.java
+++ b/com/android/server/wm/WindowManagerDebugConfig.java
@@ -60,6 +60,7 @@ public class WindowManagerDebugConfig {
static final boolean DEBUG_SCREENSHOT = false;
static final boolean DEBUG_BOOT = false;
static final boolean DEBUG_LAYOUT_REPEATS = false;
+ static final boolean DEBUG_SURFACE_TRACE = false;
static final boolean DEBUG_WINDOW_TRACE = false;
static final boolean DEBUG_TASK_MOVEMENT = false;
static final boolean DEBUG_TASK_POSITIONING = false;
diff --git a/com/android/server/wm/WindowManagerService.java b/com/android/server/wm/WindowManagerService.java
index b133bd45..1fb21887 100644
--- a/com/android/server/wm/WindowManagerService.java
+++ b/com/android/server/wm/WindowManagerService.java
@@ -2384,7 +2384,7 @@ public class WindowManagerService extends IWindowManager.Stub
final Rect insets = new Rect();
final Rect stableInsets = new Rect();
Rect surfaceInsets = null;
- final boolean freeform = win != null && win.inFreeformWindowingMode();
+ final boolean freeform = win != null && win.inFreeformWorkspace();
if (win != null) {
// Containing frame will usually cover the whole screen, including dialog windows.
// For freeform workspace windows it will not cover the whole screen and it also
@@ -2794,7 +2794,7 @@ public class WindowManagerService extends IWindowManager.Stub
for (final WindowState win : mWindowMap.values()) {
final Task task = win.getTask();
if (task != null && mTmpTaskIds.get(task.mTaskId, -1) != -1
- && task.inFreeformWindowingMode()) {
+ && task.inFreeformWorkspace()) {
final AppWindowToken appToken = win.mAppToken;
if (appToken != null && appToken.mAppAnimator != null) {
appToken.mAppAnimator.startProlongAnimation(scaleUp ?
@@ -3391,8 +3391,7 @@ public class WindowManagerService extends IWindowManager.Stub
// Notify whether the docked stack exists for the current user
final DisplayContent displayContent = getDefaultDisplayContentLocked();
- final TaskStack stack =
- displayContent.getSplitScreenPrimaryStackStackIgnoringVisibility();
+ final TaskStack stack = displayContent.getDockedStackIgnoringVisibility();
displayContent.mDividerControllerLocked.notifyDockedStackExistsChanged(
stack != null && stack.hasTaskForUser(newUserId));
@@ -6899,6 +6898,11 @@ public class WindowManagerService extends IWindowManager.Stub
dumpSessionsLocked(pw, true);
}
return;
+ } else if ("surfaces".equals(cmd)) {
+ synchronized(mWindowMap) {
+ WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, null);
+ }
+ return;
} else if ("displays".equals(cmd) || "d".equals(cmd)) {
synchronized(mWindowMap) {
mRoot.dumpDisplayContents(pw);
@@ -6963,6 +6967,10 @@ public class WindowManagerService extends IWindowManager.Stub
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
+ WindowSurfaceController.SurfaceTrace.dumpAllSurfaces(pw, dumpAll ?
+ "-------------------------------------------------------------------------------"
+ : null);
+ pw.println();
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
@@ -7124,7 +7132,7 @@ public class WindowManagerService extends IWindowManager.Stub
public int getDockedStackSide() {
synchronized (mWindowMap) {
final TaskStack dockedStack = getDefaultDisplayContentLocked()
- .getSplitScreenPrimaryStackStackIgnoringVisibility();
+ .getDockedStackIgnoringVisibility();
return dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide();
}
}
@@ -7596,10 +7604,10 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
- public boolean isStackVisible(int windowingMode) {
+ public boolean isStackVisible(int stackId) {
synchronized (mWindowMap) {
final DisplayContent dc = getDefaultDisplayContentLocked();
- return dc.isStackVisible(windowingMode);
+ return dc.isStackVisible(stackId);
}
}
diff --git a/com/android/server/wm/WindowState.java b/com/android/server/wm/WindowState.java
index e1715284..4ff0f391 100644
--- a/com/android/server/wm/WindowState.java
+++ b/com/android/server/wm/WindowState.java
@@ -16,7 +16,10 @@
package com.android.server.wm;
+import static android.app.ActivityManager.StackId;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT;
@@ -80,6 +83,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RESIZE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -811,12 +815,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
final WindowState imeWin = mService.mInputMethodWindow;
// IME is up and obscuring this window. Adjust the window position so it is visible.
if (imeWin != null && imeWin.isVisibleNow() && mService.mInputMethodTarget == this) {
- if (inFreeformWindowingMode()
+ final int stackId = getStackId();
+ if (stackId == FREEFORM_WORKSPACE_STACK_ID
&& mContainingFrame.bottom > contentFrame.bottom) {
// In freeform we want to move the top up directly.
// TODO: Investigate why this is contentFrame not parentFrame.
mContainingFrame.top -= mContainingFrame.bottom - contentFrame.bottom;
- } else if (!inPinnedWindowingMode()
+ } else if (stackId != PINNED_STACK_ID
&& mContainingFrame.bottom > parentFrame.bottom) {
// But in docked we want to behave like fullscreen and behave as if the task
// were given smaller bounds for the purposes of layout. Skip adjustments for
@@ -893,7 +898,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// For pinned workspace the frame isn't limited in any particular
// way since SystemUI controls the bounds. For freeform however
// we want to keep things inside the content frame.
- final Rect limitFrame = task.inPinnedWindowingMode() ? mFrame : mContentFrame;
+ final Rect limitFrame = task.inPinnedWorkspace() ? mFrame : mContentFrame;
// Keep the frame out of the blocked system area, limit it in size to the content area
// and make sure that there is always a minimum visible so that the user can drag it
// into a usable area..
@@ -1205,7 +1210,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// application when it has finished drawing.
if (getOrientationChanging() || dragResizingChanged
|| isResizedWhileNotDragResizing()) {
- if (DEBUG_ANIM || DEBUG_ORIENTATION || DEBUG_RESIZE) {
+ if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION || DEBUG_RESIZE) {
Slog.v(TAG_WM, "Orientation or resize start waiting for draw"
+ ", mDrawState=DRAW_PENDING in " + this
+ ", surfaceController " + winAnimator.mSurfaceController);
@@ -1657,9 +1662,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
//
// Anyway we don't need to synchronize position and content updates for these
// windows since they aren't at the base layer and could be moved around anyway.
- if (!computeDragResizing() && mAttrs.type == TYPE_BASE_APPLICATION
- && !mWinAnimator.isForceScaled() && !isGoneForLayoutLw()
- && !getTask().inPinnedWindowingMode()) {
+ if (!computeDragResizing() && mAttrs.type == TYPE_BASE_APPLICATION &&
+ !mWinAnimator.isForceScaled() && !isGoneForLayoutLw() &&
+ !getTask().inPinnedWorkspace()) {
setResizedWhileNotDragResizing(true);
}
}
@@ -2191,6 +2196,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
}
+ // TODO: Strange usage of word workspace here and above.
+ boolean inPinnedWorkspace() {
+ final Task task = getTask();
+ return task != null && task.inPinnedWorkspace();
+ }
+
void applyAdjustForImeIfNeeded() {
final Task task = getTask();
if (task != null && task.mStack != null && task.mStack.isAdjustedForIme()) {
@@ -2224,7 +2235,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
} else {
getVisibleBounds(mTmpRect);
}
- if (inFreeformWindowingMode()) {
+ if (inFreeformWorkspace()) {
// For freeform windows we the touch region to include the whole surface for the
// shadows.
final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics();
@@ -2360,8 +2371,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// just in case they have the divider at an unstable position. Better
// also reset drag resizing state, because the owner can't do it
// anymore.
- final TaskStack stack =
- dc.getSplitScreenPrimaryStackStackIgnoringVisibility();
+ final TaskStack stack = dc.getDockedStackIgnoringVisibility();
if (stack != null) {
stack.resetDockedStackToMiddle();
}
@@ -2928,7 +2938,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return mTmpRect;
}
- private int getStackId() {
+ @Override
+ public int getStackId() {
final TaskStack stack = getStack();
if (stack == null) {
return INVALID_STACK_ID;
@@ -2972,6 +2983,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
}
+ boolean inFreeformWorkspace() {
+ final Task task = getTask();
+ return task != null && task.inFreeformWorkspace();
+ }
+
@Override
public boolean isInMultiWindowMode() {
final Task task = getTask();
@@ -3089,7 +3105,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// background.
return (getDisplayContent().mDividerControllerLocked.isResizing()
|| mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) &&
- !task.inFreeformWindowingMode() && !isGoneForLayoutLw();
+ !task.inFreeformWorkspace() && !isGoneForLayoutLw();
}
@@ -3679,7 +3695,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// Force the show in the next prepareSurfaceLocked() call.
mWinAnimator.mLastAlpha = -1;
- if (DEBUG_ANIM) Slog.v(TAG,
+ if (DEBUG_SURFACE_TRACE || DEBUG_ANIM) Slog.v(TAG,
"performShowLocked: mDrawState=HAS_DRAWN in " + this);
mWinAnimator.mDrawState = HAS_DRAWN;
mService.scheduleAnimationLocked();
@@ -3740,7 +3756,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
windowInfo.accessibilityIdOfAnchor = mAttrs.accessibilityIdOfAnchor;
windowInfo.focused = isFocused();
Task task = getTask();
- windowInfo.inPictureInPicture = (task != null) && task.inPinnedWindowingMode();
+ windowInfo.inPictureInPicture = (task != null) && task.inPinnedWorkspace();
if (mIsChildWindow) {
windowInfo.parentToken = getParentWindow().mClient.asBinder();
@@ -4203,7 +4219,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// If a freeform window is animating from a position where it would be cutoff, it would be
// cutoff during the animation. We don't want that, so for the duration of the animation
// we ignore the decor cropping and depend on layering to position windows correctly.
- final boolean cropToDecor = !(inFreeformWindowingMode() && isAnimatingLw());
+ final boolean cropToDecor = !(inFreeformWorkspace() && isAnimatingLw());
if (cropToDecor) {
// Intersect with the decor rect, offsetted by window position.
systemDecorRect.intersect(decorRect.left - left, decorRect.top - top,
@@ -4287,7 +4303,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// scale for the animation using the source hint rect
// (see WindowStateAnimator#setSurfaceBoundariesLocked()).
if (isDragResizeChanged() || isResizedWhileNotDragResizing()
- || (surfaceInsetsChanging() && !inPinnedWindowingMode())) {
+ || (surfaceInsetsChanging() && !inPinnedWorkspace())) {
mLastSurfaceInsets.set(mAttrs.surfaceInsets);
setDragResizing();
diff --git a/com/android/server/wm/WindowStateAnimator.java b/com/android/server/wm/WindowStateAnimator.java
index 52669031..1b7e5278 100644
--- a/com/android/server/wm/WindowStateAnimator.java
+++ b/com/android/server/wm/WindowStateAnimator.java
@@ -31,6 +31,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEAT
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_CROP;
@@ -508,7 +509,7 @@ class WindowStateAnimator {
boolean layoutNeeded = false;
if (mDrawState == DRAW_PENDING) {
- if (DEBUG_ANIM || SHOW_TRANSACTIONS || DEBUG_ORIENTATION)
+ if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || SHOW_TRANSACTIONS || DEBUG_ORIENTATION)
Slog.v(TAG, "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING " + mWin + " in "
+ mSurfaceController);
if (DEBUG_STARTING_WINDOW && startingWindow) {
@@ -531,7 +532,7 @@ class WindowStateAnimator {
if (mDrawState != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW) {
return false;
}
- if (DEBUG_ANIM) {
+ if (DEBUG_SURFACE_TRACE || DEBUG_ANIM) {
Slog.i(TAG, "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW " + mSurfaceController);
}
mDrawState = READY_TO_SHOW;
@@ -1032,7 +1033,7 @@ class WindowStateAnimator {
//Slog.i(TAG_WM, "Not applying alpha transform");
}
- if ((DEBUG_ANIM || WindowManagerService.localLOGV)
+ if ((DEBUG_SURFACE_TRACE || WindowManagerService.localLOGV)
&& (mShownAlpha == 1.0 || mShownAlpha == 0.0)) Slog.v(
TAG, "computeShownFrameLocked: Animating " + this + " mAlpha=" + mAlpha
+ " self=" + (selfTransformation ? mTransformation.getAlpha() : "null")
@@ -1111,7 +1112,7 @@ class WindowStateAnimator {
*/
private boolean useFinalClipRect() {
return (isAnimationSet() && resolveStackClip() == STACK_CLIP_AFTER_ANIM)
- || mDestroyPreservedSurfaceUponRedraw || mWin.inPinnedWindowingMode();
+ || mDestroyPreservedSurfaceUponRedraw || mWin.inPinnedWorkspace();
}
/**
@@ -1176,7 +1177,7 @@ class WindowStateAnimator {
return false;
}
- if (w.inPinnedWindowingMode()) {
+ if (w.inPinnedWorkspace()) {
return false;
}
diff --git a/com/android/server/wm/WindowSurfaceController.java b/com/android/server/wm/WindowSurfaceController.java
index d56df55d..2e1e3f76 100644
--- a/com/android/server/wm/WindowSurfaceController.java
+++ b/com/android/server/wm/WindowSurfaceController.java
@@ -22,6 +22,7 @@ import static android.view.Surface.SCALING_MODE_SCALE_TO_WINDOW;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -564,4 +565,262 @@ class WindowSurfaceController {
public String toString() {
return mSurfaceControl.toString();
}
+
+ static class SurfaceTrace extends SurfaceControl {
+ private final static String SURFACE_TAG = TAG_WITH_CLASS_NAME ? "SurfaceTrace" : TAG_WM;
+ private final static boolean LOG_SURFACE_TRACE = DEBUG_SURFACE_TRACE;
+ final static ArrayList<SurfaceTrace> sSurfaces = new ArrayList<SurfaceTrace>();
+
+ private float mSurfaceTraceAlpha = 0;
+ private int mLayer;
+ private final PointF mPosition = new PointF();
+ private final Point mSize = new Point();
+ private final Rect mWindowCrop = new Rect();
+ private final Rect mFinalCrop = new Rect();
+ private boolean mShown = false;
+ private int mLayerStack;
+ private boolean mIsOpaque;
+ private float mDsdx, mDtdx, mDsdy, mDtdy;
+ private final String mName;
+
+ public SurfaceTrace(SurfaceSession s, String name, int w, int h, int format, int flags,
+ int windowType, int ownerUid)
+ throws OutOfResourcesException {
+ super(s, name, w, h, format, flags, windowType, ownerUid);
+ mName = name != null ? name : "Not named";
+ mSize.set(w, h);
+ if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "ctor: " + this + ". Called by "
+ + Debug.getCallers(3));
+ synchronized (sSurfaces) {
+ sSurfaces.add(0, this);
+ }
+ }
+
+ public SurfaceTrace(SurfaceSession s,
+ String name, int w, int h, int format, int flags) {
+ super(s, name, w, h, format, flags);
+ mName = name != null ? name : "Not named";
+ mSize.set(w, h);
+ if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "ctor: " + this + ". Called by "
+ + Debug.getCallers(3));
+ synchronized (sSurfaces) {
+ sSurfaces.add(0, this);
+ }
+ }
+
+ @Override
+ public void setAlpha(float alpha) {
+ if (mSurfaceTraceAlpha != alpha) {
+ if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setAlpha(" + alpha + "): OLD:" + this +
+ ". Called by " + Debug.getCallers(3));
+ mSurfaceTraceAlpha = alpha;
+ }
+ super.setAlpha(alpha);
+ }
+
+ @Override
+ public void setLayer(int zorder) {
+ if (zorder != mLayer) {
+ if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setLayer(" + zorder + "): OLD:" + this
+ + ". Called by " + Debug.getCallers(3));
+ mLayer = zorder;
+ }
+ super.setLayer(zorder);
+
+ synchronized (sSurfaces) {
+ sSurfaces.remove(this);
+ int i;
+ for (i = sSurfaces.size() - 1; i >= 0; i--) {
+ SurfaceTrace s = sSurfaces.get(i);
+ if (s.mLayer < zorder) {
+ break;
+ }
+ }
+ sSurfaces.add(i + 1, this);
+ }
+ }
+
+ @Override
+ public void setPosition(float x, float y) {
+ if (x != mPosition.x || y != mPosition.y) {
+ if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setPosition(" + x + "," + y + "): OLD:"
+ + this + ". Called by " + Debug.getCallers(3));
+ mPosition.set(x, y);
+ }
+ super.setPosition(x, y);
+ }
+
+ @Override
+ public void setGeometryAppliesWithResize() {
+ if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setGeometryAppliesWithResize(): OLD: "
+ + this + ". Called by" + Debug.getCallers(3));
+ super.setGeometryAppliesWithResize();
+ }
+
+ @Override
+ public void setSize(int w, int h) {
+ if (w != mSize.x || h != mSize.y) {
+ if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setSize(" + w + "," + h + "): OLD:"
+ + this + ". Called by " + Debug.getCallers(3));
+ mSize.set(w, h);
+ }
+ super.setSize(w, h);
+ }
+
+ @Override
+ public void setWindowCrop(Rect crop) {
+ if (crop != null) {
+ if (!crop.equals(mWindowCrop)) {
+ if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setWindowCrop("
+ + crop.toShortString() + "): OLD:" + this + ". Called by "
+ + Debug.getCallers(3));
+ mWindowCrop.set(crop);
+ }
+ }
+ super.setWindowCrop(crop);
+ }
+
+ @Override
+ public void setFinalCrop(Rect crop) {
+ if (crop != null) {
+ if (!crop.equals(mFinalCrop)) {
+ if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setFinalCrop("
+ + crop.toShortString() + "): OLD:" + this + ". Called by "
+ + Debug.getCallers(3));
+ mFinalCrop.set(crop);
+ }
+ }
+ super.setFinalCrop(crop);
+ }
+
+ @Override
+ public void setLayerStack(int layerStack) {
+ if (layerStack != mLayerStack) {
+ if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setLayerStack(" + layerStack + "): OLD:"
+ + this + ". Called by " + Debug.getCallers(3));
+ mLayerStack = layerStack;
+ }
+ super.setLayerStack(layerStack);
+ }
+
+ @Override
+ public void setOpaque(boolean isOpaque) {
+ if (isOpaque != mIsOpaque) {
+ if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setOpaque(" + isOpaque + "): OLD:"
+ + this + ". Called by " + Debug.getCallers(3));
+ mIsOpaque = isOpaque;
+ }
+ super.setOpaque(isOpaque);
+ }
+
+ @Override
+ public void setSecure(boolean isSecure) {
+ super.setSecure(isSecure);
+ }
+
+ @Override
+ public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
+ if (dsdx != mDsdx || dtdx != mDtdx || dsdy != mDsdy || dtdy != mDtdy) {
+ if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setMatrix(" + dsdx + "," + dtdx + ","
+ + dsdy + "," + dtdy + "): OLD:" + this + ". Called by "
+ + Debug.getCallers(3));
+ mDsdx = dsdx;
+ mDtdx = dtdx;
+ mDsdy = dsdy;
+ mDtdy = dtdy;
+ }
+ super.setMatrix(dsdx, dtdx, dsdy, dtdy);
+ }
+
+ @Override
+ public void hide() {
+ if (mShown) {
+ if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "hide: OLD:" + this + ". Called by "
+ + Debug.getCallers(3));
+ mShown = false;
+ }
+ super.hide();
+ }
+
+ @Override
+ public void show() {
+ if (!mShown) {
+ if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "show: OLD:" + this + ". Called by "
+ + Debug.getCallers(3));
+ mShown = true;
+ }
+ super.show();
+ }
+
+ @Override
+ public void destroy() {
+ super.destroy();
+ if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "destroy: " + this + ". Called by "
+ + Debug.getCallers(3));
+ synchronized (sSurfaces) {
+ sSurfaces.remove(this);
+ }
+ }
+
+ @Override
+ public void release() {
+ super.release();
+ if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "release: " + this + ". Called by "
+ + Debug.getCallers(3));
+ synchronized (sSurfaces) {
+ sSurfaces.remove(this);
+ }
+ }
+
+ @Override
+ public void setTransparentRegionHint(Region region) {
+ if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setTransparentRegionHint(" + region
+ + "): OLD: " + this + " . Called by " + Debug.getCallers(3));
+ super.setTransparentRegionHint(region);
+ }
+
+ static void dumpAllSurfaces(PrintWriter pw, String header) {
+ synchronized (sSurfaces) {
+ final int N = sSurfaces.size();
+ if (N <= 0) {
+ return;
+ }
+ if (header != null) {
+ pw.println(header);
+ }
+ pw.println("WINDOW MANAGER SURFACES (dumpsys window surfaces)");
+ for (int i = 0; i < N; i++) {
+ SurfaceTrace s = sSurfaces.get(i);
+ pw.print(" Surface #"); pw.print(i); pw.print(": #");
+ pw.print(Integer.toHexString(System.identityHashCode(s)));
+ pw.print(" "); pw.println(s.mName);
+ pw.print(" mLayerStack="); pw.print(s.mLayerStack);
+ pw.print(" mLayer="); pw.println(s.mLayer);
+ pw.print(" mShown="); pw.print(s.mShown); pw.print(" mAlpha=");
+ pw.print(s.mSurfaceTraceAlpha); pw.print(" mIsOpaque=");
+ pw.println(s.mIsOpaque);
+ pw.print(" mPosition="); pw.print(s.mPosition.x); pw.print(",");
+ pw.print(s.mPosition.y);
+ pw.print(" mSize="); pw.print(s.mSize.x); pw.print("x");
+ pw.println(s.mSize.y);
+ pw.print(" mCrop="); s.mWindowCrop.printShortString(pw); pw.println();
+ pw.print(" mFinalCrop="); s.mFinalCrop.printShortString(pw); pw.println();
+ pw.print(" Transform: ("); pw.print(s.mDsdx); pw.print(", ");
+ pw.print(s.mDtdx); pw.print(", "); pw.print(s.mDsdy);
+ pw.print(", "); pw.print(s.mDtdy); pw.println(")");
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Surface " + Integer.toHexString(System.identityHashCode(this)) + " "
+ + mName + " (" + mLayerStack + "): shown=" + mShown + " layer=" + mLayer
+ + " alpha=" + mSurfaceTraceAlpha + " " + mPosition.x + "," + mPosition.y
+ + " " + mSize.x + "x" + mSize.y
+ + " crop=" + mWindowCrop.toShortString()
+ + " opaque=" + mIsOpaque
+ + " (" + mDsdx + "," + mDtdx + "," + mDsdy + "," + mDtdy + ")";
+ }
+ }
}
diff --git a/com/android/server/wm/WindowSurfacePlacer.java b/com/android/server/wm/WindowSurfacePlacer.java
index fa33fe8f..af1fa2fe 100644
--- a/com/android/server/wm/WindowSurfacePlacer.java
+++ b/com/android/server/wm/WindowSurfacePlacer.java
@@ -449,9 +449,6 @@ class WindowSurfacePlacer {
// animating?
wtoken.setVisibility(animLp, false, transit, false, voiceInteraction);
wtoken.updateReportedVisibilityLocked();
- // setAllAppWinAnimators so the windows get onExitAnimationDone once the animation is
- // done.
- wtoken.setAllAppWinAnimators();
// Force the allDrawn flag, because we want to start
// this guy's animations regardless of whether it's
// gotten drawn.