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