Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3d21c809 authored by Kurt Dresner's avatar Kurt Dresner
Browse files

Add projection state APIs to UiModeManager and UiModeManagerService.

Bug: 134997071
Bug: 169702986
Test: Code builds, runs, unit tests added for new functionality.
Change-Id: I29cfb198101cdc5d1f4de84f8701928643b756c3
parent ef3da571
Loading
Loading
Loading
Loading
+41 −27
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.job.controllers.idle;

import static android.app.UiModeManager.PROJECTION_TYPE_NONE;

import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;

import android.app.AlarmManager;
@@ -34,7 +36,9 @@ import com.android.server.job.JobSchedulerService;
import com.android.server.job.StateControllerProto;

import java.io.PrintWriter;
import java.util.Set;

/** Class to track device idle state. */
public final class DeviceIdlenessTracker extends BroadcastReceiver implements IdlenessTracker {
    private static final String TAG = "JobScheduler.DeviceIdlenessTracker";
    private static final boolean DEBUG = JobSchedulerService.DEBUG
@@ -50,8 +54,10 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id
    private boolean mIdle;
    private boolean mScreenOn;
    private boolean mDockIdle;
    private boolean mInCarMode;
    private boolean mProjectionActive;
    private IdlenessListener mIdleListener;
    private final UiModeManager.OnProjectionStateChangeListener mOnProjectionStateChangeListener =
            this::onProjectionStateChanged;

    private AlarmManager.OnAlarmListener mIdleAlarmListener = () -> {
        handleIdleTrigger();
@@ -60,10 +66,7 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id
    public DeviceIdlenessTracker() {
        // At boot we presume that the user has just "interacted" with the
        // device in some meaningful way.
        mIdle = false;
        mScreenOn = true;
        mDockIdle = false;
        mInCarMode = false;
    }

    @Override
@@ -98,11 +101,34 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id
        filter.addAction(Intent.ACTION_DOCK_IDLE);
        filter.addAction(Intent.ACTION_DOCK_ACTIVE);

        // Car mode
        filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE_PRIORITIZED);
        filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE_PRIORITIZED);

        context.registerReceiver(this, filter);

        // TODO(b/172579710): Move the callbacks off the main executor and on to
        //  JobSchedulerBackgroundThread.getExecutor() once synchronization is fixed in this class.
        context.getSystemService(UiModeManager.class).addOnProjectionStateChangeListener(
                UiModeManager.PROJECTION_TYPE_ALL, context.getMainExecutor(),
                mOnProjectionStateChangeListener);
    }

    private void onProjectionStateChanged(@UiModeManager.ProjectionType int activeProjectionTypes,
            Set<String> projectingPackages) {
        boolean projectionActive = activeProjectionTypes != PROJECTION_TYPE_NONE;
        if (mProjectionActive == projectionActive) {
            return;
        }
        if (DEBUG) {
            Slog.v(TAG, "Projection state changed: " + projectionActive);
        }
        mProjectionActive = projectionActive;
        if (mProjectionActive) {
            cancelIdlenessCheck();
            if (mIdle) {
                mIdle = false;
                mIdleListener.reportNewIdleState(mIdle);
            }
        } else {
            maybeScheduleIdlenessCheck("Projection ended");
        }
    }

    @Override
@@ -110,8 +136,7 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id
        pw.print("  mIdle: "); pw.println(mIdle);
        pw.print("  mScreenOn: "); pw.println(mScreenOn);
        pw.print("  mDockIdle: "); pw.println(mDockIdle);
        pw.print("  mInCarMode: ");
        pw.println(mInCarMode);
        pw.print("  mProjectionActive: "); pw.println(mProjectionActive);
    }

    @Override
@@ -129,8 +154,9 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id
                StateControllerProto.IdleController.IdlenessTracker.DeviceIdlenessTracker.IS_DOCK_IDLE,
                mDockIdle);
        proto.write(
                StateControllerProto.IdleController.IdlenessTracker.DeviceIdlenessTracker.IN_CAR_MODE,
                mInCarMode);
                StateControllerProto.IdleController.IdlenessTracker.DeviceIdlenessTracker
                        .PROJECTION_ACTIVE,
                mProjectionActive);

        proto.end(diToken);
        proto.end(token);
@@ -186,18 +212,6 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id
                }
                maybeScheduleIdlenessCheck(action);
                break;
            case UiModeManager.ACTION_ENTER_CAR_MODE_PRIORITIZED:
                mInCarMode = true;
                cancelIdlenessCheck();
                if (mIdle) {
                    mIdle = false;
                    mIdleListener.reportNewIdleState(mIdle);
                }
                break;
            case UiModeManager.ACTION_EXIT_CAR_MODE_PRIORITIZED:
                mInCarMode = false;
                maybeScheduleIdlenessCheck(action);
                break;
            case ActivityManagerService.ACTION_TRIGGER_IDLE:
                handleIdleTrigger();
                break;
@@ -205,7 +219,7 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id
    }

    private void maybeScheduleIdlenessCheck(String reason) {
        if ((!mScreenOn || mDockIdle) && !mInCarMode) {
        if ((!mScreenOn || mDockIdle) && !mProjectionActive) {
            final long nowElapsed = sElapsedRealtimeClock.millis();
            final long when = nowElapsed + mInactivityIdleThreshold;
            if (DEBUG) {
@@ -222,7 +236,7 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id

    private void handleIdleTrigger() {
        // idle time starts now. Do not set mIdle if screen is on.
        if (!mIdle && (!mScreenOn || mDockIdle) && !mInCarMode) {
        if (!mIdle && (!mScreenOn || mDockIdle) && !mProjectionActive) {
            if (DEBUG) {
                Slog.v(TAG, "Idle trigger fired @ " + sElapsedRealtimeClock.millis());
            }
@@ -231,7 +245,7 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id
        } else {
            if (DEBUG) {
                Slog.v(TAG, "TRIGGER_IDLE received but not changing state; idle="
                        + mIdle + " screen=" + mScreenOn + " car=" + mInCarMode);
                        + mIdle + " screen=" + mScreenOn + " projection=" + mProjectionActive);
            }
        }
    }
+10 −0
Original line number Diff line number Diff line
@@ -182,6 +182,7 @@ package android {
    field public static final String READ_PRINT_SERVICES = "android.permission.READ_PRINT_SERVICES";
    field public static final String READ_PRINT_SERVICE_RECOMMENDATIONS = "android.permission.READ_PRINT_SERVICE_RECOMMENDATIONS";
    field public static final String READ_PRIVILEGED_PHONE_STATE = "android.permission.READ_PRIVILEGED_PHONE_STATE";
    field public static final String READ_PROJECTION_STATE = "android.permission.READ_PROJECTION_STATE";
    field public static final String READ_RUNTIME_PROFILES = "android.permission.READ_RUNTIME_PROFILES";
    field public static final String READ_SEARCH_INDEXABLES = "android.permission.READ_SEARCH_INDEXABLES";
    field public static final String READ_SYSTEM_UPDATE_INFO = "android.permission.READ_SYSTEM_UPDATE_INFO";
@@ -234,6 +235,7 @@ package android {
    field public static final String SUSPEND_APPS = "android.permission.SUSPEND_APPS";
    field public static final String SYSTEM_CAMERA = "android.permission.SYSTEM_CAMERA";
    field public static final String TETHER_PRIVILEGED = "android.permission.TETHER_PRIVILEGED";
    field public static final String TOGGLE_AUTOMOTIVE_PROJECTION = "android.permission.TOGGLE_AUTOMOTIVE_PROJECTION";
    field public static final String TV_INPUT_HARDWARE = "android.permission.TV_INPUT_HARDWARE";
    field public static final String TV_VIRTUAL_REMOTE_CONTROLLER = "android.permission.TV_VIRTUAL_REMOTE_CONTROLLER";
    field public static final String UNLIMITED_SHORTCUTS_API_CALLS = "android.permission.UNLIMITED_SHORTCUTS_API_CALLS";
@@ -796,7 +798,11 @@ package android.app {
  }
  public class UiModeManager {
    method @RequiresPermission(android.Manifest.permission.READ_PROJECTION_STATE) public void addOnProjectionStateChangeListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.app.UiModeManager.OnProjectionStateChangeListener);
    method @RequiresPermission(android.Manifest.permission.ENTER_CAR_MODE_PRIORITIZED) public void enableCarMode(@IntRange(from=0) int, int);
    method @RequiresPermission(android.Manifest.permission.READ_PROJECTION_STATE) public int getActiveProjectionTypes();
    method @NonNull @RequiresPermission(android.Manifest.permission.READ_PROJECTION_STATE) public java.util.Set<java.lang.String> getProjectingPackages(int);
    method @RequiresPermission(android.Manifest.permission.READ_PROJECTION_STATE) public void removeOnProjectionStateChangeListener(@NonNull android.app.UiModeManager.OnProjectionStateChangeListener);
    field public static final String ACTION_ENTER_CAR_MODE_PRIORITIZED = "android.app.action.ENTER_CAR_MODE_PRIORITIZED";
    field public static final String ACTION_EXIT_CAR_MODE_PRIORITIZED = "android.app.action.EXIT_CAR_MODE_PRIORITIZED";
    field public static final int DEFAULT_PRIORITY = 0; // 0x0
@@ -804,6 +810,10 @@ package android.app {
    field public static final String EXTRA_PRIORITY = "android.app.extra.PRIORITY";
  }
  public static interface UiModeManager.OnProjectionStateChangeListener {
    method public void onProjectionStateChanged(int, @NonNull java.util.Set<java.lang.String>);
  }
  public final class Vr2dDisplayProperties implements android.os.Parcelable {
    ctor public Vr2dDisplayProperties(int, int, int);
    method public int describeContents();
+10 −0
Original line number Diff line number Diff line
@@ -182,6 +182,7 @@ package android {
    field public static final String READ_PRINT_SERVICES = "android.permission.READ_PRINT_SERVICES";
    field public static final String READ_PRINT_SERVICE_RECOMMENDATIONS = "android.permission.READ_PRINT_SERVICE_RECOMMENDATIONS";
    field public static final String READ_PRIVILEGED_PHONE_STATE = "android.permission.READ_PRIVILEGED_PHONE_STATE";
    field public static final String READ_PROJECTION_STATE = "android.permission.READ_PROJECTION_STATE";
    field public static final String READ_RUNTIME_PROFILES = "android.permission.READ_RUNTIME_PROFILES";
    field public static final String READ_SEARCH_INDEXABLES = "android.permission.READ_SEARCH_INDEXABLES";
    field public static final String READ_SYSTEM_UPDATE_INFO = "android.permission.READ_SYSTEM_UPDATE_INFO";
@@ -234,6 +235,7 @@ package android {
    field public static final String SUSPEND_APPS = "android.permission.SUSPEND_APPS";
    field public static final String SYSTEM_CAMERA = "android.permission.SYSTEM_CAMERA";
    field public static final String TETHER_PRIVILEGED = "android.permission.TETHER_PRIVILEGED";
    field public static final String TOGGLE_AUTOMOTIVE_PROJECTION = "android.permission.TOGGLE_AUTOMOTIVE_PROJECTION";
    field public static final String TV_INPUT_HARDWARE = "android.permission.TV_INPUT_HARDWARE";
    field public static final String TV_VIRTUAL_REMOTE_CONTROLLER = "android.permission.TV_VIRTUAL_REMOTE_CONTROLLER";
    field public static final String UNLIMITED_SHORTCUTS_API_CALLS = "android.permission.UNLIMITED_SHORTCUTS_API_CALLS";
@@ -744,7 +746,11 @@ package android.app {
  }
  public class UiModeManager {
    method @RequiresPermission(android.Manifest.permission.READ_PROJECTION_STATE) public void addOnProjectionStateChangeListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.app.UiModeManager.OnProjectionStateChangeListener);
    method @RequiresPermission(android.Manifest.permission.ENTER_CAR_MODE_PRIORITIZED) public void enableCarMode(@IntRange(from=0) int, int);
    method @RequiresPermission(android.Manifest.permission.READ_PROJECTION_STATE) public int getActiveProjectionTypes();
    method @NonNull @RequiresPermission(android.Manifest.permission.READ_PROJECTION_STATE) public java.util.Set<java.lang.String> getProjectingPackages(int);
    method @RequiresPermission(android.Manifest.permission.READ_PROJECTION_STATE) public void removeOnProjectionStateChangeListener(@NonNull android.app.UiModeManager.OnProjectionStateChangeListener);
    field public static final String ACTION_ENTER_CAR_MODE_PRIORITIZED = "android.app.action.ENTER_CAR_MODE_PRIORITIZED";
    field public static final String ACTION_EXIT_CAR_MODE_PRIORITIZED = "android.app.action.EXIT_CAR_MODE_PRIORITIZED";
    field public static final int DEFAULT_PRIORITY = 0; // 0x0
@@ -752,6 +758,10 @@ package android.app {
    field public static final String EXTRA_PRIORITY = "android.app.extra.PRIORITY";
  }
  public static interface UiModeManager.OnProjectionStateChangeListener {
    method public void onProjectionStateChanged(int, @NonNull java.util.Set<java.lang.String>);
  }
  public final class Vr2dDisplayProperties implements android.os.Parcelable {
    ctor public Vr2dDisplayProperties(int, int, int);
    method public int describeContents();
+5 −0
Original line number Diff line number Diff line
@@ -308,6 +308,11 @@ package android.app {
  public class UiModeManager {
    method public boolean isNightModeLocked();
    method public boolean isUiModeLocked();
    method @RequiresPermission(value=android.Manifest.permission.TOGGLE_AUTOMOTIVE_PROJECTION, conditional=true) public boolean releaseProjection(int);
    method @RequiresPermission(value=android.Manifest.permission.TOGGLE_AUTOMOTIVE_PROJECTION, conditional=true) public boolean requestProjection(int);
    field public static final int PROJECTION_TYPE_ALL = 65535; // 0xffff
    field public static final int PROJECTION_TYPE_AUTOMOTIVE = 1; // 0x1
    field public static final int PROJECTION_TYPE_NONE = 0; // 0x0
  }

  public class WallpaperManager {
+22 −0
Original line number Diff line number Diff line
/*
 * 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 android.app;

/** {@hide} */
oneway interface IOnProjectionStateChangeListener {
  void onProjectionStateChanged(int activeProjectionTypes, in List<String> projectingPackages);
}
 No newline at end of file
Loading