1 /*
2  * Copyright (C) 2018 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.internal.app;
18 
19 import android.Manifest;
20 import android.app.AlertDialog;
21 import android.content.DialogInterface;
22 import android.content.Intent;
23 import android.content.pm.PackageManager;
24 import android.content.pm.ResolveInfo;
25 import android.os.Bundle;
26 import android.os.UserHandle;
27 import android.util.Slog;
28 import android.view.WindowManager;
29 
30 import com.android.internal.R;
31 
32 public class SuspendedAppActivity extends AlertActivity
33         implements DialogInterface.OnClickListener {
34     private static final String TAG = "SuspendedAppActivity";
35     public static final String EXTRA_SUSPENDED_PACKAGE =
36             "SuspendedAppActivity.extra.SUSPENDED_PACKAGE";
37     public static final String EXTRA_SUSPENDING_PACKAGE =
38             "SuspendedAppActivity.extra.SUSPENDING_PACKAGE";
39     public static final String EXTRA_DIALOG_MESSAGE = "SuspendedAppActivity.extra.DIALOG_MESSAGE";
40 
41     private Intent mMoreDetailsIntent;
42     private int mUserId;
43     private PackageManager mPm;
44 
getAppLabel(String packageName)45     private CharSequence getAppLabel(String packageName) {
46         try {
47             return mPm.getApplicationInfoAsUser(packageName, 0, mUserId).loadLabel(mPm);
48         } catch (PackageManager.NameNotFoundException ne) {
49             Slog.e(TAG, "Package " + packageName + " not found", ne);
50         }
51         return packageName;
52     }
53 
getMoreDetailsActivity(String suspendingPackage, String suspendedPackage, int userId)54     private Intent getMoreDetailsActivity(String suspendingPackage, String suspendedPackage,
55             int userId) {
56         final Intent moreDetailsIntent = new Intent(Intent.ACTION_SHOW_SUSPENDED_APP_DETAILS)
57                 .setPackage(suspendingPackage);
58         final String requiredPermission = Manifest.permission.SEND_SHOW_SUSPENDED_APP_DETAILS;
59         final ResolveInfo resolvedInfo = mPm.resolveActivityAsUser(moreDetailsIntent, 0, userId);
60         if (resolvedInfo != null && resolvedInfo.activityInfo != null
61                 && requiredPermission.equals(resolvedInfo.activityInfo.permission)) {
62             moreDetailsIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, suspendedPackage)
63                     .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
64             return moreDetailsIntent;
65         }
66         return null;
67     }
68 
69     @Override
onCreate(Bundle icicle)70     public void onCreate(Bundle icicle) {
71         super.onCreate(icicle);
72         mPm = getPackageManager();
73         getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
74 
75         final Intent intent = getIntent();
76         mUserId = intent.getIntExtra(Intent.EXTRA_USER_ID, -1);
77         if (mUserId < 0) {
78             Slog.wtf(TAG, "Invalid user: " + mUserId);
79             finish();
80             return;
81         }
82         final String suppliedMessage = intent.getStringExtra(EXTRA_DIALOG_MESSAGE);
83         final String suspendedPackage = intent.getStringExtra(EXTRA_SUSPENDED_PACKAGE);
84         final String suspendingPackage = intent.getStringExtra(EXTRA_SUSPENDING_PACKAGE);
85         final CharSequence suspendedAppLabel = getAppLabel(suspendedPackage);
86         final CharSequence dialogMessage;
87         if (suppliedMessage == null) {
88             dialogMessage = getString(R.string.app_suspended_default_message, suspendedAppLabel,
89                     getAppLabel(suspendingPackage));
90         } else {
91             dialogMessage = String.format(getResources().getConfiguration().getLocales().get(0),
92                     suppliedMessage, suspendedAppLabel);
93         }
94 
95         final AlertController.AlertParams ap = mAlertParams;
96         ap.mTitle = getString(R.string.app_suspended_title);
97         ap.mMessage = dialogMessage;
98         ap.mPositiveButtonText = getString(android.R.string.ok);
99         mMoreDetailsIntent = getMoreDetailsActivity(suspendingPackage, suspendedPackage, mUserId);
100         if (mMoreDetailsIntent != null) {
101             ap.mNeutralButtonText = getString(R.string.app_suspended_more_details);
102         }
103         ap.mPositiveButtonListener = ap.mNeutralButtonListener = this;
104         setupAlert();
105     }
106 
107     @Override
onClick(DialogInterface dialog, int which)108     public void onClick(DialogInterface dialog, int which) {
109         switch (which) {
110             case AlertDialog.BUTTON_NEUTRAL:
111                 startActivityAsUser(mMoreDetailsIntent, UserHandle.of(mUserId));
112                 Slog.i(TAG, "Started more details activity");
113                 break;
114         }
115         finish();
116     }
117 
createSuspendedAppInterceptIntent(String suspendedPackage, String suspendingPackage, String dialogMessage, int userId)118     public static Intent createSuspendedAppInterceptIntent(String suspendedPackage,
119             String suspendingPackage, String dialogMessage, int userId) {
120         return new Intent()
121                 .setClassName("android", SuspendedAppActivity.class.getName())
122                 .putExtra(EXTRA_SUSPENDED_PACKAGE, suspendedPackage)
123                 .putExtra(EXTRA_DIALOG_MESSAGE, dialogMessage)
124                 .putExtra(EXTRA_SUSPENDING_PACKAGE, suspendingPackage)
125                 .putExtra(Intent.EXTRA_USER_ID, userId)
126                 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
127                         | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
128     }
129 }
130