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