1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.wm.shell.splitscreen; 18 19 import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__LAUNCHER; 20 import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__MULTI_INSTANCE; 21 import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__UNKNOWN_ENTER; 22 import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__APP_DOES_NOT_SUPPORT_MULTIWINDOW; 23 import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__APP_FINISHED; 24 import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__CHILD_TASK_ENTER_PIP; 25 import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__DEVICE_FOLDED; 26 import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__DRAG_DIVIDER; 27 import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__FULLSCREEN_REQUEST; 28 import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__FULLSCREEN_SHORTCUT; 29 import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__DESKTOP_MODE; 30 import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RECREATE_SPLIT; 31 import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME; 32 import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__ROOT_TASK_VANISHED; 33 import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED; 34 import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED_SHOW_ON_TOP; 35 import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__UNKNOWN_EXIT; 36 import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN; 37 import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; 38 import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; 39 import static com.android.wm.shell.splitscreen.SplitScreenController.ENTER_REASON_DRAG; 40 import static com.android.wm.shell.splitscreen.SplitScreenController.ENTER_REASON_LAUNCHER; 41 import static com.android.wm.shell.splitscreen.SplitScreenController.ENTER_REASON_MULTI_INSTANCE; 42 import static com.android.wm.shell.splitscreen.SplitScreenController.ENTER_REASON_UNKNOWN; 43 import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW; 44 import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_APP_FINISHED; 45 import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_CHILD_TASK_ENTER_PIP; 46 import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DEVICE_FOLDED; 47 import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DRAG_DIVIDER; 48 import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DESKTOP_MODE; 49 import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_FULLSCREEN_REQUEST; 50 import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_FULLSCREEN_SHORTCUT; 51 import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RECREATE_SPLIT; 52 import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RETURN_HOME; 53 import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_ROOT_TASK_VANISHED; 54 import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_SCREEN_LOCKED; 55 import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP; 56 import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_UNKNOWN; 57 58 import android.annotation.Nullable; 59 import android.util.Slog; 60 61 import com.android.internal.logging.InstanceId; 62 import com.android.internal.logging.InstanceIdSequence; 63 import com.android.internal.protolog.ProtoLog; 64 import com.android.internal.util.FrameworkStatsLog; 65 import com.android.wm.shell.shared.split.SplitScreenConstants.SplitPosition; 66 import com.android.wm.shell.splitscreen.SplitScreenController.ExitReason; 67 68 /** 69 * Helper class that to log Drag & Drop UIEvents for a single session, see also go/uievent 70 */ 71 public class SplitscreenEventLogger { 72 73 // Used to generate instance ids for this drag if one is not provided 74 private final InstanceIdSequence mIdSequence; 75 76 // The instance id for the current splitscreen session (from start to end) 77 private InstanceId mLoggerSessionId; 78 79 // Drag info 80 private @SplitPosition int mDragEnterPosition; 81 private @Nullable InstanceId mEnterSessionId; 82 83 // For deduping async events 84 private int mLastMainStagePosition = -1; 85 private int mLastMainStageUid = -1; 86 private int mLastSideStagePosition = -1; 87 private int mLastSideStageUid = -1; 88 private float mLastSplitRatio = -1f; 89 private @SplitScreenController.SplitEnterReason int mEnterReason = ENTER_REASON_UNKNOWN; 90 SplitscreenEventLogger()91 public SplitscreenEventLogger() { 92 mIdSequence = new InstanceIdSequence(Integer.MAX_VALUE); 93 } 94 95 /** 96 * Return whether a splitscreen session has started. 97 */ hasStartedSession()98 public boolean hasStartedSession() { 99 return mLoggerSessionId != null; 100 } 101 isEnterRequestedByDrag()102 public boolean isEnterRequestedByDrag() { 103 return mEnterReason == ENTER_REASON_DRAG; 104 } 105 106 /** 107 * May be called before logEnter() to indicate that the session was started from a drag. 108 */ enterRequestedByDrag(@plitPosition int position, InstanceId enterSessionId)109 public void enterRequestedByDrag(@SplitPosition int position, InstanceId enterSessionId) { 110 mDragEnterPosition = position; 111 enterRequested(enterSessionId, ENTER_REASON_DRAG); 112 } 113 114 /** 115 * May be called before logEnter() to indicate that the session was started from launcher. 116 * This specifically is for all the scenarios where split started without a drag interaction 117 */ enterRequested(@ullable InstanceId enterSessionId, @SplitScreenController.SplitEnterReason int enterReason)118 public void enterRequested(@Nullable InstanceId enterSessionId, 119 @SplitScreenController.SplitEnterReason int enterReason) { 120 mEnterSessionId = enterSessionId; 121 mEnterReason = enterReason; 122 } 123 124 /** 125 * @return if an enterSessionId has been set via either 126 * {@link #enterRequested(InstanceId, int)} or 127 * {@link #enterRequestedByDrag(int, InstanceId)} 128 */ hasValidEnterSessionId()129 public boolean hasValidEnterSessionId() { 130 return mEnterSessionId != null; 131 } 132 133 /** 134 * Logs when the user enters splitscreen. 135 */ logEnter(float splitRatio, @SplitPosition int mainStagePosition, int mainStageUid, @SplitPosition int sideStagePosition, int sideStageUid, boolean isLandscape)136 public void logEnter(float splitRatio, 137 @SplitPosition int mainStagePosition, int mainStageUid, 138 @SplitPosition int sideStagePosition, int sideStageUid, 139 boolean isLandscape) { 140 if (hasStartedSession()) { 141 ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logEnter: no-op, previous session has not ended"); 142 return; 143 } 144 145 mLoggerSessionId = mIdSequence.newInstanceId(); 146 int enterReason = getLoggerEnterReason(isLandscape); 147 updateMainStageState(getMainStagePositionFromSplitPosition(mainStagePosition, isLandscape), 148 mainStageUid); 149 updateSideStageState(getSideStagePositionFromSplitPosition(sideStagePosition, isLandscape), 150 sideStageUid); 151 updateSplitRatioState(splitRatio); 152 153 ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logEnter: enterReason=%d splitRatio=%f " 154 + "mainStagePosition=%d mainStageUid=%d sideStagePosition=%d " 155 + "sideStageUid=%d isLandscape=%b mEnterSessionId=%d mLoggerSessionId=%d", 156 enterReason, splitRatio, mLastMainStagePosition, mLastMainStageUid, 157 mLastSideStagePosition, mLastSideStageUid, isLandscape, 158 mEnterSessionId != null ? mEnterSessionId.getId() : 0, mLoggerSessionId.getId()); 159 160 FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED, 161 FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__ENTER, 162 enterReason, 163 0 /* exitReason */, 164 splitRatio, 165 mLastMainStagePosition, 166 mLastMainStageUid, 167 mLastSideStagePosition, 168 mLastSideStageUid, 169 mEnterSessionId != null ? mEnterSessionId.getId() : 0, 170 mLoggerSessionId.getId()); 171 } 172 getLoggerEnterReason(boolean isLandscape)173 private int getLoggerEnterReason(boolean isLandscape) { 174 switch (mEnterReason) { 175 case ENTER_REASON_MULTI_INSTANCE: 176 return SPLITSCREEN_UICHANGED__ENTER_REASON__MULTI_INSTANCE; 177 case ENTER_REASON_LAUNCHER: 178 return SPLITSCREEN_UICHANGED__ENTER_REASON__LAUNCHER; 179 case ENTER_REASON_DRAG: 180 return getDragEnterReasonFromSplitPosition(mDragEnterPosition, isLandscape); 181 case ENTER_REASON_UNKNOWN: 182 default: 183 return SPLITSCREEN_UICHANGED__ENTER_REASON__UNKNOWN_ENTER; 184 } 185 } 186 187 /** 188 * Returns the framework logging constant given a splitscreen exit reason. 189 */ getLoggerExitReason(@xitReason int exitReason)190 private int getLoggerExitReason(@ExitReason int exitReason) { 191 switch (exitReason) { 192 case EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW: 193 return SPLITSCREEN_UICHANGED__EXIT_REASON__APP_DOES_NOT_SUPPORT_MULTIWINDOW; 194 case EXIT_REASON_APP_FINISHED: 195 return SPLITSCREEN_UICHANGED__EXIT_REASON__APP_FINISHED; 196 case EXIT_REASON_DEVICE_FOLDED: 197 return SPLITSCREEN_UICHANGED__EXIT_REASON__DEVICE_FOLDED; 198 case EXIT_REASON_DRAG_DIVIDER: 199 return SPLITSCREEN_UICHANGED__EXIT_REASON__DRAG_DIVIDER; 200 case EXIT_REASON_RETURN_HOME: 201 return SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME; 202 case EXIT_REASON_ROOT_TASK_VANISHED: 203 return SPLITSCREEN_UICHANGED__EXIT_REASON__ROOT_TASK_VANISHED; 204 case EXIT_REASON_SCREEN_LOCKED: 205 return SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED; 206 case EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP: 207 return SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED_SHOW_ON_TOP; 208 case EXIT_REASON_CHILD_TASK_ENTER_PIP: 209 return SPLITSCREEN_UICHANGED__EXIT_REASON__CHILD_TASK_ENTER_PIP; 210 case EXIT_REASON_RECREATE_SPLIT: 211 return SPLITSCREEN_UICHANGED__EXIT_REASON__RECREATE_SPLIT; 212 case EXIT_REASON_FULLSCREEN_SHORTCUT: 213 return SPLITSCREEN_UICHANGED__EXIT_REASON__FULLSCREEN_SHORTCUT; 214 case EXIT_REASON_DESKTOP_MODE: 215 return SPLITSCREEN_UICHANGED__EXIT_REASON__DESKTOP_MODE; 216 case EXIT_REASON_FULLSCREEN_REQUEST: 217 return SPLITSCREEN_UICHANGED__EXIT_REASON__FULLSCREEN_REQUEST; 218 case EXIT_REASON_UNKNOWN: 219 // Fall through 220 default: 221 Slog.e("SplitscreenEventLogger", "Unknown exit reason: " + exitReason); 222 return SPLITSCREEN_UICHANGED__EXIT_REASON__UNKNOWN_EXIT; 223 } 224 } 225 226 /** 227 * Logs when the user exits splitscreen. Only one of the main or side stages should be 228 * specified to indicate which position was focused as a part of exiting (both can be unset). 229 */ logExit(@xitReason int exitReason, @SplitPosition int mainStagePosition, int mainStageUid, @SplitPosition int sideStagePosition, int sideStageUid, boolean isLandscape)230 public void logExit(@ExitReason int exitReason, 231 @SplitPosition int mainStagePosition, int mainStageUid, 232 @SplitPosition int sideStagePosition, int sideStageUid, boolean isLandscape) { 233 if (mLoggerSessionId == null) { 234 ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logExit: no-op, mLoggerSessionId is null"); 235 // Ignore changes until we've started logging the session 236 return; 237 } 238 if ((mainStagePosition != SPLIT_POSITION_UNDEFINED 239 && sideStagePosition != SPLIT_POSITION_UNDEFINED) 240 || (mainStageUid != 0 && sideStageUid != 0)) { 241 ProtoLog.d(WM_SHELL_SPLIT_SCREEN, 242 "logExit: no-op, only main or side stage should be set, not both/none"); 243 throw new IllegalArgumentException("Only main or side stage should be set"); 244 } 245 246 ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logExit: exitReason=%d mainStagePosition=%d" 247 + " mainStageUid=%d sideStagePosition=%d sideStageUid=%d isLandscape=%b" 248 + " mLoggerSessionId=%d", getLoggerExitReason(exitReason), 249 getMainStagePositionFromSplitPosition(mainStagePosition, isLandscape), mainStageUid, 250 getSideStagePositionFromSplitPosition(sideStagePosition, isLandscape), sideStageUid, 251 isLandscape, mLoggerSessionId.getId()); 252 253 FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED, 254 FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__EXIT, 255 0 /* enterReason */, 256 getLoggerExitReason(exitReason), 257 0f /* splitRatio */, 258 getMainStagePositionFromSplitPosition(mainStagePosition, isLandscape), 259 mainStageUid, 260 getSideStagePositionFromSplitPosition(sideStagePosition, isLandscape), 261 sideStageUid, 262 0 /* dragInstanceId */, 263 mLoggerSessionId.getId()); 264 265 // Reset states 266 mLoggerSessionId = null; 267 mDragEnterPosition = SPLIT_POSITION_UNDEFINED; 268 mEnterSessionId = null; 269 mLastMainStagePosition = -1; 270 mLastMainStageUid = -1; 271 mLastSideStagePosition = -1; 272 mLastSideStageUid = -1; 273 mEnterReason = ENTER_REASON_UNKNOWN; 274 } 275 276 /** 277 * Logs when an app in the main stage changes. 278 */ logMainStageAppChange(@plitPosition int mainStagePosition, int mainStageUid, boolean isLandscape)279 public void logMainStageAppChange(@SplitPosition int mainStagePosition, int mainStageUid, 280 boolean isLandscape) { 281 if (mLoggerSessionId == null) { 282 // Ignore changes until we've started logging the session 283 return; 284 } 285 if (!updateMainStageState(getMainStagePositionFromSplitPosition(mainStagePosition, 286 isLandscape), mainStageUid)) { 287 // Ignore if there are no user perceived changes 288 return; 289 } 290 291 FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED, 292 FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__APP_CHANGE, 293 0 /* enterReason */, 294 0 /* exitReason */, 295 0f /* splitRatio */, 296 mLastMainStagePosition, 297 mLastMainStageUid, 298 0 /* sideStagePosition */, 299 0 /* sideStageUid */, 300 0 /* dragInstanceId */, 301 mLoggerSessionId.getId()); 302 } 303 304 /** 305 * Logs when an app in the side stage changes. 306 */ logSideStageAppChange(@plitPosition int sideStagePosition, int sideStageUid, boolean isLandscape)307 public void logSideStageAppChange(@SplitPosition int sideStagePosition, int sideStageUid, 308 boolean isLandscape) { 309 if (mLoggerSessionId == null) { 310 // Ignore changes until we've started logging the session 311 return; 312 } 313 if (!updateSideStageState(getSideStagePositionFromSplitPosition(sideStagePosition, 314 isLandscape), sideStageUid)) { 315 // Ignore if there are no user perceived changes 316 return; 317 } 318 319 FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED, 320 FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__APP_CHANGE, 321 0 /* enterReason */, 322 0 /* exitReason */, 323 0f /* splitRatio */, 324 0 /* mainStagePosition */, 325 0 /* mainStageUid */, 326 mLastSideStagePosition, 327 mLastSideStageUid, 328 0 /* dragInstanceId */, 329 mLoggerSessionId.getId()); 330 } 331 332 /** 333 * Logs when the splitscreen ratio changes. 334 */ logResize(float splitRatio)335 public void logResize(float splitRatio) { 336 if (mLoggerSessionId == null) { 337 ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logResize: no-op, mLoggerSessionId is null"); 338 // Ignore changes until we've started logging the session 339 return; 340 } 341 if (splitRatio <= 0f || splitRatio >= 1f) { 342 ProtoLog.d(WM_SHELL_SPLIT_SCREEN, 343 "logResize: no-op, splitRatio indicates that user is dismissing, not resizing"); 344 // Don't bother reporting resizes that end up dismissing the split, that will be logged 345 // via the exit event 346 return; 347 } 348 if (!updateSplitRatioState(splitRatio)) { 349 ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logResize: no-op, split ratio was not changed"); 350 // Ignore if there are no user perceived changes 351 return; 352 } 353 354 ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logResize: splitRatio=%f mLoggerSessionId=%d", 355 mLastSplitRatio, mLoggerSessionId.getId()); 356 FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED, 357 FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__RESIZE, 358 0 /* enterReason */, 359 0 /* exitReason */, 360 mLastSplitRatio, 361 mLastMainStagePosition, 362 mLastMainStageUid, 363 mLastSideStagePosition, 364 mLastSideStageUid, 365 0 /* dragInstanceId */, 366 mLoggerSessionId.getId()); 367 } 368 369 /** 370 * Logs when the apps in splitscreen are swapped. 371 */ logSwap(@plitPosition int mainStagePosition, int mainStageUid, @SplitPosition int sideStagePosition, int sideStageUid, boolean isLandscape)372 public void logSwap(@SplitPosition int mainStagePosition, int mainStageUid, 373 @SplitPosition int sideStagePosition, int sideStageUid, boolean isLandscape) { 374 if (mLoggerSessionId == null) { 375 ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logSwap: no-op, mLoggerSessionId is null"); 376 // Ignore changes until we've started logging the session 377 return; 378 } 379 380 updateMainStageState(getMainStagePositionFromSplitPosition(mainStagePosition, isLandscape), 381 mainStageUid); 382 updateSideStageState(getSideStagePositionFromSplitPosition(sideStagePosition, isLandscape), 383 sideStageUid); 384 385 ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logSwap: mainStagePosition=%d mainStageUid=%d " 386 + "sideStagePosition=%d sideStageUid=%d mLoggerSessionId=%d", 387 mLastMainStagePosition, mLastMainStageUid, mLastSideStagePosition, 388 mLastSideStageUid, mLoggerSessionId.getId()); 389 FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED, 390 FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__SWAP, 391 0 /* enterReason */, 392 0 /* exitReason */, 393 0f /* splitRatio */, 394 mLastMainStagePosition, 395 mLastMainStageUid, 396 mLastSideStagePosition, 397 mLastSideStageUid, 398 0 /* dragInstanceId */, 399 mLoggerSessionId.getId()); 400 } 401 updateMainStageState(int mainStagePosition, int mainStageUid)402 private boolean updateMainStageState(int mainStagePosition, int mainStageUid) { 403 boolean changed = (mLastMainStagePosition != mainStagePosition) 404 || (mLastMainStageUid != mainStageUid); 405 if (!changed) { 406 return false; 407 } 408 409 mLastMainStagePosition = mainStagePosition; 410 mLastMainStageUid = mainStageUid; 411 return true; 412 } 413 updateSideStageState(int sideStagePosition, int sideStageUid)414 private boolean updateSideStageState(int sideStagePosition, int sideStageUid) { 415 boolean changed = (mLastSideStagePosition != sideStagePosition) 416 || (mLastSideStageUid != sideStageUid); 417 if (!changed) { 418 return false; 419 } 420 421 mLastSideStagePosition = sideStagePosition; 422 mLastSideStageUid = sideStageUid; 423 return true; 424 } 425 updateSplitRatioState(float splitRatio)426 private boolean updateSplitRatioState(float splitRatio) { 427 boolean changed = Float.compare(mLastSplitRatio, splitRatio) != 0; 428 if (!changed) { 429 return false; 430 } 431 432 mLastSplitRatio = splitRatio; 433 return true; 434 } 435 getDragEnterReasonFromSplitPosition(@plitPosition int position, boolean isLandscape)436 public int getDragEnterReasonFromSplitPosition(@SplitPosition int position, 437 boolean isLandscape) { 438 if (isLandscape) { 439 return position == SPLIT_POSITION_TOP_OR_LEFT 440 ? FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__DRAG_LEFT 441 : FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__DRAG_RIGHT; 442 } else { 443 return position == SPLIT_POSITION_TOP_OR_LEFT 444 ? FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__DRAG_TOP 445 : FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__DRAG_BOTTOM; 446 } 447 } 448 getMainStagePositionFromSplitPosition(@plitPosition int position, boolean isLandscape)449 private int getMainStagePositionFromSplitPosition(@SplitPosition int position, 450 boolean isLandscape) { 451 if (position == SPLIT_POSITION_UNDEFINED) { 452 return 0; 453 } 454 if (isLandscape) { 455 return position == SPLIT_POSITION_TOP_OR_LEFT 456 ? FrameworkStatsLog.SPLITSCREEN_UICHANGED__MAIN_STAGE_POSITION__LEFT 457 : FrameworkStatsLog.SPLITSCREEN_UICHANGED__MAIN_STAGE_POSITION__RIGHT; 458 } else { 459 return position == SPLIT_POSITION_TOP_OR_LEFT 460 ? FrameworkStatsLog.SPLITSCREEN_UICHANGED__MAIN_STAGE_POSITION__TOP 461 : FrameworkStatsLog.SPLITSCREEN_UICHANGED__MAIN_STAGE_POSITION__BOTTOM; 462 } 463 } 464 getSideStagePositionFromSplitPosition(@plitPosition int position, boolean isLandscape)465 private int getSideStagePositionFromSplitPosition(@SplitPosition int position, 466 boolean isLandscape) { 467 if (position == SPLIT_POSITION_UNDEFINED) { 468 return 0; 469 } 470 if (isLandscape) { 471 return position == SPLIT_POSITION_TOP_OR_LEFT 472 ? FrameworkStatsLog.SPLITSCREEN_UICHANGED__SIDE_STAGE_POSITION__LEFT 473 : FrameworkStatsLog.SPLITSCREEN_UICHANGED__SIDE_STAGE_POSITION__RIGHT; 474 } else { 475 return position == SPLIT_POSITION_TOP_OR_LEFT 476 ? FrameworkStatsLog.SPLITSCREEN_UICHANGED__SIDE_STAGE_POSITION__TOP 477 : FrameworkStatsLog.SPLITSCREEN_UICHANGED__SIDE_STAGE_POSITION__BOTTOM; 478 } 479 } 480 } 481