OSDN Git Service

CEC: Let playback device send <Standby> upon power off
authorJinsuk Kim <jinsukkim@google.com>
Mon, 11 May 2015 05:17:04 +0000 (14:17 +0900)
committerJinsuk Kim <jinsukkim@google.com>
Tue, 12 May 2015 04:22:12 +0000 (13:22 +0900)
Let playback device send a command <Standby> based on the setting.
ACTION_SHUTDOWN leads to broadcast command to put all the devices
to sleep, and ACTION_SCREEN_OFF optionally turns off TV only.

Change-Id: Id458b23ce86b0c3179efa21cce85b721a47001be

services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
services/core/java/com/android/server/hdmi/HdmiControlService.java

index 8031c05..77b800e 100644 (file)
@@ -737,6 +737,9 @@ abstract class HdmiCecLocalDevice {
         }
     }
 
+    void setAutoDeviceOff(boolean enabled) {
+    }
+
     /**
      * Called when a hot-plug event issued.
      *
@@ -829,8 +832,11 @@ abstract class HdmiCecLocalDevice {
      *
      * @param initiatedByCec true if this power sequence is initiated
      *        by the reception the CEC messages like &lt;Standby&gt;
+     * @param standbyAction Intent action that drives the standby process,
+     *        either {@link HdmiControlService#STANDBY_SCREEN_OFF} or
+     *        {@link HdmiControlService#STANDBY_SHUTDOWN}
      */
-    protected void onStandby(boolean initiatedByCec) {}
+    protected void onStandby(boolean initiatedByCec, int standbyAction) {}
 
     /**
      * Disable device. {@code callback} is used to get notified when all pending
index fd3364a..30a9b43 100644 (file)
@@ -23,6 +23,7 @@ import android.os.PowerManager;
 import android.os.PowerManager.WakeLock;
 import android.os.RemoteException;
 import android.os.SystemProperties;
+import android.provider.Settings.Global;
 import android.util.Slog;
 
 import com.android.internal.util.IndentingPrintWriter;
@@ -47,8 +48,17 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice {
     // Lazily initialized - should call getWakeLock() to get the instance.
     private ActiveWakeLock mWakeLock;
 
+    // If true, turn off TV upon standby. False by default.
+    private boolean mAutoTvOff;
+
     HdmiCecLocalDevicePlayback(HdmiControlService service) {
         super(service, HdmiDeviceInfo.DEVICE_PLAYBACK);
+
+        mAutoTvOff = mService.readBooleanSetting(Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED, false);
+
+        // The option is false by default. Update settings db as well to have the right
+        // initial setting on UI.
+        mService.writeBooleanSetting(Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED, mAutoTvOff);
     }
 
     @Override
@@ -141,6 +151,35 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice {
         }
     }
 
+    @Override
+    @ServiceThreadOnly
+    protected void onStandby(boolean initiatedByCec, int standbyAction) {
+        assertRunOnServiceThread();
+        if (!mService.isControlEnabled() || initiatedByCec) {
+            return;
+        }
+        switch (standbyAction) {
+            case HdmiControlService.STANDBY_SCREEN_OFF:
+                if (mAutoTvOff) {
+                    mService.sendCecCommand(
+                            HdmiCecMessageBuilder.buildStandby(mAddress, Constants.ADDR_TV));
+                }
+                break;
+            case HdmiControlService.STANDBY_SHUTDOWN:
+                // ACTION_SHUTDOWN is taken as a signal to power off all the devices.
+                mService.sendCecCommand(
+                        HdmiCecMessageBuilder.buildStandby(mAddress, Constants.ADDR_BROADCAST));
+                break;
+        }
+    }
+
+    @Override
+    @ServiceThreadOnly
+    void setAutoDeviceOff(boolean enabled) {
+        assertRunOnServiceThread();
+        mAutoTvOff = enabled;
+    }
+
     @ServiceThreadOnly
     void setActiveSource(boolean on) {
         assertRunOnServiceThread();
@@ -295,6 +334,7 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice {
     protected void dump(final IndentingPrintWriter pw) {
         super.dump(pw);
         pw.println("mIsActiveSource: " + mIsActiveSource);
+        pw.println("mAutoTvOff:" + mAutoTvOff);
     }
 
     // Wrapper interface over PowerManager.WakeLock
index 51ba32d..96cb51c 100644 (file)
@@ -1583,6 +1583,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
         }
     }
 
+    @Override
     @ServiceThreadOnly
     void setAutoDeviceOff(boolean enabled) {
         assertRunOnServiceThread();
@@ -1659,7 +1660,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
 
     @Override
     @ServiceThreadOnly
-    protected void onStandby(boolean initiatedByCec) {
+    protected void onStandby(boolean initiatedByCec, int standbyAction) {
         assertRunOnServiceThread();
         // Seq #11
         if (!mService.isControlEnabled()) {
index 2cbc1b9..66f7861 100644 (file)
@@ -106,6 +106,12 @@ public final class HdmiControlService extends SystemService {
     static final int INITIATED_BY_WAKE_UP_MESSAGE = 3;
     static final int INITIATED_BY_HOTPLUG = 4;
 
+    // The reason code representing the intent action that drives the standby
+    // procedure. The procedure starts either by Intent.ACTION_SCREEN_OFF or
+    // Intent.ACTION_SHUTDOWN.
+    static final int STANDBY_SCREEN_OFF = 0;
+    static final int STANDBY_SHUTDOWN = 1;
+
     /**
      * Interface to report send result.
      */
