All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.com.android.server.display.DisplayDeviceRepository Maven / Gradle / Ivy

/*
 * Copyright (C) 2020 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.display;

import android.annotation.NonNull;
import android.os.Trace;
import android.util.Slog;
import android.view.Display;
import android.view.DisplayAddress;

import com.android.internal.annotations.GuardedBy;
import com.android.server.display.DisplayManagerService.SyncRoot;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * Container for all the display devices present in the system.  If an object wants to get events
 * about all the DisplayDevices without needing to listen to all of the DisplayAdapters, they can
 * listen and interact with the instance of this class.
 * 

* The collection of {@link DisplayDevice}s and their usage is protected by the provided * {@link DisplayManagerService.SyncRoot} lock object. */ class DisplayDeviceRepository implements DisplayAdapter.Listener { private static final String TAG = "DisplayDeviceRepository"; private static final Boolean DEBUG = false; public static final int DISPLAY_DEVICE_EVENT_ADDED = 1; public static final int DISPLAY_DEVICE_EVENT_CHANGED = 2; public static final int DISPLAY_DEVICE_EVENT_REMOVED = 3; /** * List of all currently connected display devices. Indexed by the displayId. * TODO: multi-display - break the notion that this is indexed by displayId. */ @GuardedBy("mSyncRoot") private final List mDisplayDevices = new ArrayList<>(); /** Listeners for {link DisplayDevice} events. */ @GuardedBy("mSyncRoot") private final List mListeners = new ArrayList<>(); /** Global lock object from {@link DisplayManagerService}. */ private final SyncRoot mSyncRoot; private final PersistentDataStore mPersistentDataStore; /** * @param syncRoot The global lock for DisplayManager related objects. * @param persistentDataStore Settings data store from {@link DisplayManagerService}. */ DisplayDeviceRepository(@NonNull SyncRoot syncRoot, @NonNull PersistentDataStore persistentDataStore) { mSyncRoot = syncRoot; mPersistentDataStore = persistentDataStore; } public void addListener(@NonNull Listener listener) { mListeners.add(listener); } @Override public void onDisplayDeviceEvent(DisplayDevice device, int event) { String tag = null; if (DEBUG) { tag = "DisplayDeviceRepository#onDisplayDeviceEvent (event=" + event + ")"; Trace.beginAsyncSection(tag, 0); } switch (event) { case DISPLAY_DEVICE_EVENT_ADDED: handleDisplayDeviceAdded(device); break; case DISPLAY_DEVICE_EVENT_CHANGED: handleDisplayDeviceChanged(device); break; case DISPLAY_DEVICE_EVENT_REMOVED: handleDisplayDeviceRemoved(device); break; } if (DEBUG) { Trace.endAsyncSection(tag, 0); } } @Override public void onTraversalRequested() { final int size = mListeners.size(); for (int i = 0; i < size; i++) { mListeners.get(i).onTraversalRequested(); } } public boolean containsLocked(DisplayDevice d) { return mDisplayDevices.contains(d); } public int sizeLocked() { return mDisplayDevices.size(); } public void forEachLocked(Consumer consumer) { final int count = mDisplayDevices.size(); for (int i = 0; i < count; i++) { consumer.accept(mDisplayDevices.get(i)); } } public DisplayDevice getByAddressLocked(@NonNull DisplayAddress address) { for (int i = mDisplayDevices.size() - 1; i >= 0; i--) { final DisplayDevice device = mDisplayDevices.get(i); if (address.equals(device.getDisplayDeviceInfoLocked().address)) { return device; } } return null; } // String uniqueId -> DisplayDevice object with that given uniqueId public DisplayDevice getByUniqueIdLocked(@NonNull String uniqueId) { for (int i = mDisplayDevices.size() - 1; i >= 0; i--) { final DisplayDevice displayDevice = mDisplayDevices.get(i); if (displayDevice.getUniqueId().equals(uniqueId)) { return displayDevice; } } return null; } private void handleDisplayDeviceAdded(DisplayDevice device) { synchronized (mSyncRoot) { DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); if (mDisplayDevices.contains(device)) { Slog.w(TAG, "Attempted to add already added display device: " + info); return; } Slog.i(TAG, "Display device added: " + info); device.mDebugLastLoggedDeviceInfo = info; mDisplayDevices.add(device); sendEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED); } } private void handleDisplayDeviceChanged(DisplayDevice device) { synchronized (mSyncRoot) { final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); if (!mDisplayDevices.contains(device)) { Slog.w(TAG, "Attempted to change non-existent display device: " + info); return; } if (DEBUG) { Trace.beginSection("handleDisplayDeviceChanged"); } int diff = device.mDebugLastLoggedDeviceInfo.diff(info); if (diff == DisplayDeviceInfo.DIFF_STATE) { Slog.i(TAG, "Display device changed state: \"" + info.name + "\", " + Display.stateToString(info.state)); } else if (diff != 0) { Slog.i(TAG, "Display device changed: " + info); } if ((diff & DisplayDeviceInfo.DIFF_COLOR_MODE) != 0) { try { mPersistentDataStore.setColorMode(device, info.colorMode); } finally { mPersistentDataStore.saveIfNeeded(); } } device.mDebugLastLoggedDeviceInfo = info; device.applyPendingDisplayDeviceInfoChangesLocked(); sendEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED); if (DEBUG) { Trace.endSection(); } } } private void handleDisplayDeviceRemoved(DisplayDevice device) { synchronized (mSyncRoot) { DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); if (!mDisplayDevices.remove(device)) { Slog.w(TAG, "Attempted to remove non-existent display device: " + info); return; } Slog.i(TAG, "Display device removed: " + info); device.mDebugLastLoggedDeviceInfo = info; sendEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED); } } private void sendEventLocked(DisplayDevice device, int event) { final int size = mListeners.size(); for (int i = 0; i < size; i++) { mListeners.get(i).onDisplayDeviceEventLocked(device, event); } } /** * Listens to {@link DisplayDevice} events from {@link DisplayDeviceRepository}. */ public interface Listener { void onDisplayDeviceEventLocked(DisplayDevice device, int event); // TODO: multi-display - Try to remove the need for requestTraversal...it feels like // a shoe-horned method for a shoe-horned feature. void onTraversalRequested(); }; }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy