/*
 * Copyright (C) 2016 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.afwsamples.testdpc.common;

import android.annotation.TargetApi;
import android.app.Fragment;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.UserManager;
import android.support.v13.app.FragmentTabHost;
import android.support.v7.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.afwsamples.testdpc.DeviceAdminReceiver;
import com.afwsamples.testdpc.R;

/**
 * This fragment provides functionalities to show the same policy fragment for both the managed
 * user and its parent user in separate tabs, if applicable.
 *
 * If there is no parent user (for example, if the managed user is controlled by a Device Owner),
 * the fragment will be shown directly.
 *
 * Please notice that all subclasses of this fragment only support N or above.
 */
@TargetApi(VERSION_CODES.N)
public abstract class ProfileOrParentFragment extends BaseSearchablePolicyPreferenceFragment {
    private static final String LOG_TAG = "ProfileOrParentFragment";

    private static final String EXTRA_PARENT_PROFILE = "com.afwsamples.testdpc.extra.PARENT";

    // Tag to append to the name of the SharedPreferences if we are running as a parent instance.
    private static final String TAG_PARENT = ":parent";

    public abstract static class Container extends Fragment {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            final UserManager userManager = (UserManager)
                    getActivity().getSystemService(Context.USER_SERVICE);

            if (userManager.getUserProfiles().size() == 1 || Util.isBeforeN()) {
                // No need for a tabbed view if there's just one item, or if the OS we are running
                // under does not support parent policies.
                try {
                    getFragmentManager()
                            .popBackStack();
                    getFragmentManager()
                            .beginTransaction()
                            .replace(R.id.container, getContentClass().newInstance())
                            .addToBackStack(null)
                            .commit();
                } catch (Fragment.InstantiationException | java.lang.InstantiationException |
                        IllegalAccessException ine) {
                    Log.e(LOG_TAG, "Failed to instantiate " + getContentClass(), ine);
                }
                return;
            }

            // FragmentTabHost needs to be retained to keep track of tabs properly.
            setRetainInstance(true);
        }

        @Override
        public View onCreateView(
                LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            FragmentTabHost tabHost = new FragmentTabHost(getActivity());
            tabHost.setup(getActivity(), getChildFragmentManager(), View.generateViewId());

            // Tab for the parent profile
            Bundle parentArgs = new Bundle();
            parentArgs.putBoolean(EXTRA_PARENT_PROFILE, true);
            tabHost.addTab(
                    tabHost.newTabSpec("parent").setIndicator(getString(R.string.personal_profile)),
                    getContentClass(), parentArgs);

            // Tab for the work profile
            Bundle workArgs = new Bundle();
            workArgs.putBoolean(EXTRA_PARENT_PROFILE, false);
            tabHost.addTab(
                    tabHost.newTabSpec("profile").setIndicator(getString(R.string.work_profile)),
                    getContentClass(), workArgs);

            // Mark work tab as the current one.
            tabHost.setCurrentTab(1);

            return tabHost;
        }

        public abstract Class<? extends ProfileOrParentFragment> getContentClass();
    }

    private DevicePolicyManager mDevicePolicyManager;
    private ComponentName mAdminComponent;
    private boolean mParentInstance;
    private boolean mProfileOwner;
    private boolean mDeviceOwner;

    /**
     * @return a {@link DevicePolicyManager} instance for the profile this tab should affect.
     */
    protected final DevicePolicyManager getDpm() {
        return mDevicePolicyManager;
    }

    protected final ComponentName getAdmin() {
        return mAdminComponent;
    }

    /**
     * @return {@code true} if this tab is supposed to affect the parent profile, {@code false}
     *         otherwise.
     */
    protected final boolean isParentProfileInstance() {
        return mParentInstance;
    }

    /**
     * @return {@code true} if this tab represents a top-level user, {@code false} otherwise.
     */
    protected final boolean isManagedProfileInstance() {
        return mProfileOwner && !isParentProfileInstance();
    }

    protected boolean isDeviceOwner() {
        return mDeviceOwner;
    }

    protected boolean isProfileOwner() {
        return mProfileOwner;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // Check arguments- see whether we're supposed to run on behalf of the parent profile.
        final Bundle arguments = getArguments();
        if (arguments != null) {
            mParentInstance = arguments.getBoolean(EXTRA_PARENT_PROFILE, false);
        }

        mAdminComponent = DeviceAdminReceiver.getComponentName(getActivity());

        // Get a device policy manager for the current user.
        mDevicePolicyManager = (DevicePolicyManager)
                getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);

        // Store whether we are the profile owner for faster lookup.
        mProfileOwner = mDevicePolicyManager.isProfileOwnerApp(getActivity().getPackageName());
        mDeviceOwner = mDevicePolicyManager.isDeviceOwnerApp(getActivity().getPackageName());

        // Put at last to make sure all initializations above are done before subclass's
        // onCreatePreferences is called.
        super.onCreate(savedInstanceState);

        // Switch to parent profile if we are running on their behalf.
        // This needs to be called after super.onCreate because preference manager is set up
        // inside super.onCreate.
        if (mParentInstance) {
            mDevicePolicyManager = mDevicePolicyManager.getParentProfileInstance(mAdminComponent);
            final PreferenceManager pm = getPreferenceManager();
            pm.setSharedPreferencesName(pm.getSharedPreferencesName() + TAG_PARENT);
        }
    }
}

@@ -6593,24 +6593,165 @@
 geName());%0A%0A
+        if (mParentInstance) %7B%0A            mDevicePolicyManager = mDevicePolicyManager.getParentProfileInstance(mAdminComponent);%0A        %7D%0A%0A
         // P
@@ -7147,107 +7147,8 @@
 ) %7B%0A
-            mDevicePolicyManager = mDevicePolicyManager.getParentProfileInstance(mAdminComponent);%0A
     

Initialize parent instance of DevicePolicyManager earlier