• 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.support.annotation.Nullable;
32 import android.util.Log;
33 import android.widget.TextView;
34 
35 import java.io.File;
36 
37 /**
38  * Installation failed: Return status code to the caller or display failure UI to user
39  */
40 public class InstallFailed extends Activity {
41     private static final String LOG_TAG = InstallFailed.class.getSimpleName();
42 
43     /** Label of the app that failed to install */
44     private CharSequence mLabel;
45 
46     /**
47      * Convert an package installer status code into the user friendly label.
48      *
49      * @param statusCode The status code from the package installer.
50      *
51      * @return The user friendly label for the status code
52      */
getExplanationFromErrorCode(int statusCode)53     private int getExplanationFromErrorCode(int statusCode) {
54         Log.d(LOG_TAG, "Installation status code: " + statusCode);
55 
56         switch (statusCode) {
57             case PackageInstaller.STATUS_FAILURE_BLOCKED:
58                 return R.string.install_failed_blocked;
59             case PackageInstaller.STATUS_FAILURE_CONFLICT:
60                 return R.string.install_failed_conflict;
61             case PackageInstaller.STATUS_FAILURE_INCOMPATIBLE:
62                 return R.string.install_failed_incompatible;
63             case PackageInstaller.STATUS_FAILURE_INVALID:
64                 return R.string.install_failed_invalid_apk;
65             default:
66                 return R.string.install_failed;
67         }
68     }
69 
70     @Override
onCreate(@ullable Bundle savedInstanceState)71     protected void onCreate(@Nullable Bundle savedInstanceState) {
72         super.onCreate(savedInstanceState);
73 
74         int statusCode = getIntent().getIntExtra(PackageInstaller.EXTRA_STATUS,
75                 PackageInstaller.STATUS_FAILURE);
76 
77         if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
78             int legacyStatus = getIntent().getIntExtra(PackageInstaller.EXTRA_LEGACY_STATUS,
79                     PackageManager.INSTALL_FAILED_INTERNAL_ERROR);
80 
81             // Return result if requested
82             Intent result = new Intent();
83             result.putExtra(Intent.EXTRA_INSTALL_RESULT, legacyStatus);
84             setResult(Activity.RESULT_FIRST_USER, result);
85             finish();
86         } else {
87             Intent intent = getIntent();
88             ApplicationInfo appInfo = intent
89                     .getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
90             Uri packageURI = intent.getData();
91 
92             setContentView(R.layout.install_failed);
93 
94             // Set header icon and title
95             PackageUtil.AppSnippet as;
96             PackageManager pm = getPackageManager();
97 
98             if ("package".equals(packageURI.getScheme())) {
99                 as = new PackageUtil.AppSnippet(pm.getApplicationLabel(appInfo),
100                         pm.getApplicationIcon(appInfo));
101             } else {
102                 final File sourceFile = new File(packageURI.getPath());
103                 as = PackageUtil.getAppSnippet(this, appInfo, sourceFile);
104             }
105 
106             // Store label for dialog
107             mLabel = as.label;
108 
109             PackageUtil.initSnippetForNewApp(this, as, R.id.app_snippet);
110 
111             // Show out of space dialog if needed
112             if (statusCode == PackageInstaller.STATUS_FAILURE_STORAGE) {
113                 (new OutOfSpaceDialog()).show(getFragmentManager(), "outofspace");
114             }
115 
116             // Get status messages
117             ((TextView) findViewById(R.id.simple_status)).setText(
118                     getExplanationFromErrorCode(statusCode));
119 
120             // Set up "done" button
121             findViewById(R.id.done_button).setOnClickListener(view -> finish());
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