• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.tv.settings.device.apps;
18 
19 import android.app.Activity;
20 import android.app.ActivityManager;
21 import android.content.ActivityNotFoundException;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.pm.IPackageDataObserver;
25 import android.content.pm.PackageManager;
26 import android.graphics.drawable.Drawable;
27 import android.os.Bundle;
28 import android.os.Handler;
29 import android.os.UserHandle;
30 import android.support.annotation.NonNull;
31 import android.support.v17.preference.LeanbackPreferenceFragment;
32 import android.support.v7.preference.Preference;
33 import android.support.v7.preference.PreferenceScreen;
34 import android.util.Log;
35 import android.widget.Toast;
36 
37 import com.android.settingslib.applications.ApplicationsState;
38 import com.android.tv.settings.R;
39 
40 import java.util.ArrayList;
41 
42 public class AppManagementFragment extends LeanbackPreferenceFragment {
43     private static final String TAG = "AppManagementFragment";
44 
45     private static final String ARG_PACKAGE_NAME = "packageName";
46 
47     // Result code identifiers
48     private static final int REQUEST_UNINSTALL = 1;
49     private static final int REQUEST_MANAGE_SPACE = 2;
50     private static final int REQUEST_UNINSTALL_UPDATES = 3;
51 
52     private PackageManager mPackageManager;
53     private String mPackageName;
54     private ApplicationsState mApplicationsState;
55     private ApplicationsState.Session mSession;
56     private ApplicationsState.AppEntry mEntry;
57     private final ApplicationsState.Callbacks mCallbacks = new ApplicationsStateCallbacks();
58 
59     private ForceStopPreference mForceStopPreference;
60     private UninstallPreference mUninstallPreference;
61     private EnableDisablePreference mEnableDisablePreference;
62     private AppStoragePreference mAppStoragePreference;
63     private ClearDataPreference mClearDataPreference;
64     private ClearCachePreference mClearCachePreference;
65     private ClearDefaultsPreference mClearDefaultsPreference;
66     private NotificationsPreference mNotificationsPreference;
67 
68     private final Handler mHandler = new Handler();
69     private Runnable mBailoutRunnable = new Runnable() {
70         @Override
71         public void run() {
72             if (isResumed() && !getFragmentManager().popBackStackImmediate()) {
73                 getActivity().onBackPressed();
74             }
75         }
76     };
77 
prepareArgs(@onNull Bundle args, String packageName)78     public static void prepareArgs(@NonNull Bundle args, String packageName) {
79         args.putString(ARG_PACKAGE_NAME, packageName);
80     }
81 
82     @Override
onCreate(Bundle savedInstanceState)83     public void onCreate(Bundle savedInstanceState) {
84         mPackageName = getArguments().getString(ARG_PACKAGE_NAME);
85 
86         final Activity activity = getActivity();
87         mPackageManager = activity.getPackageManager();
88         mApplicationsState = ApplicationsState.getInstance(activity.getApplication());
89         mSession = mApplicationsState.newSession(mCallbacks);
90         mEntry = mApplicationsState.getEntry(mPackageName, UserHandle.myUserId());
91 
92         super.onCreate(savedInstanceState);
93     }
94 
95     @Override
onResume()96     public void onResume() {
97         super.onResume();
98         mSession.resume();
99 
100         if (mEntry == null) {
101             Log.w(TAG, "App not found, trying to bail out");
102             navigateBack();
103         }
104 
105         if (mClearDefaultsPreference != null) {
106             mClearDefaultsPreference.refresh();
107         }
108         if (mEnableDisablePreference != null) {
109             mEnableDisablePreference.refresh();
110         }
111     }
112 
113     @Override
onPause()114     public void onPause() {
115         super.onPause();
116         mSession.pause();
117         mHandler.removeCallbacks(mBailoutRunnable);
118     }
119 
120     @Override
onActivityResult(int requestCode, int resultCode, Intent data)121     public void onActivityResult(int requestCode, int resultCode, Intent data) {
122         super.onActivityResult(requestCode, resultCode, data);
123         if (mEntry == null) {
124             return;
125         }
126         switch (requestCode) {
127             case REQUEST_UNINSTALL:
128                 if (resultCode == Activity.RESULT_OK) {
129                     final int userId =  UserHandle.getUserId(mEntry.info.uid);
130                     mApplicationsState.removePackage(mPackageName, userId);
131                     navigateBack();
132                 }
133                 break;
134             case REQUEST_MANAGE_SPACE:
135                 mClearDataPreference.setClearingData(false);
136                 if(resultCode == Activity.RESULT_OK) {
137                     final int userId = UserHandle.getUserId(mEntry.info.uid);
138                     mApplicationsState.requestSize(mPackageName, userId);
139                 } else {
140                     Log.w(TAG, "Failed to clear data!");
141                 }
142                 break;
143             case REQUEST_UNINSTALL_UPDATES:
144                 mUninstallPreference.refresh();
145                 break;
146         }
147     }
148 
navigateBack()149     private void navigateBack() {
150         // need to post this to avoid recursing in the fragment manager.
151         mHandler.removeCallbacks(mBailoutRunnable);
152         mHandler.post(mBailoutRunnable);
153     }
154 
155     @Override
onPreferenceTreeClick(Preference preference)156     public boolean onPreferenceTreeClick(Preference preference) {
157         if (preference.getIntent() != null) {
158             try {
159                 startActivity(preference.getIntent());
160             } catch (ActivityNotFoundException e) {
161                 Log.e(TAG, "Could not find activity to launch", e);
162                 // TODO(b/30507703): don't reuse this string
163                 Toast.makeText(getContext(), R.string.status_unavailable,
164                         Toast.LENGTH_SHORT).show();
165             }
166             return true;
167         } else {
168             return super.onPreferenceTreeClick(preference);
169         }
170     }
171 
172     @Override
onCreatePreferences(Bundle savedInstanceState, String rootKey)173     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
174         final Context themedContext = getPreferenceManager().getContext();
175         final PreferenceScreen screen =
176                 getPreferenceManager().createPreferenceScreen(themedContext);
177         screen.setTitle(getAppName());
178 
179         if (mEntry == null) {
180             setPreferenceScreen(screen);
181             return;
182         }
183 
184         final Preference versionPreference = new Preference(themedContext);
185         versionPreference.setSelectable(false);
186         versionPreference.setTitle(getString(R.string.device_apps_app_management_version,
187                 mEntry.getVersion(getActivity())));
188         versionPreference.setSummary(mPackageName);
189         screen.addPreference(versionPreference);
190 
191         // Open
192         Intent appLaunchIntent =
193                 mPackageManager.getLeanbackLaunchIntentForPackage(mEntry.info.packageName);
194         if (appLaunchIntent == null) {
195             appLaunchIntent = mPackageManager.getLaunchIntentForPackage(mEntry.info.packageName);
196         }
197         if (appLaunchIntent != null) {
198             final Preference openPreference = new Preference(themedContext);
199             openPreference.setIntent(appLaunchIntent);
200             openPreference.setTitle(R.string.device_apps_app_management_open);
201             screen.addPreference(openPreference);
202         }
203 
204         // Force stop
205         mForceStopPreference = new ForceStopPreference(themedContext, mEntry);
206         screen.addPreference(mForceStopPreference);
207 
208         // Uninstall
209         mUninstallPreference = new UninstallPreference(themedContext, mEntry);
210         screen.addPreference(mUninstallPreference);
211 
212         // Disable/Enable
213         mEnableDisablePreference = new EnableDisablePreference(themedContext, mEntry);
214         screen.addPreference(mEnableDisablePreference);
215 
216         // Storage used
217         mAppStoragePreference = new AppStoragePreference(themedContext, mEntry);
218         screen.addPreference(mAppStoragePreference);
219 
220         // Clear data
221         mClearDataPreference = new ClearDataPreference(themedContext, mEntry);
222         screen.addPreference(mClearDataPreference);
223 
224         // Clear cache
225         mClearCachePreference = new ClearCachePreference(themedContext, mEntry);
226         screen.addPreference(mClearCachePreference);
227 
228         // Clear defaults
229         mClearDefaultsPreference = new ClearDefaultsPreference(themedContext, mEntry);
230         screen.addPreference(mClearDefaultsPreference);
231 
232         // Notifications
233         mNotificationsPreference = new NotificationsPreference(themedContext, mEntry);
234         screen.addPreference(mNotificationsPreference);
235 
236         // Permissions
237         final Preference permissionsPreference = new Preference(themedContext);
238         permissionsPreference.setTitle(R.string.device_apps_app_management_permissions);
239         permissionsPreference.setIntent(new Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS)
240                 .putExtra(Intent.EXTRA_PACKAGE_NAME, mPackageName));
241         screen.addPreference(permissionsPreference);
242 
243         setPreferenceScreen(screen);
244     }
245 
getAppName()246     public String getAppName() {
247         if (mEntry == null) {
248             return null;
249         }
250         mEntry.ensureLabel(getActivity());
251         return mEntry.label;
252     }
253 
getAppIcon()254     public Drawable getAppIcon() {
255         if (mEntry == null) {
256             return null;
257         }
258         mApplicationsState.ensureIcon(mEntry);
259         return mEntry.icon;
260     }
261 
clearData()262     public void clearData() {
263         mClearDataPreference.setClearingData(true);
264         String spaceManagementActivityName = mEntry.info.manageSpaceActivityName;
265         if (spaceManagementActivityName != null) {
266             if (!ActivityManager.isUserAMonkey()) {
267                 Intent intent = new Intent(Intent.ACTION_DEFAULT);
268                 intent.setClassName(mEntry.info.packageName, spaceManagementActivityName);
269                 startActivityForResult(intent, REQUEST_MANAGE_SPACE);
270             }
271         } else {
272             ActivityManager am = (ActivityManager) getActivity().getSystemService(
273                     Context.ACTIVITY_SERVICE);
274             boolean success = am.clearApplicationUserData(
275                     mEntry.info.packageName, new IPackageDataObserver.Stub() {
276                         public void onRemoveCompleted(
277                                 final String packageName, final boolean succeeded) {
278                             mHandler.post(new Runnable() {
279                                 @Override
280                                 public void run() {
281                                     mClearDataPreference.setClearingData(false);
282                                     if (succeeded) {
283                                         dataCleared(true);
284                                     } else {
285                                         dataCleared(false);
286                                     }
287                                 }
288                             });
289                         }
290                     });
291             if (!success) {
292                 mClearDataPreference.setClearingData(false);
293                 dataCleared(false);
294             }
295         }
296         mClearDataPreference.refresh();
297     }
298 
dataCleared(boolean succeeded)299     private void dataCleared(boolean succeeded) {
300         if (succeeded) {
301             final int userId =  UserHandle.getUserId(mEntry.info.uid);
302             mApplicationsState.requestSize(mPackageName, userId);
303         } else {
304             Log.w(TAG, "Failed to clear data!");
305             mClearDataPreference.refresh();
306         }
307     }
308 
clearCache()309     public void clearCache() {
310         mClearCachePreference.setClearingCache(true);
311         mPackageManager.deleteApplicationCacheFiles(mEntry.info.packageName,
312                 new IPackageDataObserver.Stub() {
313                     public void onRemoveCompleted(final String packageName,
314                             final boolean succeeded) {
315                         mHandler.post(new Runnable() {
316                             @Override
317                             public void run() {
318                                 mClearCachePreference.setClearingCache(false);
319                                 cacheCleared(succeeded);
320                             }
321                         });
322                     }
323                 });
324         mClearCachePreference.refresh();
325     }
326 
cacheCleared(boolean succeeded)327     private void cacheCleared(boolean succeeded) {
328         if (succeeded) {
329             final int userId =  UserHandle.getUserId(mEntry.info.uid);
330             mApplicationsState.requestSize(mPackageName, userId);
331         } else {
332             Log.w(TAG, "Failed to clear cache!");
333             mClearCachePreference.refresh();
334         }
335     }
336 
launchUninstall()337     public void launchUninstall() {
338         if (mUninstallPreference.canUninstall() || mUninstallPreference.canUninstallUpdates()) {
339             Intent uninstallIntent = mUninstallPreference.getUninstallIntent();
340             uninstallIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
341             startActivityForResult(uninstallIntent, REQUEST_UNINSTALL);
342         }
343         mUninstallPreference.refresh();
344     }
345 
346     private class ApplicationsStateCallbacks implements ApplicationsState.Callbacks {
347 
348         @Override
onRunningStateChanged(boolean running)349         public void onRunningStateChanged(boolean running) {
350             if (mForceStopPreference != null) {
351                 mForceStopPreference.refresh();
352             }
353         }
354 
355         @Override
onPackageListChanged()356         public void onPackageListChanged() {
357             if (mEntry == null) {
358                 return;
359             }
360             final int userId = UserHandle.getUserId(mEntry.info.uid);
361             mEntry = mApplicationsState.getEntry(mPackageName, userId);
362             if (mEntry == null) {
363                 navigateBack();
364             }
365             onCreatePreferences(null, null);
366         }
367 
368         @Override
onRebuildComplete(ArrayList<ApplicationsState.AppEntry> apps)369         public void onRebuildComplete(ArrayList<ApplicationsState.AppEntry> apps) {}
370 
371         @Override
onPackageIconChanged()372         public void onPackageIconChanged() {}
373 
374         @Override
onPackageSizeChanged(String packageName)375         public void onPackageSizeChanged(String packageName) {
376             if (mAppStoragePreference == null) {
377                 // Nothing to do here.
378                 return;
379             }
380             mAppStoragePreference.refresh();
381             mClearDataPreference.refresh();
382             mClearCachePreference.refresh();
383         }
384 
385         @Override
onAllSizesComputed()386         public void onAllSizesComputed() {
387             if (mAppStoragePreference == null) {
388                 // Nothing to do here.
389                 return;
390             }
391             mAppStoragePreference.refresh();
392             mClearDataPreference.refresh();
393             mClearCachePreference.refresh();
394         }
395 
396         @Override
onLauncherInfoChanged()397         public void onLauncherInfoChanged() {}
398 
399         @Override
onLoadEntriesCompleted()400         public void onLoadEntriesCompleted() {
401             if (mAppStoragePreference == null) {
402                 // Nothing to do here.
403                 return;
404             }
405             mAppStoragePreference.refresh();
406             mClearDataPreference.refresh();
407             mClearCachePreference.refresh();
408         }
409     }
410 }
411