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