1 /*
2  * Copyright (C) 2019 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.development;
18 
19 import android.app.ActivityManager;
20 import android.content.Context;
21 import android.os.Build;
22 import android.os.Handler;
23 import android.os.Looper;
24 import android.os.RemoteException;
25 import android.os.UserManager;
26 import android.util.Log;
27 import android.widget.Toast;
28 
29 import androidx.preference.Preference;
30 
31 import com.android.settings.R;
32 import com.android.settings.core.PreferenceControllerMixin;
33 import com.android.settingslib.development.DeveloperOptionsPreferenceController;
34 
35 public class SystemServerHeapDumpPreferenceController extends DeveloperOptionsPreferenceController
36         implements PreferenceControllerMixin {
37 
38     private static final String KEY_SYSTEM_SERVER_HEAP_DUMP = "system_server_heap_dump";
39 
40     /** How long to keep the preference disabled before re-enabling. */
41     private static final long ENABLE_TIMEOUT_MILLIS = 5000L;
42 
43     private final UserManager mUserManager;
44 
45     private Handler mHandler;
46 
SystemServerHeapDumpPreferenceController(Context context)47     public SystemServerHeapDumpPreferenceController(Context context) {
48         super(context);
49 
50         mUserManager = context.getSystemService(UserManager.class);
51         mHandler = new Handler(Looper.getMainLooper());
52     }
53 
54     @Override
isAvailable()55     public boolean isAvailable() {
56         return Build.IS_DEBUGGABLE
57                 && !mUserManager.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES);
58     }
59 
60     @Override
getPreferenceKey()61     public String getPreferenceKey() {
62         return KEY_SYSTEM_SERVER_HEAP_DUMP;
63     }
64 
65     @Override
handlePreferenceTreeClick(Preference preference)66     public boolean handlePreferenceTreeClick(Preference preference) {
67         if (!KEY_SYSTEM_SERVER_HEAP_DUMP.equals(preference.getKey())) {
68             return false;
69         }
70         try {
71             // Temporarily disable the preference so the user doesn't start two dumps in a row.
72             preference.setEnabled(false);
73             Toast.makeText(mContext, R.string.capturing_system_heap_dump_message,
74                     Toast.LENGTH_SHORT).show();
75             ActivityManager.getService().requestSystemServerHeapDump();
76             mHandler.postDelayed(() -> preference.setEnabled(true), ENABLE_TIMEOUT_MILLIS);
77             return true;
78         } catch (RemoteException e) {
79             Log.e(TAG, "error taking system heap dump", e);
80             Toast.makeText(mContext, R.string.error_capturing_system_heap_dump_message,
81                     Toast.LENGTH_SHORT).show();
82         }
83         return false;
84     }
85 }
86