• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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