Home | History | Annotate | Download | only in applications
      1 /*
      2  * Copyright (C) 2015 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.settings.applications;
     18 
     19 import android.app.Activity;
     20 import android.app.AlertDialog;
     21 import android.app.Dialog;
     22 import android.app.DialogFragment;
     23 import android.app.Fragment;
     24 import android.app.admin.DevicePolicyManager;
     25 import android.content.BroadcastReceiver;
     26 import android.content.Context;
     27 import android.content.Intent;
     28 import android.content.IntentFilter;
     29 import android.content.pm.PackageInfo;
     30 import android.content.pm.PackageManager;
     31 import android.content.pm.PackageManager.NameNotFoundException;
     32 import android.hardware.usb.IUsbManager;
     33 import android.os.Bundle;
     34 import android.os.IBinder;
     35 import android.os.ServiceManager;
     36 import android.os.UserHandle;
     37 import android.os.UserManager;
     38 import android.text.TextUtils;
     39 import android.util.Log;
     40 
     41 import com.android.internal.logging.nano.MetricsProto;
     42 import com.android.settings.SettingsActivity;
     43 import com.android.settings.SettingsPreferenceFragment;
     44 import com.android.settings.Utils;
     45 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
     46 import com.android.settings.enterprise.DevicePolicyManagerWrapper;
     47 import com.android.settings.enterprise.DevicePolicyManagerWrapperImpl;
     48 import com.android.settings.overlay.FeatureFactory;
     49 import com.android.settingslib.RestrictedLockUtils;
     50 import com.android.settingslib.applications.ApplicationsState;
     51 import com.android.settingslib.applications.ApplicationsState.AppEntry;
     52 
     53 import java.util.ArrayList;
     54 
     55 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
     56 
     57 public abstract class AppInfoBase extends SettingsPreferenceFragment
     58         implements ApplicationsState.Callbacks {
     59 
     60     public static final String ARG_PACKAGE_NAME = "package";
     61     public static final String ARG_PACKAGE_UID = "uid";
     62 
     63     protected static final String TAG = AppInfoBase.class.getSimpleName();
     64     protected static final boolean localLOGV = false;
     65 
     66     protected EnforcedAdmin mAppsControlDisallowedAdmin;
     67     protected boolean mAppsControlDisallowedBySystem;
     68 
     69     protected ApplicationFeatureProvider mApplicationFeatureProvider;
     70     protected ApplicationsState mState;
     71     protected ApplicationsState.Session mSession;
     72     protected ApplicationsState.AppEntry mAppEntry;
     73     protected PackageInfo mPackageInfo;
     74     protected int mUserId;
     75     protected String mPackageName;
     76 
     77     protected IUsbManager mUsbManager;
     78     protected DevicePolicyManagerWrapper mDpm;
     79     protected UserManager mUserManager;
     80     protected PackageManager mPm;
     81 
     82     // Dialog identifiers used in showDialog
     83     protected static final int DLG_BASE = 0;
     84 
     85     protected boolean mFinishing;
     86     protected boolean mListeningToPackageRemove;
     87 
     88     @Override
     89     public void onCreate(Bundle savedInstanceState) {
     90         super.onCreate(savedInstanceState);
     91         mFinishing = false;
     92         final Activity activity = getActivity();
     93         mApplicationFeatureProvider = FeatureFactory.getFactory(activity)
     94                 .getApplicationFeatureProvider(activity);
     95         mState = ApplicationsState.getInstance(activity.getApplication());
     96         mSession = mState.newSession(this);
     97         mDpm = new DevicePolicyManagerWrapperImpl(
     98                 (DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE));
     99         mUserManager = (UserManager) activity.getSystemService(Context.USER_SERVICE);
    100         mPm = activity.getPackageManager();
    101         IBinder b = ServiceManager.getService(Context.USB_SERVICE);
    102         mUsbManager = IUsbManager.Stub.asInterface(b);
    103 
    104         retrieveAppEntry();
    105         startListeningToPackageRemove();
    106     }
    107 
    108     @Override
    109     public void onResume() {
    110         super.onResume();
    111         mSession.resume();
    112         mAppsControlDisallowedAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(getActivity(),
    113                 UserManager.DISALLOW_APPS_CONTROL, mUserId);
    114         mAppsControlDisallowedBySystem = RestrictedLockUtils.hasBaseUserRestriction(getActivity(),
    115                 UserManager.DISALLOW_APPS_CONTROL, mUserId);
    116 
    117         if (!refreshUi()) {
    118             setIntentAndFinish(true, true);
    119         }
    120     }
    121 
    122     @Override
    123     public void onPause() {
    124         mSession.pause();
    125         super.onPause();
    126     }
    127 
    128     @Override
    129     public void onDestroy() {
    130         stopListeningToPackageRemove();
    131         mSession.release();
    132         super.onDestroy();
    133     }
    134 
    135     protected String retrieveAppEntry() {
    136         final Bundle args = getArguments();
    137         mPackageName = (args != null) ? args.getString(ARG_PACKAGE_NAME) : null;
    138         if (mPackageName == null) {
    139             Intent intent = (args == null) ?
    140                     getActivity().getIntent() : (Intent) args.getParcelable("intent");
    141             if (intent != null) {
    142                 mPackageName = intent.getData().getSchemeSpecificPart();
    143             }
    144         }
    145         mUserId = UserHandle.myUserId();
    146         mAppEntry = mState.getEntry(mPackageName, mUserId);
    147         if (mAppEntry != null) {
    148             // Get application info again to refresh changed properties of application
    149             try {
    150                 mPackageInfo = mPm.getPackageInfo(mAppEntry.info.packageName,
    151                         PackageManager.MATCH_DISABLED_COMPONENTS |
    152                         PackageManager.MATCH_ANY_USER |
    153                         PackageManager.GET_SIGNATURES |
    154                         PackageManager.GET_PERMISSIONS);
    155             } catch (NameNotFoundException e) {
    156                 Log.e(TAG, "Exception when retrieving package:" + mAppEntry.info.packageName, e);
    157             }
    158         } else {
    159             Log.w(TAG, "Missing AppEntry; maybe reinstalling?");
    160             mPackageInfo = null;
    161         }
    162 
    163         return mPackageName;
    164     }
    165 
    166     protected void setIntentAndFinish(boolean finish, boolean appChanged) {
    167         if (localLOGV) Log.i(TAG, "appChanged="+appChanged);
    168         Intent intent = new Intent();
    169         intent.putExtra(ManageApplications.APP_CHG, appChanged);
    170         SettingsActivity sa = (SettingsActivity)getActivity();
    171         sa.finishPreferencePanel(this, Activity.RESULT_OK, intent);
    172         mFinishing = true;
    173     }
    174 
    175     protected void showDialogInner(int id, int moveErrorCode) {
    176         DialogFragment newFragment = MyAlertDialogFragment.newInstance(id, moveErrorCode);
    177         newFragment.setTargetFragment(this, 0);
    178         newFragment.show(getFragmentManager(), "dialog " + id);
    179     }
    180 
    181     protected abstract boolean refreshUi();
    182     protected abstract AlertDialog createDialog(int id, int errorCode);
    183 
    184     @Override
    185     public void onRunningStateChanged(boolean running) {
    186         // No op.
    187     }
    188 
    189     @Override
    190     public void onRebuildComplete(ArrayList<AppEntry> apps) {
    191         // No op.
    192     }
    193 
    194     @Override
    195     public void onPackageIconChanged() {
    196         // No op.
    197     }
    198 
    199     @Override
    200     public void onPackageSizeChanged(String packageName) {
    201         // No op.
    202     }
    203 
    204     @Override
    205     public void onAllSizesComputed() {
    206         // No op.
    207     }
    208 
    209     @Override
    210     public void onLauncherInfoChanged() {
    211         // No op.
    212     }
    213 
    214     @Override
    215     public void onLoadEntriesCompleted() {
    216         // No op.
    217     }
    218 
    219     @Override
    220     public void onPackageListChanged() {
    221         refreshUi();
    222     }
    223 
    224     public static void startAppInfoFragment(Class<?> fragment, int titleRes,
    225             String pkg, int uid, Fragment source, int request, int sourceMetricsCategory) {
    226         startAppInfoFragment(fragment, titleRes, pkg, uid, source.getActivity(), request,
    227                 sourceMetricsCategory);
    228     }
    229 
    230     public static void startAppInfoFragment(Class<?> fragment, int titleRes,
    231             String pkg, int uid, Activity source, int request, int sourceMetricsCategory) {
    232         Bundle args = new Bundle();
    233         args.putString(AppInfoBase.ARG_PACKAGE_NAME, pkg);
    234         args.putInt(AppInfoBase.ARG_PACKAGE_UID, uid);
    235 
    236         Intent intent = Utils.onBuildStartFragmentIntent(source, fragment.getName(),
    237                 args, null, titleRes, null, false, sourceMetricsCategory);
    238         source.startActivityForResultAsUser(intent, request,
    239                 new UserHandle(UserHandle.getUserId(uid)));
    240     }
    241 
    242     public static class MyAlertDialogFragment extends InstrumentedDialogFragment {
    243 
    244         private static final String ARG_ID = "id";
    245 
    246         @Override
    247         public int getMetricsCategory() {
    248             return MetricsProto.MetricsEvent.DIALOG_APP_INFO_ACTION;
    249         }
    250 
    251         @Override
    252         public Dialog onCreateDialog(Bundle savedInstanceState) {
    253             int id = getArguments().getInt(ARG_ID);
    254             int errorCode = getArguments().getInt("moveError");
    255             Dialog dialog = ((AppInfoBase) getTargetFragment()).createDialog(id, errorCode);
    256             if (dialog == null) {
    257                 throw new IllegalArgumentException("unknown id " + id);
    258             }
    259             return dialog;
    260         }
    261 
    262         public static MyAlertDialogFragment newInstance(int id, int errorCode) {
    263             MyAlertDialogFragment dialogFragment = new MyAlertDialogFragment();
    264             Bundle args = new Bundle();
    265             args.putInt(ARG_ID, id);
    266             args.putInt("moveError", errorCode);
    267             dialogFragment.setArguments(args);
    268             return dialogFragment;
    269         }
    270     }
    271 
    272     protected void startListeningToPackageRemove() {
    273         if (mListeningToPackageRemove) {
    274             return;
    275         }
    276         mListeningToPackageRemove = true;
    277         final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED);
    278         filter.addDataScheme("package");
    279         getContext().registerReceiver(mPackageRemovedReceiver, filter);
    280     }
    281 
    282     protected void stopListeningToPackageRemove() {
    283         if (!mListeningToPackageRemove) {
    284             return;
    285         }
    286         mListeningToPackageRemove = false;
    287         getContext().unregisterReceiver(mPackageRemovedReceiver);
    288     }
    289 
    290     protected void onPackageRemoved() {
    291         getActivity().finishAndRemoveTask();
    292     }
    293 
    294     protected final BroadcastReceiver mPackageRemovedReceiver = new BroadcastReceiver() {
    295         @Override
    296         public void onReceive(Context context, Intent intent) {
    297             String packageName = intent.getData().getSchemeSpecificPart();
    298             if (!mFinishing && (mAppEntry == null || mAppEntry.info == null
    299                     || TextUtils.equals(mAppEntry.info.packageName, packageName))) {
    300                 onPackageRemoved();
    301             }
    302         }
    303     };
    304 
    305 }
    306