blob: d793ef945f400d5e1e1d59cda4cdf70ac4505d48 [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.wifi.util;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Process;
import android.os.UserHandle;
import android.os.WorkSource;
import android.util.Log;
/**
* Class for wrapping a WorkSource object and providing some (wifi specific) utility methods.
*
* This is primarily used in {@link com.android.server.wifi.HalDeviceManager} class.
*/
public class WorkSourceHelper {
private static final String TAG = "WorkSourceHelper";
private static final int APP_INFO_FLAGS_SYSTEM_APP =
ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
private final WorkSource mWorkSource;
private final WifiPermissionsUtil mWifiPermissionsUtil;
private final ActivityManager mActivityManager;
private final PackageManager mPackageManager;
public WorkSourceHelper(
@NonNull WorkSource workSource,
@NonNull WifiPermissionsUtil wifiPermissionsUtil,
@NonNull ActivityManager activityManager,
@NonNull PackageManager packageManager) {
mWorkSource = workSource;
mWifiPermissionsUtil = wifiPermissionsUtil;
mActivityManager = activityManager;
mPackageManager = packageManager;
}
@Override
public String toString() {
return mWorkSource.toString();
}
private boolean isPrivileged(int uid) {
return mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)
|| mWifiPermissionsUtil.checkNetworkSetupWizardPermission(uid)
|| mWifiPermissionsUtil.checkNetworkStackPermission(uid)
|| mWifiPermissionsUtil.checkMainlineNetworkStackPermission(uid);
}
/**
* Returns whether any of the one or more worksource objects contains a privileged app
* request.
*
* Privileged = Request from an app with NETWORK_SETTINGS, NETWORK_SETUP_WIZARD or
* NETWORK_STACK permissions.
*/
public boolean hasAnyPrivilegedAppRequest() {
for (int i = 0; i < mWorkSource.size(); i++) {
if (isPrivileged(mWorkSource.getUid(i))) return true;
}
return false;
}
private boolean isSystem(String packageName, int uid) {
// when checking ActiveModeWarden#INTERNAL_REQUESTOR_WS
if (packageName == null) {
return false;
}
try {
ApplicationInfo info = mPackageManager.getApplicationInfoAsUser(
packageName, 0, UserHandle.getUserHandleForUid(uid));
return (info.flags & APP_INFO_FLAGS_SYSTEM_APP) != 0;
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "Failed to retrieve app info for packageName=" + packageName + " uid=" + uid,
e);
// In case of exception, assume unknown app (more strict checking)
// Note: This case will never happen since checkPackage is
// called to verify validity before checking App's version.
return false;
}
}
/**
* Returns whether any of the one or more worksource objects contains a system app
* request.
*/
public boolean hasAnySystemAppRequest() {
for (int i = 0; i < mWorkSource.size(); i++) {
if (isSystem(mWorkSource.getPackageName(i), mWorkSource.getUid(i))) return true;
}
return false;
}
/**
* Check if the request comes from foreground app.
*/
private boolean isForegroundApp(@NonNull String requestorPackageName) {
try {
return mActivityManager.getPackageImportance(requestorPackageName)
<= IMPORTANCE_FOREGROUND;
} catch (SecurityException e) {
Log.e(TAG, "Failed to check the app state", e);
return false;
}
}
/**
* Returns whether any of the one or more worksource objects contains a foreground app
* request.
*/
public boolean hasAnyForegroundAppRequest() {
for (int i = 0; i < mWorkSource.size(); i++) {
if (isForegroundApp(mWorkSource.getPackageName(i))) return true;
}
return false;
}
/**
* Check if the request comes from foreground service.
*/
private boolean isForegroundService(@NonNull String requestorPackageName) {
try {
int importance = mActivityManager.getPackageImportance(requestorPackageName);
return IMPORTANCE_FOREGROUND < importance
&& importance <= IMPORTANCE_FOREGROUND_SERVICE;
} catch (SecurityException e) {
Log.e(TAG, "Failed to check the app state", e);
return false;
}
}
/**
* Returns whether any of the one or more worksource objects contains a foreground service
* request.
*/
public boolean hasAnyForegroundServiceRequest() {
for (int i = 0; i < mWorkSource.size(); i++) {
if (isForegroundService(mWorkSource.getPackageName(i))) return true;
}
return false;
}
/**
* Returns whether any of the one or more worksource objects contains an internal
* (i.e uid = Process.WIFI_UID) request.
*/
public boolean hasAnyInternalRequest() {
for (int i = 0; i < mWorkSource.size(); i++) {
if (mWorkSource.getUid(i) == Process.WIFI_UID) return true;
}
return false;
}
}