1 /* 2 * Copyright (C) 2022 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.applications; 18 19 import android.Manifest; 20 import android.app.AppGlobals; 21 import android.app.job.JobScheduler; 22 import android.content.Context; 23 import android.content.pm.IPackageManager; 24 import android.os.RemoteException; 25 import android.os.UserHandle; 26 import android.util.Log; 27 28 import com.android.internal.annotations.VisibleForTesting; 29 import com.android.internal.util.ArrayUtils; 30 import com.android.settingslib.applications.ApplicationsState; 31 import com.android.settingslib.applications.ApplicationsState.AppEntry; 32 import com.android.settingslib.applications.ApplicationsState.AppFilter; 33 34 import libcore.util.EmptyArray; 35 36 import java.util.List; 37 38 /** 39 * Connects app op info to the ApplicationsState. Extends {@link AppStateAppOpsBridge} to tailor 40 * to the semantics of {@link Manifest.permission#RUN_USER_INITIATED_JOBS}. 41 * Also provides app filters that can use the info. 42 */ 43 public class AppStateLongBackgroundTasksBridge extends AppStateBaseBridge { 44 private static final String PERMISSION = Manifest.permission.RUN_USER_INITIATED_JOBS; 45 private static final String TAG = "LongBackgroundTasksBridge"; 46 47 @VisibleForTesting 48 JobScheduler mJobScheduler; 49 @VisibleForTesting 50 String[] mRequesterPackages; 51 AppStateLongBackgroundTasksBridge(Context context, ApplicationsState appState, Callback callback)52 public AppStateLongBackgroundTasksBridge(Context context, ApplicationsState appState, 53 Callback callback) { 54 super(appState, callback); 55 56 mJobScheduler = context.getSystemService(JobScheduler.class); 57 final IPackageManager iPm = AppGlobals.getPackageManager(); 58 try { 59 mRequesterPackages = iPm.getAppOpPermissionPackages(PERMISSION, context.getUserId()); 60 } catch (RemoteException re) { 61 Log.e(TAG, "Cannot reach package manager", re); 62 mRequesterPackages = EmptyArray.STRING; 63 } 64 } 65 66 /** 67 * Returns information regarding {@link Manifest.permission#RUN_USER_INITIATED_JOBS} for the 68 * given package and uid. 69 */ createPermissionState(String packageName, int uid)70 public LongBackgroundTasksState createPermissionState(String packageName, int uid) { 71 final int userId = UserHandle.getUserId(uid); 72 73 final boolean permissionRequested = ArrayUtils.contains(mRequesterPackages, packageName); 74 final boolean permissionGranted = mJobScheduler.hasRunUserInitiatedJobsPermission( 75 packageName, userId); 76 return new LongBackgroundTasksState(permissionRequested, permissionGranted); 77 } 78 79 @Override updateExtraInfo(AppEntry app, String pkg, int uid)80 protected void updateExtraInfo(AppEntry app, String pkg, int uid) { 81 app.extraInfo = createPermissionState(pkg, uid); 82 } 83 84 @Override loadAllExtraInfo()85 protected void loadAllExtraInfo() { 86 final List<AppEntry> allApps = mAppSession.getAllApps(); 87 for (int i = 0; i < allApps.size(); i++) { 88 final AppEntry currentEntry = allApps.get(i); 89 updateExtraInfo(currentEntry, currentEntry.info.packageName, currentEntry.info.uid); 90 } 91 } 92 93 public static final AppFilter FILTER_LONG_JOBS_APPS = new AppFilter() { 94 95 @Override 96 public void init() { 97 } 98 99 @Override 100 public boolean filterApp(AppEntry info) { 101 if (info.extraInfo instanceof LongBackgroundTasksState) { 102 final LongBackgroundTasksState state = (LongBackgroundTasksState) info.extraInfo; 103 return state.shouldBeVisible(); 104 } 105 return false; 106 } 107 }; 108 109 /** 110 * Class to denote the state of an app regarding 111 * {@link Manifest.permission#RUN_USER_INITIATED_JOBS}. 112 */ 113 public static class LongBackgroundTasksState { 114 private boolean mPermissionRequested; 115 private boolean mPermissionGranted; 116 LongBackgroundTasksState(boolean permissionRequested, boolean permissionGranted)117 LongBackgroundTasksState(boolean permissionRequested, boolean permissionGranted) { 118 mPermissionRequested = permissionRequested; 119 mPermissionGranted = permissionGranted; 120 } 121 122 /** Should the app associated with this state appear on the Settings screen */ shouldBeVisible()123 public boolean shouldBeVisible() { 124 return mPermissionRequested; 125 } 126 127 /** Is the permission granted to the app associated with this state */ isAllowed()128 public boolean isAllowed() { 129 return mPermissionGranted; 130 } 131 } 132 } 133