Merge "Created metric events for scoped directory access API." into nyc-dev

This commit is contained in:
Felipe Leme
2016-03-01 18:58:26 +00:00
committed by Android (Google) Code Review
4 changed files with 144 additions and 10 deletions

View File

@@ -507,7 +507,7 @@ public class Environment {
* </ul>
* @hide
*/
private static final String[] STANDARD_DIRECTORIES = {
public static final String[] STANDARD_DIRECTORIES = {
DIRECTORY_MUSIC,
DIRECTORY_PODCASTS,
DIRECTORY_RINGTONES,

View File

@@ -16,10 +16,12 @@
package com.android.documentsui;
import static android.os.Environment.STANDARD_DIRECTORIES;
import static com.android.documentsui.Shared.DEBUG;
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.StringDef;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
@@ -32,6 +34,7 @@ import com.android.documentsui.model.RootInfo;
import com.android.documentsui.services.FileOperationService;
import com.android.documentsui.services.FileOperationService.OpType;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -376,6 +379,84 @@ public final class Metrics {
logHistogram(context, histogram, getOpCode(operationType, PROVIDER_INTRA));
}
// Types for logInvalidScopedAccessRequest
public static final String SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS =
"scoped_directory_access_invalid_args";
public static final String SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY =
"scoped_directory_access_invalid_dir";
public static final String SCOPED_DIRECTORY_ACCESS_ERROR =
"scoped_directory_access_error";
@StringDef(value = {
SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS,
SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY,
SCOPED_DIRECTORY_ACCESS_ERROR
})
@Retention(RetentionPolicy.SOURCE)
public @interface InvalidScopedAccess{}
public static void logInvalidScopedAccessRequest(Context context,
@InvalidScopedAccess String type) {
MetricsLogger.count(context, type, 1);
switch (type) {
case SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS:
case SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY:
case SCOPED_DIRECTORY_ACCESS_ERROR:
MetricsLogger.count(context, type, 1);
break;
default:
Log.wtf(TAG, "invalid InvalidScopedAccess: " + type);
}
}
// Types for logValidScopedAccessRequest
public static final int SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED = 0;
public static final int SCOPED_DIRECTORY_ACCESS_GRANTED = 1;
public static final int SCOPED_DIRECTORY_ACCESS_DENIED = 2;
@IntDef(flag = true, value = {
SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED,
SCOPED_DIRECTORY_ACCESS_GRANTED,
SCOPED_DIRECTORY_ACCESS_DENIED
})
@Retention(RetentionPolicy.SOURCE)
public @interface ScopedAccessGrant {}
public static void logValidScopedAccessRequest(Activity activity, String directory,
@ScopedAccessGrant int type) {
int index = -1;
for (int i = 0; i < STANDARD_DIRECTORIES.length; i++) {
if (STANDARD_DIRECTORIES[i].equals(directory)) {
index = i;
break;
}
}
final String packageName = activity.getCallingPackage();
switch (type) {
case SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED:
MetricsLogger.action(activity,
MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_PACKAGE,
packageName);
MetricsLogger.action(activity,
MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_FOLDER, index);
break;
case SCOPED_DIRECTORY_ACCESS_GRANTED:
MetricsLogger.action(activity,
MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_PACKAGE, packageName);
MetricsLogger.action(activity,
MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_FOLDER, index);
break;
case SCOPED_DIRECTORY_ACCESS_DENIED:
MetricsLogger.action(activity,
MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_PACKAGE, packageName);
MetricsLogger.action(activity,
MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_FOLDER, index);
break;
default:
Log.wtf(TAG, "invalid ScopedAccessGrant: " + type);
}
}
/**
* Internal method for making a MetricsLogger.count call. Increments the given counter by 1.
*

View File

@@ -17,9 +17,18 @@
package com.android.documentsui;
import static android.os.Environment.isStandardDirectory;
import static android.os.Environment.STANDARD_DIRECTORIES;
import static android.os.storage.StorageVolume.EXTRA_DIRECTORY_NAME;
import static android.os.storage.StorageVolume.EXTRA_STORAGE_VOLUME;
import static com.android.documentsui.Shared.DEBUG;
import static com.android.documentsui.Metrics.logInvalidScopedAccessRequest;
import static com.android.documentsui.Metrics.logValidScopedAccessRequest;
import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED;
import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_DENIED;
import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_ERROR;
import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_GRANTED;
import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS;
import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY;
import android.app.Activity;
import android.app.ActivityManager;
@@ -73,6 +82,7 @@ public class OpenExternalDirectoryActivity extends Activity {
final Intent intent = getIntent();
if (intent == null) {
if (DEBUG) Log.d(TAG, "missing intent");
logInvalidScopedAccessRequest(this, SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS);
setResult(RESULT_CANCELED);
finish();
return;
@@ -82,12 +92,14 @@ public class OpenExternalDirectoryActivity extends Activity {
if (DEBUG)
Log.d(TAG, "extra " + EXTRA_STORAGE_VOLUME + " is not a StorageVolume: "
+ storageVolume);
logInvalidScopedAccessRequest(this, SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS);
setResult(RESULT_CANCELED);
finish();
return;
}
final String directoryName = intent.getStringExtra(EXTRA_DIRECTORY_NAME);
if (directoryName == null) {
logInvalidScopedAccessRequest(this, SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS);
if (DEBUG) Log.d(TAG, "missing extra " + EXTRA_DIRECTORY_NAME + " on " + intent);
setResult(RESULT_CANCELED);
finish();
@@ -125,6 +137,7 @@ public class OpenExternalDirectoryActivity extends Activity {
} catch (IOException e) {
Log.e(TAG, "Could not get canonical file for volume " + storageVolume.dump()
+ " and directory " + directoryName);
logInvalidScopedAccessRequest(activity, SCOPED_DIRECTORY_ACCESS_ERROR);
return false;
}
final StorageManager sm =
@@ -138,6 +151,7 @@ public class OpenExternalDirectoryActivity extends Activity {
if (DEBUG)
Log.d(TAG, "Directory '" + directory + "' is not standard (full path: '"
+ file.getAbsolutePath() + "')");
logInvalidScopedAccessRequest(activity, SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY);
return false;
}
@@ -159,6 +173,8 @@ public class OpenExternalDirectoryActivity extends Activity {
// Checks if the user has granted the permission already.
final Intent intent = getIntentForExistingPermission(activity, file);
if (intent != null) {
logValidScopedAccessRequest(activity, directory,
SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED);
activity.setResult(RESULT_OK, intent);
activity.finish();
return true;
@@ -166,12 +182,14 @@ public class OpenExternalDirectoryActivity extends Activity {
if (volumeLabel == null) {
Log.e(TAG, "Could not get volume for " + file);
logInvalidScopedAccessRequest(activity, SCOPED_DIRECTORY_ACCESS_ERROR);
return false;
}
// Gets the package label.
final String appLabel = getAppLabel(activity);
if (appLabel == null) {
// Error already logged.
return false;
}
@@ -198,6 +216,7 @@ public class OpenExternalDirectoryActivity extends Activity {
try {
return pm.getApplicationLabel(pm.getApplicationInfo(packageName, 0)).toString();
} catch (NameNotFoundException e) {
logInvalidScopedAccessRequest(activity, SCOPED_DIRECTORY_ACCESS_ERROR);
Log.w(TAG, "Could not get label for package " + packageName);
return null;
}
@@ -217,18 +236,21 @@ public class OpenExternalDirectoryActivity extends Activity {
return volume.isVisibleForWrite(userId) && root.equals(path);
}
private static Uri getGrantedUriPermission(ContentProviderClient provider, File file) {
private static Uri getGrantedUriPermission(Context context, ContentProviderClient provider,
File file) {
// Calls ExternalStorageProvider to get the doc id for the file
final Bundle bundle;
try {
bundle = provider.call("getDocIdForFileCreateNewDir", file.getPath(), null);
} catch (RemoteException e) {
Log.e(TAG, "Did not get doc id from External Storage provider for " + file, e);
logInvalidScopedAccessRequest(context, SCOPED_DIRECTORY_ACCESS_ERROR);
return null;
}
final String docId = bundle == null ? null : bundle.getString("DOC_ID");
if (docId == null) {
Log.e(TAG, "Did not get doc id from External Storage provider for " + file);
logInvalidScopedAccessRequest(context, SCOPED_DIRECTORY_ACCESS_ERROR);
return null;
}
Log.d(TAG, "doc id for " + file + ": " + docId);
@@ -242,9 +264,9 @@ public class OpenExternalDirectoryActivity extends Activity {
return uri;
}
private static Intent createGrantedUriPermissionsIntent(ContentProviderClient provider,
File file) {
final Uri uri = getGrantedUriPermission(provider, file);
private static Intent createGrantedUriPermissionsIntent(Context context,
ContentProviderClient provider, File file) {
final Uri uri = getGrantedUriPermission(context, provider, file);
return createGrantedUriPermissionsIntent(uri);
}
@@ -261,7 +283,8 @@ public class OpenExternalDirectoryActivity extends Activity {
private static Intent getIntentForExistingPermission(OpenExternalDirectoryActivity activity,
File file) {
final String packageName = activity.getCallingPackage();
final Uri grantedUri = getGrantedUriPermission(activity.getExternalStorageClient(), file);
final Uri grantedUri =
getGrantedUriPermission(activity, activity.getExternalStorageClient(), file);
if (DEBUG)
Log.d(TAG, "checking if " + packageName + " already has permission for " + grantedUri);
final ActivityManager am =
@@ -298,7 +321,7 @@ public class OpenExternalDirectoryActivity extends Activity {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final String folder = mFile.getName();
final String directory = mFile.getName();
final Activity activity = getActivity();
final OnClickListener listener = new OnClickListener() {
@@ -306,12 +329,16 @@ public class OpenExternalDirectoryActivity extends Activity {
public void onClick(DialogInterface dialog, int which) {
Intent intent = null;
if (which == DialogInterface.BUTTON_POSITIVE) {
intent = createGrantedUriPermissionsIntent(
intent = createGrantedUriPermissionsIntent(mActivity,
mActivity.getExternalStorageClient(), mFile);
}
if (which == DialogInterface.BUTTON_NEGATIVE || intent == null) {
logValidScopedAccessRequest(activity, directory,
SCOPED_DIRECTORY_ACCESS_DENIED);
activity.setResult(RESULT_CANCELED);
} else {
logValidScopedAccessRequest(activity, directory,
SCOPED_DIRECTORY_ACCESS_GRANTED);
activity.setResult(RESULT_OK, intent);
}
activity.finish();
@@ -320,7 +347,7 @@ public class OpenExternalDirectoryActivity extends Activity {
final CharSequence message = TextUtils
.expandTemplate(
getText(R.string.open_external_dialog_request), mAppLabel, folder,
getText(R.string.open_external_dialog_request), mAppLabel, directory,
mVolumeLabel);
return new AlertDialog.Builder(activity, R.style.AlertDialogTheme)
.setMessage(message)
@@ -333,6 +360,7 @@ public class OpenExternalDirectoryActivity extends Activity {
public void onCancel(DialogInterface dialog) {
super.onCancel(dialog);
final Activity activity = getActivity();
logValidScopedAccessRequest(activity, mFile.getName(), SCOPED_DIRECTORY_ACCESS_DENIED);
activity.setResult(RESULT_CANCELED);
activity.finish();
}

View File

@@ -478,5 +478,30 @@ message MetricsEvent {
// Logged when we execute an app transition. This indicates the device uptime in seconds when
// the transition was executed.
APP_TRANSITION_DEVICE_UPTIME_SECONDS = 325;
// User granted access to the request folder; action takes an integer
// representing the folder's index on Environment.STANDARD_DIRECTORIES
ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_FOLDER = 326;
// User denied access to the request folder; action takes an integer
// representing the folder's index on Environment.STANDARD_DIRECTORIES
ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_FOLDER = 327;
// User granted access to the request folder; action pass package name
// of calling package.
ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_PACKAGE = 328;
// User denied access to the request folder; action pass package name
// of calling package.
ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_PACKAGE = 329;
// App requested access to a directory it has already been granted
// access before; action takes an integer representing the folder's
// index on Environment.STANDARD_DIRECTORIES
ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_FOLDER = 330;
// App requested access to a directory it has already been granted
// access before; action pass package name of calling package.
ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_PACKAGE = 331;
}
}