Loading services/core/java/com/android/server/wm/AppCompatCameraStatePolicy.java +13 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.wm; import android.annotation.NonNull; import android.annotation.Nullable; /** * Interface that camera compat policies to implement to be notified of camera open/close signals. Loading @@ -23,8 +24,10 @@ import android.annotation.NonNull; interface AppCompatCameraStatePolicy { /** * Notifies the compat listener that a task has opened camera. * * @param appProcess The process in the {@link Task} which requested camera to be opened. */ void onCameraOpened(@NonNull ActivityRecord cameraActivity); void onCameraOpened(@NonNull WindowProcessController appProcess, @NonNull Task task); /** * Checks whether a listener is ready to do a cleanup when camera is closed. Loading @@ -35,10 +38,17 @@ interface AppCompatCameraStatePolicy { // change based on the cameraId - CameraStateMonitor should keep track of this. // This method actually checks "did an activity only temporarily close the camera", because a // refresh for compatibility is triggered. boolean canCameraBeClosed(@NonNull String cameraId); boolean canCameraBeClosed(@NonNull String cameraId, @NonNull Task task); /** * Notifies the compat listener that camera is closed. * * <p>Due to delays in notifying that camera is closed (currently 2 seconds), and the cause of * camera close could the that the task is closed, the app process and/or task might be null. As * parts of camera compat are done on activity level, application level, or even camera compat * policy level, the policies are notified even if the task or app are not active anymore. * * @param appProcess The process in the {@link Task} which requested camera to be opened. */ void onCameraClosed(); void onCameraClosed(@Nullable WindowProcessController appProcess, @Nullable Task task); } services/core/java/com/android/server/wm/AppCompatCameraStateSource.java +8 −7 Original line number Diff line number Diff line Loading @@ -16,7 +16,8 @@ package com.android.server.wm; import androidx.annotation.NonNull; import android.annotation.NonNull; import android.annotation.Nullable; import java.util.ArrayList; Loading @@ -37,9 +38,9 @@ class AppCompatCameraStateSource implements AppCompatCameraStatePolicy { } @Override public void onCameraOpened(@NonNull ActivityRecord cameraActivity) { public void onCameraOpened(@NonNull WindowProcessController appProcess, @NonNull Task task) { for (int i = 0; i < mCameraStatePolicies.size(); i++) { mCameraStatePolicies.get(i).onCameraOpened(cameraActivity); mCameraStatePolicies.get(i).onCameraOpened(appProcess, task); } } Loading @@ -47,9 +48,9 @@ class AppCompatCameraStateSource implements AppCompatCameraStatePolicy { * @return {@code false} if any listener has reported that they cannot process camera close now. */ @Override public boolean canCameraBeClosed(@NonNull String cameraId) { public boolean canCameraBeClosed(@NonNull String cameraId, @NonNull Task task) { for (int i = 0; i < mCameraStatePolicies.size(); i++) { if (!mCameraStatePolicies.get(i).canCameraBeClosed(cameraId)) { if (!mCameraStatePolicies.get(i).canCameraBeClosed(cameraId, task)) { return false; } } Loading @@ -57,9 +58,9 @@ class AppCompatCameraStateSource implements AppCompatCameraStatePolicy { } @Override public void onCameraClosed() { public void onCameraClosed(@Nullable WindowProcessController appProcess, @Nullable Task task) { for (int i = 0; i < mCameraStatePolicies.size(); i++) { mCameraStatePolicies.get(i).onCameraClosed(); mCameraStatePolicies.get(i).onCameraClosed(appProcess, task); } } } services/core/java/com/android/server/wm/AppCompatCameraStateStrategy.java +13 −7 Original line number Diff line number Diff line Loading @@ -22,12 +22,12 @@ import android.annotation.NonNull; * * <p>{@link AppCompatCameraStateStrategy} implementations should track which apps hold the camera * access, and any ongoing camera state changes changes. 'track' methods should always be called * before appropriate 'maybeNotify' methods for the same task-cameraId pair, but the order of * before appropriate 'notifyPolicy' methods for the same task-cameraId pair, but the order of * open/close can vary, for example due to built-in delays from the caller. */ interface AppCompatCameraStateStrategy { /** * Allows saving cameraId, to be processed later on * Allows saving information: task, process, cameraId, to be processed later on * {@link AppCompatCameraStateStrategy#notifyPolicyCameraOpenedIfNeeded} after a delay. * * <p>The {@link AppCompatCameraStateStrategy} should track which camera operations have been Loading @@ -36,18 +36,21 @@ interface AppCompatCameraStateStrategy { * processed. Examples of quickly closing and opening the camera: activity relaunch due to * configuration change, switching front/back cameras, new app requesting camera and taking the * access rights away from the existing camera app. * * @return CameraAppInfo of the app which opened the camera with given cameraId. */ void trackOnCameraOpened(@NonNull String cameraId); @NonNull CameraAppInfo trackOnCameraOpened(@NonNull String cameraId, @NonNull String packageName); /** * Processes camera opened signal, and if the change is relevant for {@link * AppCompatCameraStatePolicy} calls {@link AppCompatCameraStatePolicy#onCameraOpened}. */ void notifyPolicyCameraOpenedIfNeeded(@NonNull String cameraId, @NonNull String packageName, void notifyPolicyCameraOpenedIfNeeded(@NonNull CameraAppInfo cameraAppInfo, @NonNull AppCompatCameraStatePolicy policy); /** * Allows saving cameraId to be processed later on * Allows saving information: task, process, cameraId, to be processed later on * {@link AppCompatCameraStateStrategy#notifyPolicyCameraClosedIfNeeded} after a delay. * * <p>The {@link AppCompatCameraStateStrategy} should track which camera operations have been Loading @@ -56,8 +59,11 @@ interface AppCompatCameraStateStrategy { * processed. Examples of quickly closing and opening the camera: activity relaunch due to * configuration change, switching front/back cameras, new app requesting camera and taking the * access rights away from the existing camera app. * * @return CameraAppInfo of the app which closed the camera with given cameraId. */ void trackOnCameraClosed(@NonNull String cameraId); @NonNull CameraAppInfo trackOnCameraClosed(@NonNull String cameraId); /** Loading @@ -67,7 +73,7 @@ interface AppCompatCameraStateStrategy { * @return true if policies were able to handle the camera closed event, or false if it needs to * be rescheduled. */ boolean notifyPolicyCameraClosedIfNeeded(@NonNull String cameraId, boolean notifyPolicyCameraClosedIfNeeded(@NonNull CameraAppInfo cameraAppInfo, @NonNull AppCompatCameraStatePolicy policy); /** Returns whether a given activity holds any camera opened. */ Loading services/core/java/com/android/server/wm/AppCompatCameraStateStrategyForPackage.java +52 −15 Original line number Diff line number Diff line Loading @@ -15,6 +15,9 @@ */ package com.android.server.wm; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.os.Process.INVALID_PID; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; Loading Loading @@ -51,54 +54,74 @@ class AppCompatCameraStateStrategyForPackage implements AppCompatCameraStateStra } @Override public void trackOnCameraOpened(@NonNull String cameraId) { @NonNull public CameraAppInfo trackOnCameraOpened(@NonNull String cameraId, @NonNull String packageName) { mScheduledToBeRemovedCameraIdSet.remove(cameraId); mScheduledCompatModeUpdateCameraIdSet.add(cameraId); return createCameraAppInfo(cameraId, packageName); } @Override public void notifyPolicyCameraOpenedIfNeeded(@NonNull String cameraId, @NonNull String packageName, @NonNull AppCompatCameraStatePolicy policy) { if (!mScheduledCompatModeUpdateCameraIdSet.remove(cameraId)) { public void notifyPolicyCameraOpenedIfNeeded(@NonNull CameraAppInfo cameraAppInfo, @NonNull AppCompatCameraStatePolicy policy) { if (!mScheduledCompatModeUpdateCameraIdSet.remove(cameraAppInfo.mCameraId)) { // Camera compat mode update has happened already or was cancelled // because camera was closed. return; } mCameraIdPackageBiMapping.put(packageName, cameraId); // If there are multiple activities of the same package name and none of // them are the top running activity, we do not apply treatment (rather than // guessing and applying it to the wrong activity). final ActivityRecord cameraActivity = findUniqueActivityWithPackageName(packageName); if (cameraActivity == null) { final ActivityRecord cameraActivity = cameraAppInfo.mPackageName == null ? null : findUniqueActivityWithPackageName(cameraAppInfo.mPackageName); final Task task = cameraActivity == null ? null : cameraActivity.getTask(); final WindowProcessController app = cameraActivity == null ? null : cameraActivity.app; if (cameraActivity == null || task == null || app == null) { // If camera is active, activity, task and app process must exist. No need to notify // listeners or track the package otherwise. return; } policy.onCameraOpened(cameraActivity); mCameraIdPackageBiMapping.put(cameraAppInfo.mPackageName, cameraAppInfo.mCameraId); policy.onCameraOpened(app, task); } /** * @return CameraAppInfo of the app which opened camera with given cameraId. */ @Override public void trackOnCameraClosed(@NonNull String cameraId) { @NonNull public CameraAppInfo trackOnCameraClosed(@NonNull String cameraId) { mScheduledToBeRemovedCameraIdSet.add(cameraId); // No need to update window size for this camera if it's already closed. mScheduledCompatModeUpdateCameraIdSet.remove(cameraId); final String packageName = mCameraIdPackageBiMapping.getPackageNameForCameraId(cameraId); return createCameraAppInfo(cameraId, packageName); } @Override public boolean notifyPolicyCameraClosedIfNeeded(@NonNull String cameraId, public boolean notifyPolicyCameraClosedIfNeeded(@NonNull CameraAppInfo cameraAppInfo, @NonNull AppCompatCameraStatePolicy policy) { if (!mScheduledToBeRemovedCameraIdSet.remove(cameraId)) { if (!mScheduledToBeRemovedCameraIdSet.remove(cameraAppInfo.mCameraId)) { // Already reconnected to this camera, no need to clean up. return true; } final boolean canClose = policy.canCameraBeClosed(cameraId); final String packageName = mCameraIdPackageBiMapping.getPackageNameForCameraId(cameraAppInfo.mCameraId); final ActivityRecord activity = packageName == null ? null : findUniqueActivityWithPackageName(packageName); final Task task = activity == null ? null : activity.getTask(); final WindowProcessController app = activity == null ? null : activity.app; final boolean canClose = task == null || policy.canCameraBeClosed( cameraAppInfo.mCameraId, task); if (canClose) { // Finish cleaning up. mCameraIdPackageBiMapping.removeCameraId(cameraId); policy.onCameraClosed(); mCameraIdPackageBiMapping.removeCameraId(cameraAppInfo.mCameraId); policy.onCameraClosed(app, task); return true; } else { mScheduledToBeRemovedCameraIdSet.add(cameraId); mScheduledToBeRemovedCameraIdSet.add(cameraAppInfo.mCameraId); // Not ready to process closure yet - the camera activity might be refreshing. // Try again later. return false; Loading Loading @@ -163,4 +186,18 @@ class AppCompatCameraStateStrategyForPackage implements AppCompatCameraStateStra public String toString() { return "CameraIdPackageNameBiMapping=" + mCameraIdPackageBiMapping.toString(); } @NonNull private CameraAppInfo createCameraAppInfo(@NonNull String cameraId, @Nullable String packageName) { final ActivityRecord cameraActivity = packageName == null ? null : findUniqueActivityWithPackageName(packageName); final Task cameraTask = cameraActivity == null ? null : cameraActivity.getTask(); final WindowProcessController cameraApp = cameraActivity == null ? null : cameraActivity.app; return new CameraAppInfo(cameraId, cameraApp == null ? INVALID_PID : cameraApp.getPid(), cameraTask == null ? INVALID_TASK_ID : cameraTask.mTaskId, packageName); } } services/core/java/com/android/server/wm/CameraAppInfo.java 0 → 100644 +70 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.wm; import android.annotation.NonNull; import android.annotation.Nullable; import java.util.Objects; /** Data class to track apps and tasks which opened camera, for camera compat mode. */ final class CameraAppInfo { // ID of the camera the app is using. @NonNull final String mCameraId; // Process ID for the app which opened the camera. final int mPid; // Task ID for the app which opened the camera. final int mTaskId; // TODO(b/380840084): remove after refactoring flag is launched. @Nullable final String mPackageName; CameraAppInfo(@NonNull String cameraId, int pid, int taskId, @Nullable String packageName) { mCameraId = cameraId; mPid = pid; mTaskId = taskId; mPackageName = packageName; } @Override public int hashCode() { return Objects.hash(mCameraId, mPid, mTaskId, mPackageName); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof CameraAppInfo other)) { return false; } return mPid == other.mPid && mTaskId == other.mTaskId && Objects.equals(mCameraId, other.mCameraId) && Objects.equals(mPackageName, other.mPackageName); } @Override public String toString() { return "{mCameraId=" + mCameraId + ", mPid=" + mPid + ", mTaskId=" + mTaskId + ", mPackageName=" + mPackageName + "}"; } } Loading
services/core/java/com/android/server/wm/AppCompatCameraStatePolicy.java +13 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.wm; import android.annotation.NonNull; import android.annotation.Nullable; /** * Interface that camera compat policies to implement to be notified of camera open/close signals. Loading @@ -23,8 +24,10 @@ import android.annotation.NonNull; interface AppCompatCameraStatePolicy { /** * Notifies the compat listener that a task has opened camera. * * @param appProcess The process in the {@link Task} which requested camera to be opened. */ void onCameraOpened(@NonNull ActivityRecord cameraActivity); void onCameraOpened(@NonNull WindowProcessController appProcess, @NonNull Task task); /** * Checks whether a listener is ready to do a cleanup when camera is closed. Loading @@ -35,10 +38,17 @@ interface AppCompatCameraStatePolicy { // change based on the cameraId - CameraStateMonitor should keep track of this. // This method actually checks "did an activity only temporarily close the camera", because a // refresh for compatibility is triggered. boolean canCameraBeClosed(@NonNull String cameraId); boolean canCameraBeClosed(@NonNull String cameraId, @NonNull Task task); /** * Notifies the compat listener that camera is closed. * * <p>Due to delays in notifying that camera is closed (currently 2 seconds), and the cause of * camera close could the that the task is closed, the app process and/or task might be null. As * parts of camera compat are done on activity level, application level, or even camera compat * policy level, the policies are notified even if the task or app are not active anymore. * * @param appProcess The process in the {@link Task} which requested camera to be opened. */ void onCameraClosed(); void onCameraClosed(@Nullable WindowProcessController appProcess, @Nullable Task task); }
services/core/java/com/android/server/wm/AppCompatCameraStateSource.java +8 −7 Original line number Diff line number Diff line Loading @@ -16,7 +16,8 @@ package com.android.server.wm; import androidx.annotation.NonNull; import android.annotation.NonNull; import android.annotation.Nullable; import java.util.ArrayList; Loading @@ -37,9 +38,9 @@ class AppCompatCameraStateSource implements AppCompatCameraStatePolicy { } @Override public void onCameraOpened(@NonNull ActivityRecord cameraActivity) { public void onCameraOpened(@NonNull WindowProcessController appProcess, @NonNull Task task) { for (int i = 0; i < mCameraStatePolicies.size(); i++) { mCameraStatePolicies.get(i).onCameraOpened(cameraActivity); mCameraStatePolicies.get(i).onCameraOpened(appProcess, task); } } Loading @@ -47,9 +48,9 @@ class AppCompatCameraStateSource implements AppCompatCameraStatePolicy { * @return {@code false} if any listener has reported that they cannot process camera close now. */ @Override public boolean canCameraBeClosed(@NonNull String cameraId) { public boolean canCameraBeClosed(@NonNull String cameraId, @NonNull Task task) { for (int i = 0; i < mCameraStatePolicies.size(); i++) { if (!mCameraStatePolicies.get(i).canCameraBeClosed(cameraId)) { if (!mCameraStatePolicies.get(i).canCameraBeClosed(cameraId, task)) { return false; } } Loading @@ -57,9 +58,9 @@ class AppCompatCameraStateSource implements AppCompatCameraStatePolicy { } @Override public void onCameraClosed() { public void onCameraClosed(@Nullable WindowProcessController appProcess, @Nullable Task task) { for (int i = 0; i < mCameraStatePolicies.size(); i++) { mCameraStatePolicies.get(i).onCameraClosed(); mCameraStatePolicies.get(i).onCameraClosed(appProcess, task); } } }
services/core/java/com/android/server/wm/AppCompatCameraStateStrategy.java +13 −7 Original line number Diff line number Diff line Loading @@ -22,12 +22,12 @@ import android.annotation.NonNull; * * <p>{@link AppCompatCameraStateStrategy} implementations should track which apps hold the camera * access, and any ongoing camera state changes changes. 'track' methods should always be called * before appropriate 'maybeNotify' methods for the same task-cameraId pair, but the order of * before appropriate 'notifyPolicy' methods for the same task-cameraId pair, but the order of * open/close can vary, for example due to built-in delays from the caller. */ interface AppCompatCameraStateStrategy { /** * Allows saving cameraId, to be processed later on * Allows saving information: task, process, cameraId, to be processed later on * {@link AppCompatCameraStateStrategy#notifyPolicyCameraOpenedIfNeeded} after a delay. * * <p>The {@link AppCompatCameraStateStrategy} should track which camera operations have been Loading @@ -36,18 +36,21 @@ interface AppCompatCameraStateStrategy { * processed. Examples of quickly closing and opening the camera: activity relaunch due to * configuration change, switching front/back cameras, new app requesting camera and taking the * access rights away from the existing camera app. * * @return CameraAppInfo of the app which opened the camera with given cameraId. */ void trackOnCameraOpened(@NonNull String cameraId); @NonNull CameraAppInfo trackOnCameraOpened(@NonNull String cameraId, @NonNull String packageName); /** * Processes camera opened signal, and if the change is relevant for {@link * AppCompatCameraStatePolicy} calls {@link AppCompatCameraStatePolicy#onCameraOpened}. */ void notifyPolicyCameraOpenedIfNeeded(@NonNull String cameraId, @NonNull String packageName, void notifyPolicyCameraOpenedIfNeeded(@NonNull CameraAppInfo cameraAppInfo, @NonNull AppCompatCameraStatePolicy policy); /** * Allows saving cameraId to be processed later on * Allows saving information: task, process, cameraId, to be processed later on * {@link AppCompatCameraStateStrategy#notifyPolicyCameraClosedIfNeeded} after a delay. * * <p>The {@link AppCompatCameraStateStrategy} should track which camera operations have been Loading @@ -56,8 +59,11 @@ interface AppCompatCameraStateStrategy { * processed. Examples of quickly closing and opening the camera: activity relaunch due to * configuration change, switching front/back cameras, new app requesting camera and taking the * access rights away from the existing camera app. * * @return CameraAppInfo of the app which closed the camera with given cameraId. */ void trackOnCameraClosed(@NonNull String cameraId); @NonNull CameraAppInfo trackOnCameraClosed(@NonNull String cameraId); /** Loading @@ -67,7 +73,7 @@ interface AppCompatCameraStateStrategy { * @return true if policies were able to handle the camera closed event, or false if it needs to * be rescheduled. */ boolean notifyPolicyCameraClosedIfNeeded(@NonNull String cameraId, boolean notifyPolicyCameraClosedIfNeeded(@NonNull CameraAppInfo cameraAppInfo, @NonNull AppCompatCameraStatePolicy policy); /** Returns whether a given activity holds any camera opened. */ Loading
services/core/java/com/android/server/wm/AppCompatCameraStateStrategyForPackage.java +52 −15 Original line number Diff line number Diff line Loading @@ -15,6 +15,9 @@ */ package com.android.server.wm; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.os.Process.INVALID_PID; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; Loading Loading @@ -51,54 +54,74 @@ class AppCompatCameraStateStrategyForPackage implements AppCompatCameraStateStra } @Override public void trackOnCameraOpened(@NonNull String cameraId) { @NonNull public CameraAppInfo trackOnCameraOpened(@NonNull String cameraId, @NonNull String packageName) { mScheduledToBeRemovedCameraIdSet.remove(cameraId); mScheduledCompatModeUpdateCameraIdSet.add(cameraId); return createCameraAppInfo(cameraId, packageName); } @Override public void notifyPolicyCameraOpenedIfNeeded(@NonNull String cameraId, @NonNull String packageName, @NonNull AppCompatCameraStatePolicy policy) { if (!mScheduledCompatModeUpdateCameraIdSet.remove(cameraId)) { public void notifyPolicyCameraOpenedIfNeeded(@NonNull CameraAppInfo cameraAppInfo, @NonNull AppCompatCameraStatePolicy policy) { if (!mScheduledCompatModeUpdateCameraIdSet.remove(cameraAppInfo.mCameraId)) { // Camera compat mode update has happened already or was cancelled // because camera was closed. return; } mCameraIdPackageBiMapping.put(packageName, cameraId); // If there are multiple activities of the same package name and none of // them are the top running activity, we do not apply treatment (rather than // guessing and applying it to the wrong activity). final ActivityRecord cameraActivity = findUniqueActivityWithPackageName(packageName); if (cameraActivity == null) { final ActivityRecord cameraActivity = cameraAppInfo.mPackageName == null ? null : findUniqueActivityWithPackageName(cameraAppInfo.mPackageName); final Task task = cameraActivity == null ? null : cameraActivity.getTask(); final WindowProcessController app = cameraActivity == null ? null : cameraActivity.app; if (cameraActivity == null || task == null || app == null) { // If camera is active, activity, task and app process must exist. No need to notify // listeners or track the package otherwise. return; } policy.onCameraOpened(cameraActivity); mCameraIdPackageBiMapping.put(cameraAppInfo.mPackageName, cameraAppInfo.mCameraId); policy.onCameraOpened(app, task); } /** * @return CameraAppInfo of the app which opened camera with given cameraId. */ @Override public void trackOnCameraClosed(@NonNull String cameraId) { @NonNull public CameraAppInfo trackOnCameraClosed(@NonNull String cameraId) { mScheduledToBeRemovedCameraIdSet.add(cameraId); // No need to update window size for this camera if it's already closed. mScheduledCompatModeUpdateCameraIdSet.remove(cameraId); final String packageName = mCameraIdPackageBiMapping.getPackageNameForCameraId(cameraId); return createCameraAppInfo(cameraId, packageName); } @Override public boolean notifyPolicyCameraClosedIfNeeded(@NonNull String cameraId, public boolean notifyPolicyCameraClosedIfNeeded(@NonNull CameraAppInfo cameraAppInfo, @NonNull AppCompatCameraStatePolicy policy) { if (!mScheduledToBeRemovedCameraIdSet.remove(cameraId)) { if (!mScheduledToBeRemovedCameraIdSet.remove(cameraAppInfo.mCameraId)) { // Already reconnected to this camera, no need to clean up. return true; } final boolean canClose = policy.canCameraBeClosed(cameraId); final String packageName = mCameraIdPackageBiMapping.getPackageNameForCameraId(cameraAppInfo.mCameraId); final ActivityRecord activity = packageName == null ? null : findUniqueActivityWithPackageName(packageName); final Task task = activity == null ? null : activity.getTask(); final WindowProcessController app = activity == null ? null : activity.app; final boolean canClose = task == null || policy.canCameraBeClosed( cameraAppInfo.mCameraId, task); if (canClose) { // Finish cleaning up. mCameraIdPackageBiMapping.removeCameraId(cameraId); policy.onCameraClosed(); mCameraIdPackageBiMapping.removeCameraId(cameraAppInfo.mCameraId); policy.onCameraClosed(app, task); return true; } else { mScheduledToBeRemovedCameraIdSet.add(cameraId); mScheduledToBeRemovedCameraIdSet.add(cameraAppInfo.mCameraId); // Not ready to process closure yet - the camera activity might be refreshing. // Try again later. return false; Loading Loading @@ -163,4 +186,18 @@ class AppCompatCameraStateStrategyForPackage implements AppCompatCameraStateStra public String toString() { return "CameraIdPackageNameBiMapping=" + mCameraIdPackageBiMapping.toString(); } @NonNull private CameraAppInfo createCameraAppInfo(@NonNull String cameraId, @Nullable String packageName) { final ActivityRecord cameraActivity = packageName == null ? null : findUniqueActivityWithPackageName(packageName); final Task cameraTask = cameraActivity == null ? null : cameraActivity.getTask(); final WindowProcessController cameraApp = cameraActivity == null ? null : cameraActivity.app; return new CameraAppInfo(cameraId, cameraApp == null ? INVALID_PID : cameraApp.getPid(), cameraTask == null ? INVALID_TASK_ID : cameraTask.mTaskId, packageName); } }
services/core/java/com/android/server/wm/CameraAppInfo.java 0 → 100644 +70 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.wm; import android.annotation.NonNull; import android.annotation.Nullable; import java.util.Objects; /** Data class to track apps and tasks which opened camera, for camera compat mode. */ final class CameraAppInfo { // ID of the camera the app is using. @NonNull final String mCameraId; // Process ID for the app which opened the camera. final int mPid; // Task ID for the app which opened the camera. final int mTaskId; // TODO(b/380840084): remove after refactoring flag is launched. @Nullable final String mPackageName; CameraAppInfo(@NonNull String cameraId, int pid, int taskId, @Nullable String packageName) { mCameraId = cameraId; mPid = pid; mTaskId = taskId; mPackageName = packageName; } @Override public int hashCode() { return Objects.hash(mCameraId, mPid, mTaskId, mPackageName); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof CameraAppInfo other)) { return false; } return mPid == other.mPid && mTaskId == other.mTaskId && Objects.equals(mCameraId, other.mCameraId) && Objects.equals(mPackageName, other.mPackageName); } @Override public String toString() { return "{mCameraId=" + mCameraId + ", mPid=" + mPid + ", mTaskId=" + mTaskId + ", mPackageName=" + mPackageName + "}"; } }