1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.fuelgauge; 18 19 import android.app.AppOpsManager; 20 import android.content.Context; 21 import android.util.Log; 22 23 import androidx.annotation.VisibleForTesting; 24 25 import com.android.settingslib.fuelgauge.PowerAllowlistBackend; 26 27 /** A utility class for application usage operation. */ 28 public class BatteryOptimizeUtils { 29 private static final String TAG = "BatteryOptimizeUtils"; 30 private static final String UNKNOWN_PACKAGE = "unknown"; 31 32 @VisibleForTesting AppOpsManager mAppOpsManager; 33 @VisibleForTesting BatteryUtils mBatteryUtils; 34 @VisibleForTesting PowerAllowlistBackend mPowerAllowListBackend; 35 private final String mPackageName; 36 private final int mUid; 37 38 private int mMode; 39 private boolean mAllowListed; 40 41 /** 42 * Usage type of application. 43 */ 44 public enum AppUsageState { 45 UNKNOWN, 46 RESTRICTED, 47 UNRESTRICTED, 48 OPTIMIZED, 49 } 50 BatteryOptimizeUtils(Context context, int uid, String packageName)51 public BatteryOptimizeUtils(Context context, int uid, String packageName) { 52 mUid = uid; 53 mPackageName = packageName; 54 mAppOpsManager = context.getSystemService(AppOpsManager.class); 55 mBatteryUtils = BatteryUtils.getInstance(context); 56 mPowerAllowListBackend = PowerAllowlistBackend.getInstance(context); 57 mMode = mAppOpsManager 58 .checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mPackageName); 59 mAllowListed = mPowerAllowListBackend.isAllowlisted(mPackageName); 60 } 61 getAppUsageState()62 public AppUsageState getAppUsageState() { 63 refreshState(); 64 if (!mAllowListed && mMode == AppOpsManager.MODE_IGNORED) { 65 return AppUsageState.RESTRICTED; 66 } else if (mAllowListed && mMode == AppOpsManager.MODE_ALLOWED) { 67 return AppUsageState.UNRESTRICTED; 68 } else if (!mAllowListed && mMode == AppOpsManager.MODE_ALLOWED) { 69 return AppUsageState.OPTIMIZED; 70 } else { 71 Log.d(TAG, "get unknown app usage state."); 72 return AppUsageState.UNKNOWN; 73 } 74 } 75 setAppUsageState(AppUsageState state)76 public void setAppUsageState(AppUsageState state) { 77 switch (state) { 78 case RESTRICTED: 79 mBatteryUtils.setForceAppStandby(mUid, mPackageName, AppOpsManager.MODE_IGNORED); 80 mPowerAllowListBackend.removeApp(mPackageName); 81 break; 82 case UNRESTRICTED: 83 mBatteryUtils.setForceAppStandby(mUid, mPackageName, AppOpsManager.MODE_ALLOWED); 84 mPowerAllowListBackend.addApp(mPackageName); 85 break; 86 case OPTIMIZED: 87 mBatteryUtils.setForceAppStandby(mUid, mPackageName, AppOpsManager.MODE_ALLOWED); 88 mPowerAllowListBackend.removeApp(mPackageName); 89 break; 90 default: 91 Log.d(TAG, "set unknown app usage state."); 92 } 93 } 94 95 /** 96 * Return {@code true} if package name is valid (can get an uid). 97 */ isValidPackageName()98 public boolean isValidPackageName() { 99 return mBatteryUtils.getPackageUid(mPackageName) != BatteryUtils.UID_NULL; 100 } 101 102 /** 103 * Return {@code true} if this package is system or default active app. 104 */ isSystemOrDefaultApp()105 public boolean isSystemOrDefaultApp() { 106 mPowerAllowListBackend.refreshList(); 107 108 return mPowerAllowListBackend.isSysAllowlisted(mPackageName) 109 || mPowerAllowListBackend.isDefaultActiveApp(mPackageName); 110 } 111 getPackageName()112 String getPackageName() { 113 return mPackageName == null ? UNKNOWN_PACKAGE : mPackageName; 114 } 115 refreshState()116 private void refreshState() { 117 mPowerAllowListBackend.refreshList(); 118 mAllowListed = mPowerAllowListBackend.isAllowlisted(mPackageName); 119 mMode = mAppOpsManager 120 .checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mPackageName); 121 Log.d(TAG, String.format("refresh %s state, allowlisted = %s, mode = %d", 122 mPackageName, 123 mAllowListed, 124 mMode)); 125 } 126 } 127