LenovoLegionToolkit

Форк
0
213 строк · 7.5 Кб
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Runtime.InteropServices;
5
using System.Threading.Tasks;
6
using LenovoLegionToolkit.Lib.Extensions;
7
using LenovoLegionToolkit.Lib.Settings;
8
using LenovoLegionToolkit.Lib.SoftwareDisabler;
9
using LenovoLegionToolkit.Lib.Utils;
10
using Windows.Win32;
11
using Windows.Win32.Foundation;
12
using Windows.Win32.System.Power;
13

14
namespace LenovoLegionToolkit.Lib.Controllers;
15

16
public class PowerPlanController
17
{
18
    private static readonly Dictionary<PowerModeState, Guid> DefaultPowerModes = new()
19
    {
20
        { PowerModeState.Quiet , Guid.Parse("16edbccd-dee9-4ec4-ace5-2f0b5f2a8975")},
21
        { PowerModeState.Balance , Guid.Parse("85d583c5-cf2e-4197-80fd-3789a227a72c")},
22
        { PowerModeState.Performance , Guid.Parse("52521609-efc9-4268-b9ba-67dea73f18b2")},
23
        { PowerModeState.GodMode , Guid.Parse("85d583c5-cf2e-4197-80fd-3789a227a72c")},
24
    };
25

26
    private readonly ApplicationSettings _settings;
27

28
    private readonly VantageDisabler _vantageDisabler;
29

30
    public PowerPlanController(ApplicationSettings settings, VantageDisabler vantageDisabler)
31
    {
32
        _settings = settings ?? throw new ArgumentNullException(nameof(settings));
33
        _vantageDisabler = vantageDisabler ?? throw new ArgumentNullException(nameof(vantageDisabler));
34
    }
35

36
    public IEnumerable<PowerPlan> GetPowerPlans()
37
    {
38
        var powerPlansGuid = GetPowerPlansGuid();
39
        var activePowerPlanGuid = GetActivePowerPlanGuid();
40

41
        foreach (var powerPlanGuid in powerPlansGuid)
42
        {
43
            var powerPlaneName = GetPowerPlanName(powerPlanGuid);
44
            yield return new PowerPlan(powerPlanGuid, powerPlaneName, powerPlanGuid == activePowerPlanGuid);
45
        }
46
    }
47

48
    public async Task ActivatePowerPlanAsync(PowerModeState powerModeState, bool alwaysActivateDefaults = false)
49
    {
50
        if (Log.Instance.IsTraceEnabled)
51
            Log.Instance.Trace($"Activating... [powerModeState={powerModeState}, alwaysActivateDefaults={alwaysActivateDefaults}]");
52

53
        var powerPlanId = _settings.Store.PowerPlans.GetValueOrDefault(powerModeState);
54
        var isDefault = false;
55

56
        if (powerPlanId == Guid.Empty)
57
        {
58
            if (Log.Instance.IsTraceEnabled)
59
                Log.Instance.Trace($"Power plan for power mode {powerModeState} was not found in settings");
60

61
            if (DefaultPowerModes.TryGetValue(powerModeState, out var defaultPowerPlanId))
62
                powerPlanId = defaultPowerPlanId;
63
            else
64
                throw new InvalidOperationException("Unknown state");
65

66
            isDefault = true;
67
        }
68

69
        if (Log.Instance.IsTraceEnabled)
70
            Log.Instance.Trace($"Power plan to be activated is {powerPlanId} [isDefault={isDefault}]");
71

72
        if (!await ShouldActivateAsync(alwaysActivateDefaults, isDefault).ConfigureAwait(false))
73
        {
74
            if (Log.Instance.IsTraceEnabled)
75
                Log.Instance.Trace($"Power plan {powerPlanId} will not be activated [isDefault={isDefault}]");
76

77
            return;
78
        }
79

80
        var powerPlans = GetPowerPlans().ToArray();
81

82
        if (Log.Instance.IsTraceEnabled)
83
        {
84
            Log.Instance.Trace($"Available power plans:");
85
            foreach (var powerPlan in powerPlans)
86
                Log.Instance.Trace($" - {powerPlan.Name} [guid={powerPlan.Guid}, isActive={powerPlan.IsActive}]");
87
        }
88

89
        var powerPlanToActivate = powerPlans.FirstOrDefault(pp => pp.Guid == powerPlanId);
90
        if (powerPlanToActivate.Equals(default(PowerPlan)))
91
        {
92
            if (Log.Instance.IsTraceEnabled)
93
                Log.Instance.Trace($"Power plan {powerPlanId} was not found");
94
            return;
95
        }
96

97
        if (powerPlanToActivate.IsActive)
98
        {
99
            if (Log.Instance.IsTraceEnabled)
100
                Log.Instance.Trace($"Power plan {powerPlanToActivate.Guid} is already active. [name={powerPlanToActivate.Name}]");
101
            return;
102
        }
103

104
        SetActivePowerPlan(powerPlanToActivate.Guid);
105

106
        if (Log.Instance.IsTraceEnabled)
107
            Log.Instance.Trace($"Power plan {powerPlanToActivate.Guid} activated. [name={powerPlanToActivate.Name}]");
108
    }
109

110
    public PowerModeState[] GetMatchingPowerModes(Guid powerPlanGuid)
111
    {
112
        var powerModes = new Dictionary<PowerModeState, Guid>(DefaultPowerModes);
113

114
        foreach (var kv in _settings.Store.PowerPlans)
115
        {
116
            powerModes[kv.Key] = kv.Value;
117
        }
118

119
        return powerModes.Where(kv => kv.Value == powerPlanGuid)
120
            .Select(kv => kv.Key)
121
            .ToArray();
122
    }
123

124
    private async Task<bool> ShouldActivateAsync(bool alwaysActivateDefaults, bool isDefault)
125
    {
126
        var activateWhenVantageEnabled = _settings.Store.ActivatePowerProfilesWithVantageEnabled;
127
        if (activateWhenVantageEnabled)
128
        {
129
            if (Log.Instance.IsTraceEnabled)
130
                Log.Instance.Trace($"Activate power profiles with Vantage is enabled");
131

132
            return true;
133
        }
134

135
        if (isDefault && alwaysActivateDefaults)
136
        {
137
            if (Log.Instance.IsTraceEnabled)
138
                Log.Instance.Trace($"Power plan is default and always active defaults is set");
139

140
            return true;
141
        }
142

143
        var status = await _vantageDisabler.GetStatusAsync().ConfigureAwait(false);
144
        if (status is SoftwareStatus.NotFound or SoftwareStatus.Disabled)
145
        {
146
            if (Log.Instance.IsTraceEnabled)
147
                Log.Instance.Trace($"Vantage is active [status={status}]");
148

149
            return true;
150
        }
151

152
        if (Log.Instance.IsTraceEnabled)
153
            Log.Instance.Trace($"Criteria for activation not met [activateWhenVantageEnabled={activateWhenVantageEnabled}, isDefault={isDefault}, alwaysActivateDefaults={alwaysActivateDefaults}, status={status}]");
154

155
        return false;
156
    }
157

158
    private static unsafe IEnumerable<Guid> GetPowerPlansGuid()
159
    {
160
        var list = new List<Guid>();
161

162
        var bufferSize = (uint)Marshal.SizeOf<Guid>();
163
        var buffer = new byte[bufferSize];
164

165
        fixed (byte* bufferPtr = buffer)
166
        {
167
            uint index = 0;
168
            while (PInvoke.PowerEnumerate(null, null, null, POWER_DATA_ACCESSOR.ACCESS_SCHEME, index, bufferPtr, ref bufferSize) == WIN32_ERROR.ERROR_SUCCESS)
169
            {
170
                list.Add(new Guid(buffer));
171
                index++;
172
            }
173
        }
174

175
        return list;
176
    }
177

178
    private static unsafe string GetPowerPlanName(Guid powerPlanGuid)
179
    {
180
        var nameSize = 2048u;
181
        var namePtr = Marshal.AllocHGlobal((int)nameSize);
182

183
        try
184
        {
185
            if (PInvoke.PowerReadFriendlyName(null, powerPlanGuid, null, null, (byte*)namePtr.ToPointer(), ref nameSize) != WIN32_ERROR.ERROR_SUCCESS)
186
                PInvokeExtensions.ThrowIfWin32Error("PowerReadFriendlyName");
187

188
            return Marshal.PtrToStringUni(namePtr) ?? string.Empty;
189
        }
190
        catch
191
        {
192
            return powerPlanGuid.ToString();
193
        }
194
        finally
195
        {
196
            Marshal.FreeHGlobal(namePtr);
197
        }
198
    }
199

200
    private static unsafe Guid GetActivePowerPlanGuid()
201
    {
202
        if (PInvoke.PowerGetActiveScheme(null, out var guid) != WIN32_ERROR.ERROR_SUCCESS)
203
            PInvokeExtensions.ThrowIfWin32Error("PowerGetActiveScheme");
204

205
        return Marshal.PtrToStructure<Guid>(new IntPtr(guid));
206
    }
207

208
    private static void SetActivePowerPlan(Guid powerPlanGuid)
209
    {
210
        if (PInvoke.PowerSetActiveScheme(null, powerPlanGuid) != WIN32_ERROR.ERROR_SUCCESS)
211
            PInvokeExtensions.ThrowIfWin32Error("PowerSetActiveScheme");
212
    }
213
}
214

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.