blob: 54105bb8432dc8d7636783eb5107b9bead0e3cb9 [file] [log] [blame]
Alan Viverette3da604b2020-06-10 18:34:39 +00001/*
2 * Copyright (C) 2016 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
17package com.android.packageinstaller;
18
19import android.annotation.Nullable;
20import android.app.Activity;
21import android.app.AlertDialog;
22import android.app.Dialog;
23import android.app.DialogFragment;
24import android.content.Context;
25import android.content.DialogInterface;
26import android.content.Intent;
27import android.content.pm.ApplicationInfo;
28import android.content.pm.PackageInstaller;
29import android.content.pm.PackageManager;
30import android.net.Uri;
31import android.os.Bundle;
32import android.util.Log;
33import android.view.View;
34
35import com.android.internal.app.AlertActivity;
36
37import java.io.File;
38
39/**
40 * Installation failed: Return status code to the caller or display failure UI to user
41 */
42public class InstallFailed extends AlertActivity {
43 private static final String LOG_TAG = InstallFailed.class.getSimpleName();
44
45 /** Label of the app that failed to install */
46 private CharSequence mLabel;
47
48 /**
49 * Unhide the appropriate label for the statusCode.
50 *
51 * @param statusCode The status code from the package installer.
52 */
53 private void setExplanationFromErrorCode(int statusCode) {
54 Log.d(LOG_TAG, "Installation status code: " + statusCode);
55
56 View viewToEnable;
57 switch (statusCode) {
58 case PackageInstaller.STATUS_FAILURE_BLOCKED:
59 viewToEnable = requireViewById(R.id.install_failed_blocked);
60 break;
61 case PackageInstaller.STATUS_FAILURE_CONFLICT:
62 viewToEnable = requireViewById(R.id.install_failed_conflict);
63 break;
64 case PackageInstaller.STATUS_FAILURE_INCOMPATIBLE:
65 viewToEnable = requireViewById(R.id.install_failed_incompatible);
66 break;
67 case PackageInstaller.STATUS_FAILURE_INVALID:
68 viewToEnable = requireViewById(R.id.install_failed_invalid_apk);
69 break;
70 default:
71 viewToEnable = requireViewById(R.id.install_failed);
72 break;
73 }
74
75 viewToEnable.setVisibility(View.VISIBLE);
76 }
77
78 @Override
79 protected void onCreate(@Nullable Bundle savedInstanceState) {
80 super.onCreate(savedInstanceState);
81
82 int statusCode = getIntent().getIntExtra(PackageInstaller.EXTRA_STATUS,
83 PackageInstaller.STATUS_FAILURE);
84
85 if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
86 int legacyStatus = getIntent().getIntExtra(PackageInstaller.EXTRA_LEGACY_STATUS,
87 PackageManager.INSTALL_FAILED_INTERNAL_ERROR);
88
89 // Return result if requested
90 Intent result = new Intent();
91 result.putExtra(Intent.EXTRA_INSTALL_RESULT, legacyStatus);
92 setResult(Activity.RESULT_FIRST_USER, result);
93 finish();
94 } else {
95 Intent intent = getIntent();
96 ApplicationInfo appInfo = intent
97 .getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
98 Uri packageURI = intent.getData();
99
100 // Set header icon and title
101 PackageUtil.AppSnippet as;
102 PackageManager pm = getPackageManager();
103
104 if ("package".equals(packageURI.getScheme())) {
105 as = new PackageUtil.AppSnippet(pm.getApplicationLabel(appInfo),
106 pm.getApplicationIcon(appInfo));
107 } else {
108 final File sourceFile = new File(packageURI.getPath());
109 as = PackageUtil.getAppSnippet(this, appInfo, sourceFile);
110 }
111
112 // Store label for dialog
113 mLabel = as.label;
114
115 mAlert.setIcon(as.icon);
116 mAlert.setTitle(as.label);
117 mAlert.setView(R.layout.install_content_view);
118 mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.done),
119 (ignored, ignored2) -> finish(), null);
120 setupAlert();
121
122 // Show out of space dialog if needed
123 if (statusCode == PackageInstaller.STATUS_FAILURE_STORAGE) {
124 (new OutOfSpaceDialog()).show(getFragmentManager(), "outofspace");
125 }
126
127 // Get status messages
128 setExplanationFromErrorCode(statusCode);
129 }
130 }
131
132 /**
133 * Dialog shown when we ran out of space during installation. This contains a link to the
134 * "manage applications" settings page.
135 */
136 public static class OutOfSpaceDialog extends DialogFragment {
137 private InstallFailed mActivity;
138
139 @Override
140 public void onAttach(Context context) {
141 super.onAttach(context);
142
143 mActivity = (InstallFailed) context;
144 }
145
146 @Override
147 public Dialog onCreateDialog(Bundle savedInstanceState) {
148 return new AlertDialog.Builder(mActivity)
149 .setTitle(R.string.out_of_space_dlg_title)
150 .setMessage(getString(R.string.out_of_space_dlg_text, mActivity.mLabel))
151 .setPositiveButton(R.string.manage_applications, (dialog, which) -> {
152 // launch manage applications
153 Intent intent = new Intent("android.intent.action.MANAGE_PACKAGE_STORAGE");
154 startActivity(intent);
155 mActivity.finish();
156 })
157 .setNegativeButton(R.string.cancel, (dialog, which) -> mActivity.finish())
158 .create();
159 }
160
161 @Override
162 public void onCancel(DialogInterface dialog) {
163 super.onCancel(dialog);
164
165 mActivity.finish();
166 }
167 }
168}