Merge "Move packages between candidate volumes."
This commit is contained in:
@@ -36,7 +36,7 @@
|
||||
<ListView android:id="@android:id/list"
|
||||
style="@style/PreferenceFragmentListSinglePane"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingStart="@dimen/settings_side_margin"
|
||||
android:paddingEnd="@dimen/settings_side_margin"
|
||||
android:paddingTop="@dimen/dashboard_padding_top"
|
||||
|
@@ -23,13 +23,12 @@ import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.IPackageDataObserver;
|
||||
import android.content.pm.IPackageMoveObserver;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.os.storage.VolumeInfo;
|
||||
import android.text.format.Formatter;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
@@ -38,11 +37,16 @@ import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.settings.DropDownPreference;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.applications.ApplicationsState.AppEntry;
|
||||
import com.android.settings.applications.ApplicationsState.Callbacks;
|
||||
import com.android.settings.DropDownPreference;
|
||||
import com.android.settings.deviceinfo.StorageWizardMoveConfirm;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class AppStorageSettings extends AppInfoWithHeader
|
||||
implements OnClickListener, Callbacks, DropDownPreference.Callback {
|
||||
@@ -53,7 +57,6 @@ public class AppStorageSettings extends AppInfoWithHeader
|
||||
private static final int OP_FAILED = 2;
|
||||
private static final int MSG_CLEAR_USER_DATA = 1;
|
||||
private static final int MSG_CLEAR_CACHE = 3;
|
||||
private static final int MSG_PACKAGE_MOVE = 4;
|
||||
|
||||
// invalid size value used initially and also when size retrieval through PackageManager
|
||||
// fails for whatever reason
|
||||
@@ -64,13 +67,11 @@ public class AppStorageSettings extends AppInfoWithHeader
|
||||
|
||||
private static final int DLG_CLEAR_DATA = DLG_BASE + 1;
|
||||
private static final int DLG_CANNOT_CLEAR_DATA = DLG_BASE + 2;
|
||||
private static final int DLG_MOVE_FAILED = DLG_BASE + 3;
|
||||
|
||||
private static final String KEY_MOVE_PREFERENCE = "app_location_setting";
|
||||
private static final String KEY_STORAGE_SETTINGS = "storage_settings";
|
||||
private static final String KEY_CACHE_SETTINGS = "cache_settings";
|
||||
|
||||
private CanBeOnSdCardChecker mCanBeOnSdCardChecker;
|
||||
private TextView mTotalSize;
|
||||
private TextView mAppSize;
|
||||
private TextView mDataSize;
|
||||
@@ -83,7 +84,6 @@ public class AppStorageSettings extends AppInfoWithHeader
|
||||
private Button mClearCacheButton;
|
||||
|
||||
private DropDownPreference mMoveDropDown;
|
||||
private boolean mMoveInProgress = false;
|
||||
|
||||
private boolean mCanClearData = true;
|
||||
private boolean mHaveSizes = false;
|
||||
@@ -97,7 +97,6 @@ public class AppStorageSettings extends AppInfoWithHeader
|
||||
|
||||
private ClearCacheObserver mClearCacheObserver;
|
||||
private ClearUserDataObserver mClearDataObserver;
|
||||
private PackageMoveObserver mPackageMoveObserver;
|
||||
|
||||
// Resource strings
|
||||
private CharSequence mInvalidSizeStr;
|
||||
@@ -107,7 +106,6 @@ public class AppStorageSettings extends AppInfoWithHeader
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mCanBeOnSdCardChecker = new CanBeOnSdCardChecker();
|
||||
addPreferencesFromResource(R.xml.app_storage_settings);
|
||||
setupViews();
|
||||
}
|
||||
@@ -166,18 +164,19 @@ public class AppStorageSettings extends AppInfoWithHeader
|
||||
|
||||
@Override
|
||||
public boolean onItemSelected(int pos, Object value) {
|
||||
boolean selectedExternal = (Boolean) value;
|
||||
boolean isExternal = (mAppEntry.info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
|
||||
if (selectedExternal ^ isExternal) {
|
||||
if (mPackageMoveObserver == null) {
|
||||
mPackageMoveObserver = new PackageMoveObserver();
|
||||
}
|
||||
int moveFlags = selectedExternal ? PackageManager.MOVE_EXTERNAL_MEDIA
|
||||
: PackageManager.MOVE_INTERNAL;
|
||||
mMoveInProgress = true;
|
||||
refreshButtons();
|
||||
mPm.movePackage(mAppEntry.info.packageName, mPackageMoveObserver, moveFlags);
|
||||
final Context context = getActivity();
|
||||
|
||||
// If not current volume, kick off move wizard
|
||||
final VolumeInfo targetVol = (VolumeInfo) value;
|
||||
final VolumeInfo currentVol = context.getPackageManager().getApplicationCurrentVolume(
|
||||
mAppEntry.info);
|
||||
if (!Objects.equals(targetVol, currentVol)) {
|
||||
final Intent intent = new Intent(context, StorageWizardMoveConfirm.class);
|
||||
intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, targetVol.getId());
|
||||
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, mAppEntry.info.packageName);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -260,27 +259,17 @@ public class AppStorageSettings extends AppInfoWithHeader
|
||||
retrieveAppEntry();
|
||||
refreshButtons();
|
||||
refreshSizeInfo();
|
||||
boolean isExternal = (mAppEntry.info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
|
||||
mMoveDropDown.setSelectedItem(isExternal ? 1 : 0);
|
||||
|
||||
final VolumeInfo currentVol = getActivity().getPackageManager()
|
||||
.getApplicationCurrentVolume(mAppEntry.info);
|
||||
mMoveDropDown.setSelectedValue(currentVol);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void refreshButtons() {
|
||||
if (!mMoveInProgress) {
|
||||
initMoveDropDown();
|
||||
initDataButtons();
|
||||
} else {
|
||||
mMoveDropDown.setSummary(R.string.moving);
|
||||
mMoveDropDown.setSelectable(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateMoveEnabled(boolean enabled) {
|
||||
mMoveDropDown.clearItems();
|
||||
mMoveDropDown.addItem(R.string.storage_type_internal, false);
|
||||
if (enabled) {
|
||||
mMoveDropDown.addItem(R.string.storage_type_external, true);
|
||||
}
|
||||
initMoveDropDown();
|
||||
initDataButtons();
|
||||
}
|
||||
|
||||
private void initDataButtons() {
|
||||
@@ -310,20 +299,18 @@ public class AppStorageSettings extends AppInfoWithHeader
|
||||
}
|
||||
|
||||
private void initMoveDropDown() {
|
||||
if (Environment.isExternalStorageEmulated()) {
|
||||
updateMoveEnabled(false);
|
||||
return;
|
||||
final Context context = getActivity();
|
||||
final StorageManager storage = context.getSystemService(StorageManager.class);
|
||||
|
||||
final List<VolumeInfo> candidates = context.getPackageManager()
|
||||
.getApplicationCandidateVolumes(mAppEntry.info);
|
||||
Collections.sort(candidates, VolumeInfo.getDescriptionComparator());
|
||||
|
||||
mMoveDropDown.clearItems();
|
||||
for (VolumeInfo vol : candidates) {
|
||||
final String volDescrip = storage.getBestVolumeDescription(vol);
|
||||
mMoveDropDown.addItem(volDescrip, vol);
|
||||
}
|
||||
boolean dataOnly = (mPackageInfo == null) && (mAppEntry != null);
|
||||
boolean moveDisable = true;
|
||||
if ((mAppEntry.info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
|
||||
// Always let apps move to internal storage from sdcard.
|
||||
moveDisable = false;
|
||||
} else {
|
||||
mCanBeOnSdCardChecker.init();
|
||||
moveDisable = !mCanBeOnSdCardChecker.check(mAppEntry.info);
|
||||
}
|
||||
updateMoveEnabled(!moveDisable);
|
||||
mMoveDropDown.setSelectable(!mAppControlRestricted);
|
||||
}
|
||||
|
||||
@@ -351,21 +338,6 @@ public class AppStorageSettings extends AppInfoWithHeader
|
||||
}
|
||||
}
|
||||
|
||||
private void processMoveMsg(Message msg) {
|
||||
int result = msg.arg1;
|
||||
String packageName = mAppEntry.info.packageName;
|
||||
// Refresh the button attributes.
|
||||
mMoveInProgress = false;
|
||||
if (result == PackageManager.MOVE_SUCCEEDED) {
|
||||
Log.i(TAG, "Moved resources for " + packageName);
|
||||
// Refresh size information again.
|
||||
mState.requestSize(mPackageName, mUserId);
|
||||
} else {
|
||||
showDialogInner(DLG_MOVE_FAILED, result);
|
||||
}
|
||||
refreshUi();
|
||||
}
|
||||
|
||||
/*
|
||||
* Private method to handle clear message notification from observer when
|
||||
* the async operation from PackageManager is complete
|
||||
@@ -382,24 +354,6 @@ public class AppStorageSettings extends AppInfoWithHeader
|
||||
}
|
||||
}
|
||||
|
||||
private CharSequence getMoveErrMsg(int errCode) {
|
||||
switch (errCode) {
|
||||
case PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE:
|
||||
return getActivity().getString(R.string.insufficient_storage);
|
||||
case PackageManager.MOVE_FAILED_DOESNT_EXIST:
|
||||
return getActivity().getString(R.string.does_not_exist);
|
||||
case PackageManager.MOVE_FAILED_FORWARD_LOCKED:
|
||||
return getActivity().getString(R.string.app_forward_locked);
|
||||
case PackageManager.MOVE_FAILED_INVALID_LOCATION:
|
||||
return getActivity().getString(R.string.invalid_location);
|
||||
case PackageManager.MOVE_FAILED_SYSTEM_PACKAGE:
|
||||
return getActivity().getString(R.string.system_package);
|
||||
case PackageManager.MOVE_FAILED_INTERNAL_ERROR:
|
||||
return "";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AlertDialog createDialog(int id, int errorCode) {
|
||||
switch (id) {
|
||||
@@ -427,14 +381,6 @@ public class AppStorageSettings extends AppInfoWithHeader
|
||||
}
|
||||
})
|
||||
.create();
|
||||
case DLG_MOVE_FAILED:
|
||||
CharSequence msg = getActivity().getString(R.string.move_app_failed_dlg_text,
|
||||
getMoveErrMsg(errorCode));
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setTitle(getActivity().getText(R.string.move_app_failed_dlg_title))
|
||||
.setMessage(msg)
|
||||
.setNeutralButton(R.string.dlg_ok, null)
|
||||
.create();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -459,9 +405,6 @@ public class AppStorageSettings extends AppInfoWithHeader
|
||||
// Refresh size info
|
||||
mState.requestSize(mPackageName, mUserId);
|
||||
break;
|
||||
case MSG_PACKAGE_MOVE:
|
||||
processMoveMsg(msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -508,13 +451,4 @@ public class AppStorageSettings extends AppInfoWithHeader
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
class PackageMoveObserver extends IPackageMoveObserver.Stub {
|
||||
public void packageMoved(String packageName, int returnCode) throws RemoteException {
|
||||
final Message msg = mHandler.obtainMessage(MSG_PACKAGE_MOVE);
|
||||
msg.arg1 = returnCode;
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -295,20 +295,6 @@ public class ApplicationsState {
|
||||
}
|
||||
};
|
||||
|
||||
public static final AppFilter FILTER_ON_SD_CARD = new AppFilter() {
|
||||
final CanBeOnSdCardChecker mCanBeOnSdCardChecker
|
||||
= new CanBeOnSdCardChecker();
|
||||
|
||||
public void init() {
|
||||
mCanBeOnSdCardChecker.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean filterApp(AppEntry entry) {
|
||||
return mCanBeOnSdCardChecker.check(entry.info);
|
||||
}
|
||||
};
|
||||
|
||||
public static final AppFilter FILTER_DISABLED = new AppFilter() {
|
||||
public void init() {
|
||||
}
|
||||
|
@@ -20,15 +20,11 @@ import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.IPackageManager;
|
||||
import android.content.pm.IntentFilterVerificationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.preference.PreferenceFrameLayout;
|
||||
@@ -53,7 +49,6 @@ import android.widget.Filterable;
|
||||
import android.widget.ListView;
|
||||
import android.widget.Spinner;
|
||||
|
||||
import com.android.internal.content.PackageHelper;
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.settings.HelpUtils;
|
||||
import com.android.settings.InstrumentedFragment;
|
||||
@@ -74,47 +69,6 @@ import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
final class CanBeOnSdCardChecker {
|
||||
final IPackageManager mPm;
|
||||
int mInstallLocation;
|
||||
|
||||
CanBeOnSdCardChecker() {
|
||||
mPm = IPackageManager.Stub.asInterface(
|
||||
ServiceManager.getService("package"));
|
||||
}
|
||||
|
||||
void init() {
|
||||
try {
|
||||
mInstallLocation = mPm.getInstallLocation();
|
||||
} catch (RemoteException e) {
|
||||
Log.e("CanBeOnSdCardChecker", "Is Package Manager running?");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
boolean check(ApplicationInfo info) {
|
||||
boolean canBe = false;
|
||||
if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
|
||||
canBe = true;
|
||||
} else {
|
||||
if ((info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
|
||||
if (info.installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL ||
|
||||
info.installLocation == PackageInfo.INSTALL_LOCATION_AUTO) {
|
||||
canBe = true;
|
||||
} else if (info.installLocation
|
||||
== PackageInfo.INSTALL_LOCATION_UNSPECIFIED) {
|
||||
if (mInstallLocation == PackageHelper.APP_INSTALL_EXTERNAL) {
|
||||
// For apps with no preference and the default value set
|
||||
// to install on sdcard.
|
||||
canBe = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return canBe;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Activity to pick an application that will be used to display installation information and
|
||||
* options to uninstall/delete user data for system applications. This activity
|
||||
|
@@ -41,7 +41,6 @@ import com.android.settings.search.SearchIndexableRaw;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -91,21 +90,6 @@ public class StorageSettings extends SettingsPreferenceFragment implements Index
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
private static final Comparator<VolumeInfo> sVolumeComparator = new Comparator<VolumeInfo>() {
|
||||
@Override
|
||||
public int compare(VolumeInfo lhs, VolumeInfo rhs) {
|
||||
if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(lhs.getId())) {
|
||||
return -1;
|
||||
} else if (lhs.getDescription() == null) {
|
||||
return 1;
|
||||
} else if (rhs.getDescription() == null) {
|
||||
return -1;
|
||||
} else {
|
||||
return lhs.getDescription().compareTo(rhs.getDescription());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final StorageEventListener mStorageListener = new StorageEventListener() {
|
||||
@Override
|
||||
public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
|
||||
@@ -133,7 +117,7 @@ public class StorageSettings extends SettingsPreferenceFragment implements Index
|
||||
mExternalCategory.removeAll();
|
||||
|
||||
final List<VolumeInfo> volumes = mStorageManager.getVolumes();
|
||||
Collections.sort(volumes, sVolumeComparator);
|
||||
Collections.sort(volumes, VolumeInfo.getDescriptionComparator());
|
||||
|
||||
for (VolumeInfo vol : volumes) {
|
||||
if (vol.getType() == VolumeInfo.TYPE_PRIVATE) {
|
||||
|
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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.settings.deviceinfo;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.os.Bundle;
|
||||
import android.os.storage.VolumeInfo;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.settings.R;
|
||||
|
||||
public class StorageWizardMoveConfirm extends StorageWizardBase {
|
||||
private String mPackageName;
|
||||
private ApplicationInfo mApp;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.storage_wizard_generic);
|
||||
|
||||
try {
|
||||
mPackageName = getIntent().getStringExtra(Intent.EXTRA_PACKAGE_NAME);
|
||||
mApp = getPackageManager().getApplicationInfo(mPackageName, 0);
|
||||
} catch (NameNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
Preconditions.checkNotNull(mVolume);
|
||||
Preconditions.checkNotNull(mApp);
|
||||
|
||||
// Sanity check that target volume is candidate
|
||||
Preconditions.checkState(
|
||||
getPackageManager().getApplicationCandidateVolumes(mApp).contains(mVolume));
|
||||
|
||||
final String appName = getPackageManager().getApplicationLabel(mApp).toString();
|
||||
final String volumeName = mStorage.getBestVolumeDescription(mVolume);
|
||||
|
||||
setHeaderText(R.string.storage_wizard_move_confirm_title, appName);
|
||||
setBodyText(R.string.storage_wizard_move_confirm_body, appName, volumeName);
|
||||
|
||||
getNextButton().setText(R.string.move_app);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNavigateNext() {
|
||||
final Intent intent = new Intent(this, StorageWizardMoveProgress.class);
|
||||
intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, mVolume.getId());
|
||||
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, mPackageName);
|
||||
startActivity(intent);
|
||||
finishAffinity();
|
||||
}
|
||||
}
|
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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.settings.deviceinfo;
|
||||
|
||||
import static com.android.settings.deviceinfo.StorageSettings.TAG;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.IPackageMoveObserver;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.os.storage.VolumeInfo;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.settings.R;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
public class StorageWizardMoveProgress extends StorageWizardBase {
|
||||
private String mPackageName;
|
||||
private ApplicationInfo mApp;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.storage_wizard_progress);
|
||||
|
||||
try {
|
||||
mPackageName = getIntent().getStringExtra(Intent.EXTRA_PACKAGE_NAME);
|
||||
mApp = getPackageManager().getApplicationInfo(mPackageName, 0);
|
||||
} catch (NameNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
Preconditions.checkNotNull(mVolume);
|
||||
Preconditions.checkNotNull(mApp);
|
||||
|
||||
final String appName = getPackageManager().getApplicationLabel(mApp).toString();
|
||||
final String volumeName = mStorage.getBestVolumeDescription(mVolume);
|
||||
|
||||
setHeaderText(R.string.storage_wizard_move_progress_title, appName);
|
||||
setBodyText(R.string.storage_wizard_move_progress_body, volumeName, appName);
|
||||
|
||||
setCurrentProgress(20);
|
||||
|
||||
getNextButton().setVisibility(View.GONE);
|
||||
|
||||
new MoveTask().execute();
|
||||
}
|
||||
|
||||
private CharSequence moveStatusToMessage(int returnCode) {
|
||||
switch (returnCode) {
|
||||
case PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE:
|
||||
return getString(R.string.insufficient_storage);
|
||||
case PackageManager.MOVE_FAILED_DOESNT_EXIST:
|
||||
return getString(R.string.does_not_exist);
|
||||
case PackageManager.MOVE_FAILED_FORWARD_LOCKED:
|
||||
return getString(R.string.app_forward_locked);
|
||||
case PackageManager.MOVE_FAILED_INVALID_LOCATION:
|
||||
return getString(R.string.invalid_location);
|
||||
case PackageManager.MOVE_FAILED_SYSTEM_PACKAGE:
|
||||
return getString(R.string.system_package);
|
||||
case PackageManager.MOVE_FAILED_INTERNAL_ERROR:
|
||||
default:
|
||||
return getString(R.string.insufficient_storage);
|
||||
}
|
||||
}
|
||||
|
||||
private class LocalPackageMoveObserver extends IPackageMoveObserver.Stub {
|
||||
public int returnCode;
|
||||
public CountDownLatch finished = new CountDownLatch(1);
|
||||
|
||||
@Override
|
||||
public void packageMoved(String packageName, int returnCode) throws RemoteException {
|
||||
this.returnCode = returnCode;
|
||||
this.finished.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
public class MoveTask extends AsyncTask<Void, Void, Integer> {
|
||||
@Override
|
||||
protected Integer doInBackground(Void... params) {
|
||||
try {
|
||||
final LocalPackageMoveObserver observer = new LocalPackageMoveObserver();
|
||||
|
||||
if (mApp.isExternalAsec()) {
|
||||
getPackageManager().movePackage(mPackageName, observer,
|
||||
PackageManager.MOVE_INTERNAL);
|
||||
} else if (mVolume.getType() == VolumeInfo.TYPE_PUBLIC) {
|
||||
getPackageManager().movePackage(mPackageName, observer,
|
||||
PackageManager.MOVE_EXTERNAL_MEDIA);
|
||||
} else {
|
||||
getPackageManager().movePackageAndData(mPackageName, mVolume.fsUuid, observer);
|
||||
}
|
||||
|
||||
observer.finished.await();
|
||||
return observer.returnCode;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failed to move", e);
|
||||
return PackageManager.MOVE_FAILED_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Integer returnCode) {
|
||||
final Context context = StorageWizardMoveProgress.this;
|
||||
if (returnCode == PackageManager.MOVE_SUCCEEDED) {
|
||||
finishAffinity();
|
||||
|
||||
} else {
|
||||
Log.w(TAG, "Move failed with status " + returnCode);
|
||||
Toast.makeText(context, moveStatusToMessage(returnCode), Toast.LENGTH_LONG).show();
|
||||
finishAffinity();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user