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.widget.TextView;
34327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
35327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmannimport java.io.File;
36327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
37327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann/**
38327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann * Installation failed: Return status code to the caller or display failure UI to user
39327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann */
40327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmannpublic class InstallFailed extends Activity {
41327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    private static final String LOG_TAG = InstallFailed.class.getSimpleName();
42327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
43327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    /** Label of the app that failed to install */
44327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    private CharSequence mLabel;
45327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
46327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    /**
47327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann     * Convert an package installer status code into the user friendly label.
48327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann     *
49327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann     * @param statusCode The status code from the package installer.
50327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann     *
51327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann     * @return The user friendly label for the status code
52327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann     */
53327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    private int getExplanationFromErrorCode(int statusCode) {
54327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        Log.d(LOG_TAG, "Installation status code: " + statusCode);
55327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
56327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        switch (statusCode) {
57327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            case PackageInstaller.STATUS_FAILURE_BLOCKED:
58327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                return R.string.install_failed_blocked;
59327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            case PackageInstaller.STATUS_FAILURE_CONFLICT:
60327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                return R.string.install_failed_conflict;
61327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            case PackageInstaller.STATUS_FAILURE_INCOMPATIBLE:
62327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                return R.string.install_failed_incompatible;
63327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            case PackageInstaller.STATUS_FAILURE_INVALID:
64327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                return R.string.install_failed_invalid_apk;
65327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            default:
66327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                return R.string.install_failed;
67327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        }
68327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    }
69327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
70327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    @Override
71327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    protected void onCreate(@Nullable Bundle savedInstanceState) {
72327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        super.onCreate(savedInstanceState);
73327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
74327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        int statusCode = getIntent().getIntExtra(PackageInstaller.EXTRA_STATUS,
75327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                PackageInstaller.STATUS_FAILURE);
76327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
77327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
78ac9155b2b20164da52cdc0d82a6ab5c3a9d7ec38Philip P. Moltmann            int legacyStatus = getIntent().getIntExtra(PackageInstaller.EXTRA_LEGACY_STATUS,
79ac9155b2b20164da52cdc0d82a6ab5c3a9d7ec38Philip P. Moltmann                    PackageManager.INSTALL_FAILED_INTERNAL_ERROR);
80ac9155b2b20164da52cdc0d82a6ab5c3a9d7ec38Philip P. Moltmann
81327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            // Return result if requested
82327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            Intent result = new Intent();
83ac9155b2b20164da52cdc0d82a6ab5c3a9d7ec38Philip P. Moltmann            result.putExtra(Intent.EXTRA_INSTALL_RESULT, legacyStatus);
84327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            setResult(Activity.RESULT_FIRST_USER, result);
85327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            finish();
86327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        } else {
87327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            Intent intent = getIntent();
88327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            ApplicationInfo appInfo = intent
89327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                    .getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
90327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            Uri packageURI = intent.getData();
91327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
92327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            setContentView(R.layout.install_failed);
93327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
94327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            // Set header icon and title
95327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            PackageUtil.AppSnippet as;
96327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            PackageManager pm = getPackageManager();
97327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
98327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            if ("package".equals(packageURI.getScheme())) {
99327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                as = new PackageUtil.AppSnippet(pm.getApplicationLabel(appInfo),
100327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                        pm.getApplicationIcon(appInfo));
101327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            } else {
102327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                final File sourceFile = new File(packageURI.getPath());
103327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                as = PackageUtil.getAppSnippet(this, appInfo, sourceFile);
104327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            }
105327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
106327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            // Store label for dialog
107327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            mLabel = as.label;
108327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
109327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            PackageUtil.initSnippetForNewApp(this, as, R.id.app_snippet);
110327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
111327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            // Show out of space dialog if needed
112327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            if (statusCode == PackageInstaller.STATUS_FAILURE_STORAGE) {
113327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                (new OutOfSpaceDialog()).show(getFragmentManager(), "outofspace");
114327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            }
115327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
116327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            // Get status messages
11716a26ad865898986a0ed789284a34f61531211f4Philip P. Moltmann            ((TextView) findViewById(R.id.simple_status)).setText(
11816a26ad865898986a0ed789284a34f61531211f4Philip P. Moltmann                    getExplanationFromErrorCode(statusCode));
119327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
120327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            // Set up "done" button
121327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            findViewById(R.id.done_button).setOnClickListener(view -> finish());
122327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        }
123327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    }
124327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
125327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    /**
126327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann     * Dialog shown when we ran out of space during installation. This contains a link to the
127327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann     * "manage applications" settings page.
128327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann     */
129327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    public static class OutOfSpaceDialog extends DialogFragment {
130327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        private InstallFailed mActivity;
131327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
132327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        @Override
133327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        public void onAttach(Context context) {
134327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            super.onAttach(context);
135327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
136327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            mActivity = (InstallFailed) context;
137327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        }
138327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
139327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        @Override
140327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        public Dialog onCreateDialog(Bundle savedInstanceState) {
141327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            return new AlertDialog.Builder(mActivity)
142327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                    .setTitle(R.string.out_of_space_dlg_title)
143327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                    .setMessage(getString(R.string.out_of_space_dlg_text, mActivity.mLabel))
144327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                    .setPositiveButton(R.string.manage_applications, (dialog, which) -> {
145327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                        // launch manage applications
146327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                        Intent intent = new Intent("android.intent.action.MANAGE_PACKAGE_STORAGE");
147327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                        startActivity(intent);
148327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                        mActivity.finish();
149327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                    })
150327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                    .setNegativeButton(R.string.cancel, (dialog, which) -> mActivity.finish())
151327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann                    .create();
152327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        }
153327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
154327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        @Override
155327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        public void onCancel(DialogInterface dialog) {
156327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            super.onCancel(dialog);
157327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann
158327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann            mActivity.finish();
159327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann        }
160327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann    }
161327a359bc96d8b532362fe966a451188f307b7cfPhilip P. Moltmann}
162