Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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] Enable Broker Discovery by default in MSAL/Broker API (#2818)
- [MINOR] Share SharedPreferencesInMemoryCache across instances of BrokerOAuth2TokenCache
- [MINOR] Use SharedPreferencesInMemoryCache implementation in Broker (#2802)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// 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.adal.internal

/**
* Enum representing the battery optimization status of the application.
*/
enum class BatteryOptimizationStatus {
OptOut,
NotOptOut,
CannotRetrievePowerManager,
UnknownError
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// 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.adal.internal

enum class DeviceDozeModeStatus {
NotInDozeMode,
Idle,
LightIdle,
CannotRetrievePowerManager,
UnknownError
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,25 @@
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;

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 +109,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 + ":getDeviceIdleMode";

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 +151,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 +170,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;
}
});
}
}
Loading