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