1 /* 2 * Copyright (C) 2017 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.systemui; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.content.Context; 22 import android.content.DialogInterface; 23 import android.content.Intent; 24 import android.content.pm.ApplicationInfo; 25 import android.content.pm.PackageManager; 26 import android.net.Uri; 27 import android.os.Bundle; 28 import android.provider.Settings; 29 import android.util.IconDrawableFactory; 30 import android.util.Log; 31 import android.view.LayoutInflater; 32 import android.view.View; 33 import android.view.ViewGroup; 34 import android.widget.AdapterView; 35 import android.widget.ArrayAdapter; 36 import android.widget.ImageView; 37 import android.widget.ListView; 38 import android.widget.TextView; 39 40 import com.android.internal.app.AlertActivity; 41 import com.android.internal.app.AlertController; 42 import com.android.internal.logging.MetricsLogger; 43 import com.android.internal.logging.nano.MetricsProto; 44 import com.android.systemui.res.R; 45 46 import java.util.ArrayList; 47 48 import javax.inject.Inject; 49 50 /** 51 * Show a list of currently running foreground services (supplied by the caller) 52 * that the user can tap through to their application details. 53 */ 54 public final class ForegroundServicesDialog extends AlertActivity implements 55 AdapterView.OnItemSelectedListener, DialogInterface.OnClickListener, 56 AlertController.AlertParams.OnPrepareListViewListener { 57 58 private static final String TAG = "ForegroundServicesDialog"; 59 60 LayoutInflater mInflater; 61 62 private final MetricsLogger mMetricsLogger; 63 64 private String[] mPackages; 65 private PackageItemAdapter mAdapter; 66 67 private DialogInterface.OnClickListener mAppClickListener = 68 new DialogInterface.OnClickListener() { 69 public void onClick(DialogInterface dialog, int which) { 70 String pkg = mAdapter.getItem(which).packageName; 71 Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); 72 intent.setData(Uri.fromParts("package", pkg, null)); 73 startActivity(intent); 74 finish(); 75 } 76 }; 77 78 @Inject ForegroundServicesDialog(MetricsLogger metricsLogger)79 ForegroundServicesDialog(MetricsLogger metricsLogger) { 80 super(); 81 mMetricsLogger = metricsLogger; 82 } 83 84 @Override onCreate(Bundle savedInstanceState)85 protected void onCreate(Bundle savedInstanceState) { 86 super.onCreate(savedInstanceState); 87 88 mInflater = LayoutInflater.from(this); 89 90 mAdapter = new PackageItemAdapter(this); 91 92 final AlertController.AlertParams p = mAlertParams; 93 p.mAdapter = mAdapter; 94 p.mOnClickListener = mAppClickListener; 95 p.mCustomTitleView = mInflater.inflate(R.layout.foreground_service_title, null); 96 p.mIsSingleChoice = true; 97 p.mOnItemSelectedListener = this; 98 p.mPositiveButtonText = getString(com.android.internal.R.string.done_label); 99 p.mPositiveButtonListener = this; 100 p.mOnPrepareListViewListener = this; 101 102 updateApps(getIntent()); 103 if (mPackages == null) { 104 Log.w(TAG, "No packages supplied"); 105 finish(); 106 return; 107 } 108 109 setupAlert(); 110 } 111 112 @Override onResume()113 protected void onResume() { 114 super.onResume(); 115 mMetricsLogger.visible(MetricsProto.MetricsEvent.RUNNING_BACKGROUND_APPS_DIALOG); 116 } 117 118 @Override onPause()119 protected void onPause() { 120 super.onPause(); 121 mMetricsLogger.hidden(MetricsProto.MetricsEvent.RUNNING_BACKGROUND_APPS_DIALOG); 122 } 123 124 @Override onNewIntent(Intent intent)125 protected void onNewIntent(Intent intent) { 126 super.onNewIntent(intent); 127 updateApps(intent); 128 } 129 130 @Override onStop()131 protected void onStop() { 132 super.onStop(); 133 134 // This is a transient dialog, if the user leaves it then it goes away, 135 // they can return back to it from the notification. 136 if (!isChangingConfigurations()) { 137 finish(); 138 } 139 } 140 updateApps(Intent intent)141 void updateApps(Intent intent) { 142 mPackages = intent.getStringArrayExtra("packages"); 143 if (mPackages != null) { 144 mAdapter.setPackages(mPackages); 145 } 146 } 147 onPrepareListView(ListView listView)148 public void onPrepareListView(ListView listView) { 149 } 150 151 /* 152 * On click of Ok/Cancel buttons 153 */ onClick(DialogInterface dialog, int which)154 public void onClick(DialogInterface dialog, int which) { 155 finish(); 156 } 157 onItemSelected(AdapterView parent, View view, int position, long id)158 public void onItemSelected(AdapterView parent, View view, int position, long id) { 159 } 160 onNothingSelected(AdapterView parent)161 public void onNothingSelected(AdapterView parent) { 162 } 163 164 static private class PackageItemAdapter extends ArrayAdapter<ApplicationInfo> { 165 final PackageManager mPm; 166 final LayoutInflater mInflater; 167 final IconDrawableFactory mIconDrawableFactory; 168 PackageItemAdapter(Context context)169 public PackageItemAdapter(Context context) { 170 super(context, R.layout.foreground_service_item); 171 mPm = context.getPackageManager(); 172 mInflater = LayoutInflater.from(context); 173 mIconDrawableFactory = IconDrawableFactory.newInstance(context, true); 174 } 175 setPackages(String[] packages)176 public void setPackages(String[] packages) { 177 clear(); 178 179 ArrayList<ApplicationInfo> apps = new ArrayList<>(); 180 for (int i = 0; i < packages.length; i++) { 181 try { 182 apps.add(mPm.getApplicationInfo(packages[i], 183 PackageManager.MATCH_KNOWN_PACKAGES)); 184 } catch (PackageManager.NameNotFoundException e) { 185 } 186 } 187 188 apps.sort(new ApplicationInfo.DisplayNameComparator(mPm)); 189 addAll(apps); 190 } 191 192 public @NonNull getView(int position, @Nullable View convertView, @NonNull ViewGroup parent)193 View getView(int position, @Nullable View convertView, 194 @NonNull ViewGroup parent) { 195 final View view; 196 if (convertView == null) { 197 view = mInflater.inflate(R.layout.foreground_service_item, parent, false); 198 } else { 199 view = convertView; 200 } 201 202 ImageView icon = view.findViewById(R.id.app_icon); 203 icon.setImageDrawable(mIconDrawableFactory.getBadgedIcon(getItem(position))); 204 205 TextView label = view.findViewById(R.id.app_name); 206 label.setText(getItem(position).loadLabel(mPm)); 207 208 return view; 209 } 210 } 211 } 212