From 78c9088dabac1c042567faa3196dfd21fae900ef Mon Sep 17 00:00:00 2001
From: Tad <tad@spotco.us>
Date: Sat, 21 Oct 2017 11:53:09 -0400
Subject: [PATCH] Reduced Resolution Feature 2/2

Change-Id: If92489ee9dc119acdeeb8f05f0d70970eef55817
---
 core/java/android/os/IPowerManager.aidl            |  3 +
 core/java/android/os/PowerManager.java             | 32 ++++++++
 core/java/android/os/PowerManagerInternal.java     |  2 +
 .../android/server/power/PowerManagerService.java  | 85 ++++++++++++++++++++++
 4 files changed, 122 insertions(+)

diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 26eb7f169a0..d6051d0db74 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -75,4 +75,7 @@ interface IPowerManager
     void setKeyboardLight(boolean on, int key);
 
     void wakeUpWithProximityCheck(long time, String reason, String opPackageName);
+
+    boolean isReducedResolution();
+    boolean setReducedResolution(boolean mode);
 }
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 5c8effec0ed..8c1d2fdf65b 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -988,6 +988,38 @@ public final class PowerManager {
         }
     }
 
+    /**
+     * Returns true if the WindowManager is running at a reduced resolution
+     *
+     * @return Returns true if WindowManager is set to a reduced resolution, else false.
+     *
+     * @hide
+     */
+    public boolean isReducedResolution() {
+        try {
+            return mService.isReducedResolution();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Set the reduced resolution mode
+     *
+     * @return True if the set was allowed.
+     *
+     * @see #isReducedResolution()
+     *
+     * @hide
+     */
+    public boolean setReducedResolution(boolean mode) {
+        try {
+            return mService.setReducedResolution(mode);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     /**
      * Returns true if the device is currently in idle mode.  This happens when a device
      * has been sitting unused and unmoving for a sufficiently long period of time, so that
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
index bbafb5662cd..e0c71a044a5 100644
--- a/core/java/android/os/PowerManagerInternal.java
+++ b/core/java/android/os/PowerManagerInternal.java
@@ -173,6 +173,8 @@ public abstract class PowerManagerInternal {
 
     public abstract boolean setPowerSaveMode(boolean mode);
 
+    public abstract boolean setReducedResolution(boolean mode);
+
     public abstract void setFeature(int featureId, int data);
 
     public abstract int getFeature(int featureId);
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 55d0809ee4e..33cb0a93bb7 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -29,6 +29,7 @@ import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.database.ContentObserver;
+import android.graphics.Point;
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
@@ -49,6 +50,7 @@ import android.os.PowerManager;
 import android.os.PowerManagerInternal;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.Trace;
@@ -67,6 +69,7 @@ import android.util.Slog;
 import android.util.SparseIntArray;
 import android.util.TimeUtils;
 import android.view.Display;
+import android.view.IWindowManager;
 import android.view.WindowManagerPolicy;
 
 import com.android.internal.app.IAppOpsService;
@@ -203,6 +206,7 @@ public final class PowerManagerService extends SystemService
     private final Context mContext;
     private final ServiceThread mHandlerThread;
     private final PowerManagerHandler mHandler;
+    private IWindowManager mWm;
 
     private LightsManager mLightsManager;
     private BatteryManagerInternal mBatteryManagerInternal;
@@ -2658,6 +2662,60 @@ public final class PowerManagerService extends SystemService
         }
     }
 
+    private boolean isReducedResolutionInternal() {
+        synchronized (mLock) {
+            try {
+                Point initialSize = new Point();
+                Point baseSize = new Point();
+
+                mWm = IWindowManager.Stub.asInterface(ServiceManager.checkService(
+                        Context.WINDOW_SERVICE));
+
+                mWm.getInitialDisplaySize(Display.DEFAULT_DISPLAY, initialSize);
+                mWm.getBaseDisplaySize(Display.DEFAULT_DISPLAY, baseSize);
+
+                return !initialSize.equals(baseSize);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    private boolean setReducedResolutionInternal(boolean mode) {
+        synchronized (mLock) {
+            try {
+                mWm = IWindowManager.Stub.asInterface(ServiceManager.checkService(
+                        Context.WINDOW_SERVICE));
+                if (mode) {
+                    Point initialSize = new Point();
+                    mWm.getInitialDisplaySize(Display.DEFAULT_DISPLAY, initialSize);
+
+                    Point newSize;
+
+                    if (initialSize.x == 1440 && initialSize.y == 2560) {//16:9
+                        newSize = new Point(1080, 1920);//.75
+                    } else if(initialSize.x == 1200 && initialSize.y == 1920) {//16:10
+                        newSize = new Point(900, 1440);//.75
+                    } else if(initialSize.x == 1080 && initialSize.y == 1920) {//16:9
+                        newSize = new Point(720, 1280);//.50
+                    } else if(initialSize.x == 768 && initialSize.y == 1280) {//5:3
+                        newSize = new Point(576, 960);//.75
+                    } else {
+                        return false;
+                    }
+
+                    mWm.setForcedDisplaySize(Display.DEFAULT_DISPLAY, newSize.x, newSize.y);
+                    return isReducedResolutionInternal();
+                } else {
+                    mWm.clearForcedDisplaySize(Display.DEFAULT_DISPLAY);
+                    return !isReducedResolutionInternal();
+                }
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
     boolean isDeviceIdleModeInternal() {
         synchronized (mLock) {
             return mDeviceIdleMode;
@@ -3833,6 +3891,28 @@ public final class PowerManagerService extends SystemService
             }
         }
 
+        @Override // Binder call
+        public boolean isReducedResolution() {
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                return isReducedResolutionInternal();
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
+        public boolean setReducedResolution(boolean mode) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.DEVICE_POWER, null);
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                return setReducedResolutionInternal(mode);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
         @Override // Binder call
         public boolean isDeviceIdleMode() {
             final long ident = Binder.clearCallingIdentity();
@@ -4214,6 +4294,11 @@ public final class PowerManagerService extends SystemService
             return setLowPowerModeInternal(mode);
         }
 
+        @Override
+        public boolean setReducedResolution(boolean mode) {
+            return setReducedResolutionInternal(mode);
+        }
+
         @Override
         public int getFeature(int featureId) {
             return nativeGetFeature(featureId);
-- 
2.14.2

