Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
vNext
----------
- [MINOR] Determine whether broker app opts out from battery optimization (#2819)
- [MINOR] Cache Active Broker In Memory (BrokerDiscoveryClient) (#2817)
- [MINOR] Enable Broker Discovery by default in MSAL/Broker API (#2818)
- [MINOR] Share SharedPreferencesInMemoryCache across instances of BrokerOAuth2TokenCache
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,27 @@
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;

import com.microsoft.identity.common.internal.BatteryOptimizationStatus;
import com.microsoft.identity.common.internal.DeviceDozeModeStatus;
import com.microsoft.identity.common.logging.Logger;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
* Wrapper class for PowerManager.
*/

public class PowerManagerWrapper {

private static final String TAG = PowerManagerWrapper.class.getSimpleName();

private static PowerManagerWrapper sInstance;

private static final String UNKNOWN_STATUS = "Unknown";

// In-memory cache for battery optimization status for each apps.
private final Map<String, BatteryOptimizationStatus> batteryOptOutCache = new ConcurrentHashMap<>();
/**
* Set instance of PowerManagerWrapper.
*
Expand Down Expand Up @@ -99,6 +111,40 @@ public String getDeviceIdleMode(@NonNull final Context context){
return "";
}

/**
* Gets the Device Doze Mode Status.
*
* This is exposed to OneAuth.
*
* @param context The context to use for PowerManager.
* @return a {@link DeviceDozeModeStatus}
*/
@NonNull
public DeviceDozeModeStatus getDeviceDozeModeStatus(@NonNull final Context context){
final String methodTag = TAG + ":getDeviceDozeModeStatus";

try {
final PowerManager powerManager = ((PowerManager) context.getSystemService(Context.POWER_SERVICE));
if (powerManager == null) {
Logger.error(methodTag, "PowerManager is null", null);
return DeviceDozeModeStatus.CannotRetrievePowerManager;
}
if (powerManager.isDeviceIdleMode()) {
return DeviceDozeModeStatus.Idle;
}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
powerManager.isDeviceLightIdleMode()) {
return DeviceDozeModeStatus.LightIdle;
}

return DeviceDozeModeStatus.NotInDozeMode;
} catch (Exception e){
Logger.error(methodTag, "Unknown Exception when checking doze mode status", e);
return DeviceDozeModeStatus.UnknownError;
}
}

/**
* Gets a string representing Power Optimization settings of the calling app
* Will return an empty string if the app isn't opting out.
Expand All @@ -107,10 +153,6 @@ public String getDeviceIdleMode(@NonNull final Context context){
@NonNull
public String getPowerOptimizationSettings(@NonNull final Context context){
try {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return UNKNOWN_STATUS;
}

final PowerManager powerManager = ((PowerManager) context.getSystemService(Context.POWER_SERVICE));
if (powerManager.isIgnoringBatteryOptimizations(context.getPackageName())){
return "OptOut";
Expand All @@ -130,8 +172,41 @@ public String getPowerOptimizationSettings(@NonNull final Context context){
* @param connectionContext Context used to query if app is ignoring battery optimizations.
* @return true if the given application package name is on the device's power allow list.
*/
@RequiresApi(Build.VERSION_CODES.M)
public boolean isIgnoringBatteryOptimizations(final Context connectionContext) {
return ((PowerManager) connectionContext.getSystemService(Context.POWER_SERVICE)).isIgnoringBatteryOptimizations(connectionContext.getPackageName());
}

/**
* Checks if the app with the given package name is opted out from battery optimization.
* Caches the result in memory using computeIfAbsent for thread safety.
* Returns a string indicating the result or exception type.
*
* This is exposed to OneAuth.
*
* @param packageName The package name to check.
* @param context The context to use for PowerManager.
* @return a {@link BatteryOptimizationStatus}
*/
public BatteryOptimizationStatus isAppOptedOutFromBatteryOptimization(@NonNull final String packageName, @NonNull final Context context) {
final String methodTag = TAG + ":isAppOptedOutFromBatteryOptimization";

return batteryOptOutCache.computeIfAbsent(packageName, key -> {
try {
final PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (powerManager == null) {
Logger.error(methodTag, "PowerManager is null", null);
return BatteryOptimizationStatus.CannotRetrievePowerManager;
}

if (powerManager.isIgnoringBatteryOptimizations(key)) {
return BatteryOptimizationStatus.OptOut;
} else {
return BatteryOptimizationStatus.NotOptOut;
}
} catch (Exception e) {
Logger.error(methodTag, "Unknown Exception when checking battery optimization status for package: " + packageName, e);
return BatteryOptimizationStatus.UnknownError;
}
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright (c) Microsoft Corporation.
// All rights reserved.
//
// This code is licensed under the MIT License.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package com.microsoft.identity.common.internal

/**
* Enum representing the battery optimization status of the application.
*/
enum class BatteryOptimizationStatus {
/** The application has opted out of battery optimization. */
OptOut,

/** The application has not opted out of battery optimization. */
NotOptOut,

/** Unable to retrieve the PowerManager service to determine battery optimization status. */
CannotRetrievePowerManager,

/** An unknown error occurred while checking battery optimization status. */
UnknownError
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) Microsoft Corporation.
// All rights reserved.
//
// This code is licensed under the MIT License.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package com.microsoft.identity.common.internal

/**
* Represents the current doze mode status of an Android device.
* Doze mode is a battery-saving feature that restricts app behavior when the device is idle.
*/
enum class DeviceDozeModeStatus {
/** The device is not in doze mode and operating normally. */
NotInDozeMode,

/** The device is in idle state. */
Idle,

/** The device is in light idle state. */
LightIdle,

/** Unable to retrieve the PowerManager service to determine doze mode status. */
CannotRetrievePowerManager,

/** An unknown error occurred while checking doze mode status. */
UnknownError
}
Loading