Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
  **
  ** Copyright 2007, The Android Open Source Project
  **
  ** Licensed under the Apache License, Version 2.0 (the "License");
  ** you may not use this file except in compliance with the License.
  ** You may obtain a copy of the License at
  **
  **     http://www.apache.org/licenses/LICENSE-2.0
 **
 ** Unless required by applicable law or agreed to in writing, software
 ** distributed under the License is distributed on an "AS IS" BASIS,
 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
 package com.android.packageinstaller;
 
 
 import java.io.File;
 
 /*
  * This activity is launched when a new application is installed via side loading
  * The package is first parsed and the user is notified of parse errors via a dialog.
  * If the package is successfully parsed, the user is notified to turn on the install unknown
  * applications setting. A memory check is made at this point and the user is notified of out
  * of memory conditions if any. If the package is already existing on the device, 
  * a confirmation dialog (to replace the existing package) is presented to the user.
  * Based on the user response the package is then installed by launching InstallAppConfirm
  * sub activity. All state transitions are handled in this activity
  */
 public class PackageInstallerActivity extends Activity implements OnCancelListenerOnClickListener {
     private static final String TAG = "PackageInstaller";
     private Uri mPackageURI;    
     private Uri mOriginatingURI;
     private Uri mReferrerURI;
     private int mOriginatingUid = .;
     private ManifestDigest mPkgDigest;
 
     private boolean localLOGV = false;
     PackageManager mPm;
 
     // ApplicationInfo object primarily used for already existing applications
     private ApplicationInfo mAppInfo = null;
 
     // View for install progress
     // Buttons to indicate user acceptance
     private Button mOk;
     private Button mCancel;
     private boolean mOkCanInstall = false;
 
     static final String PREFS_ALLOWED_SOURCES = "allowed_sources";
 
     // Dialog identifiers used in showDialog
     private static final int DLG_BASE = 0;
     private static final int DLG_UNKNOWN_APPS =  + 1;
     private static final int DLG_PACKAGE_ERROR =  + 2;
     private static final int DLG_OUT_OF_SPACE =  + 3;
     private static final int DLG_INSTALL_ERROR =  + 4;
     private static final int DLG_ALLOW_SOURCE =  + 5;
 
     private void startInstallConfirm() {
         TabHost tabHost = (TabHost)findViewById(android.R.id.tabhost);
         tabHost.setup();
         ViewPager viewPager = (ViewPager)findViewById(..);
        TabsAdapter adapter = new TabsAdapter(thistabHostviewPager);
        boolean permVisible = false;
         = null;
         = false;
        int msg = 0;
        if ( != null) {
            AppSecurityPermissions perms = new AppSecurityPermissions(this);
            final int NP = perms.getPermissionCount(.);
            final int ND = perms.getPermissionCount(.);
            if ( != null) {
                msg = (. & .) != 0
                        ? ..
                        : ..;
                 = new CaffeinatedScrollView(this);
                .setFillViewport(true);
                if (perms.getPermissionCount(.) > 0) {
                    permVisible = true;
                    .addView(perms.getPermissionsView(
                            .));
                } else {
                    LayoutInflater inflater = (LayoutInflater)getSystemService(
                            .);
                    TextView label = (TextView)inflater.inflate(..null);
                    label.setText(..);
                    .addView(label);
                }
                adapter.addTab(tabHost.newTabSpec("new").setIndicator(
                        getText(..)), );
            } else  {
                findViewById(..).setVisibility(.);
                findViewById(..).setVisibility(.);
            }
            if (NP > 0 || ND > 0) {
                permVisible = true;
                LayoutInflater inflater = (LayoutInflater)getSystemService(
                        .);
                View root = inflater.inflate(..null);
                if ( == null) {
                     = (CaffeinatedScrollView)root.findViewById(..);
                }
                if (NP > 0) {
                    ((ViewGroup)root.findViewById(..)).addView(
                            perms.getPermissionsView(.));
                } else {
                    root.findViewById(..).setVisibility(.);
                }
                if (ND > 0) {
                    ((ViewGroup)root.findViewById(..)).addView(
                            perms.getPermissionsView(.));
                } else {
                    root.findViewById(..).setVisibility(.);
                }
                adapter.addTab(tabHost.newTabSpec("all").setIndicator(
                        getText(..)), root);
            }
        }
        if (!permVisible) {
            if ( != null) {
                // This is an update to an application, but there are no
                // permissions at all.
                msg = (. & .) != 0
                        ? ..
                        : ..;
            } else {
                // This is a new application with no permissions.
                msg = ..;
            }
            tabHost.setVisibility(.);
            findViewById(..).setVisibility(.);
            findViewById(..).setVisibility(.);
             = null;
        }
        if (msg != 0) {
            ((TextView)findViewById(..)).setText(msg);
        }
         = (Button)findViewById(..);
        .setOnClickListener(this);
        .setOnClickListener(this);
        if ( == null) {
            // There is nothing to scroll view, so the ok button is immediately
            // set to install.
            .setText(..);
             = true;
        } else {
            .setFullScrollAction(new Runnable() {
                @Override
                public void run() {
                    .setText(..);
                     = true;
                }
            });
        }
    }
    private void showDialogInner(int id) {
        // TODO better fix for this? Remove dialog so that it gets created again
        removeDialog(id);
        showDialog(id);
    }
    @Override
    public Dialog onCreateDialog(int idBundle bundle) {
        switch (id) {
        case :
            return new AlertDialog.Builder(this)
                    .setTitle(..)
                    .setMessage(..)
                    .setNegativeButton(..new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialogint which) {
                            Log.i("Finishing off activity so that user can navigate to settings manually");
                            finish();
                        }})
                    .setPositiveButton(..new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialogint which) {
                            Log.i("Launching settings");
                            launchSettingsAppAndFinish();
                        }
                    })
                    .setOnCancelListener(this)
                    .create(); 
        case  :
            return new AlertDialog.Builder(this)
                    .setTitle(..)
                    .setMessage(..)
                    .setPositiveButton(..new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialogint which) {
                            finish();
                        }
                    })
                    .setOnCancelListener(this)
                    .create();
        case :
            // Guaranteed not to be null. will default to package name if not set by app
            CharSequence appTitle = .getApplicationLabel(.);
            String dlgText = getString(..
                    appTitle.toString());
            return new AlertDialog.Builder(this)
                    .setTitle(..)
                    .setMessage(dlgText)
                    .setPositiveButton(..new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialogint which) {
                            //launch manage applications
                            Intent intent = new Intent("android.intent.action.MANAGE_PACKAGE_STORAGE");
                            intent.setFlags(.);
                            startActivity(intent);   
                            finish();
                        }
                    })
                    .setNegativeButton(..new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialogint which) {
                            Log.i("Canceling installation");
                            finish();
                        }
                  })
                  .setOnCancelListener(this)
                  .create();
        case  :
            // Guaranteed not to be null. will default to package name if not set by app
            CharSequence appTitle1 = .getApplicationLabel(.);
            String dlgText1 = getString(..,
                    appTitle1.toString());
            return new AlertDialog.Builder(this)
                    .setTitle(..)
                    .setNeutralButton(..new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialogint which) {
                            finish();
                        }
                    })
                    .setMessage(dlgText1)
                    .setOnCancelListener(this)
                    .create();
        case :
            CharSequence appTitle2 = .getApplicationLabel();
            String dlgText2 = getString(..,
                    appTitle2.toString());
            return new AlertDialog.Builder(this)
                    .setTitle(..)
                    .setMessage(dlgText2)
                    .setNegativeButton(..new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialogint which) {
                            setResult();
                            finish();
                        }})
                    .setPositiveButton(..new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialogint which) {
                            SharedPreferences prefs = getSharedPreferences(,
                                    .);
                            prefs.edit().putBoolean(.true).apply();
                            startInstallConfirm();
                        }
                    })
                    .setOnCancelListener(this)
                    .create();
       }
       return null;
   }
    private void launchSettingsAppAndFinish() {
        // Create an intent to launch SettingsTwo activity
        Intent launchSettingsIntent = new Intent(.);
        launchSettingsIntent.setFlags(.);
        startActivity(launchSettingsIntent);
        finish();
    }
    
    private boolean isInstallingUnknownAppsAllowed() {
        return Settings.Global.getInt(getContentResolver(),
            .., 0) > 0;
    }
    
    private void initiateInstall() {
        String pkgName = .;
        // Check if there is already a package on the device with this name
        // but it has been renamed to something else.
        String[] oldName = .canonicalToCurrentPackageNames(new String[] { pkgName });
        if (oldName != null && oldName.length > 0 && oldName[0] != null) {
            pkgName = oldName[0];
            . = pkgName;
            .. = pkgName;
        }
        // Check if package is already installed. display confirmation dialog if replacing pkg
        try {
            // This is a little convoluted because we want to get all uninstalled
            // apps, but this may include apps with just data, and if it is just
            // data we still want to count it as "installed".
             = .getApplicationInfo(pkgName,
                    .);
            if ((.&.) == 0) {
                 = null;
            }
        } catch (NameNotFoundException e) {
             = null;
        }
        startInstallConfirm();
    }
    void setPmResult(int pmResult) {
        Intent result = new Intent();
        result.putExtra(.pmResult);
        setResult(pmResult == .
                ?  : result);
    }
    @Override
    protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        // get intent information
        final Intent intent = getIntent();
         = intent.getData();
         = getPackageManager();
        final String scheme = .getScheme();
        if (scheme != null && !"file".equals(scheme) && !"package".equals(scheme)) {
            Log.w("Unsupported scheme " + scheme);
            return;
        }
        final PackageUtil.AppSnippet as;
        if ("package".equals(.getScheme())) {
            try {
                 = .getPackageInfo(.getSchemeSpecificPart(),
                        . | .);
            } catch (NameNotFoundException e) {
            }
            if ( == null) {
                Log.w("Requested package " + .getScheme()
                        + " not available. Discontinuing installation");
                showDialogInner();
                setPmResult(.);
                return;
            }
                    .getApplicationIcon(.));
        } else {
            final File sourceFile = new File(.getPath());
            PackageParser.Package parsed = PackageUtil.getPackageInfo(sourceFile);
            // Check for parse errors
            if (parsed == null) {
                Log.w("Parse error when parsing manifest. Discontinuing installation");
                showDialogInner();
                setPmResult(.);
                return;
            }
             = PackageParser.generatePackageInfo(parsednull,
                    ., 0, 0, null,
                    new PackageUserState());
             = parsed.manifestDigest;
            as = PackageUtil.getAppSnippet(this.sourceFile);
        }
        
        //set view
        PackageUtil.initSnippetForNewApp(thisas..);
         = getOriginatingUid(intent);
        // Deal with install source.
        String callerPackage = getCallingPackage();
        if (callerPackage != null && intent.getBooleanExtra(
                .false)) {
            try {
                 = .getApplicationInfo(callerPackage, 0);
                if ( != null) {
                    if ((.&.) != 0) {
                        // System apps don't need to be approved.
                        initiateInstall();
                        return;
                    }
                    /* for now this is disabled, since the user would need to
                     * have enabled the global "unknown sources" setting in the
                     * first place in order to get here.
                    SharedPreferences prefs = getSharedPreferences(PREFS_ALLOWED_SOURCES,
                            Context.MODE_PRIVATE);
                    if (prefs.getBoolean(mSourceInfo.packageName, false)) {
                        // User has already allowed this one.
                        initiateInstall();
                        return;
                    }
                    //ask user to enable setting first
                    showDialogInner(DLG_ALLOW_SOURCE);
                    return;
                     */
                }
            } catch (NameNotFoundException e) {
            }
        }
        // Check unknown sources.
        if (!isInstallingUnknownAppsAllowed()) {
            //ask user to enable setting first
            showDialogInner();
            return;
        }
        initiateInstall();
    }

    