@@ -143,7 +149,7 @@ public final class HdmiControlService extends SystemService {
             switch (intent.getAction()) {
                 case Intent.ACTION_SCREEN_OFF:
                     if (isPowerOnOrTransient()) {
-                        onStandby();
+                        onStandby(STANDBY_SCREEN_OFF);
                     }
                     break;
                 case Intent.ACTION_SCREEN_ON:
@@ -157,6 +163,11 @@ public final class HdmiControlService extends SystemService {
                         onLanguageChanged(language);
                     }
                     break;
+                case Intent.ACTION_SHUTDOWN:
+                    if (isPowerOnOrTransient()) {
+                        onStandby(STANDBY_SHUTDOWN);
+                    }
+                    break;
             }
         }
 
@@ -510,8 +521,9 @@ public final class HdmiControlService extends SystemService {
                     setCecOption(OPTION_CEC_AUTO_WAKEUP, toInt(enabled));
                     break;
                 case Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED:
-                    if (isTvDeviceEnabled()) {
-                        tv().setAutoDeviceOff(enabled);
+                    for (int type : mLocalDevices) {
+                        HdmiCecLocalDevice localDevice = mCecController.getLocalDevice(type);
+                        localDevice.setAutoDeviceOff(enabled);
                     }
                     // No need to propagate to HAL.
                     break;
@@ -1994,7 +2006,7 @@ public final class HdmiControlService extends SystemService {
     }
 
     @ServiceThreadOnly
-    private void onStandby() {
+    private void onStandby(final int standbyAction) {
         assertRunOnServiceThread();
         if (!canGoToStandby()) return;
         mPowerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY;
@@ -2008,7 +2020,7 @@ public final class HdmiControlService extends SystemService {
                 Slog.v(TAG, "On standby-action cleared:" + device.mDeviceType);
                 devices.remove(device);
                 if (devices.isEmpty()) {
-                    onStandbyCompleted();
+                    onStandbyCompleted(standbyAction);
                     // We will not clear local devices here, since some OEM/SOC will keep passing
                     // the received packets until the application processor enters to the sleep
                     // actually.
@@ -2062,7 +2074,7 @@ public final class HdmiControlService extends SystemService {
     }
 
     @ServiceThreadOnly
-    private void onStandbyCompleted() {
+    private void onStandbyCompleted(int standbyAction) {
         assertRunOnServiceThread();
         Slog.v(TAG, "onStandbyCompleted");
 
@@ -2071,7 +2083,7 @@ public final class HdmiControlService extends SystemService {
         }
         mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY;
         for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {
-            device.onStandby(mStandbyMessageReceived);
+            device.onStandby(mStandbyMessageReceived, standbyAction);
         }
         mStandbyMessageReceived = false;
         mAddressAllocated = false;