1 /*
2  * Copyright (C) 2023 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.ondevicepersonalization.services.util;
18 
19 import android.adservices.ondevicepersonalization.IsolatedServiceException;
20 import android.annotation.NonNull;
21 import android.content.ComponentName;
22 import android.content.ContentResolver;
23 import android.content.Context;
24 import android.os.Build;
25 import android.provider.Settings;
26 
27 import com.android.odp.module.common.PackageUtils;
28 import com.android.ondevicepersonalization.internal.util.LoggerFactory;
29 import com.android.ondevicepersonalization.services.FlagsFactory;
30 import com.android.ondevicepersonalization.services.OdpServiceException;
31 
32 import java.util.Objects;
33 
34 /** Fuctions for testing and debugging. */
35 public class DebugUtils {
36     private static final LoggerFactory.Logger sLogger = LoggerFactory.getLogger();
37     private static final String TAG = DebugUtils.class.getSimpleName();
38 
39     /** Returns true if the device is debuggable. */
isDeveloperModeEnabled(@onNull Context context)40     public static boolean isDeveloperModeEnabled(@NonNull Context context) {
41         ContentResolver resolver = Objects.requireNonNull(context.getContentResolver());
42         return Build.isDebuggable()
43                 || Settings.Global.getInt(
44                     resolver, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
45     }
46 
47     /** Returns the exception code reported by the service if debugging is allowed. */
getIsolatedServiceExceptionCode( @onNull Context context, @NonNull ComponentName service, @NonNull OdpServiceException e)48     public static int getIsolatedServiceExceptionCode(
49             @NonNull Context context,
50             @NonNull ComponentName service,
51             @NonNull OdpServiceException e) {
52         try {
53             if (!FlagsFactory.getFlags().isIsolatedServiceDebuggingEnabled()) {
54                 return 0;
55             }
56             if (isDeveloperModeEnabled(context)
57                     && PackageUtils.isPackageDebuggable(context, service.getPackageName())) {
58                 if (e.getCause() != null && e.getCause() instanceof IsolatedServiceException) {
59                     return ((IsolatedServiceException) e.getCause()).getErrorCode();
60                 }
61             }
62         } catch (Exception e2) {
63             sLogger.e(e2, TAG + ": failed to get code");
64         }
65         return 0;
66     }
67 
68     /** Returns the exception message if debugging is allowed. */
getErrorMessage(@onNull Context context, Throwable t)69     public static String getErrorMessage(@NonNull Context context, Throwable t) {
70         try {
71             if (t != null && isDeveloperModeEnabled(context)
72                     && FlagsFactory.getFlags().isIsolatedServiceDebuggingEnabled()) {
73                 return t.getClass().getSimpleName() + ": " + t.getMessage();
74             }
75         } catch (Exception e) {
76             sLogger.e(e, TAG + ": failed to get message");
77         }
78         return null;
79     }
80 
DebugUtils()81     private DebugUtils() {}
82 }
83