InstallFailed.java revision 74fa089b8c39d84b737607a3e3d2cde4d3b42d24
1327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann/*
2327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann * Copyright (C) 2016 The Android Open Source Project
3327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann *
4327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann *  Licensed under the Apache License, Version 2.0 (the "License");
5327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann *  you may not use this file except in compliance with the License.
6327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann *  You may obtain a copy of the License at
7327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann *
8327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann *       http://www.apache.org/licenses/LICENSE-2.0
9327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann *
10327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann *  Unless required by applicable law or agreed to in writing, software
11327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann *  distributed under the License is distributed on an "AS IS" BASIS,
12327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann *  See the License for the specific language governing permissions and
14327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann *  limitations under the License.
15327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann */
16327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
17327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmannpackage com.android.packageinstaller;
18327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
19327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmannimport android.app.Activity;
20327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmannimport android.app.AlertDialog;
21327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmannimport android.app.Dialog;
22327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmannimport android.app.DialogFragment;
23327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmannimport android.content.Context;
24327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmannimport android.content.DialogInterface;
25327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmannimport android.content.Intent;
26327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmannimport android.content.pm.ApplicationInfo;
27327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmannimport android.content.pm.PackageInstaller;
28327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmannimport android.content.pm.PackageManager;
29327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmannimport android.net.Uri;
30327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmannimport android.os.Bundle;
3174fa089b8c39d84b737607a3e3d2cde4d3b42d24Philip P. Moltmannimport android.support.annotation.Nullable;
32327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmannimport android.util.Log;
33327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmannimport android.view.View;
34327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmannimport android.widget.TextView;
35327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
36327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmannimport java.io.File;
37327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
38327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann/**
39327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann * Installation failed: Return status code to the caller or display failure UI to user
40327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann */
41327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmannpublic class InstallFailed extends Activity {
42327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    private static final String LOG_TAG = InstallFailed.class.getSimpleName();
43327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
44327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    /** Label of the app that failed to install */
45327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    private CharSequence mLabel;
46327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
47327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    /**
48327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann     * Convert an package installer status code into the user friendly label.
49327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann     *
50327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann     * @param statusCode The status code from the package installer.
51327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann     *
52327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann     * @return The user friendly label for the status code
53327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann     */
54327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    private int getExplanationFromErrorCode(int statusCode) {
55327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        Log.d(LOG_TAG, "Installation status code: " + statusCode);
56327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
57327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        switch (statusCode) {
58327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            case PackageInstaller.STATUS_FAILURE_BLOCKED:
59327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                return R.string.install_failed_blocked;
60327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            case PackageInstaller.STATUS_FAILURE_CONFLICT:
61327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                return R.string.install_failed_conflict;
62327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            case PackageInstaller.STATUS_FAILURE_INCOMPATIBLE:
63327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                return R.string.install_failed_incompatible;
64327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            case PackageInstaller.STATUS_FAILURE_INVALID:
65327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                return R.string.install_failed_invalid_apk;
66327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            default:
67327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                return R.string.install_failed;
68327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        }
69327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    }
70327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
71327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    @Override
72327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    protected void onCreate(@Nullable Bundle savedInstanceState) {
73327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        super.onCreate(savedInstanceState);
74327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
75327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        int statusCode = getIntent().getIntExtra(PackageInstaller.EXTRA_STATUS,
76327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                PackageInstaller.STATUS_FAILURE);
77327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
78327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
79ac9155b2b20164da52cdc0d82a6ab5c3a9d7ec38Philip P. Moltmann            int legacyStatus = getIntent().getIntExtra(PackageInstaller.EXTRA_LEGACY_STATUS,
80ac9155b2b20164da52cdc0d82a6ab5c3a9d7ec38Philip P. Moltmann                    PackageManager.INSTALL_FAILED_INTERNAL_ERROR);
81ac9155b2b20164da52cdc0d82a6ab5c3a9d7ec38Philip P. Moltmann
82327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            // Return result if requested
83327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            Intent result = new Intent();
84ac9155b2b20164da52cdc0d82a6ab5c3a9d7ec38Philip P. Moltmann            result.putExtra(Intent.EXTRA_INSTALL_RESULT, legacyStatus);
85327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            setResult(Activity.RESULT_FIRST_USER, result);
86327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            finish();
87327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        } else {
88327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            Intent intent = getIntent();
89327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            ApplicationInfo appInfo = intent
90327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                    .getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
91327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            Uri packageURI = intent.getData();
92327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
93327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            setContentView(R.layout.install_failed);
94327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
95327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            // Set header icon and title
96327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            PackageUtil.AppSnippet as;
97327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            PackageManager pm = getPackageManager();
98327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
99327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            if ("package".equals(packageURI.getScheme())) {
100327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                as = new PackageUtil.AppSnippet(pm.getApplicationLabel(appInfo),
101327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                        pm.getApplicationIcon(appInfo));
102327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            } else {
103327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                final File sourceFile = new File(packageURI.getPath());
104327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                as = PackageUtil.getAppSnippet(this, appInfo, sourceFile);
105327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            }
106327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
107327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            // Store label for dialog
108327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            mLabel = as.label;
109327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
110327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            PackageUtil.initSnippetForNewApp(this, as, R.id.app_snippet);
111327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
112327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            // Show out of space dialog if needed
113327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            if (statusCode == PackageInstaller.STATUS_FAILURE_STORAGE) {
114327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                (new OutOfSpaceDialog()).show(getFragmentManager(), "outofspace");
115327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            }
116327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
117327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            // Get status messages
118327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            int statusLabel = getExplanationFromErrorCode(statusCode);
119327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            String extendedStatusMessage = getIntent()
120327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                    .getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE);
121327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
122327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            // Show simple or extended failure screen
123327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            if (extendedStatusMessage == null) {
124327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                ((TextView) findViewById(R.id.simple_status)).setText(statusLabel);
125327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            } else {
126327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                // Switch from simple failure screen to extended view
127327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                findViewById(R.id.simple_status_view).setVisibility(View.GONE);
128327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                findViewById(R.id.extended_status_view).setVisibility(View.VISIBLE);
129327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
130327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                ((TextView) findViewById(R.id.extended_status)).setText(statusLabel);
131327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                ((TextView) findViewById(R.id.extended_status_message))
132327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                        .setText(extendedStatusMessage);
133327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            }
134327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
135327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            // Set up "done" button
136327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            findViewById(R.id.done_button).setOnClickListener(view -> finish());
137327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        }
138327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    }
139327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
140327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    /**
141327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann     * Dialog shown when we ran out of space during installation. This contains a link to the
142327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann     * "manage applications" settings page.
143327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann     */
144327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    public static class OutOfSpaceDialog extends DialogFragment {
145327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        private InstallFailed mActivity;
146327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
147327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        @Override
148327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        public void onAttach(Context context) {
149327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            super.onAttach(context);
150327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
151327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            mActivity = (InstallFailed) context;
152327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        }
153327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
154327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        @Override
155327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        public Dialog onCreateDialog(Bundle savedInstanceState) {
156327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            return new AlertDialog.Builder(mActivity)
157327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                    .setTitle(R.string.out_of_space_dlg_title)
158327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                    .setMessage(getString(R.string.out_of_space_dlg_text, mActivity.mLabel))
159327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                    .setPositiveButton(R.string.manage_applications, (dialog, which) -> {
160327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                        // launch manage applications
161327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                        Intent intent = new Intent("android.intent.action.MANAGE_PACKAGE_STORAGE");
162327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                        startActivity(intent);
163327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                        mActivity.finish();
164327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                    })
165327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                    .setNegativeButton(R.string.cancel, (dialog, which) -> mActivity.finish())
166327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                    .create();
167327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        }
168327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
169327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        @Override
170327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        public void onCancel(DialogInterface dialog) {
171327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            super.onCancel(dialog);
172327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
173327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            mActivity.finish();
174327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        }
175327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    }
176327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann}
177