Get the ApplicationInfo for the calling package, if available
    private ApplicationInfo getSourceInfo() {
        String callingPackage = getCallingPackage();
        if (callingPackage != null) {
            try {
                return .getApplicationInfo(callingPackage, 0);
            } catch (NameNotFoundException ex) {
                // ignore
            }
        }
        return null;
    }


    
Get the originating uid if possible, or VerificationParams.NO_UID if not available
    private int getOriginatingUid(Intent intent) {
        // The originating uid from the intent. We only trust/use this if it comes from a
        // system application
        int uidFromIntent = intent.getIntExtra(.,
                .);
        // Get the source info from the calling package, if available. This will be the
        // definitive calling package, but it only works if the intent was started using
        // startActivityForResult,
        ApplicationInfo sourceInfo = getSourceInfo();
        if (sourceInfo != null) {
            if (uidFromIntent != . &&
                    (. & .) != 0) {
                return uidFromIntent;
            }
            // We either didn't get a uid in the intent, or we don't trust it. Use the
            // uid of the calling package instead.
            return sourceInfo.uid;
        }
        // We couldn't get the specific calling package. Let's get the uid instead
        int callingUid;
        try {
            callingUid = ActivityManagerNative.getDefault()
                    .getLaunchedFromUid(getActivityToken());
        } catch (android.os.RemoteException ex) {
            Log.w("Could not determine the launching uid.");
            // nothing else we can do
            return .;
        }
        // If we got a uid from the intent, we need to verify that the caller is a
        // system package before we use it
        if (uidFromIntent != .) {
            String[] callingPackages = .getPackagesForUid(callingUid);
            if (callingPackages != null) {
                for (String packageNamecallingPackages) {
                    try {
                        ApplicationInfo applicationInfo =
                                .getApplicationInfo(packageName, 0);
                        if ((applicationInfo.flags & .) != 0) {
                            return uidFromIntent;
                        }
                    } catch (NameNotFoundException ex) {
                        // ignore it, and try the next package
                    }
                }
            }
        }
        // We either didn't get a uid from the intent, or we don't trust it. Use the
        // calling uid instead.
        return callingUid;
    }
    // Generic handling when pressing back key
    public void onCancel(DialogInterface dialog) {
        finish();
    }
    public void onClick(View v) {
        if(v == ) {
            if ( ||  == null) {
                // Start subactivity to actually install the application
                Intent newIntent = new Intent();
                newIntent.putExtra(.,
                        .);
                newIntent.setData();
                newIntent.setClass(thisInstallAppProgress.class);
                newIntent.putExtra(.);
                String installerPackageName = getIntent().getStringExtra(
                        .);
                if ( != null) {
                    newIntent.putExtra(.);
                }
                if ( != null) {
                    newIntent.putExtra(.);
                }
                if ( != .) {
                    newIntent.putExtra(.);
                }
                if (installerPackageName != null) {
                    newIntent.putExtra(.,
                            installerPackageName);
                }
                if (getIntent().getBooleanExtra(.false)) {
                    newIntent.putExtra(.true);
                    newIntent.addFlags(.);
                }
                if() Log.i("downloaded app uri="+);
                startActivity(newIntent);
                finish();
            } else {
                .pageScroll(.);
            }
        } else if(v == ) {
            // Cancel and finish
            setResult();
            finish();
        }
    }