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.car.settings.applications; 18 19 import android.car.Car; 20 import android.car.drivingstate.CarUxRestrictions; 21 import android.car.watchdog.CarWatchdogManager; 22 import android.car.watchdog.PackageKillableState; 23 import android.content.Context; 24 import android.content.pm.PackageInfo; 25 import android.os.UserHandle; 26 27 import androidx.annotation.Nullable; 28 import androidx.annotation.VisibleForTesting; 29 import androidx.preference.TwoStatePreference; 30 31 import com.android.car.settings.applications.performance.PerfImpactingAppsUtils; 32 import com.android.car.settings.common.ConfirmationDialogFragment; 33 import com.android.car.settings.common.FragmentController; 34 import com.android.car.settings.common.Logger; 35 import com.android.car.settings.common.PreferenceController; 36 37 /** Controller for preference which turns on / off prioritize app performance setting. */ 38 public class PrioritizeAppPerformancePreferenceController 39 extends PreferenceController<TwoStatePreference> { 40 private static final Logger LOG = 41 new Logger(PrioritizeAppPerformancePreferenceController.class); 42 43 @VisibleForTesting 44 static final String TURN_ON_PRIORITIZE_APP_PERFORMANCE_DIALOG_TAG = 45 "com.android.car.settings.applications.TurnOnPrioritizeAppPerformanceDialogTag"; 46 47 @Nullable 48 private Car mCar; 49 @Nullable 50 private CarWatchdogManager mCarWatchdogManager; 51 private String mPackageName; 52 private UserHandle mUserHandle; 53 54 private final ConfirmationDialogFragment.ConfirmListener mConfirmListener = arguments -> { 55 if (!isCarConnected()) { 56 return; 57 } 58 setKillableState(false); 59 getPreference().setChecked(true); 60 }; 61 PrioritizeAppPerformancePreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions)62 public PrioritizeAppPerformancePreferenceController(Context context, String preferenceKey, 63 FragmentController fragmentController, 64 CarUxRestrictions uxRestrictions) { 65 super(context, preferenceKey, fragmentController, uxRestrictions); 66 } 67 68 @Override onCreateInternal()69 protected void onCreateInternal() { 70 connectToCar(); 71 72 ConfirmationDialogFragment dialogFragment = 73 (ConfirmationDialogFragment) getFragmentController().findDialogByTag( 74 TURN_ON_PRIORITIZE_APP_PERFORMANCE_DIALOG_TAG); 75 ConfirmationDialogFragment.resetListeners( 76 dialogFragment, mConfirmListener, /* rejectListener= */ null, 77 /* neutralListener= */ null); 78 } 79 80 @Override onDestroyInternal()81 protected void onDestroyInternal() { 82 if (mCar != null) { 83 mCar.disconnect(); 84 mCar = null; 85 } 86 } 87 88 /** 89 * Set the package info of the application. 90 */ setPackageInfo(PackageInfo packageInfo)91 public void setPackageInfo(PackageInfo packageInfo) { 92 mPackageName = packageInfo.packageName; 93 mUserHandle = UserHandle.getUserHandleForUid(packageInfo.applicationInfo.uid); 94 } 95 96 @Override getPreferenceType()97 protected Class<TwoStatePreference> getPreferenceType() { 98 return TwoStatePreference.class; 99 } 100 101 @Override updateState(TwoStatePreference preference)102 protected void updateState(TwoStatePreference preference) { 103 if (!isCarConnected()) { 104 return; 105 } 106 int killableState = PerfImpactingAppsUtils.getKillableState(mPackageName, mUserHandle, 107 mCarWatchdogManager); 108 preference.setChecked(killableState == PackageKillableState.KILLABLE_STATE_NO); 109 preference.setEnabled(killableState != PackageKillableState.KILLABLE_STATE_NEVER); 110 } 111 112 @Override handlePreferenceChanged(TwoStatePreference preference, Object newValue)113 protected boolean handlePreferenceChanged(TwoStatePreference preference, Object newValue) { 114 boolean isToggledOn = (boolean) newValue; 115 if (isToggledOn) { 116 PerfImpactingAppsUtils.showPrioritizeAppConfirmationDialog(getContext(), 117 getFragmentController(), mConfirmListener, 118 TURN_ON_PRIORITIZE_APP_PERFORMANCE_DIALOG_TAG); 119 return false; 120 } 121 if (!isCarConnected()) { 122 return false; 123 } 124 setKillableState(true); 125 return true; 126 } 127 setKillableState(boolean isKillable)128 private void setKillableState(boolean isKillable) { 129 mCarWatchdogManager.setKillablePackageAsUser(mPackageName, mUserHandle, isKillable); 130 } 131 isCarConnected()132 private boolean isCarConnected() { 133 if (mCarWatchdogManager == null) { 134 LOG.e("CarWatchdogManager is null. Could not set killable state for '" + mPackageName 135 + "'."); 136 connectToCar(); 137 return false; 138 } 139 return true; 140 } 141 connectToCar()142 private void connectToCar() { 143 if (mCar != null && mCar.isConnected()) { 144 mCar.disconnect(); 145 mCar = null; 146 } 147 mCar = Car.createCar(getContext(), null, Car.CAR_WAIT_TIMEOUT_WAIT_FOREVER, 148 (car, isReady) -> { 149 mCarWatchdogManager = isReady 150 ? (CarWatchdogManager) car.getCarManager(Car.CAR_WATCHDOG_SERVICE) 151 : null; 152 }); 153 } 154 } 155